Posts Tagged ‘Normal Map


Normal/Bump Mapping

Oddly, it turns out that my very simple method for bump-mapping shouldn’t have worked at all, as the normals stored in the normal-map are in a completely different coordinate-space (tangent space) to the rest of the scene. This explains why the bump map isn’t very convincing.

I may be wrong on this (as I frequently am), but it looks as if it may not be possible to do bump-mapping ‘the proper way’ in QC, as all the methods I’ve seen seem to require values to be calculated outside the shader, then passed in per-vertex. This isn’t something you can do in QC, unfortunately.

On a more positive note, it may be possible to use my very simple (and wrong) approach to approximate lighting on vertex-displaced meshes. I’ll have to do some more research on this one.


Vertex Displacement Mapping + Normalmap

Normal mapping and vertex-displacement mapping from the same texture.
This ones uses the Kineme texture tools to create the displacement texture. It’s a classic use of the technique.

Not sure I’ll ever use this one ‘in anger’ but it’s an interesting test. I’m glad the lighting works so well, too.

The base colour comes from the normal map, incidentally.

Vertex Displace Mountains 03
Vertex Displace Mountains 04
Vertex Displace Mountains 05

The final screenshot shows the mesh from the back. Not quite sure why it looks so different from that side…

Next I have to work out if I can use the same technique with radial displacement. Think that might be a bit more tricky.


Bump Mapping

Thought I’d have a go using the Normal Map code from the last post to do some bump-mapping.
Turns out it’s quite easy to use the output of the Normal Map CIFilter as normals in a Fragment Shader. All that needs to be done is to transform it into the correct range by multiplying the RGB value of each pixel by 2.0, then subtracting 1.0.

Some examples using a simple Phong lighting model, and normals extracted from first a static image, then the live video from the iSight camera, run through the Normal Map CIFilter:

Bump Mapping 01
Bump Mapping 02

Here’s the GLSL code:

Vertex Shader:

varying vec3 normal, lightDir, eyeVec;

void main()
	// Normal from mesh
	normal = gl_NormalMatrix * gl_Normal;

	// Current Vertex coordinates transformed into World space
	vec3 Vertex = vec3(gl_ModelViewMatrix * gl_Vertex);

	// Light Direction
	lightDir = vec3(gl_LightSource[0] - Vertex);
	// Eye Vector
	eyeVec = -Vertex;

	gl_Position = ftransform();

	gl_FrontColor = gl_Color;
	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

Fragment Shader:

varying vec3 normal, lightDir, eyeVec;
uniform sampler2D texture;
uniform sampler2D normalMap;

void main (void)
	// Base color
	vec4 final_color =
	(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) +
	(gl_LightSource[0].ambient * gl_FrontMaterial.ambient);

	vec3 N = texture2D(normalMap, gl_TexCoord[0].st).rgb * 2.0 - 1.0;
	//vec3 N = normalize(normal);	// Normal
	vec3 L = normalize(lightDir);	// Light Direction (normalized)
	float lambertTerm = dot(N,L);	// Base lighting (no ambient or specular contribution)

	if(lambertTerm > 0.0)
		// Add diffuse contribution
		final_color += gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * lambertTerm;
		// Compute specular contribution
		vec3 E = normalize(eyeVec);
		vec3 R = reflect(-L, N);
		float specular = pow(max(dot(R, E), 0.0), gl_FrontMaterial.shininess);
		// Add specular contribution
		final_color += gl_LightSource[0].specular * gl_FrontMaterial.specular * specular;

	// Output
	gl_FragColor = final_color;// * texture2D(texture, gl_TexCoord[0].xy);

You’ll need to stick the GLSL shader inside a Lighting Patch in order to be able to set the properties for the light.
You’ll get an error in the Frag shader about the varying normal not being used.


May 2019
« Aug    


Blog Stats

  • 487,906 hits