I’m new here so… Hi
I’m very new to GLSL (and shaders in general), been trying it out now for all of the last two days so I am looking for some good feedback please.
Been writing a few simple shaders, mostly using tutorials like lighthouse3D etc. The usual toon, point lights etc. Bit of reference from a HLSL dvd(light theory etc).
I decided to try out a normal map equipped shader - I think it is ok, but I have come to the point where I have looked through so many different tutorials, forum posts etc that I’m just not sure any more if it is ok or not…
If anyone has time to have a scan for noobish errors or to give hints that would be great.
I decided to dump it in with a single point light phong model.
Vert shader:
varying vec3 normal;
varying vec3 lightDir;
varying vec3 lightDirTS;
varying vec3 eyeVecTS;
varying float atten;
varying vec4 ambientGlobal;
varying vec4 ambient;
varying vec4 diffuse;
attribute vec3 tangent;
attribute vec3 binormal;
void main(void)
{
// Transform normal to eye-space
normal = normalize( gl_NormalMatrix * gl_Normal );
// Transform vertex to eye-space
vec4 vertPos = gl_ModelViewMatrix * gl_Vertex;
// Create transformation matrix
mat3 mTBN = mat3( tangent, binormal, gl_Normal );
// Calc vector from light to vertex & then normalise
vec3 dir = vec3( gl_LightSource[0].position - vertPos );
lightDir = normalize( dir );
// Calc light dir in tangent space
vec3 dirTemp = mTBN * normalize( dir );
lightDirTS = normalize( dirTemp );
// Calc eye vector in tangent space
vec3 eyeTemp = mTBN * normalize( vec3(-vertPos) );
eyeVecTS = normalize( eyeTemp );
// Calc distance between vertex & light
float dist = length( dir );
// Calc attenuation
atten = 1.0 / ( gl_LightSource[0].constantAttenuation +
gl_LightSource[0].linearAttenuation * dist +
gl_LightSource[0].quadraticAttenuation * dist * dist );
atten = clamp( atten, 0.0, 1.0 );
// Ambient components
ambientGlobal = gl_FrontMaterial.ambient * gl_LightModel.ambient;
ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
// Diffuse component
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
// Use first set of texcoords in fragment shader
gl_TexCoord[0] = gl_MultiTexCoord0;
// Position handled using fixed functionality
gl_Position = ftransform();
}
Frag shader:
varying vec3 normal;
varying vec3 lightDir;
varying vec3 lightDirTS;
varying vec3 eyeVecTS;
varying float atten;
varying vec4 ambientGlobal;
varying vec4 ambient;
varying vec4 diffuse;
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
void main(void)
{
vec3 N = normalize( normal );
vec3 L = normalize( lightDir );
vec3 Ln = normalize( lightDirTS );
// Sample diffuse map
vec4 diffMap = texture2D( diffuseMap, gl_TexCoord[0].st );
// Sample normal map in -1.0 to 1.0 space
vec3 Nn = normalize( texture2D(normalMap, gl_TexCoord[0].st).xyz * 2.0 - 1.0 );
Nn.y = -Nn.y;
// Calc diff/ambient contribution from normal map
float LnDotNn = max( dot(Ln, Nn), 0.0 );
// Final colour always includes any contribution from global ambient
vec4 colour = ambientGlobal * LnDotNn * diffMap;
// If norm dot light dir is > 0 then calc diffuse & specular contributions
float NDotL = max( dot(N, L), 0.0 );
if ( NDotL > 0.0 )
{
// Normalise the interpolated eye vector & Calc reflection vector of light from normal
vec3 eye = normalize( eyeVecTS );
vec3 ref = reflect( -Ln, Nn );
// Calc dot product of eye & reflection vectors, clamp between 0 & 1
float refDotEye = max( dot(ref, eye), 0.0 );
// Calc specular component taking into account attenuation
vec4 spec = gl_FrontMaterial.specular * gl_LightSource[0].specular *
pow( refDotEye, gl_FrontMaterial.shininess );
// Self-Shadowing
float shadow = saturate( 4.0 * NDotL );
// Add light components taking into account attenuation
colour += atten * clamp( shadow * (diffMap * LnDotNn * (ambient + diffuse) + spec), 0.0, 1.0 );
}
gl_FragColor = colour;
}