gonetz / GLideN64

A new generation, open-source graphics plugin for N64 emulators.
Other
754 stars 174 forks source link

Mischief Makers - Mathfun questions are black and unreadable #1183

Closed lKomus closed 7 years ago

lKomus commented 7 years ago

This was tested with GLideN64's last master, it used to work with Glide64.

GLideN64 project64_2016-10-18_09-34-58 Glide64 project64_2016-10-18_09-35-15

Savestate: Mischief Makers (U) (V1.0).pj.zip

gonetz commented 7 years ago

Could you provide savestate for older version of Project64 or for another emulator?

gonetz commented 7 years ago

This and #1181 are the same problem. N64 uses fixed point arithmetic and non-trivial clamp of the result. Negative value of a color is clamped to zero, but if its absolute value is large enough it can became one! Here the board has color -1. GL clamps it to zero and it is black. N64 clamps it to 1 and it is white. Glide64 uses a hack, which somehow works for this case, but not for #1181

Shader code to fix it looks like this:

if (color1.r < -0.51) color1.r = 1.0; else if (color1.r < 0.0) color1.r = 0.0;
if (color1.g < -0.51) color1.g = 1.0; else if (color1.g < 0.0) color1.g = 0.0;
if (color1.b < -0.51) color1.b = 1.0; else if (color1.b < 0.0) color1.b = 0.0;

This looks ugly. Can somebody suggest better code? Preferably one vector operation.

lKomus commented 7 years ago

Sorry I wasn't available until now. Here's a savestate made with PJ64 1.6 MISCHIEF MAKERS.pj.zip

fzurita commented 7 years ago
ivec4 color1_temp = ivec4(clamp(color1, -1, 0)/-0.51)*1000; //This results in 0 or >1000 if we convert to integer, 1000 was selected for being a large number.
color1 = color1+color1_temp ; //You end up with either the same number or a number much greater than 1

With the above, if a component was <= -0.51, you end up with a number much greater than one, which will get clamped to 1.

The result of clamp(color1, -1, 0)/-0.51*1000 needs to be casted to an ivec4. Is there an easy way to do that?

gonetz commented 7 years ago

I probably missed something, but your code will map any negative value to 1. Values -0.51 < c < 0 must be clamped to zero.

fzurita commented 7 years ago

Yeah, it's just pseudo code, so it's not exact, but I'll demonstrate: With an input vec4 of (-0.45, -0.45, -0.45, -0.45);

vec4 temp1 = clamp(color1, -1, 0);  //temp1 = (-0.45, -0.45, -0.45, -0.45);
temp1 = temp1/-0.51;      //temp1 = (0.88, 0.88, 0.88, 0.88);
ivec4 temp2 = temp1; // Cast this to an integer somehow? temp2 = (0, 0, 0, 0)
ivec4 temp2 = temp2*1000; //temp2 = (0, 0, 0, 0)
color1 = color1 + temp2; //Cast temp2 back to a float somehow? Then you end up with color1 of  (-0.45, -0.45, -0.45, -0.45)

Now with an input vec4 of (-0.6, -0.6, -0.6, -0.6);

vec4 temp1 = clamp(color1, -1, 0);  //temp1 = (-0.6, -0.6, -0.6, -0.6);
temp1 = temp1/-0.51;      //temp1 = (1.17, 1.17, 1.17, 1.17);
ivec4 temp2 = temp1; // Cast this to an integer somehow? temp2 = (1, 1, 1, 1)
ivec4 temp2 = temp2*1000; //temp2 = (1000, 1000, 1000, 1000)
color1 = color1 + temp2; //Cast temp2 back to a float somehow? Then you end up with color1 of  (999.4, 999.4, 999.4, 999.4)

A positive value would give the same result as the first case. This only works ok if there is an easy way to cast between ivec4 and vec4.

fzurita commented 7 years ago

I guess to cast a vec4 to a ivec4 you could do

ivec4 temp = ivec4(int(color1.r), int(color1.g), int(color1.b), int(color1.a));

and the same backwards... Any easier way?

gonetz commented 7 years ago

This code does the trick

    vec3 clampColor = clamp(color1, -1.0, 0.0)/-0.51;
    ivec3 iClampColor = ivec3(clampColor)*1000;
    color1 = clamp(color1 + vec3(iClampColor), 0.0, 1.0);

Thanks!

gonetz commented 7 years ago

@lKomus thanks for the save

fzurita commented 7 years ago

No problem!

gonetz commented 7 years ago

The fix is in https://github.com/gonetz/GLideN64/tree/color_clamp branch. @fzurita , @loganmc10 Please check that I that fix does not break anything.

fzurita commented 7 years ago

