Normals - can't calculate upward correctly

I have a shader question.

I’m not getting the results that I expect I’m trying to calculate if the normal is facing upward and if so I want to alter the color.

vertex:

varying vec3 myNormal;

void main()
{
     .....
	myNormal = normalize(g_WorldViewMatrix * vec4(inNormal, 0.0)).xyz;
     ......
}

frag:

varying vec3 myNormal;
void main()
{
    ....
   float angle = acos(dot(myNormal, vec3(0, 1, 0)));
// for now just seeing if the value is > 0
	    if (angle > 0)
			color = vec4(1, 0, 0, 1);
     ....
}

Everything is red. There is a ton of flicking between red and black when walking in many models.

Most of the game is a simple QUAD and they stay black no matter what. There are some FULL 3D Models in the game but 90% is jsut a QUAD

Thanks for any ideas.

I figured it out.

Any normal where it is with in a certain angle will accumulate snow over time.

Thanks.

3 Likes

You say you figured it out but for anyone else with a similar issue…

normals should not be multiplied by the world view matrix because that will translate them in addition to rotating them which makes them not normals anymore.

The NormalMatrix or WorldNormalMatrix is what will transform a normal into view space or world space respectively.

So the first could be used to determine “is this pointing up in the camera” and the second could determine “is this pointing to the sky”… by dotting with vec3(0.0, 1.0, 0.0).

…and in a shader, there is rarely ever a use for acos() in these sorts of cases. In your frag code, dot < 1 would give the same results without the inverse cosine. 1.0 = points straight up, 0.0 = points 90 degrees off. .707 is 45 degrees and so on.

Interesting effect, I’ve always wondered how @jayfella managed to change the amount of snow in this demo. Could you tell us how to get this effect or share the shader code?

Regards

The snow is done exactly as I described in my post. His slider is pretty much directly a threshold for the dot product mentioned.

Also, the code for that demo should be around somewhere, I think.

It would be easier to understand with the example code. I would like to know more.

If it really exists, would anyone be able to point me where I can find the source code for this demo?

If there are examples, I was not able to find it. There appears to be very very old forum post that talk about it, but those post should be deleted. Post from 10years ago in JME do not apply to current JME at all anymore and make people waste time looking into those things that are no only able to be used.

I don’t know how he did it but this is my way. My snow doesn’t build up as in this example from the link, they use a bump map to give it height. I didn’t do this, my game is an old style 80s game and don’t want to much realism in it.

I followed this example for Unity.

So basically, I have an abstractApp that watches the weather temperature and then when it is below 32f. When it starts to snow it uses a accumulator to accumulate the snow over a period of time.
So I pass down variables to the shader. The Snow Color, snow strength (Accumulator of time, how much snow has fallen), The Angle to compare against and a Snow Texture (in a since a height map).

I have 5 different texture to pick from so the fallen snow collection is not the same every time it snows. So if there is no snow on the ground then it picks a new texture to use.

If it stops snowing and stays below 32f then the accumulator will stay where it is at so that screen keeps showing snow. When the temperature goes over 32f then based on temp. it will start to reduce the accumulator (snow melting effect) and the snow will start to be reduced on the screen until the accumulator because 0 or starts to snow again.

So in the shader, I look at the ‘inNormal’ and do a dot comparison against straight up and then compare the result. If when a certain degree, allowed up to a certain angle from straight up to collect snow, then I look at the texture and see if the color of of Green is below the accumulator meaning more snow has fallen in that spot to allow it to much.

    float angle = (dot(myNormal, vec3(0, 1, 0)));
    vec4 noise_texture = texture2D(m_snowData.snowTexture, newTexCoord1);
    float newValue = clamp(min(0.99, noise_texture.g), 0, 1) + 0.1;
   if (newValue <= m_snowData.strength && angle > 0.4)
	color = vec4(0.8, 0.8, 1, 1);

Then after that I use that color for the output. Only thing I might add is check if the current text coord alpha mode is above certain range to do snow affect or not. That way a transparent item doesn’t get affected in correctly.

That is a very simple way of doing it.

I’m about to do that for the rain, but the only thing I’m changing instead of using the straight color light snow, I’m going to change it to mix the item textcoord and water color that has a low alpha range so the original texture color is still seen through the water color still. I would not do an affect like the water is moving, to simple of a game for me.

Hope that helps.

2 Likes

Thank you for your time and patience @kevinba99. Shaders are inherently complicated objects and without a working example it will probably take me months to put all the shards together.

