Author: I_dovelemon
Source: CSDN
Date: 2014/10/26
Theme: Cube mapping, Skybox
Introduction
In 3D games, especially in outdoor game scenes, it is often necessary to simulate the effects of the sky. As shown in the following:
In this picture, the reader can see that there is a sky in the scene, and no matter how the game character moves in the scene, it cannot be close to the sky. By adding such effects, the game world is more colorful and closer to the real world. In this section, we want to tell you how to achieve such a sky effect in DirectX.
Cube Mapping
Cube mapping is one of the enviroment mapping. We know that the traditional texture mapping method is to use a 2D image to map to the surface of the 2D. This mapping method describes how one by one is mapped in the chapter on texture mapping in my blog. From what we can find, this is a one-to-two mapping method on a plane. Cube mapping is a mapping method for 3D space. For an object in a 3D space, we sometimes find that using a 2D texture to map every surface of a 3D object is much worse than the overall feeling of the object. So, is there a way to take a holistic look at the texture and then map it to a 3D object so that the texture of the object looks very harmonious and overall comfortable. You can do this with cube mapping.
Cube mapping is a 6-faceted texture that forms a 3D texture that is logically cube cubes. That's what it looks like:
Such a diagram, it has 6 faces, respectively, corresponding to a cube of 6 faces. In general, we will make this texture diagram in the following order:
As you can see, these 6 faces form a cube. With this logic, a texture that can be viewed as a cube, we need to define the coordinates on this texture. Obviously, for a 3D texture map, you should naturally use 3D space coordinates to represent it. So, how the 3D spatial coordinates are mapped to this 3D spatial texture.
Let's take a look at one of the following examples, in order to explain the convenience, I plotted in 2D space, see:
The outer cube is the texture of our 3D space, and the inside sphere is the object that we want to map the cubic texture to. In cube mapping, we emit a ray from the geometric center of the sphere to the point where we want to map the sphere, and the ray also intersects the cube, so we can use the point that intersects the cube as the point texture on the sphere. In this way, for any point on a sphere, we can find the corresponding texture on the cube. So the remaining question is, where does the texture coordinates come from?
From the above description, the reader will find that this ray should be the coordinate value of the coordinate point on the sphere (if the center point of the model coordinates) V (x, Y, z). So how do we get the textures on our texture based on this texture coordinate? You know, although logically it is a 3D texture graph, but actually in storage, still use 2D method to store. So, we need to get from Vector v which one of the points intersecting the ray is on which side?
For any one vector v (x, y, z), we select any of its absolute maximum components, then this component indicates which polygon the ray intersects with. For example, for Vector v ( -3,1,0), the ray emitted by this vector is intersected with the left side of the cube, the-X polygon. For Vector v (1,4,-1), the ray emitted by this vector intersects the upper part of the cube, that is, the +y polygon. This is obviously the fact that readers can draw on their own pictures and understand.
After getting to which polygon the vector intersects, the remaining question is how to get the texture from that polygon. This problem has changed into a 2D plane to get the texture of the problem. From the Texture mapping section, we know that texture mapping is based on the top-left coordinate of the texture (0,0), and the lower-right coordinate is ((), that is, the texture coordinates of the U and V coordinate ranges (0,1). So, how do we get this coordinate value?
On top of that, we use the largest component of absolute value to determine which polygon to intersect, so is the remaining two components associated with the texture coordinates? The answer is yes, the reader can imagine, in 3D space, when we are facing the 3D texture of a face, is not its coordinates corresponding to the remaining two components? That is, by transforming the remaining two values into a space of [0,1] through a linear transformation, we can get the above texture values based on this pixel value.
Such a linear transformation is very simple, we know, an absolute value of the largest component, then we can use the absolute value of this component as a reference, because the absolute value of other values will be smaller than this value, that is, the other value divided by the value after the value of the range is [ -1,1]. We translate this result into a range of [0,2] and then multiply that by 0.5 to become [0,1]. Since the previous transformation is linear, so the one by one corresponding to this property does not change with the transformation, that is, the original value corresponding to the texture, after the transformation, still this texture, just from the 3D space coordinates into 2D space texture coordinates, so that we can access the texture map.
Above is the process of cube mapping. This process is supported in DirectX. We don't have to do it ourselves. Our job is simply to create a 3D texture map like this. Then attach this graph to the 3D object that we want to map. In the above discussion, we have learned that the texture coordinates of this mapping are the model coordinates of the 3D object itself.
Sky Box
Well, after explaining the cube mapping, now to explain how to achieve the sky. There are many ways to achieve the sky. In general, we can create a sky geometry, which can be a sphere, or it can be a cube. Here we use the sphere to represent the sky box. After creating the Sky box, when drawing, we need to be aware that, as we said above, no matter how the camera moves, there is always no way to approach the edge of Skybox. To achieve this effect, either the sky box is infinitely large, obviously there is no infinite concept in the computer, then only the Sky box with the camera to move together. That is, the camera always cures the center of the Sky Box and sets the Z-value of the sky box to be the farthest Z-value. This will ensure that the sky is always surrounded by the outermost perimeter. Here is the code that implements this skybox.
<span style= "Font-family:microsoft Yahei;" >//load the Texturehr (D3DXCreateCubeTextureFromFile (M_pdevice, L "Grassenvmap1024.dds", &m_pCubeTex)); </ Span>
Call D3DXCreateCubeTextureFromFile to read the 3D texture graph. This texture map can be produced by some software. We don't show you how to make these pictures here.
<span style= "Font-family:microsoft Yahei;" >void Cubedemo::d rawcube () {UINT pass = 0; M_peffect->begin (&pass, 0); for (UINT i = 0; i< Pass; i + +) {M_PEF Fect->beginpass (i);D 3DXMATRIX m;D 3DXMatrixIdentity (&m);D 3DXMatrixTranslation (&m, M_camera.pos (). x, M_ Camera.pos (). Y,m_camera.pos (). z); M_peffect->setmatrix (M_GWVP, & (M * M_camera.viewproj ()));m_peffect-> SetTexture (M_gtex, M_pcubetex); M_spheremesh->drawsubset (0); M_spheremesh->drawsubset (0);m_pEffect-> Endpass ();} M_peffect->end ();} </span>
This function is used to pan the sky box so that the camera is always at the center of the Sky Box.
<span style= "Font-family:microsoft Yahei;" >//---------------------------------------------------------------------//Declaration:copyright (c), by XJ, 2014. All right reserved.//brief:this shader file would define the skybox using the cube mapping//file:skybox.fx//author:xj date:2014/10/26//version:1.0//------------------------------------------------------------------------/*** Define the variant*/uniform extern float4x4 GWVP;//The world-view-projection matrixuniform extern texture GTEx;//The Cube mapping Texturesampler envmaps = Sampler_state{texture = <gTex>; Minfilter = LINEAR; Magfilter = LINEAR; Mipfilter = LINEAR; Addressu = WRAP; ADDRESSV = WRAP;}; void Skyvs (Float3 posl:position0, out Float4 Posh:position0, out Float3 oenvtex:texcoord0) {//set the z = w, to make The z/w =1, which means the vertex is always in the far Planeposh = Mul ((FLOAT4 (POSL, 1.0f)), GWVP). Xyww;//save the Verte X position as the texture Coordinateoenvtex = POSL;} FloAT4 skyps (float3 oenvtex:texcoord0): Color0{return texcube (Envmaps, Oenvtex);} Technique Skybox{pass P0{vertexshader = compile vs_2_0 Skyvs ();p ixelshader = Compile ps_2_0 skyps (); Cullmode = None; Zfunc= always; Stencilenable = true; Stencilfunc = always; Stencilpass = Replace; Stencilref = 0;}} </span>
This is the shader file for the Sky box. As you can see, we set the Z-value of the coordinate value after homogeneous to W in VS, so that when the final homogeneous operation is performed, z/w = 1. And we know that in DirectX, the space after 3 basic transformations is a x[-1,1]-y[-1,1]-z[0,1] space. That is, if the z-value is 1, the distance is the farthest, in large, it will be the hardware of the running water cut off. So, with this approach, we can guarantee that the sky box is used at the farthest.
It is also important to note that the mapping method we are using at this time is not the previous tex2d mapping, but the Texcube mapping method.
Here's the final:
Well, today's notes to this end!!!
DirectX reading notes (+) Cube mapping Skybox