We can use a sphere as the sky dome to simulate the sky.
Sky Dome is the sky dome. It is a way to simulate the sky in 3D scenarios. The sky simulated by Sky Dome is more realistic than sky box, it is easy to apply the fog effect to sky box scenarios, but sky dome does not. Because sky box is a square, the distance from the viewpoint to each vertex is not equal, and sky dome is a sphere, when the viewpoint is set to the center of the sphere, the distance to each vertex is equal. The visible degree of the fog effect is directly related to the distance from the viewpoint to the vertex.
Let's take a look at this. Use the previous sphere model to simulate Sky Dome.
We have already created a model for the sphere. The problem now is how to mount the sky texture to the sphere. This will use a new texture method cubemap and the coloring tool. let's take a look at the effect:
Well, the effect is like this. Now let's take a look at the specific implementation:
First of all, you need to understand the principle of cubemap. There are many tutorials on the Internet. You can search for them. Here we will discuss the implementation details of the Sky Dome.
Prepare six images first. The cubemap requires six textures:
- Gl_texture_cube_map_positive_x?
- Gl_texture_cube_map_negative_x?
- Gl_texture_cube_map_positive_y?
- Gl_texture_cube_map_negative_y?
- Gl_texture_cube_map_positive_z?
- Gl_texture_cube_map_negative_z?
Each of the six images must be consecutive with the four adjacent textures in four directions, so that they do not cause the barrier. Use the following method to create a cubemap:
bool loadCubemapTexture(const char* xpos,const char* xneg,const char* ypos,const char* yneg,const char* zpos,const char* zneg,GLuint& id) {BmpLoader bmpXpos,bmpXneg,bmpYpos,bmpYneg,bmpZpos,bmpZneg;if(!bmpXpos.loadBitmap((char*)xpos)||!bmpXneg.loadBitmap((char*)xneg)||!bmpYpos.loadBitmap((char*)ypos)||!bmpYneg.loadBitmap((char*)yneg)||!bmpZpos.loadBitmap((char*)zpos)||!bmpZneg.loadBitmap((char*)zneg)) {printf("loadBitmap error\n");return false;}glGenTextures(1,&id);glBindTexture(GL_TEXTURE_CUBE_MAP,id);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);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);glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,0,GL_RGB,bmpXpos.bitInfo->biWidth,bmpXpos.bitInfo->biHeight,0,GL_RGB,GL_UNSIGNED_BYTE,bmpXpos.image);glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,0,GL_RGB,bmpXneg.bitInfo->biWidth,bmpXneg.bitInfo->biHeight,0,GL_RGB,GL_UNSIGNED_BYTE,bmpXneg.image);glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,0,GL_RGB,bmpYpos.bitInfo->biWidth,bmpYpos.bitInfo->biHeight,0,GL_RGB,GL_UNSIGNED_BYTE,bmpYpos.image);glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,0,GL_RGB,bmpYneg.bitInfo->biWidth,bmpYneg.bitInfo->biHeight,0,GL_RGB,GL_UNSIGNED_BYTE,bmpYneg.image);glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,0,GL_RGB,bmpZpos.bitInfo->biWidth,bmpZpos.bitInfo->biHeight,0,GL_RGB,GL_UNSIGNED_BYTE,bmpZpos.image);glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,0,GL_RGB,bmpZneg.bitInfo->biWidth,bmpZneg.bitInfo->biHeight,0,GL_RGB,GL_UNSIGNED_BYTE,bmpZneg.image);return true;}
Note that these six textures belong to the same cubemap object from now on. They are a whole.
initCubemapTexture(YZ_PATH,YZ_PATH,XZ_PATH,XZ_PATH,XY_PATH,XY_PATH,CUBE_MAP_TEXTURE);
The name of the cubemap object is cube_map_texture.
With glbindtexture (gl_texture_cube_map, cube_map_texture), we can use this texture object. Wait a moment, the texture is available, but there is no texture coordinate.
Let's take a look at what the OpenGL official website says:
The texture coordinates for cubemaps are 3D vector directions ctions. These are conceptually directions from within the cube defined by the cubemap, pointing in a participant direction.
Well, the texture coordinate of cubemap is a 3D vector, not a 2D vector of the traditional texture coordinate. It should be a vector from the center of the sphere to the surface of the sphere ,:
Now, let's take a look at how the shader is written: vertex shader:
varying vec3 texCoord;void main() {texCoord = vec3(gl_Vertex.x, gl_Vertex.y, gl_Vertex.z);texCoord = normalize(texCoord);gl_Position = ftransform();}
Fragment shader:
uniform samplerCube texCube;varying vec3 texCoord;void main() { gl_FragColor = textureCube(texCube, texCoord);}
Then write the rendering code:
useShader(shaderTex);glBindTexture(GL_TEXTURE_CUBE_MAP,CUBE_MAP_TEXTURE);glPushMatrix();glTranslatef(0,-10,-200);glScalef(100,100,100);sphere->render();glPopMatrix();
First, use the coordinate axis texture. Let's see if the effect is correct:
Yo, the effect is wrong. The XY axis is reversed. What should I do? Modify vertex shader!
varying vec3 texCoord;void main() {texCoord = vec3(gl_Vertex.x, -gl_Vertex.y, -gl_Vertex.z);texCoord = normalize(texCoord);gl_Position = ftransform();}
Well, that's right. Just change the sky texture. What are you waiting for? Please try it!
Simulate the sky with a sphere