简体   繁体   中英

OpenGL Indexed and Array texture

I have a question regarding glDraw(arrays)(elements). The thing is, most people say elements is more efficient due to vertex reuse and caching, but I try to render a terrain, each vertex with same position a different texture coordinate. THat makes each vertex unique right? So if I do not have any vertex reuse, should I prefer arrays because its much easier to implement and renders the buffer in one go compared to elements which I need to supply not only with vertex data but also an index buffer? And is there a way to render terrains which makes it able to use elements? I just dont get how to texture the terrain properly, maybe that is the problem.

I could imagine rendering models of persons would be nice with elements, since I can supply one texture file and not need more tex coords per position of vertex. But the terrain should be rendered with arrays?

When should I choose arrays and when elements?

For terrain glDrawElements is the way to go, assuming you have a simple 2d grid, and you displace it on the vertex shader or send heights as vertex attribs. It's much faster than glDrawArrays for this kind of mesh.

For the textures: I don't know if you want to texture the terrain with one big texture, or more textures blended together, for example a simple grass pattern, or grass blended to snow with increasing height.

The first one is pretty easy: lets say your terrain's width is W and its height is H. You use one big texture over the whole map. Then the texture coord for one vertex is:

vec2 TexCoord = vec2(VertexPos.x/W,VertexPos.z/H);

For the second it changes a bit:

If your texture is a simple grass tile , or anything that you want to cover the whole terrain with, then texture coord of a vertex is:

vec2 TexCoord = vec2(VertexPos.x/XdirectionTileSize,VertexPos.z/ZdirectionTileSize);

XdirectionTileSize and ZdirectionTileSize are the dimensions of one pattern. For example you want to fetch a grass texture over the terrain with 1 meters * 1 meters resolution, and your vertices are each 2 meters away from each other, then set them to 0.5 (1/2).

For more textures you can define more tile-sizes, and one big texture map with each color defining one material. Example: red is grass, blue is snow, green is sand, and alpha is rock. Then you blend the textures like this: (You can fetch this big material map just like the one big texture)

color = materialmap.r*grass + materialmap.b*snow + materialmap.g*sand + materialmap.a*rock;

And finally my favorite method for terrain texturing is procedural shader splatting . I won't write it here. For example the Frostbite Engine (Battlefields) uses this. Here's a link to a very good presentation: Terrain Rendering in Frostbite Using Procedural Shader Splatting . In short it's like masking. Rendering the heights, normals, slopes into an FBO texture, and using it like in deferred rendering/shading.

For quality: if your texcoords are calculated in a shader with vertex positions on a plane (.xy, .xz), it can distort textures with increasing slope. The solution for this problem is triplanar texturing. Bottom of the page: Generating Complex Procedural Terrains Using the GPU . In short: it projects the texture to the terrain from 3 planes (xz, xy, yz) and mixes/blends them with normals.

Of course you can mix these texturing methods. I know it doesn't directly answer your question, but I don't think you should pass texture coordinates as vertex attribs. It's much easier defining them with big textures, tiles, or splatting. Oh, and I hope you use shaders;).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM