GLSL Parallax Mapping

Started by
18 comments, last by Vexator 17 years, 8 months ago
Parallax mapping seems somewhat simple. I understand the equations and have shaders set up to perform it. Thing is I need another more keen eye in the ways of GLSL to take a look at this code. I can't figure out what's wrong with it. I am currently supplying correct variables please take a look.

// vertex shader
varying vec3 normal, lightVector, halfVector, viewVector, texCoord;
	
void main()
{
	vec4 worldPos;

	normal = normalize(gl_NormalMatrix * gl_Normal);
	vec3 tangent = gl_MultiTexCoord1.xyz;;
	vec3 binormal = cross(tangent, normal);

	mat3 TBNMatrix;
	TBNMatrix[0] =  gl_NormalMatrix * tangent;
	TBNMatrix[1] =  gl_NormalMatrix * binormal;
	TBNMatrix[2] =  normal;

	worldPos = gl_ModelViewMatrix * gl_Vertex;
	lightVec = normalize(vec3(gl_LightSource[0].position - worldPos));

	viewVector = vec3(-worldPos) * TBNMatrix ;

	halfVector = normalize(gl_LightSource[0].halfVector.xyz);

	gl_TexCoord[0] = gl_MultiTexCoord0;
	texCoord = glMultiTexCoord0;
	gl_Position = ftransform();

}

// fragment shader
varying vec3 normal, lightVector, halfVector, viewVector, texCoord;
uniform sampler2D decalMap, heightMap, normalMap;

void main()
{
	vec4 diffuseLight, specularLight;	
	float shine = 64.0;
	float scale = 0.5;
	float bias = 0.25;

	normal = normalize(normal);
	lightVector = normalize(lightVector);
	viewVector = normalize(viewVector);

	// Get the height value and calculate the new texture coord.
	float height = scale * texture2D(heightMap, texCoord).r - bias;
	vec2 newTexCoord = height * viewVector + texCoord;

	// Get the bump map normal.
	vec3 normalTex = texture2D(normalMap, newTexCoord).xyz;
	
	// Convert from 0 to 1 range to -1 to 1.
	normalTex = normalize(2.0 * normalTex + 1.0);

	// Calculate the bump value as n dot l.
	float dp = saturate(dot(normalMap, lightVector));
	
	// Get the decal texture color with the new tex coords.
	vec4 decalCol = texture2D(decalMap, newTexCoord);

	float lightIntensity = max(dot(normal, lightVector), 0.0);

	diffuseLight = lightIntensity * gl_LightSource[0].diffuse;
	diffuseLight = diffuseLight * dp;
	specularLight = pow(max(dot(n, normalize(halfVector)), 0.0), shine) * gl_LightSource[0].specular;
	
	vec4 lightColor = diffuseLight + specularLight + gl_LightSource[0].ambient;

	vec4 texColor = texture2D(decalMap,newTexCoord);

	vec4 color = texColor * lightColor;
	gl_FragColor = color;
}



Please have a look and please ask any questions and I'll respond. My current results are a black square, that's it, no lighting, no textures... :(
Douglas Eugene Reisinger II
Projects/Profile Site
Advertisement
Have you checked the shader log? A black square might be a result of the fragment program not being bound. Two things I could spot are:

Quote:lightVec = normalize(vec3(gl_LightSource[0].position - worldPos));
I can't find lightVec declared anywhere, maybe oyu meant lightVector (since there is an active varying by that name whose value you haven't set)?

Quote:vec3 tangent = gl_MultiTexCoord1.xyz;;
Two semicolons after that line. The compiler may ignore an empty statement, or it may issue an error (I don't know).
How does one check said shader log?
Douglas Eugene Reisinger II
Projects/Profile Site
Quote:Original post by Enalis
How does one check said shader log?

You can get the compiler output by using glGetInfoLogARB. This usually contains something like "Shader will run in hardware/software" or will give you an error message.

A black square can also mean not having a sampler bound correctly but it looks like you have an error in the shader.

Hope that helps
That function seems to crash the program, I even got the correct length to feed it.
Douglas Eugene Reisinger II
Projects/Profile Site
Got it working and you were right. There is one error in each file. If I fix those and still doesn't work I'll reply, thanks for your help!
Douglas Eugene Reisinger II
Projects/Profile Site
Ok, here's what I'm down to.
In the fragment shader only here are the errors

(18) : error C1020 : invalid operands to "add"
(18) : error C1056 : invalid initialization
(27) : warning C7506 : Opengl does not define the global function saturate

varying vec3 normal, lightVector, halfVector, viewVector, texCoord;uniform sampler2D decalMap, heightMap, normalMap;void main(){	vec4 diffuseLight, specularLight;		float shine = 64.0;	float scale = 0.5;	float bias = 0.25;	normal = normalize(normal);	lightVector = normalize(lightVector);	viewVector = normalize(viewVector);	// Get the height value and calculate the new texture coord.	float height = scale * texture2D(heightMap, gl_TexCoord[0]).r - bias;	vec2 newTexCoord = height * viewVector + gl_TexCoord[0];	// Get the bump map normal.	vec3 normalTex = texture2D(normalMap, newTexCoord).xyz;		// Convert from 0 to 1 range to -1 to 1.	normalTex = normalize(2.0 * normalTex + 1.0);	// Calculate the bump value as n dot l.	float dp = saturate(dot(normalMap, lightVector));		// Get the decal texture color with the new tex coords.	vec4 decalCol = texture2D(decalMap, newTexCoord);	float lightIntensity = max(dot(normal, lightVector), 0.0);	diffuseLight = lightIntensity * gl_LightSource[0].diffuse;	diffuseLight = diffuseLight * dp;	specularLight = pow(max(dot(n, normalize(halfVector)), 0.0), shine) * gl_LightSource[0].specular;		vec4 lightColor = diffuseLight + specularLight + gl_LightSource[0].ambient;	vec4 texColor = texture2D(decalMap,newTexCoord);	vec4 color = texColor * lightColor;//	vec4 color = texture2D(decalMap, texCoord) * 1.0;	gl_FragColor = color;}

Douglas Eugene Reisinger II
Projects/Profile Site
I had to count to find the right lines - but anyway here's what you should do:

Quote:Original post by Enalis
(18) : error C1020 : invalid operands to "add"
(18) : error C1056 : invalid initialization

You are doing a vec2 = vec3 + vec4. If you want to ignore that latter components, what you want is something like:
vec2 newTexCoord = height * viewVector.xy + gl_TexCoord[0].st;

Quote:(27) : warning C7506 : Opengl does not define the global function saturate

As it says, GLSL doesn't have a function called saturate(). I think HLSL's saturate() clamps the value to a [0, 1] range (not sure) and if that's the case you need:
float dp = clamp(dot(normalMap, lightVector), 0.0, 1.0);
Quote:Original post by Enalis
(27) : warning C7506 : Opengl does not define the global function saturate

#27 is a warning. If you remove the two previous errors, it should run ok, if you are using NVidia. If you're on an ATI, then you need to use clamp.

-[Anudhyan][Website]
Ok, thank you all for your help so far. But now here's the new problem, shit is what the shader looks like and it's not good.
Broken Parallax Shader
Douglas Eugene Reisinger II
Projects/Profile Site

This topic is closed to new replies.

Advertisement