I’m creating a game with an old school graphics style using flat shaded geometry (every polygon has it’s own set of vertices).
I wanted to add a lighting style that lights up per polygon rather than per vertex so that all the vertices of a face get the same color value instead of it being interpolated (like a directional light does, only with a set distance). Basically a faceted look.
I’m a n00b when it comes to shaders and was wondering if you have any ideas on how to accomplish this.
This is most easily accomplished by assigning each of your faces their own vertices, all with the face normal. Adjacent faces will share vertex positions, but the vertices themselves will be split due to the separate normals. You can do this automatically for any imported model by turning on normal calculation in model import settings, and setting the smoothing angle to zero.
I have separate vertices for each face, so they are not shared. The problem is that when I for example add an spotlight to the scene (in vertex render mode) it will light the vertices a different amount depending on the distance from the light. I want all of the vertices in a face to get the same amount of light.
Maybe a pic will clear things up.
You need to figure out what effect you’d want a spotlight to have, then write a shader accordingly. I bet that what you want to do is store the centroid of each triangle in its vertices, and base lighting falloff on that.
Also, I’m confused on if you want to see triangles or quads. I’m thinking triangles?
Yes I want the triangles to be shown and lit / shaded individually.
I’ll give storing the center a shot. But would I be able to do this for imported models somehow?
I’m pretty sure you can use an AssetPostprocessor to modify the imported mesh data. You could probably use the tangent attribute to store your centroid.
I followed to the point where you assign a centroid but I can’t figure out how you would use it. Lightdir needs to be the same for all 3 vertices of a triangle, and you would get it from the centroid but i have no idea what would happen after that. Averaging all 3 points would do more or less the same?
You can’t. You have to calculate the triangle center in a script and store it in the vertex data for each vertex e.g. as tangents.
Then the shader has to use the position provided in the tangent vertex data instead of the vertex position for lighting calculation for each vertex.
So would it then be impossible to update the normals when moving verts around in a vertex shader? I have a shader that animates verts but the lighting doesn’t update so it’s pretty useless (I wanted lighting similar to what the OP is after).
Instead I’d have to modify the mesh through a regular script and just use mesh.RecalculateNormals() ?
Yeah i know, it sounded pretty retarded. I was thinking about averaging the color somehow after all three points are lit with their own lightdir, but i just realized that this probably sounds pretty stupid as well
I’m really curious to see a solution to this.
Not sure why are normals being mentioned, once you detach everything, all three points of any given triangle will have the same normal? The centroid should have the same, it’s just the lightdir that get’s changed for each vertex. How exactly you get the light direction from the centroid for each vertex rather than the vertex sounds kinda complicated
You could compute the centroid with a geometry shader… For that you can’t use surface shaders, though, but since all you want is vertex lighting, it shouldn’t be all that hard. Vertex shader would just pass the data to a geometry shader, which would compute the per-triangle lighting and pass… well… just the color to a fragment shader, which would output it straight away.
I’ve been searching for answers regarding this problem too for a couple of weeks now, and this is the first answer so far which sounds like an actual solution!
But I’m new to Unity and programming and don’t know the first thing about shaders. Is this difficult to write? I’m guessing so since nobody has done it yet. Does anyone know where to start? Can anyone think of an existing shader to modify to get this behavior?