Shader for standard gl lighting, plus normal maps
BlitzMax Forums/OpenGL Module/Shader for standard gl lighting, plus normal maps
| ||
This shader will give you lighting results exactly like what you would get with non-shader GL_LIGHTS. It will also handle normal maps. You must calculate and pass in the normal map values yourself. I chose to use the texture coord array for texture unit 1 to store the adjusted light X and Y normals, to tell the program which way the light is shining. I would like to add some specular shininess to the bumpmaps. Can anyone help? Oh, and I have been using shaders for three days. Before that, I had no idea how they worked, and had never used them at all. 3D Labs' ShaderGen tool was very helpful. Vertex program: vec4 Ambient; vec4 Diffuse; uniform int activelights; uniform int lightmapenabled; void pointLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3) { float nDotVP; // normal . light direction float nDotHV; // normal . light half vector float pf; // power factor float attenuation; // computed attenuation factor float d; // distance from surface to light source vec3 VP; // direction from surface to light position vec3 halfVector; // direction of maximum highlights // Compute vector from surface to light position VP = vec3 (gl_LightSource[i].position) - ecPosition3; // Compute distance between surface and light position d = length(VP); // Normalize the vector from surface to light position VP = normalize(VP); // Compute attenuation attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + gl_LightSource[i].linearAttenuation * d + gl_LightSource[i].quadraticAttenuation * d * d); halfVector = normalize(VP + eye); nDotVP = max(0.0, dot(normal, VP)); //nDotHV = max(0.0, dot(normal, halfVector)); //if (nDotVP == 0.0) //{ // pf = 0.0; //} //else //{ // pf = pow(nDotHV, gl_FrontMaterial.shininess); //} Ambient += gl_LightSource[i].ambient * attenuation; Diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; //Specular += gl_LightSource[i].specular * pf * attenuation; } void spotLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3) { float nDotVP; // normal . light direction float nDotHV; // normal . light half vector float pf; // power factor float spotDot; // cosine of angle between spotlight float spotAttenuation; // spotlight attenuation factor float attenuation; // computed attenuation factor float d; // distance from surface to light source vec3 VP; // direction from surface to light position vec3 halfVector; // direction of maximum highlights // Compute vector from surface to light position VP = vec3 (gl_LightSource[i].position) - ecPosition3; // Compute distance between surface and light position d = length(VP); // Normalize the vector from surface to light position VP = normalize(VP); // Compute attenuation attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + gl_LightSource[i].linearAttenuation * d + gl_LightSource[i].quadraticAttenuation * d * d); // See if point on surface is inside cone of illumination spotDot = dot(-VP, normalize(gl_LightSource[i].spotDirection)); if (spotDot < gl_LightSource[i].spotCosCutoff) { spotAttenuation = 0.0; // light adds no contribution } else { spotAttenuation = pow(spotDot, gl_LightSource[i].spotExponent); } // Combine the spotlight and distance attenuation. attenuation *= spotAttenuation; halfVector = normalize(VP + eye); nDotVP = max(0.0, dot(normal, VP)); //nDotHV = max(0.0, dot(normal, halfVector)); //if (nDotVP == 0.0) //{ // pf = 0.0; //} //else //{ // pf = pow(nDotHV, gl_FrontMaterial.shininess); // // } Ambient += gl_LightSource[i].ambient * attenuation; Diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; //Specular += gl_LightSource[i].specular * pf * attenuation; } void directionalLight(in int i, in vec3 normal) { float nDotVP; // normal . light direction float nDotHV; // normal . light half vector float pf; // power factor nDotVP = max(0.0, dot(normal, normalize(vec3 (gl_LightSource[i].position)))); //nDotHV = max(0.0, dot(normal, vec3 (gl_LightSource[i].halfVector))); //if (nDotVP == 0.0) //{ // pf = 0.0; //} //else //{ // pf = pow(nDotHV, gl_FrontMaterial.shininess); //} Ambient += gl_LightSource[i].ambient; Diffuse += gl_LightSource[i].diffuse * nDotVP; //Specular += gl_LightSource[i].specular * pf; } vec3 fnormal(void) { //Compute the normal vec3 normal = gl_NormalMatrix * gl_Normal; normal = normalize(normal); return normal; } void ProcessLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3) { if (gl_LightSource[i].spotCutoff==180.0) { if (gl_LightSource[i].position.w==0.0) { directionalLight(i, normal); } else { pointLight(i, normal, eye, ecPosition3); } } else { spotLight(i,normal,eye,ecPosition3); } } void flight(in vec3 normal, in vec4 ecPosition, float alphaFade) { vec4 color; vec3 ecPosition3; vec3 eye; int i; ecPosition3 = (vec3 (ecPosition)) / ecPosition.w; eye = vec3 (0.0, 0.0, 1.0); // Clear the light intensity accumulators Ambient = vec4 (0.0); Diffuse = vec4 (0.0); //Calculate active light sources if (activelights>0) { ProcessLight(0,normal,eye,ecPosition3); if (activelights>1) { ProcessLight(1,normal,eye,ecPosition3); if (activelights>2) { ProcessLight(2,normal,eye,ecPosition3); if (activelights>3) { ProcessLight(3,normal,eye,ecPosition3); } } } } color=gl_FrontLightModelProduct.sceneColor+Ambient+Diffuse; color = clamp( color, 0.0, 1.0 ); gl_FrontColor=color; } void main (void) { vec3 transformedNormal; float alphaFade = 1.0; // Eye-coordinate position of vertex, needed in various calculations vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex; // Do fixed functionality vertex transform gl_Position = ftransform(); transformedNormal = fnormal(); flight(transformedNormal, ecPosition, alphaFade); //Enable texture coordinates gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1] = gl_MultiTexCoord1; gl_TexCoord[2] = gl_MultiTexCoord2; gl_TexCoord[3] = gl_MultiTexCoord3; }[/CODE]Fragment program: [CODE]uniform sampler2D texture0; uniform sampler2D texture1; uniform sampler2D texture2; uniform sampler2D texture3; uniform int lightmapenabled; uniform float strength; uniform int bumpmapenabled; uniform int textureenabled; void main (void) { vec4 color; //Lighting //if (lightingenabled==1) //{ if (lightmapenabled==1) { color=texture2D(texture0, gl_TexCoord[0].xy); } else { color=gl_Color; } //} //Bumpmap if (bumpmapenabled==1) { vec4 bumpmapcolor=texture2D(texture1,gl_TexCoord[2].xy); color=color*2.0*vec4(strength*((bumpmapcolor.r-0.5)*(gl_TexCoord[1].x-0.5)+(bumpmapcolor.g-0.5)*(gl_TexCoord[1].y-0.5)+(0.5/strength))); } //Base Texture color=color*texture2D(texture2,gl_TexCoord[2].xy)*2.0; gl_FragColor=clamp(color,0.0,1.0); } |