Hi guys, I figured this might be a good place to ask.
I’ve written my own viewport shader over the last day and a half, pretty much from scratch. I have one annoying little thing left that I can’t seem to fix.
The specular formula is calculated seperately from the diffuse, here’s the formula I use:
float blinnspecular(float3 normal, float3 lightvec, float3 eyevec, float glossiness)
{
normal = normalize(normal);
lightvec = normalize(lightvec);
eyevec = normalize(eyevec);
float3 halfvector = normalize(eyevec+lightvec); //add eye and light together for half vector
float specular;
specular = dot(halfvector, normal); //dot between half and normal
specular = pow(specular, glossiness); //power specular to glossiness
return specular;
}
Problem is i get specular THROUGH surfaces at certain angles:
As far as I can tell, it has to do with the dot product of the surface normal and the lightvector, as it seems to blend outward from that point. My insight into lighting math is not big enough to come up with how to solve this however. So I’d really appreciate it if somebody told me how to fix this
You can try using phong instead of blinn specular (cannot remember the phong equation, been a long time since I wrote a shader for lighting…).
Also something I’ve seen done is do:
specular *= saturate(NdotL * 4); //or whatever multiplier
That will make sure your specular doesn’t go beyond the NdotL for that light. I used to do that for my shaders. Try it before and after raising it to its specular power.
Hi rob. Thanks a lot for the reply. Doing that multiply after the specular power fixes things!
Here’s my portfolio page about it: viewportshader – Laurens Corijn
will update soon with newer version that includes the fix.
It looks like you have everything under control now, but just to elaborate, a very common thing to see in shaders is:
float diffuseTerm = saturate( dot( N, L ) );
float specularTerm = pow( saturate(dot( N, H )), power );
I suspect that if all you did to fix the shader was copy:
specular *= saturate( NdotL * 4);
What is actually happening is that in the backfacing case, NdotL is less than 0, and saturate clamps from (0,1), so you are multiplying by zero to knock out the unwanted specular. In the cases of any NdotL greater than .25, you’ll just be multiplying by 1. So most of the time, this bit of code just multiplies by zero or one.
Although that snippet might produce some sort of interesting effect as light falls off. I can’t quite picture it in my head.
Screenshots looked good. Realtime preview is always great. Cheers! and keep up the good work guys.