Cubemapping with GLSL

I have used cubemaps in the fixed pipeline, but have moved over to shaders. I was able to quickly implement cubemapping in GLSL, using an example from the Orange Book’s site. I like the fact that shader cubemaps don’t get all wavy and distorted.

However, the cubemap rotates with the camera. I want the cubemap to move with the camera, and not rotate, ever. Can anyone help?

Vertex program:

varying vec3 ReflectDir;

void main (void)
{

	//Enable texture coordinates
	gl_TexCoord[0] = gl_MultiTexCoord0;
	gl_TexCoord[1] = gl_MultiTexCoord1;
	gl_TexCoord[2] = gl_MultiTexCoord2;
	gl_TexCoord[3] = gl_MultiTexCoord3;

	//Cubemap
	gl_Position    = ftransform();
	vec3 normal    = normalize(gl_NormalMatrix*gl_Normal);
	vec4 pos       = gl_ModelViewMatrix*gl_Vertex;
	vec3 eyeDir    = pos.xyz;
	ReflectDir     = reflect(eyeDir,normal);
}

Fragment program:

uniform samplerCube cubemap;
varying vec3  ReflectDir;

void main (void)
{
	vec4 color;

	//Cubemap
	color=vec4(textureCube(cubemap,ReflectDir));
	gl_FragColor=clamp(color,0.0,1.0);
	
}

If you want to use the cube map for reflections, you could simply calculate the reflection vector in world space instead of eye space. This way the map wouldn’t change when changing the camera orientation.

How do I do that? From what I can tell, it seems I want the reflection vector added to the camera position, but not the camera rotation.

try

void main (void)
{

//Enable texture coordinates
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
gl_TexCoord[2] = gl_MultiTexCoord2;
gl_TexCoord[3] = gl_MultiTexCoord3;

//Cubemap
gl_Position    = ftransform();
ReflectDir     = gl_Vertex.xyz;

}

Your code makes it so the cubemap doesn’t move with the camera. It just stays competely stationary, as though it were a 2D texture.

I am guessing I just need to add the camera position to the vertex position, but I am completely new at GLSL. I don’t know if adding the camera position is what I am after, and even if it is, I am not sure how to go about doing that! :confused:

Well, this is actually one thing that sucks in OpenGL (and will hopefully get fixed in OpenGL 3.0): You will need the WorldMatrix (or in OpenGL Terms: The Modelmatrix). However, since OpenGL only has the Modelview Matrix you will need to provide the Modelmatrix yourself.

You need to do something like this (not tested):

Vertex Shader:

uniform vec4 cameraPosition;
varying vec4 VecToCamera;
varying vec4 normal;
...

void main()
{
 ...
 VecToCamera = cameraPosition - gl_Vertex;
 normal = gl_Normal;
}

Fragment Shader:

varying vec4 VecToCamera;
varying vec4 normal;
...

void main()
{
 ...
 vec4 DirToCamera = normalize(VecToCamera);
 vec4 nnormal = normalize(normal);
 vec4 reflectDir = normalize(reflect(DirToCamera, nnormal));

 vec4 color = textureCube(cubemap, reflectDir);
 gl_FragColor = color;
}

I had to do quite a bit of editing to get your example to compile, and when it finally did, the surfaces were just complete black. :frowning:

I did feed in the camera position. Doing some experimentation to it now.

I got it working for non-rotated objects, but I need to somehow transform the vertex position into world space.

Okay, if you use this for the vertex shader, it gives correct results:

	//Cubemap
	vec3 pos       = gl_Vertex;
	ReflectDir     = (pos-CameraPosition);

The cubemap appears upside-down, but that is a small matter.

Now when I have a model that is rotated and moved around, the results are totally wrong because of the rotation. If I transform the camera position to the object’s coordinate system, I get semi-correct results, except that the cubemap appears at the same orientation as the object! If an object is lying on its side, the cubemap will be rotated the same way. Obviously, this is because I transform the camera position to the object’s coord system.

I need some way to figure out the vector between a vertex and the camera, in world space. First, I changed the camera routine so that when I position and rotate the camera, I am using the projection matrix instead of the modelview matrix. I have it working for non-rotated world geometry, but it still doesn’t work when I have a rotated object.

vec4 camera_pos = gl_ModelViewMatrixInverse[3];
maybe (though i dont know if its legal)
vec3 camera_pos = gl_ModelViewMatrixInverse[3].xyz;

I am just passing the camera position into the shader from the main program. I am trying to get the vertex position in world space. Multiplying it by gl_ModelViewMatrix doesn’t seem to do it.

I think I can do this if I can pass a 4x4 matrix to the shader. How do I do that?

Okay, now I am passing the inverted view matrix into the texture matrix, and accessing that in the shader. Here’s what is happening:

glMatrixMode GL_PERSPECTIVE
set up the viewport here

glMatrixMode GL_MODELVIEW
set up the camera position and rotation

In the shader, the vertex position is multiplied by the ModelView matrix, which includes the camera rotation(!). So we want to multiply the result of that operation by the inverse of the camera part of the modelview matrix.

I’m still trying to figure out exactly what it needs. I am trying to get the modelview matrix after I rotate the camera, then pass the transpose of that into the shader, in the GL_TEXTURE matrix.

Although this is an old topic, I am also trying to get this right. I have a moving camera and a moving object. I want the surface to be reflective, using cubemapping.

I have tried many things with various results but there is always some rotation missing here or there. My latest trial is something like:

(vertex shader)
Normal = (gl_NormalMatrix * gl_Normal);
EyeDir = (gl_ModelViewMatrix * gl_Vertex).xyz;

(fragment shader)
vec3 reflTexCoord = reflect(EyeDir, Normal);
gl_FragColor = textureCube( tex0, cameraRotation * reflTexCoord);

The result is still not correct. This should be one of the basic tutorial examples for GLSL, yet I haven’t seen any working example for moving camera and moving objects.

Please let me know if anyone has managed to solve this problem.

Don’t resurrect old threads just to ask a question. Make a new thread.

Ok, I didn’t know that.

Anyway, I managed to get it working, in case anyone is wondering how:

Normal = tcamerarot * (gl_NormalMatrix * gl_Normal);
EyeDir = tcamerarot * (gl_ModelViewMatrix * gl_Vertex).xyz;

tcamerarot is the upper left 3/4 of the transposed gl_ModelViewMatrix.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.