gpt4 book ai didi

完全不透明或透明的 openGL Alpha 混合

转载 作者:行者123 更新时间:2023-12-05 07:33:39 32 4
gpt4 key购买 nike

原创:

我之前问过这个问题,但我最初的例子有点不完整,我想我现在可以更具体地说明我的问题。

对于上下文,我在旧的 Apple mac 计算机上使用 openGL 3.3 并尝试渲染四边形的重叠层。每个四边形都被 uv 映射到一 block 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] 所以看起来我需要在 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 击中图层后停止检查图层)。

4096x4096 bg texture "atlas"

最佳答案

你这个问题非常难懂,但好像关键是

the fragment color is just the front-most opaque texel--no additional multiplication required

所以你是说你只想绘制那些 alpha 为 1.0 的像素?而其余的则被丢弃?就像下面的例子是正确的:

您正在绘制 3 个大小为 3x1 的纹理。第一个纹理的所有 3 个像素都是不透明的;第二个有前 2 个像素不透明,最后一个只有第一个像素不透明。现在结果应该是第一个像素来自纹理 3,第二个来自纹理 2,第三个来自纹理 1。

如果这是真的那么首先让我们假设你的纹理已经输出 1.0.0为阿尔法值。清除缓冲区后,混合函数应为 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 channel .否则相同的规则适用于 alpha channel ,所以做你需要做的。

如果您需要进一步定义“不透明”,您可能需要在着色器中对其进行控制。可以应用一些阈值,例如:

void main(void)
{
vec4 texel = texture(tex0, v_uv);
color = vec4(texel.rgb, step(texel.a, 0.5));
}

请注意,即使您的输入纹理只有 0.01.0除非您使用 nearest,否则在您的着色器中可能并非如此。过滤你的纹理。内插值可以是任意大小。

关于完全不透明或透明的 openGL Alpha 混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50479307/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com