Hi,
Scenario 1:
- I am creating a 256x256 grid. Calculating normals for each vertex in grid on cpu. Sending both vertices and normal data using Opengl calls.
- Enabling lighting. Setting ambient, diffuse and specular values for both light source and material.
Scenario 2:
I am trying to write a Fragment Shader for lighting calculation.
I am not using a vertex shader. Not even a pass through vertex shader.Basically i am using Fixed pipeline combined with programmable pipeline.
Inputs I have for Fragment Shader:
- 2D Texture of size 256x256 (Each value represents a depth) (Its not a normal map)
- INC (increment value). In this case 1/256.
And here is the code:
#version 330 compatibility
uniform int textureSize;
uniform float inc;
uniform sampler2D zgrid;
const vec4 ambient = vec4(0.02f, 0.02f, 0.02f, 1.0f); // product of light and material ambient reflectance
const vec4 diffuse = vec4(0.64f, 0.64f, 0.64f, 1.0f); // product of light and material diffuse reflectance
const float shininess = 20.0f; // materail shininess
const vec4 specular = vec4(0.2f, 0.2f, 0.2f, 1.0f); // product of light and material specular reflectance
const vec3 viewDir = vec3(0.0f, 0.0f, 1.0f);
const vec3 lightd = vec3(0f,0f,1f);
vec3 getNormalPerVertex(in vec3 p0, in vec3 p1, in vec3 p2, in vec3 p3, in vec3 p4)
{
vec3 trivct1 = p0 - p1;
vec3 trivct2 = p0 - p2;
vec3 trivct3 = p0 - p3;
vec3 trivct4 = p0 - p4;
vec3 trin1 = cross(trivct1,trivct2);
vec3 trin2 = cross(trivct2,trivct3);
vec3 trin3 = cross(trivct3,trivct4);
vec3 trin4 = cross(trivct4,trivct1);
vec3 normalVector = trin1 + trin2 + trin3 + trin4;
return normalize(normalVector);
}
float getLinearInterpolatedValue(in float x, in float y, in float x1, in float y1, in float x2, in float y2, in float x1y1val, in float x2y1val, in float x1y2val, in float x2y2val)
{
float v1 = x1y1val * (x2-x) * (y2-y);
float v2 = x2y1val * (x-x1) * (y2-y);
float v3 = x1y2val * (x2-x) * (y-y1);
float v4 = x2y2val * (x-x1) * (y-y1);
float interpolatedValue = (1/(x2-x1)*(y2-y1)) * (v1 + v2 + v3 + v4);
return interpolatedValue;
}
vec4 getSpecularColor(in vec3 normalVector)
{
vec4 specularC = vec4(0.0f, 0.0f, 0.0f, 1.0f);
if(dot(normalVector, normalize(lightd)) > 0.0f)
{
vec3 halfdir = normalize(lightd + viewDir);
specularC = specular * pow(max(0.0, dot(halfdir, normalVector)), shininess);
}
return specularC;
}
vec4 getAmbientDiffuse(in vec3 normalVector)
{
vec4 diffuseLight = diffuse*max(0.0f, dot(normalize(lightd),normalVector));
return (ambient + diffuseLight);
}
vec4 getFinalColor()
{
float x = gl_TexCoord[0].x;
float y = gl_TexCoord[0].y;
//get 4 near coordinates in texel space
vec2 c1 = vec2(x+inc, y);
vec2 c2 = vec2(x, y+inc);
vec2 c3 = vec2(x-inc, y);
vec2 c4 = vec2(x, y-inc);
//convert co-ordinates from texel space to co-ordinates of cell in geometry space in which current pixel resides
vec2 gp1 = vec2(floor(c1.x * textureSize), ceil(c1.y * textureSize));
vec2 gp2 = vec2(floor(c2.x * textureSize), floor(c2.y * textureSize));
vec2 gp3 = vec2(ceil(c3.x * textureSize), floor(c3.y * textureSize));
vec2 gp4 = vec2(ceil(c4.x * textureSize), ceil(c4.y * textureSize));
vec2 gp5 = vec2(gp1.x+1, gp1.y);
vec2 gp6 = vec2(gp1.x, gp1.y+1);
vec2 gp7 = vec2(gp2.x, gp2.y+1);
vec2 gp8 = vec2(gp2.x-1, gp2.y);
vec2 gp9 = vec2(gp3.x-1, gp3.y);
vec2 gp10 = vec2(gp3.x, gp3.y-1);
vec2 gp11 = vec2(gp4.x, gp4.y-1);
vec2 gp12 = vec2(gp4.x+1, gp4.y);
//convert back to texel space
c1 = gp1/textureSize;
c2 = gp2/textureSize;
c3 = gp3/textureSize;
c4 = gp4/textureSize;
vec2 c5 = gp5/textureSize;
vec2 c6 = gp6/textureSize;
vec2 c7 = gp7/textureSize;
vec2 c8 = gp8/textureSize;
vec2 c9 = gp9/textureSize;
vec2 c10 = gp10/textureSize;
vec2 c11 = gp11/textureSize;
vec2 c12 = gp12/textureSize;
//Get z values
float z1 = texture(zgrid,c1);
float z2 = texture(zgrid,c2);
float z3 = texture(zgrid,c3);
float z4 = texture(zgrid,c4);
float z5 = texture(zgrid,c5);
float z6 = texture(zgrid,c6);
float z7 = texture(zgrid,c7);
float z8 = texture(zgrid,c8);
float z9 = texture(zgrid,c9);
float z10 = texture(zgrid,c10);
float z11 = texture(zgrid,c11);
float z12 = texture(zgrid,c12);
//create points for normal calculation
vec3 p1 = vec3(c1, z1);
vec3 p2 = vec3(c2, z2);
vec3 p3 = vec3(c3, z3);
vec3 p4 = vec3(c4, z4);
vec3 p5 = vec3(c5, z5);
vec3 p6 = vec3(c6, z6);
vec3 p7 = vec3(c7, z7);
vec3 p8 = vec3(c8, z8);
vec3 p9 = vec3(c9, z9);
vec3 p10 = vec3(c10, z10);
vec3 p11 = vec3(c11, z11);
vec3 p12 = vec3(c12, z12);
vec3 normal1 = getNormalPerVertex(p1, p5, p6, p2, p4);
vec3 normal2 = getNormalPerVertex(p2, p1, p7, p8, p3);
vec3 normal3 = getNormalPerVertex(p3, p4, p2, p9, p10);
vec3 normal4 = getNormalPerVertex(p4, p12, p1, p3, p11);
vec4 lightcolor1 = getAmbientDiffuse(normal1) + getSpecularColor(normal1) + vec4(0.04, 0.04, 0.04, 1);
vec4 lightcolor2 = getAmbientDiffuse(normal2) + getSpecularColor(normal2) + vec4(0.04, 0.04, 0.04, 1);
vec4 lightcolor3 = getAmbientDiffuse(normal3) + getSpecularColor(normal3) + vec4(0.04, 0.04, 0.04, 1);
vec4 lightcolor4 = getAmbientDiffuse(normal4) + getSpecularColor(normal4) + vec4(0.04, 0.04, 0.04, 1);
float interpolatedR = getLinearInterpolatedValue(x*textureSize, y*textureSize, gp3.x, gp3.y, gp1.x, gp1.y, lightcolor3.r, lightcolor4.r, lightcolor2.r, lightcolor1.r);
float interpolatedG = getLinearInterpolatedValue(x*textureSize, y*textureSize, gp3.x, gp3.y, gp1.x, gp1.y, lightcolor3.g, lightcolor4.g, lightcolor2.g, lightcolor1.g);
float interpolatedB = getLinearInterpolatedValue(x*textureSize, y*textureSize, gp3.x, gp3.y, gp1.x, gp1.y, lightcolor3.b, lightcolor4.b, lightcolor2.b, lightcolor1.b);
return vec4(interpolatedR, interpolatedG, interpolatedB, 1);
}
void main() {
gl_FragColor = getFinalColor();
}
But i am not getting good results like fixed pipeline lighting.
I dont want to use a normal map(beacuse it has to be computed on cpu).
Inputs to vertex shader are four corner points of grid.Not the entire grid. I dont want to send all points in grid as well. only four corner points.
If anyone has any idea or finds something wrong with this code please respond. Dont suggest normal maps, per vertex normal calculation.