Due to the format, the paste is not effective. You can download the PDF version:
Http://download.csdn.net/source/643603
Seamless terrain implementation in world craft V1.0
Xiong Jiayu, qy_tek
EMILE: Xjyhust@gmail.com
Home: http://blog.csdn.net/xjyhust
Simple Description:
This document is not a paper, I call it a note, or. Note; this document is free for all and can be used at will. If you want to reference it, please specify the Source: http://blog.csdn.net/xjyhust, and the author: Xiong Jiayu. OK, because this document is only V1.0, there is a lack of many actual test results. I will add them in later versions, but the technology in it will not change much. Finally, I hope this document will be useful to you.
Introduction to seamless terrain Technology
For the mesh part, the height map of each part is used to save the information. For the texture part, 8 diffuser textures and 4 normal map textures are used for each terrain, and the weights of each texture are mixed using the palette texture query. The scenario editor and engine runtime terrain processing methods are treated separately to ensure both efficiency and flexibility.
Seamless mesh implementation
The implementation of terrain mainly targets 2D height graphs, and the precision saved is float 32bit. To support ultra-large seamless terrain, terrain must be segmented and only visible areas are saved in the memory during running.
Implementation of the level of detail
The smallest unit after a terrain block is called Brick. Brick, which is closer to the camera, has more detailed levels of levels. It is defined as low levels of levels. Brick, Which is farther away from the camera, has a rough level of levels, this is defined as a high-level dashboard. (Do not make a mistake. The nearest part has a low level of detail, and the distance has a high level of detail .)
The general method of the level-1 is that when the level-0 is used, each vertex is rendered. When the level is set to 1, one vertex is rendered for every two vertices. When the level is set to I, rendering a vertex every (2 to the power of I ...... for details, see:
Level I level I + 1
To solve the terrain "cracking" problem, we need to process the vertex missing between different levels. There are several different processing methods:
Assuming that level I is connected to level I + 1 at this time, I add the vertex missing from the brick of level I + 1 and the boundary of level I + 1 to the original Triangle List:
In order to solve the "split" problem of this boundary, we need different triangles. Because in world craft, the distribution of the level of detail is based on the ring:
Therefore, five different cases are required for the Triangle Belt of each level, for brick with level I. Case 1: He only communicates with brick whose level is I; Case 2 to case 5: he has only one side and the brick of level I-1.
Performance and Optimization
We introduced a sheet concept for Brick rendering optimization. Sheet is a larger Division unit. In my practice, sheet is composed of 4*4 brick or 8*8 brick (depending on the size of Brick ), sheet shares a vertex buffer, which makes the efficiency more efficient. Although it is also draw n times, you do not need to modify the vertex buffer. You only need to modify the index buffer to treat brick with the same level of details, the same is true for index buffer. You only need to modify the offset. Sheet is introduced to optimize texture. You do not need to switch material frequently or write sort that is too complex.
Different editor and engine Runtime
There are several reasons for us to treat these two cases separately:
1. The editor needs to input the appropriate user in a timely manner, which requires that each terrain change be completed within a short period of time.
2. the engine does not require flexibility, so the rendered data needs to be optimized as much as possible.
There is no sheet implementation in the editor (concept only), that is, each brick has a separate vertex buffer. Brick should be as small as possible, for example, 17*17. This greatly reduces the modification scope of the vertex buffer, and users' modifications will be fed back in a timely manner, so there will not be too long "false positives ".
When the engine is running, the sheet size is 513*513 or 257*257, and the size of each brick is 65*65 or 33*33. I prefer 513*513 sheet and 33*33 brick. (The specific amount is reasonable. I did not list detailed comparison data in this. Note. Some actual test data will be listed in V2.0)
World craft terrain editing
In world craft, a large height map is used to represent a sheet, for example, a height map of 513*513, and then the size of each brick is 17*17, corresponding to a 17*17 region of the height map, because Brick uses vertex buffer separately, adjacent brick shares 17 pixel on the height map.
Take the rise/lower terrain brush as an example. The specific process is as follows:
1. determine the point that the mouse picks up (the point that the terrain is)
2. Calculate the point on the height map corresponding to the pick-up point
3. Correct the operation of the brush (also 32bit-float Bitmap) to the height map.
4. Update the affected region (only update brick in the region)
Note the following points:
1. when Brick is updated, only the position of the vertex is updated, instead of the normal state. Otherwise, the speed will be slow. The normal state is updated only when the mouse is lifted. The final result is very good.
2. When painting a height map, a definition of the brush density is introduced to indicate the number of pixels each other before painting. When the mouse moves too fast or too slowly, there will be no uneven effect. The general method is to record each image click. If the cumulative distance between click points exceeds the definition of the brush density, click the correct place on the nearest click path.
3. normal vertex updates are self-written and are not used in the NVIDIA nvmeshmender library. I don't know why. The speed of nvmeshmender is very slow. Maybe there are many vertices in mesh.
Vertex normal Calculation
For example, for each vertex Vert (the black spots in the graph), calculate the normal of the six triangles around it, and then take the average value. I don't know if this is a correct algorithm. The final result is correct. ;)
Seamless texture implementation texture palette
The texture palette uses the rgba value corresponding to the vertex on the texture of the palette as the weight value, indicating that the weights of four different textures are used. If the vertices on the palette are only red, it means that only the first texture is used for the points above the last terrain. If the vertices on the palette have four different colors, they are 0.1, 0.2, respectively, 0.3, 0.4, the final color of the terrain is a mixture of 0.1 texture Parts 1, 0.2 texture Parts 2, 0.3 texture 3, 0.4 texture Parts 4. The specific algorithm is provided by HLSL.
Why, instead of using a global texture? For specific reasons, I also mentioned a previous blog article. Here I paste it directly:
Simple repeated textures are currently the most common method, but the effect is average. When using a global texture, if the texture is not super large, the effect is also very general: Generally, the distance between two pixels in a height chart corresponds to the world of one meter and one meter in a real terrain, to use textures to show details, you can use a texture of 512*512 or 256*256. If you use a non-repeating texture to create a world of 1 km * 1 km, the required texture size is 256 K * 256 K. If the effect is slightly worse, it is a 64 K * 64 K texture even if there are only 64 pixels in a meter... In this case, the only way to use global textures is to use detailed map. I think this is an ugly practice. For an MMO online game that focuses on outdoor scenes, terrain is the most impressive image element, and the uniform details are used to fool the effect, which is naturally bad.
Use eight different textures
8 different textures are used for mixing, and two different paintors are required, plus 8 normal maps. A total of 18 textures are added, this cannot be implemented on some hardware (it seems that only dx10 hardware can be implemented), and a considerable number of variables need to be changed when setting registers.
The economical method is to use texture atlas and refer to the corresponding NVIDIA tools (as well as code and documentation ). Package each four color textures into one texture. In this way, there are two major color textures, two normal maps, and two color palette textures. There are six textures in total, it can be implemented on all ps2_0 and above hardware.
When using Atlas, pay attention to the change of texture coordinates. The original texture coordinates are [0, 1] and should be converted to [0 + texoffset, 1-texoffset]. texoffset = 1/(2 * tex_width );
Integrated diffuse map normal map
Implementation of pixel shader
Texture g_paltex;
Texture g_tex0; // base color texture
Sampler tex0 =
Sampler_state
{
Texture = <g_tex0>;
Mipfilter = point;
Minfilter = point;
Magfilter = Linear;
Addressu = wrap;
Addressv = wrap;
Addressw = wrap;
};
Sampler paltex =
Sampler_state
{
Texture = <g_paltex>;
Mipfilter = Linear;
Minfilter = Linear;
Magfilter = Linear;
};
Struct vs_output
{
Float4 position: position;
Float4 texcoord: texcoord0;
Float3 diffuse: texcoord1;
Float3 normal: texcoord2;
};
Float4 renderwithtextureps (vs_output I): Color
{
Float2 coord0 = I. texcoord. XY * g_ftexrepeat;
Coord0 = frac (coord0 );
Coord0 = coord0 * 0.5;
Float2 coord1 = coord0 + float2 (0.5, 0 );
Float2 coord2 = coord0 + float2 (0, 0.5 );
Float2 coord3 = coord0 + float2 (0.5, 0.5 );
Float4 palcolor = tex2d (paltex, I. texcoord. ZW). rgba;
Palcolor = normalize (palcolor );
Float4 vdiffuse = tex2d (tex0, coord0) * palcolor. x +
Tex2d (tex0, coord1) * palcolor. Y +
Tex2d (tex0, coord2) * palcolor. Z +
Tex2d (tex0, coord3) * palcolor. W;
Return vdiffuse * float4 (I. diffuse, 1 );
}
The preceding implementation is as follows: a palette texture and a large diffuse map (4 different textures are integrated ). Texcoord. XY in the vertex is the coordinate of the local diffuse texture, and texcoord. zw is the global texture coordinate of the palette.