Shader for emulating standard gl lighting behavior
BlitzMax Forums/OpenGL Module/Shader for emulating standard gl lighting behavior
| ||
This will give the exact same results as standard OpenGL lights. You have to tell the shader which lights are active by setting the activelights parameter to indicate the number of active lights. The shader will automatically detect what kind of light it is. I got rid of the specular color, because it was causing some weird results. I would like to add averaged normal mapping to this, but don't have a clue how. This code was based on 3DLabs' ShaderGen output. Fragment program: uniform sampler2D texture0; void main (void) { vec4 color; color = gl_Color*2.0; color *= texture2D(texture0, gl_TexCoord[0].xy); color=clamp(color,0.0,1.0); gl_FragColor = color; }Vertex program: vec4 Ambient; vec4 Diffuse; vec4 Specular; attribute short activelights; 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); Specular = vec4 (0.0); 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 * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse; color += Specular * gl_FrontMaterial.specular; color = clamp( color, 0.0, 1.0 ); gl_FrontColor = color; gl_FrontColor.a *= alphaFade; } 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; } |