GLSL Shaders Alpha Splatting Texture

I am trying to make a shader used to load four texture details onto a landscape by merging them in the fifth image, where r, g, b and components are used to determine which part of each texture should be combined. Blending works fine, but when I try to add my "mixmap" image, it fails due to a problem with the texture coordinates that I assume.

First, here are the shaders:
Vertex shader

void main() { gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = ftransform(); } 

Fragment shader

 uniform sampler2D Texture0; uniform sampler2D Texture1; uniform sampler2D Texture2; uniform sampler2D Texture3; uniform sampler2D Mixmap; varying vec3 pos; void main() { vec4 texel0 = texture2D(Texture0, gl_TexCoord[0].st).rgba; vec4 texel1 = texture2D(Texture1, gl_TexCoord[0].st).rgba; vec4 texel2 = texture2D(Texture2, gl_TexCoord[0].st).rgba; vec4 texel3 = texture2D(Texture3, gl_TexCoord[0].st).rgba; vec4 mixmapTexel = texture2D(Mixmap, gl_TexCoord[0].st).rgba; texel0 *= mixmapTexel.r; texel1 = mix(texel0, texel1, mixmapTexel.g); texel2 = mix(texel1, texel2, mixmapTexel.b); gl_FragColor = mix(texel2, texel3, mixmapTexel.a); } 

As I said, mixing works great. The problem arises because the values ​​read from my mixmap are not correct.

Here is another explanation of what I am doing. I build a swap system by loading terrain from elevation maps. Then I want to use the mixmap image to represent with rgba components how much each texture should be mixed according to height.

  • r is water

  • g - sand

  • b grass

  • a - rock

So I need to be able to get the correct pixel value from my shader in order to mix my textures correctly.

Blending between crate and text

Here's an example of mixing between a box and text so you can clearly see how the texture is applied.

Now, if I use a simple mixmap image (half red, half green), which should give me boxes on the left side of the landscape, and the text on the right, I get with argb alpha splattingexample rgba image

Here is part of the terrain generation process: it iterates through an array of peaks and creates terrain triangles

 void TerrainPage::generateDisplayList() { // create one display list mDisplayListIndex = glGenLists(1); // compile the display list, store a triangle in it glNewList(mDisplayListIndex, GL_COMPILE); glFrontFace( GL_CW ); // Vertex are added clockwise. Used to calculate normals std::vector<Vertex>::iterator it; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE); texShader.enable(); texShader.bindTexture(mTexture0, "Texture0", 0); texShader.bindTexture(mTexture1, "Texture1", 1); texShader.bindTexture(mTexture2, "Texture2", 2); texShader.bindTexture(mTexture3, "Texture3", 3); texShader.bindTexture(mMixmapTexture, "Mixmap", 4); Vertex v; int j=0; glEnable(GL_TEXTURE_2D); //mTexture.bind(); glBegin(GL_TRIANGLE_STRIP); for(int i = 0; i<mVertices.size(); i++) { if(i%(2*mWidth) == 0) glEnd(); glBegin(GL_TRIANGLE_STRIP); v = mVertices[i]; glTexCoord2f(v.texcoords[0], v.texcoords[1]); glVertex3f(v.position[0], v.position[1], v.position[2]); } glEnd(); glDisable(GL_TEXTURE_2D); texShader.disable(); glEndList(); } 

If necessary, I can provide more screenshots, some of my code too.

As a follow-up answer to the provided answer, I tried to do this by calculating the UV in the shader.

Firstly, here is the new shader

Vertex shader

 varying vec4 VertexPosition; void main() { gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = ftransform(); VertexPosition = gl_ModelViewMatrix * gl_Vertex;; } 

Fragment shader

 uniform sampler2D Texture0; uniform sampler2D Texture1; uniform sampler2D Texture2; uniform sampler2D Texture3; uniform sampler2D Mixmap; varying vec4 VertexPosition; float side = 500.; void main() { vec4 texel0 = texture2D(Texture0, gl_TexCoord[0].st).rgba; vec4 texel1 = texture2D(Texture1, gl_TexCoord[0].st).rgba; vec4 texel2 = texture2D(Texture2, gl_TexCoord[0].st).rgba; vec4 texel3 = texture2D(Texture3, gl_TexCoord[0].st).rgba; vec4 mixmapTexel = texture2D(Mixmap, VertexPosition.xz/(2.*side)).rgba; texel0 *= mixmapTexel.r; texel1 = mix(texel0, texel1, mixmapTexel.g); //texel2 = mix(texel1, texel2, mixmapTexel.b); //vec4 tx = mix(texel2, texel3, mixmapTexel.a); //vec4 tx = mixmapTexel; //vec4(1, 1, 1, 1.); gl_FragColor = texel1; //if(test > 250. ) // gl_FragColor = vec4(1.,1.,1.,1.); } 

And here are the results

enter image description here

But if I translate the camera:

enter image description here

As you can see, the box and the text this time side by side. But it looks like I'm calculating screen coordinates instead of world coordinates. I must be confused again in the coordinate system. I will try to find the right one! I just want to make sure I'm in the right direction. I will also look for several texture coordinates, this may be more convenient after I figure out how it works;)

+6
source share
1 answer

If I understand you correctly, you will need different texture coordinates for your mixmap. Right now, he uses the entire mix card per cell, so you get half the text, half the box per cell.

Try using multiple texcoords. You can also calculate the correct UV in the shader by having it at the current point x of the vertex divided by the length of the terrain in the x direction, and the same for y. If you scale your territory, be sure to also multiply the length of the terrain by the scale.

If you don’t see what I'm saying, each cell in the area receives UVs: (0,0), (1,0), (0,1) or (1,1). This works great for box texture and text, but the mixmap should be much more granular and varied.

Here is a link to another landscape tutorial. It uses DirectX, but vertex / UV generation is comparable. The biggest difference is that it uses one large texture for the entire terrain, which you need to do for your mix map, but not for other textures.

I think I understood what happened. Keep the Vertex position explicitly. Do not propagate it with modelviewmatrix, i.e.:

 varying vec4 VertexPosition; void main() { gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = ftransform(); //VertexPosition = gl_ModelViewMatrix * gl_Vertex;; VertexPosition = gl_Vertex; } 

This will fix this, sorry, I threw your fixed shader in rendermonkey and it no longer moves with the camera. Hope this helps. I was getting panning, but now it looks like this:

Fixed render

+8
source

All Articles