Hi ! I am currently writing a water shader that animates tiles of water of different shapes. This shader provides reflections using the built-in stuff that comes with Unity, as described in the following tutorial : Unity - Manual: Surface Shader examples at the chapter “Cubemap Reflection”.
It seems like the orientation of the object is taken into account when computing the reflections. However, it seems like that orientation is common to all the vertices of an object. In other words, it seems to be using the upwards direction of the object for all vertices instead of their normals.
This is causing a problem in my case, because it causes the transition between two objects having different rotations to be clearly visible, despite the transition of vertex normals being rather seameless when using the same rotation :
As you can see on the picture above, the vertical (90 degrees) water tile is darker than the curved one right below it. And the 45 degree water tile is half way dark.
So my question is : is there a way to make unity compute reflections using vertex normals instead of using the object’s upwards direction for all vertices ? Or do I have to roll my own cubemap reflection code ?
The documentation for Surface Shaders is somewhat incomplete at this point. Also the worldRefl is quite finicky and will seemingly break if you don’t use it exactly right.
See: Unity - Manual: Writing Surface Shaders
However, you probably don’t even need to do your own reflections. Unity’s Standard shading model handles this for you. If you create a new Surface Shader from the project view Unity will give you a shader using the standard shading model that you can build upon.
Well I did create a surface shader from the editor, on top of which I added a vertex shader. My surface shader is very close to what the tutorial says :
Maybe that I should assign o.Normal with the normal previously computed in my vertex shader ?
Because all my meshes, regardless of the shape created in the vertex shader, as just planes in the C# side. The shape is only created on the fly, in the vertex shader. Maybe that I should also update the tagents in my vertex shader and not just the vertex and normals ? I’m not sure what tangents are tough.
When using the standard shading model you shouldn’t need to calculate your own reflections at all. Reflections are built into the standard shading model by default. As long as your scene’s lighting has been properly baked (either manually or automatically) Unity should automatically provide a reflection probe that matches the skybox. Set the gloss and specular high enough and you should get nice reflections.
Well I am getting nice reflections already. I’m not trying to compute them myself, I wouldn’t know how to do hehehe… But what I don’t understand is why, in the image below, the curved water tile, whose perimeter is red, does not progressively gets darker as the vertex normals go from vertical to horizontal :
On this picture : the arrows represent some of the vertex normals. I would expect the water to look progressively darker and darker as you go from the green normals to the red normals. There should be a smooth transition between horizontal and vertical water “brightness” if I may call it like this.
But in my case, it seems like the reflections are taking the object’s Y direction instead of the vertex normal, which would explain why all that curved water tile has the same “brightness” at all vertexes.
I’m not familiar with baking yet. Could this be related ? Since my game world is going to be dynamically created from a file, I’ll have to perform the baking manually and at run-time, assuming it is possible.
Are you sure your vertex normals are correct? If you disable your emission reflections, does the lighting act like what you expect or is that also wrong?
Yes and no. They are correct once the vertex shader has executed, but the ones stored in the mesh are pointing upwards regardless of the shape of the mesh. I tried to make them point into another direction instead, just to make sure that the normals didn’t need to be updated in both places (i.e in the mesh and in the shader), but I’m getting the same visual result, so I suppose they don’t need to be updated into the mesh itself.
I also tried to remove the cubemap reflection by commenting the o.Emission assignment in the surface shader, but I’m getting the same result, minus the reflections of course.
Man you’re a life saver ! I’ll add your name to the credits of my game
It was indeed my normals that were partially wrong. I was using the “plane water shape” code to compute the normals for all shapes, so it was working correctly for all plane water tiles, but not for other shapes.
I first tried to debug normals by trying to store them as colors, but since this is a surface shader instead of a regular vertex + fragment shader, I guess there was something missing somewhere and it didn’t want to let me compile. So instead I assigned the normals to the vertex position for some of the vertices and I could see what was wrong.
Thanks again for the help. Now I can get back to the actual content of my game and stop working on that water which I’ve been working on for many weeks.