The problem with a “working example” is that this idea of “normal upness” is something tacked onto an existing shader. If OP gave you their whole shader then it would not be suitable for you because it is custom to their game.

If I found you jayfella’s code (which is really just a heavily enhanced version of my original IsoSurfaceDemo which you could also look at) then that would also not be very satisfying because it’s using trilinear mapping for iso surface terrain geometry and probably not what you want.

If you wanted to add this to regular JME lighting then we could walk you through it. It would be an educational and liberating experience and shaders would suddenly become less scary for you.

Otherwise, all we can do is provide a snippet because we don’t know what you are trying to do and writing custom shaders from scratch for someone else for free seems like a lot of work.

Edit: and just in case it matters, here is the original IsoSurfaceDemo that got jayfella started before it enhanced it 500x:

Based on this library:

That shader uses the “upness of normals” to figure out how to render grass on tops of things… but it’s lumped into the rest of the trilinear mapping.

1 Like

Here is my fork of jayfellas fork.

I have fixed a couple issues that were present in the shader.

Edit: Also note there is a work in progress implementation of PBR for iso surface shader in there.

1 Like

Thank you for the projects and for your patience. I don’t write commercial games, mine is simple curiosity. Let’s turn this post into a game jam, so we all learn something and nobody wastes time. Let’s start with something simple that can be fine for most cases. Let’s take this short video as a reference.

Let’s assume that our base model is not the pile of bones, but jamie or a textured cube or any model contained in the jme3-testdata package.
The goal is to try to translate the shader code into jme3.
It’s complicated? If it’s not complicated, write the .vert, .frag and j3md files here or on github.

The jme3 reference documents.

Around minute 4 where it is talking about normal vector and dot product and direction

   float angle = dot(myNormal, vec3(0, 1, 0));

It take the normal vector and does a comparision with UP vect3(0,1,0) and gets the angle between the two spaces.

Then does a clamp

float angle = clamp(dot(myNormal, vec3(0, 1, 0))0,1);

That would be the new code.

Then around 5:30 he is getting a texture to use for overlay.

vec4 noise_texture = texture2D(snowTexture, newTexCoord1);

Then around min 7, he is using a variable to control how much snow.

if (newValue <=  strength && angle > 0.4)
      color = vec4(0.8, 0.8, 1, 1);

Using strength variable from 0 to 1, compare it against the value from the snow texture and if strength is above that number alter the color of the pixel.

DONE… For the shader.

That is a simple version of snow.

Of course you use a BaseAppState to track the amount of snow and use the values from that to populate the material to get those values to the shader.

I would create a basappstate to track the amount of falling snow over time and accumulate that number from 0 to 1. Figure out how much snow is falling. I use a variable to indicate the strength of the weather pattern and then I figure out how much time it should take to cover the ground. That way I get my increment variable for the update method.

Then you need to update that material each and every time with the new values. So you have to CACHE all the materials this is going to affect and loop through them to update their values to current.

Good start.

It is always not best to copy/paste stuff. I personally find you learn less this way, just having to type it out makes you think about the lines and what is happening. Take no brain power for copy/paste and next time you don’t remember how to do it other than copy/paste over again. Atleast that is me.

1 Like

Agreed. And from an “effort versus reward” standpoint, knowing how to tinker with shaders even a little bit yields giant rewards in the long run.

…I can think of few things that I’ve invested time in that felt as satisfying in the end.

I know from a person that didn’t have any game design or know anything about opengl. When I started to write my own engine, I started watching youtube video and reading. Most of the videos I watch once without doing anything just to get the idea of what they where talking about and then watch it again.

I watched many people and in many different languages, Java and C mostly. I like seeing it different ways to really understand the theory. I don’t just like know how, but “MORE” “WHY”. But that is me.

It took several months and then it all starting to fall together and was able to start making my own engine. I have own know and it runs great and it super fast. I had to change many things to get it to work under JME because its just different and an generic engine. While mine was designed for a certain type of game. So there was so less OpenGL bindings, like shader/textures VAO AND VBO. So it would be able to more draws before it starting bringing FPS done, but again my is for a certain game.

Don’t worry, I understand that the shader code is designed for the specific purposes of your game. Thanks anyway for the tips. I too watch the tutorials of the other engines written in different programming languages ​​and I read the guides and manuals. Sometimes I wish this engine had more graphics tools.
Unfortunately now I am busy with my work and I don’t have much time. When I have the time I will do my research and create a new topic with the list of doubts I encountered.