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.

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 

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

But if I translate the camera:

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;)