How to do it...

To render an image with reflection based on a cube map, and also render the cube map itself, carry out the following steps:

  1. We'll start by defining a function that will load the six images of the cube map into a single texture target:
GLuint Texture::loadCubeMap(const std::string &baseName, 
const std::string &extension) {
GLuint texID;
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);

const char * suffixes[] = { "posx", "negx", "posy",
"negy", "posz", "negz" };
GLint w, h;

// Load the first one to get width/height
std::string texName = baseName + "_" + suffixes[0] + extension;
GLubyte * data = Texture::loadPixels(texName, w, h, false);

// Allocate immutable storage for the whole cube map texture
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, w, h);
glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);

// Load the other 5 cube-map faces
for( int i = 1; i < 6; i++ ) {
std::string texName = baseName + "_" + suffixes[i] +
extension;
data = Texture::loadPixels(texName, w, h, false);
glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R,
GL_CLAMP_TO_EDGE);

return texID;
}
  1. Use the following code for the vertex shader:
 
layout (location = 0) in vec3 VertexPosition; 
layout (location = 1) in vec3 VertexNormal; 
layout (location = 2) in vec2 VertexTexCoord; 
 
out vec3 ReflectDir;      // The direction of the reflected ray 
uniform vec3 WorldCameraPosition; uniform mat4 ModelViewMatrix; uniform mat4 ModelMatrix; uniform mat3 NormalMatrix; uniform mat4 ProjectionMatrix; uniform mat4 MVP; void main() { // Compute the reflected direction in world coords. vec3 worldPos = vec3(ModelMatrix * vec4(VertexPosition,1.0) ); vec3 worldNorm = vec3(ModelMatrix * vec4(VertexNormal, 0.0)); vec3 worldView = normalize( WorldCameraPosition - worldPos ); ReflectDir = reflect(-worldView, worldNorm );
gl_Position = MVP * vec4(VertexPosition,1.0); }
  1. Use the following code for the fragment shader:
in vec3 ReflectDir;   // The direction of the reflected ray 
 
// The cube map 
layout(binding=0) uniform samplerCube CubeMapTex; 
 
uniform float ReflectFactor; // Amount of reflection 
uniform vec4 MaterialColor;  // Color of the object's "Tint"  
 
layout( location = 0 ) out vec4 FragColor; 
 
void main() { 
  // Access the cube map texture 
  vec4 cubeMapColor = texture(CubeMapTex, ReflectDir); 
  FragColor = mix(MaterialColor, CubeMapColor, ReflectFactor);
} 
  1. In the render portion of the OpenGL program, draw a cube centered at the origin and apply the cube map to the cube. You can use the normalized position as the texture coordinate. Use a separate shader for this sky box. See the example code for details.
  2. Switch to the preceding shaders and draw the object(s) within the scene.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.33.87