ORIGINAL:
之前我曾询问过这个问题,但我最初的例子有点不完整,我想我现在可以更加具体地解决我的问题了。
对于上下文,我在旧的Apple mac计算机上使用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 +中运行也很平滑罪(时间)翻译案例。
我会发布一些代码,但它主要包括设置顶点缓冲区和大型静态数组声明以进行测试。我的着色器基本上是直通的:(例如我的片段着色器中的主要功能:)
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]所以看起来我需要忽略alpha为0.0时的颜色,即使颜色不是[0.0,0.0,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);
}
This mostly unresolved stackoverflow question讨论了我遇到的问题 - 简而言之,许多重叠的透明形状会导致延迟,但如果相同的形状不重叠,那么一切都很好。 当然,还没有找到替代混合算法。
考虑数字 - 每个纹理部分覆盖1280 x 720像素。有5层,每层3个四边形。 对于每个像素,我正在做同样的工作N层次,所以4,608,000? 我想这可能是非常昂贵的。我也做了奇怪的模运算和偏移。 如果我试图实现视差滚动的方式太笨拙,那么它将如何有效地完成?如果肯定有更好的方法,我愿意改变我的算法/设置。我很好奇如何正确设置纹理和透明层以避免我遇到的问题。
一个想法:如果我从前到后渲染怎么办?混合功能将如何变化? (我知道你通常会从后到前渲染透明对象,但是在这里我只需要在使用alpha == 1.0命中一层时停止检查图层。)
答案 0 :(得分:0)
你的这个问题非常难以理解,但似乎关键是
片段颜色只是最不透明的纹理元素 - 没有额外的 需要乘法
所以你是说你只想绘制那些alpha为1.0
的像素,而其余的被丢弃?像下面的例子一样:
您正在绘制3个大小为3x1的纹理。第一个纹理所有3个像素都是不透明的;第二个像素是前2个像素不透明,最后一个像素不透明。现在结果应该是第一个像素来自纹理3,第二个像素来自2,第三个来自1。
如果这是真的,那么首先让我们假设您的纹理已输出1.0
或.0
作为alpha值。清除缓冲区后,混合功能应为GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
颜色。这意味着即将到来的颜色将与其源alpha相乘并混合为当前颜色:
1.0
,这意味着将完全使用源颜色(乘以1.0
)并完全忽略目标颜色(乘以0.0
)destination = source*1.0 + destination*.0
。在通用语言中,这个像素将被新颜色完全重绘。.0
,这意味着将完全忽略源颜色(乘以.0
)并完全使用目标颜色(乘以1.0
)destination = source*0.0 + destination*1.0
。在通用语言中,这个像素将完全保留原样,新颜色将被忽略。您可能甚至不需要使用混合的alpha分量,因此我想GL_ZERO, GL_ONE
可以应用,表示您将保留来自glClear
的Alpha通道。否则,相同的规则适用于Alpha通道,因此请执行您需要的操作。
如果您需要进一步定义" opaque"你可能想在着色器中控制它。可以应用某些阈值,如:
void main(void)
{
vec4 texel = texture(tex0, v_uv);
color = vec4(texel.rgb, step(texel.a, 0.5));
}
请注意,即使输入纹理只有0.0
和1.0
值,除非在纹理上使用nearest
滤镜,否则在着色器中可能不是这种情况。插值可以是任何大小。