[英]GLSL Shaders texture alpha splatting
我正在尝试着色器用于在地形上加载四个纹理细节贴片,方法是根据第五个图像合并它们,其中r,g,b和一个组件用于确定每个纹理应该混合多少。 混合工作正常,但是当我尝试添加“mixmap”图像时,它会失败,因为我猜测纹理坐标有问题。
首先,这是着色器:
顶点着色器
void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}
片段着色器
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);
}
正如我所说,混合效果很好。 问题来自于从我的mixmap读取的值不正确的事实。
以下是对我正在做的事情的更多解释。 我正在构建一个从高度图加载地形的寻呼地形系统。 然后我想用我的mixmap图像用rgba组件来表示每个纹理应该根据高度混合多少。
r是水
g是沙子
b是草
一个是摇滚乐
因此,我需要能够从着色器中获取正确的像素值,以正确地混合我的纹理。
以下是在包装箱和文本之间进行混合的示例,以便您可以清楚地看到纹理的应用方式。
现在,如果我使用一个简单的mixmap图像(半红,半绿),它应该给我在地形左侧的板条箱和右边的文字,我得到
这是地形生成过程的一部分:它遍历顶点数组并创建地形三角形
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();
}
如果需要,我也可以提供更多截图,我的一些代码。
作为所提供答案的后续内容,我尝试通过计算着色器中的UV来实现。
首先,这是新的着色器
顶点着色器
varying vec4 VertexPosition;
void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
VertexPosition = gl_ModelViewMatrix * gl_Vertex;;
}
片段着色器
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.);
}
以下是结果
但是,如果我移动相机:
正如你所看到的那样,箱子和文字是并排的。 但看起来我在屏幕坐标而不是世界坐标计算。 我一定对坐标系再次感到困惑。 我会尝试找到合适的人! 我只是想确保我的方向正确。 我也会寻找多纹理坐标,一旦我弄清楚它是如何工作的,它可能会更方便;)
如果我正确理解你,你的mixmap需要不同的纹理坐标。 现在它正在使用每个单元格的整个mixmap,这就是为什么你得到半文本,每个单元格半个板条箱。
尝试使用多个texcoords。 您还可以通过将顶点的当前x pos除以x方向上的地形长度和y相同的值来计算着色器中的正确UV。 如果你缩放你的地形,一定要将地形的长度乘以比例。
如果你没有看到我在说什么,那么地形的每个单元都会得到以下的UV:(0,0),(1,0),(0,1)或(1,1)。 这对于板条箱和文本纹理来说很好,但mixmap应该更加分数和多样化。
这是另一个地形教程的链接 。 它使用DirectX,但顶点/ UV生成具有可比性。 最大的区别在于他为整个地形使用了一个大的纹理,这是你需要为mixmap做的,而不是你的其他纹理。
我想我弄清楚什么是错的。 明确存储Vertex位置。 不要将它乘以modelviewmatrix,即:
varying vec4 VertexPosition;
void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
//VertexPosition = gl_ModelViewMatrix * gl_Vertex;;
VertexPosition = gl_Vertex;
}
这将解决它,抱歉,我将你的固定着色器扔进了rendermonkey,它不再随着相机移动。 希望这可以帮助。 我正在进行平移,但现在它看起来像:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.