• Advertisement
Sign in to follow this  

GLSL Parallax Mapping

This topic is 4227 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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... :(

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
That function seems to crash the program, I even got the correct length to feed it.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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;
}



Share this post


Link to post
Share on other sites
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);

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Try the following for the height map sampling.
// use a scale of 0.05, try bias of 0 for now
float height = texture2D(heightMap, gl_TexCoord[0]).r - bias;
float offset = scale * (2.0 * height - 1.0);
vec2 newTexCoord = gl_TexCoord[0].st + viewVector.xy * height;

My shader does something to that affect.

Hope that helps

Share this post


Link to post
Share on other sites
Ok, so here's the change that I made:

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

And what I did was as I lowered the size of scale it looked more like a normal texture. When I put it at 0.0001 it nearly looked like the original texture which makes sense because there's less offset. So here's my question, would it be possible that I have the wrong viewVector or something like that?

Share this post


Link to post
Share on other sites
A few swift calculation changes and I'm almost there

float scale = 0.05
float bias = 0.025
float height = texture2D(heightMap, texCoord).r;
//float offset = scale * (2.0 * height - 1.0);
float offset = (height * scale) - bias;
vec2 newTexCoord = texCoord.st + (viewVectorNew.xy * offset);




Here are the results
Almost Working...

Share this post


Link to post
Share on other sites
maybe you should take a look at the rendermonkey and shaderdesigner examples and look how they did it :)

Share this post


Link to post
Share on other sites
I have made some parallax stuff too, but it looks kind of what the second screenshot shows, kind of messy and stretched. I used the code from the Shader Designer example. Though, I read someplace that I should use a heightmap that is bigger in size than the normal texture (i.e. texture = 256x256, heightmap = 512x512 instead of the other way around). Can this really be true?

Share this post


Link to post
Share on other sites
i had the same problems with the shader designer sample as well, but i thought that it was simply my fault. their examples seem to be coded for a static camera only.. the intensity of the light was influenced by my camera movement, etc Oo

Share this post


Link to post
Share on other sites
Ah yes, that is correct... Shader Designer uses a static camera.. hmm, so how did you solve it? Should only be a small revamp of some portion of the code I guess :)

Share this post


Link to post
Share on other sites
I am not even sure I am calculating the tangents and binormals correctly :)

Share this post


Link to post
Share on other sites
http://www.terathon.com/code/tangent.php

works fine, using it in my engine, too.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement