翻译:
我之前问过这个问题,但我的初始示例有点不完整,现在我认为我可以更具体地说明我的问题。
为了背景,我正在一台旧的苹果电脑上使用openGL 3.3,并尝试渲染重叠的四边形层。每个四边形都被uv映射到一个png 4096 x 4096纹理的一部分,该纹理具有完全透明的区域。
我想使用alpha混合,以便第N层的透明部分显示第N-1层(在其后面)的不透明部分。因为我不需要半透明度,所以我想知道 - 是否有一种方法可以配置glBlendFuncSeparate
,使片段颜色只是最前面的不透明像素 - 不需要额外的乘法?
我尝试了类似于这样的东西:
glBlendFuncSeparate(GL_SRC_COLOR, GL_DST_COLOR, GL_ONE, GL_ZERO);
但我认为我完全误解了参数的含义。我认为它们的意思是:保留源颜色并将其设置为目标颜色...应用原始alpha。(我知道这是绝对错误的)。
起初我以为这是一个xyz问题,并搜索其他原因,导致我注意到性能问题,但即使上述函数调用导致完全错误的颜色,它也会使我的动画在hello-triangle + sin(time)翻译案例中平稳运行。
我想发布一些我的代码,但它主要包括设置顶点缓冲区和大型静态数组声明进行测试。我的着色器基本上是通过的:(例如,我的片段着色器中的主函数:)
void main(void)
{
vec4 texel = texture(tex0, v_uv);
color = vec4(texel.rgb, texel.a);
}
纹理正确加载。我已经设置了从后往前的渲染。
我该如何设置这种类型的渲染?
提前感谢您。
更新:
我尝试过:
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ONE);
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
但是只有不透明白色的前层出现了。我检查了RGBA值,看起来透明部分是[1.0, 1.0, 1.0, 0.0],所以即使颜色不是[0.0, 0.0, 0.0, a],当alpha为0.0时需要忽略颜色。为了模拟这种情况,我添加了一个if (alpha is 0.0), then discard;
语句,但延迟问题仍然存在。
因此,这些函数并不完全正确,或者其他地方出了问题。
关于我的设置的更多信息:
(我在底部发布了我的大型纹理)
每个图层的顶点和索引数据太长了,无法发布,但每个五个图层中有三个四边形(我将相机位置传递给着色器,并使用z位置值进行偏移)。这可能是效率低下的另一个原因。
完整的片段和顶点着色器:
// 顶点
#version 330 core
precision highp float;
layout (location = 0) in vec3 a_position;
layout (location = 1) in vec2 a_uv;
out vec2 v_uv;
uniform mat4 u_matrix;
uniform float u_aspect;
uniform vec3 u_position_cam;
uniform int u_count_layers;
void main(void)
{
// scroll speed depends on the inverse of the z position
float speed_factor = (1.0 / pow(2.0, u_count_layers - a_position.z));
// x offset
float X = -u_position_cam.x * speed_factor;
// make sure the bg quad jumps back to the correct position
X = mod(X, (u_aspect) * 2.0);
X += a_position.x;
// y offset
float Y = -clamp(u_position_cam.y, 0.0, 2.0) * speed_factor;
Y += a_position.y;
gl_Position = u_matrix * vec4(X, Y, a_position.z, 1.0);
v_uv = a_uv;
}
// 碎片
#version 330 core
precision highp float;
in vec2 v_uv;
uniform sampler2D tex0;
out vec4 color;
void main(void)
{
vec4 texel = texture(tex0, v_uv);
color = vec4(texel);
}
这篇未解决的stackoverflow问题讨论了我正在经历的问题——简单来说,许多重叠的透明形状会导致延迟,但如果相同的形状没有重叠,那么一切都没问题。当然,还没有找到替代混合算法。
考虑数字——每个纹理部分覆盖1280 x 720像素。有5层,每层3个四边形。对于每个像素,我要做同样的工作N层次,所以是4,608,000?我想这可能非常昂贵。我还在做奇怪的取模运算和偏移量计算。如果我尝试实现视差滚动的方式太笨拙,那么该如何高效地实现呢?如果确实有更好的方法,我很愿意改变我的算法或设置。我很好奇如何正确设置纹理和透明层以避免我正在经历的问题。
一个想法:如果我从前面渲染会怎样?混合函数会如何改变?(我知道通常是从后向前渲染透明对象,但在这里,我只需要一旦碰到alpha == 1.0 就停止检测层)