If you are a fan of racing games, you must have played the world-renowned racing game "Need For Speed: UnderGround2 ). In this game, players play an underground racing driver who makes a living by a racing car and fly in a city that is always night. This game uses a large number of environment ing technologies (Real-time Evironmnet Mapping ), for example, when the road goes through the rain, you can see the night scenes on both sides, and the real reflection on the surrounding environment on the player's body. These are the merits of the Environment ing technology. This cool and gorgeous special effect has now been applied in a large number of real-time virtual display games. In the future, it may become an essential element in the game.
The most typical application of Environment ing technology is the "streamer" of the car body, which is very common in reality. When you drive your car in a street filled with neon lights, the surrounding lights will emit a spot or band (if the car is very clean ). When the car is galloping on the street, it is like colorful spots flowing on your car body, which has a very dazzling effect. Even when you pass by with another car, other cars will map to your car body.
To map environment maps, a set of environment information is required. Suppose there is a car in the scenario (this example will be used all the time in this article), the environment information of the car, that is, all the pictures you see in the surrounding area except the car. You use a camera to take six photos in different directions, which generates a set of environment information. Each pixel in the car corresponds to a point in the environment information (that is, a ing ). When rendering a car, you need to mix the corresponding points in each environment on the car body with the effect of the car body.
To map Environment Maps, perform the following steps:
A. Create an environment map
B. render the objects in the scene to the environment map.
C. When rendering the car body, the original texture and environment texture are processed and finally rendered to the screen.
Are you ready for your car? You must try setting environment textures for your car right away! However, you still need to understand the relevant knowledge before you start, otherwise it is difficult to find the correct method.
1. What is environment Paster?
I used a camera as a metaphor. In this metaphor, the six pictures are similar to a set of Environment maps, which represent the six faces of the cube. You can imagine that when your eyes are in this cube, you will see all the scenes around you, so we call them Environment Maps.
In general, the Environment textures we use cubes for reference. Therefore, they are usually called Cube maps ). Each Cube Map contains six sides, which are represented by + X,-X, + Y,-Y, + Z, and-Z in DirectX, each of its surfaces covers a 90-degree angle of view on both the horizontal and vertical planes.
2. How do we operate this set of Cube maps?
In DirectX 9, six different identifiers are used to represent each plane in the Cube Map. This group of identifiers is D3DCUBEMAP_FACES, where D3DCUBEMAP_FACE_POSITIVE_X represents the plane pointed to by the positive X axis with the center point as the origin in the Cube Map, and so on. Each plane of the Cube Map is an LPDIRECT3DSURFACE9 object. When you need to perform some operations on a plane, you need to call the GetCubeMapSurface function to obtain the Surface you specified, and then operate it like the normal Surface. In this article, we will take the plane as the rendering Target and draw all the scenes in the surrounding environment to this Cube Map. Because the Cube Map has a plane in each direction, rendering all scenes in the scene is required each time one plane is drawn. The overhead of this process is very large. If environment ing is used on an object in your scenario, rendering consumption will be increased by six times if you only need to draw the scene once! If a game originally ran 70 frames, it immediately dropped to 10 frames when creating a special effect using environment ing! This is a terrible number! You may consider: Will this technology lose the value of use because of its high overhead? The answer is no. At present, human intelligence can well handle the efficiency of Environment ing, so don't worry, and we will explain these methods in detail later.
3. How to Use Cube Map?
When you render the texture coordinates, the next step is how to use them. To draw a texture onto the screen, you need to map the coordinates with the vertices of the model. We all know that 2D pasters use the u and v coordinates to represent the Paster coordinates corresponding to the vertex. In Cube Map, only two vertices cannot represent a point in the Cube. Therefore, the texture coordinates of Cube Map are represented by three vectors, you can simply understand the color of the texture coordinates as the pixel color value at the point of intersection from the center of the box to the direction of the 3D vector to the box. For example, if you want to map a ball in the scene to the surrounding environment, the simplest way is to use the normal of each point on the ball as the texture coordinate and send it to the graphics processing chip, in this way, the ball will have a metallic texture. However, in this case, the map will be different from the real-world ing.
4. What are the actual operations of Environment ing maps?
For the convenience of application development, Microsoft DirectX 9 provides an ID3DXRenderToEnvMap interface, through which we can quickly complete environment Paster operations. Of course, as a common interface, it not only contains operations on Cube Map, but also supports other environment maps, such as Sphere Map. For more information, see the related documents of DirectX 9.
The following code creates an environment texture:
# Define CUBEMAP_SIZE 128
IDirect3DCubeTexture9 * m_pCubeMap;
ID3DXRenderToEnvMap m_pRenderToEnvMap;
// Create the RenderToEnvMap object. M_pd3dDevice and m_d3dsdBackBuffer are pointers to Direct3D devices and cache pages respectively. The CUBEMAP_SIZE macro specifies the edge length of the Cube Map, which is related to the size of the environment Map. The larger the value, the more space occupied, and the slower the painting.
If (FAILED (D3DXCreateRenderToEnvMap (m_pd3dDevice, CUBEMAP_SIZE, 1,
M_d3dsdBackBuffer.Format, TRUE, D3DFMT_D16, & m_pRenderToEnvMap )))
{
Return E_FAIL;
}
// Create an empty Cube Map. D3DUSAGE_RENDERTARGET indicates that the created Cube Map is a rendering target.
If (m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
{
If (FAILED (D3DXCreateCubeTexture (m_pd3dDevice, CUBEMAP_SIZE, 1,
D3DUSAGE_RENDERTARGET, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, & m_pCubeMap )))
{
Return E_FAIL;
}
}
Else
{
Return E_FAIL;
}
A new Projection Matrix (Projection Matrix) needs to be obtained in the rendering process. This Matrix sets the camera's angle of view and scene depth range. In addition, a new View Matrix should be calculated so that the Cube Map will change with the angle of View on the "car.
HRESULT RenderSceneIntoEnvMap ()
{
HRESULT hr;
// Sets the projection matrix.
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH (& matProj, D3DX_PI * 0.5f, 1.0f, 0.5f, 1000.0f );
// Obtain the current observation matrix
D3DXMATRIXA16 matViewDir (m_matView );
MatViewDir. _ 41 = 0.0f; matViewDir. _ 42 = 0.0f; matViewDir. _ 43 = 0.0f;
// Draw the scenario to the Cube Map
If (m_pCubeMap)
Hr = m_pRenderToEnvMap-> BeginCube (m_pCubeMap );
If (FAILED (hr ))
Return hr;
For (UINT I = 0; I <6; I ++)
{
// Set a plane in the Cube Map as the current rendering target.
M_pRenderToEnvMap-> Face (D3DCUBEMAP_FACES) I, 0 );
// Calculate the new observation matrix
D3DXMATRIXA16 matView;
MatView = D3DUtil_GetCubeMapViewMatrix (D3DCUBEMAP_FACES) I );
D3DXMatrixMultiply (& matView, & matViewDir, & matView );
// Set the projection and observation matrix and render the scene (omitted ). Note: objects in the Rendering scenario do not include objects that use environment maps.
......
}
M_pRenderToEnvMap-> End (0 );
Return S_ OK;
}
After rendering the environment map, you need to apply this environment map to the target object, that is, it will function on our car. We use a special Effect (Effect) to plot the Rendering scenario (when the screen is actually drawn. Special effects can be created from a string in the memory or from a special Effect file (suffixed with fx, generated by Effect Edit of DirectX9 SDK. You can view the relevant documentation and examples in the SDK for how to use the special effects. Because there are many things involved, I will not talk about them here. The code for the special effect file is as follows. Here we provide the implementation code based on the Fixed rendering Pipeline (Fixed Function Pipeline). In addition, you can also use the Programmable Pipeline.
TextureCUBE texCubeMap;
Matrix matWorld;
Matrix matView;
Matrix matProject;
Technique Cube
{
Pass P0
{
// Vertex state
Vertexshader = NULL;
Worldtransform [0] = ;
Viewtransform = ;
Projectiontransform = ;
// Pixel state
Texture [0] = ;
Minfilter [0] = Linear;
Magfilter [0] = Linear;
Addressu [0] = clamp;
Addressv [0] = clamp;
Addressw [0] = clamp;
Colodrop [0] = selectarg1;
Colorarg1 [0] = texture;
Texcoordindex [0] = cameraspacereflectionvector;
Texturetransformflags [0] = count3;
}
}
Notes:
1. Use static environment textures instead of real-time rendering
In addition to real-time rendering environment maps, another common practice is to read a pre-generated environment map from a file. Static pasters are easier to implement than real-time rendering. They do not need to plot the scenario to the Cube map. They only need to load the files from the hard disk during creation. Static pasters can greatly reduce rendering overhead. They are a very suitable technology for low-end environments. However, static textures greatly reduce the game's authenticity. If static textures are used, the textures on the car body will not change with the environment.
2. Reduce the rendering overhead of real-time rendering
In addition to using static environment textures, you can also use other methods to reduce system overhead. For example, "underground madness 2" uses a method that limits the paint update rate of Environment textures to achieve real-time rendering. That is to say, it requires that only a certain number of times of Environment textures are rendered per second, rather than every frame. In addition, this frequency can be adjusted by players. Another method is to limit the number of rendered objects in a scenario. For example, if A car is driven to road section A, only the buildings on both sides of road section A are drawn. Alternatively, only A part of the objects that can be clearly mapped can be drawn. In addition, the environment Paster size can be reduced, but this will affect the rendering effect, and the Environment ing effect on the car body will be blurred.
3. Use a programmable rendering pipeline
The use of programmable rendering pipelines greatly improves the flexibility of graphics card programming. As the graphics card performance increases day by day, you can draw more realistic effects from the graphics card. For environment textures, the above Code uses vertices to calculate the texture coordinates. If Pixel-by-Pixel (Per-Pixel) calculations are used, the effect will be more realistic, of course, the overhead of this operation is too large. Currently, it is limited to top-level graphics cards.