Tested GLES 3.1 and GLES 2.0 on one Android device. Everything seems to look the same, which is what we expect unless you run into this specific circumstance.

The change seems simple enough that I don't think different devices will act differently.

gonetz commented 7 years ago

Yes. I was need to be sure that these modifications will compile without issues. Thanks!

fzurita commented 7 years ago

By the way, if you want to compile Mupen64plus-ae yourself, it's much easier now. All you need is Android Studio 2.2, clone the mupen64plus-ae github and open it using Android Studio. It should all compile and run right off the bat.

fzurita commented 7 years ago

There is one difference with my approach than yours that I'm not sure you noticed. Mine is checking for <= -0.51 your checks for < -0.51

gonetz commented 7 years ago

'''< -0.51''' is more right. I guess, that intended bound is -0.5, but N64 uses fixed point arithmetic, which impossible to correctly reproduce with floats. -0.5 bound produces wrong result, -0.51 bound works correct. Precise bound is somewhere near -0.506.

fzurita commented 7 years ago

OK, so it sounds that it won't make much of a difference since we were not precisely accurate in the first place.

gonetz commented 7 years ago

It does not make any difference because combiners rarely produce negative color values. This game was full of strange bugs caused by too creative use of hardware capabilities. BTW, I need to check, how large positive color values are clamped by N64. It does not care if value negative or positive, it just manipulates with bits. Probably, if color value is above 1.5 it should be clamped to 0.

fzurita commented 7 years ago

The same mechanism can be applied to clamp 1.5 to zero.

gonetz commented 7 years ago

Yes, but I'm not sure that it is used somewhere. It can be just waste of GPU resources.

lKomus commented 7 years ago

Just noticed that contrary to what Glide64 shows, the question border should be white on real hardware project64_2016-10-23_01-59-22

The bar beneath Events should be blue: project64_2016-10-23_01-56-16

This is to provide points of references just in case. Plugin used is Angrylion

AmbientMalice commented 7 years ago

@lKomus How do they look on GLideN64?

lKomus commented 7 years ago

I can't compile GLideN64, so I can't tell you how they look on the color-clamp branch.

On the latest compiled master, the bar is just black, like everything else that needs the color clamp (I'm assuming it needs that). project64_2016-10-23_02-30-09

Also I checked videos of Mischief Makers on Youtube to make sure that the plugin isn't rendering the wrong color.

EDIT: There's also a bar under the name of the events when you're doing them, this one should be white. project64_2016-10-23_02-33-41 GLideN64 renders it in black.

ghost commented 7 years ago

Is casting booleans to floats a bad thing?

You could always write color1 = color1 + (-color1)*float(color1<0.0) + vec3(float(color1<0.51));

The first addend clamps to 0 if negative and the second adds 1 more if it is a large negative.

Edit: I made a mistake. It must be made on a per coordinate basis, so the step function can be used to apply the same idea.

color1 = color1 + (-color1)*step(color1, vec3(0.0)) + step(color1, vec3(-0.51));

fzurita commented 7 years ago

I like it better than my solution since it gets rid of the random 1000 in the middle.

gonetz commented 7 years ago

@standard-two-simplex Thanks!

fzurita commented 7 years ago

I wonder if this is the same problem as this in Paper Mario:

paper_mario-000

I don't think those are supposed to be black.

fzurita commented 7 years ago

Actually, I think that black is supposed to be full alpha.

gonetz commented 7 years ago

This is a frame buffer effect. It worked ok on desktop last time I checked it. May be it was broken recently.

fzurita commented 7 years ago

I just checked full OpenGL mode in shield TV and it was broken there. I don't think there is much difference between the Full OpenGL mode in Android and the desktop version.

oddMLan commented 7 years ago

Does it work correct with texture enhancements disabled?

fzurita commented 7 years ago

The paper Mario effect does not work correctly with texture enhancements disabled.

gonetz commented 7 years ago

Ok, please give me a savestate.

fzurita commented 7 years ago

Here you go for mupen64plus: Paper mario.sav.zip

Talk while standing on the opposite side of the orb.

gonetz commented 7 years ago

Thanks! The same on desktop, yes.

oddMLan commented 7 years ago

Reminds me how all plugins but GLideN64 and Angrylion's can't emulate the alpha of tennis ball trace properly in Mario Tennis (the orb shows with an ugly black background much like in that Paper Mario pic) How did GLideN64 accomplish that feat?

gonetz commented 7 years ago

tennis ball trace is also fb effect, which blends texture of already rendered buffer with texture of the ball.

gonetz commented 7 years ago

I fixed that crystal ball issue in Paper Mario.

fzurita commented 7 years ago

Ok, I just verified that Paper Mario is fixed.

lKomus commented 7 years ago

Confirmed to be fixed in last master!