PDA

View Full Version : Cubemapping with GLSL



halo
11-29-2006, 06:54 PM
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);

}

BoSoft
11-30-2006, 09:47 AM
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.

halo
11-30-2006, 10:36 AM
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.

zed
11-30-2006, 11:59 AM
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;
}

halo
11-30-2006, 12:07 PM
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:

CaseMillennium
11-30-2006, 10:57 PM
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.

BoSoft
12-01-2006, 03:10 AM
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;
}

halo
12-01-2006, 09:58 AM
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. :(

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

halo
12-01-2006, 12:30 PM
I got it working for non-rotated objects, but I need to somehow transform the vertex position into world space.

halo
12-01-2006, 12:42 PM
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.

zed
12-01-2006, 02:23 PM
vec4 camera_pos = gl_ModelViewMatrixInverse[3];
maybe (though i dont know if its legal)
vec3 camera_pos = gl_ModelViewMatrixInverse[3].xyz;

halo
12-01-2006, 02:29 PM
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.

halo
12-01-2006, 03:00 PM
I think I can do this if I can pass a 4x4 matrix to the shader. How do I do that?

halo
12-01-2006, 05:34 PM
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.

lubbe75
09-25-2008, 04:20 AM
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.

Korval
09-25-2008, 12:53 PM
Don't resurrect old threads just to ask a question. Make a new thread.

lubbe75
09-26-2008, 07:15 AM
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.