1
votes

So far, when learning Open GL (shader version), I've been texturing cubes by UV mapping the object coordinates to the texture coordinates. So I pass a vertex buffer and a UV buffer to my shader code.

But now when I'm reading up on skybox from various tutorials, the process seems very different, and quite confusing. First, they're using Cube Map texturing. I understood what Cube Map texturing is supposed to do, but I didn't understand how the tutorials are implementing it. For example, most of these tutorials write a separate fragment shader for the Skybox. Why can't I use the same fragment shader that I use for all my other cube objects? And, there is no explicit UV mapping being done.

Is there a good explanation of how a cube map texture is to be implemented?

1

1 Answers

5
votes

As far as tutorials go, I'll just recommend this one.

  • In contrast sampling a 2D texture works simply by passing UV coordinates and getting the current pixel color at that UV location in the texture.
  • While cubemaps use a 3D directional vector that starts from the center of the cube and travels along until it hits one of the sides allowing it to sample the pixel from that side in that particular texture.

The reason to have a separate shader for a skybox is probably convenience. You might want to make special modifications some time in the future. But also the fact that we can do this pos.xyww; to ignore writing to the depth buffer.

Now notice in the vertex shader we set texture direction vector (texDirection) equal to the position of the current vertex. Remember that all vectors interpolate when they get to the fragment shader, and so texDirection will interpolate it self from one side of the cube to the other, going all around.

Vertex Shader:

in vec3 position;
out vec3 texDirection;

uniform mat4 projection;
uniform mat4 view;


void main() {
    vec4 pos = projection * view * vec4(position, 1.0);
    gl_Position = pos.xyww; // We ignore the depth buffer here
    texDirection = position; // Let it interpolate
}  

Inside the fragment shader we sample a pixel from the skybox by shooting in the direction of our lovely interpolated texDirection. It hits one of the sides and returns a color that we store in output variable color.

Fragment Shader:

in vec3 texDirection;
out vec4 color;

uniform samplerCube skybox; // The cubemap is a uniform!

void main() {    
    color = texture(skybox, texDirection); // Get the pixel in direction of texDirection!
}