Normals interpolation in shader

Hello,

I just wrote a simple Phong shader and I got issues with the Lambert term of the diffuse component
the shading should be smooth no matter the object resolution

really subtle, but one can see the faces of the sphere while normals should be smoothly interpolated

I managed to isolate the problem around the normals

once again, hard to see, but faces should bee smooth, but appears flat shaded
seams appears on normals values

so in the shader

vec3 lightPosition=vec3(10,10,10); // hard coded for debug

void main(){
    v = vec4(worldViewMatrix * vec4(modelPosition,1));       
    normal = normalize(normalMatrix * normal); <-------------- normals should be smoothly interpolated, not sure it is the case
    lightDir = normalize(vec3(lightPosition - v.xyz));
}

shadernode definition :

VertexShaderNodes {
            ShaderNode PhongVert {
                Definition : PhongVert : Shaders/Phong/PhongVert.j3sn
                InputMappings {
                    normal = Attr.inNormal

so is there a way to tell the mesh to render smooth instead of flat?
thought this was automatic

as comparison, here is the original shader (in demoniak software)
sphere is low res like mine

here is the final (A+S+D) result
clearly there is something wrong
also the light spot is always visible around the object while it should be present when one is one the same side of the light

any help would be greatly appreaciated
thanks

That’s because you’re computing the normal in the vertex shader.
Normal is then linearly interpolated between vertices when passed as a varying to the fragment shader, and that’s why you can see the faces.

I also see it in the demoniac shot on the blue sphere btw. The torus doesn’t have this artifact because I guess it’s a lot more tessellated.
There is no real way around this, except having a higher number of polygons or, using normal mapping.

2 Likes

it does not make sens, why using per fragment lighting if it has the same effect than flat shading…?
normal mapping ? a texture you mean ?

I changed the color of the sphere, the artifact does not show up
clearly there is something wrong with my code

Remember, normals are linearly interpolated from tip to tip. That’s one of the reasons you should normalize them in the frag shader, to at least get them to be a curve again.

…but note that there will still be an error because normalizing a linearly interpolated normal will change the curve. This gets more dramatic the larger the different between the normals… which is why shapes will look better with more triangles.

Give how you have entirely dark triangles near the edges, it does seem like something is wrong, though.

Flat shading is very different
see this

the left sphere is flat shaded, the right one is smooth shaded. See how the right one present the same artefacts you’re talking about.

Yes, that’s what most game do (though not really to alleviate this issue, but more to add in some small details that the mesh resolution doesn’t allow).

You can try to normalize the normal in the frag shader as Paul said, maybe it will be less noticeable.

Seems that there are shadows, so maybe it’s another artefact.

indeed I normalized normals in the vert shader while it was originaly done in the frag shader
my bad now I know why, lol

I dont know why in the original shader there are black artifacts, I also wonder why

thx guys, couild have taken me a whole day to find what was going wrong

what I dont understand is why the light spec spot is always visible, should’nt it only visible on the side facing the light ?
It really follows the camera view as I turn around the object

vec3 lightPosition=vec3(10,10,10);

void main(){
    v = vec4(worldViewMatrix * vec4(modelPosition,1));       
    normal = normalMatrix * normal;
    lightDir = vec3(lightPosition - v.xyz);

if lightPosition is hardcoded as a global world position, should’nt it be converted with worldview matrix ?

_lightPosition = vec4(worldViewMatrix * vec4(lightPosition,1));

Yes it should, you’re right.

btw make sure all float constants have the “0.0” form. here your 1 should be 1.0
It fails on some cards/glsl version specified in the shader.

not so right, it does not work the sphere is now all black
not sure I multiply it by the right matrix

vec4 _lightPosition = vec4(worldViewMatrix * vec4(lightPosition,1.0));
lightDir = _lightPosition.xyz - v.xyz;

edit : ok it works, the light was inside the sphere :smile:

:slight_smile: Why can’t I see my light?!?! :slight_smile:

I have spent some time trying to get rid of this effect myself (not jME but shaders are shaders), but it seems not practical to get rid of starburst pattern. The problem is that linear interpolation of normals is only an approximation, and not a high quality one at that. It is however a very cheap approximation. For my use case the best way to make it less visible is to use more triangles and I guess that’s the way most people do it.

Here is a short PDF detailing another way to do interpolation of normals that is more expensive but better quality (according to the authors, haven’t implemented it myself yet)

http://www.researchgate.net/publication/221546724_Shading_by_Spherical_Linear_Interpolation_using_De_Moivre's_Formula

1 Like

actually there was a “bug” in my code due to the fact I thought normalizing in the vert shader and in the frag shader would be the same

but thx for the info

Dear Harlock, is your shader code ok now? can you send its and input files to me? I want to see it to understand shading. Thanks a lot.