Question

After reading this Tutorial about GLSL and how to use "Normal Mapping" to create such great dynamic Textures out of a simple stonewall, i am really impressed by the power of Shaders.
As i am stil new to Shaders and 3D at all, i am wondering how to apply this kind of Shader to my wip 3D game. So i was looking for some more tutorials and i have found this, which gave me some more knowledge about Shaders and their logic. But i am stil not sure if i really understood it so i ask here.
What i want to do: I have some basic Walls, made of simple, textured cubes. The Textures are more or less the same as in the first Tutorial i linked to. I have the Normal Map of this Texture, also like in the Tutorial, and i want to add the same effect to those Textures, but as i said it is 3D.
So as much as i understood i don't have to change anything, but the Normal Map. I have to know the face of the block, on which the Texture is and multiply its normal by the Faces normal (for example Vector3(-1, 0, 0) for left Face) rotate it (for example arround the Y-Axis by 90° for right Face). Is this assumption right or am i on the wrong track?
And if i am right, instead of using the Normal Map Texture, is there also a way to get the normal of every "pixel" (point) of an imported g3db Model?

Was it helpful?

Solution

You can use what ever you want as input for your shaders, but texure is the common input for per fragment modifications.

Uniform Buffer vs Texture Performances considerations

The classic normal mapping technique with tangent space informations (per pixel coordinate system) could be overridden by other techniques (ex: bump map) and even your own implementation. Take care that the tangent vectors (Tangent,Binormal,Normal) used for normal or bump mapping have to be precalculated and added to your vertex attributes. You can use a dirty trick to compute them in vertex shader, but that's leed to some glitch.

Your example use only a fragment shader so you are right that something is missing to have it working in a 3d scene.

For this to work in 3d, you need to implement a vertex shader that will take care of per vertex normal (here is a implementation) :

 [Vertex_Shader]

varying vec3 lightVec; 
varying vec3 eyeVec;
varying vec2 texCoord;
attribute vec3 vTangent; 


void main(void)
{
    gl_Position = ftransform();
    texCoord = gl_MultiTexCoord0.xy;

    vec3 n = normalize(gl_NormalMatrix * gl_Normal);
    vec3 t = normalize(gl_NormalMatrix * vTangent);
    vec3 b = cross(n, t);

    vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
    vec3 tmpVec = gl_LightSource[0].position.xyz - vVertex;

    lightVec.x = dot(tmpVec, t);
    lightVec.y = dot(tmpVec, b);
    lightVec.z = dot(tmpVec, n);

    tmpVec = -vVertex;
    eyeVec.x = dot(tmpVec, t);
    eyeVec.y = dot(tmpVec, b);
    eyeVec.z = dot(tmpVec, n);
}

[Pixel_Shader]

varying vec3 lightVec;
varying vec3 eyeVec;
varying vec2 texCoord;
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform float invRadius;

void main (void)
{
    float distSqr = dot(lightVec, lightVec);
    float att = clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0);
    vec3 lVec = lightVec * inversesqrt(distSqr);

    vec3 vVec = normalize(eyeVec);

    vec4 base = texture2D(colorMap, texCoord);

    vec3 bump = normalize( texture2D(normalMap, texCoord).xyz * 2.0 - 1.0);

    vec4 vAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;

    float diffuse = max( dot(lVec, bump), 0.0 );

    vec4 vDiffuse = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * 
                    diffuse;    

    float specular = pow(clamp(dot(reflect(-lVec, bump), vVec), 0.0, 1.0), 
                     gl_FrontMaterial.shininess );

    vec4 vSpecular = gl_LightSource[0].specular * gl_FrontMaterial.specular * 
                     specular;  

    gl_FragColor = ( vAmbient*base + 
                     vDiffuse*base + 
                     vSpecular) * att;
}

You may use a dirty trick to get tangent if you don't add them to your vertex attributes

vec3 c1 = cross( gl_Normal, vec3( 0, 0, 1 ) );
vec3 c2 = cross( gl_Normal, vec3( 0, 1, 0 ) );

if( length( c1 ) > length( c2 ) ) tangent = normalize( c1 );
else tangent = normalize( c2 );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top