gpt4 book ai didi

opengl - 全屏纹理采样的最佳方法

转载 作者:行者123 更新时间:2023-12-02 09:54:01 26 4
gpt4 key购买 nike

在片段着色器中采样全屏纹理的最佳方法是什么,例如延迟渲染器中的 g 缓冲区,或后处理着色器中的场景纹理?

目前我使用以下两种方式:

  • 将屏幕尺寸作为统一值传递给着色器,并根据 gl_FragCoord 计算 (u,v):

    vec2 texCoord = gl_FragCoord.xy / vScreenSize;
    vec3 c = texture( tex, texCoord ).rgb;

    似乎并不理想,因为需要进行除法,并且为着色器提供屏幕尺寸很麻烦。

  • gl_FragCoord.xy 转换为 ivec 并使用 texelFetch:

    vec3 c = texelFetch( tex, ivec2(gl_FragCoord.xy), 0 ).rgb;

    也不理想,因为需要从 float 转换为 int

那么有没有更好的办法呢?我真的只想在像素着色器绘制的确切位置对缓冲区进行采样。

<小时/>

//编辑:

<小时/>

好的,根据来自顶点着色器的插值纹理坐标的建议,我设法找出以下代码:

顶点着色器:

#version 150

uniform mat4 im_ModelViewProjectionMatrix;

in vec3 iv_Vertex;
noperspective out vec2 vVertCoord;

void main( void )
{
gl_Position = im_ModelViewProjectionMatrix * vec4(iv_Vertex, 1.0);
vVertCoord = (gl_Position.xy / gl_Position.w) * (0.5) + vec2(0.5);
}

我基本上通过透视除法从剪辑空间位置计算归一化设备坐标 (NDC),然后将 NDC(范围从 [-1,1])映射到区间 [0,1]。这对于全屏四边形非常有用(即使没有透视划分,因为坐标非常简单)。不过,我需要在延迟渲染器中绘制为光几何的任意几何体存在一些问题。在顶点着色器中,我输出 vVertCoord 作为 red=x 和 green=y 的颜色:

#version 150

noperspective in vec2 vVertCoord;
out vec4 colorOut;

void main( void )
{
colorOut = vec4(vVertCoord.x, vVertCoord.y, 0, 1);
}

这是我在点光球内时的结果,一切看起来都很好(黑线是故意渲染的):

All fine

但是,如果我更接近光几何,结果就是:

Not ok

左上角的红色补丁在那里做什么?您不希望在禁用调试颜色的情况下看到真实颜色的结果,因为它看起来像 lsd-trip,当您移动相机时,一切都会扭曲。这与精度有关吗?请注意,当我在像素着色器中使用 gl_FragCoord 时,一切都很好。

最佳答案

如果您只需从顶点着色器传入插值顶点坐标,则无需执行任何特殊数学运算。

例如,如果您正在绘制一个覆盖屏幕的简单单位正方形,您就可以接收全屏纹理,您可以执行如下操作:

vertex shader pseudocode:
layout(position = 0) in vec3 in_vertex;
out vec3 out_vertex;
void main()
{
//Do your matrix multiplications to your in_vertex to get its final position...
out_vertex = in_vertex;
}

然后,您的顶点着色器将正确地将 in_vertex 插值到 x:0...1、y:0...1 范围内(只要您正在绘制单位正方形)并将其传递给您的片段着色器。然后你的片段着色器将像这样使用它:

fragment shader pseudocode:
in vec3 out_vertex;
uniform sampler2D tex;
void main()
{
gl_fragcolor = texture(tex,vec2(out_vertex.x,out_vertex.y));
}

不需要其他数学运算,只要注意 out_vertex 只在 0...1 的范围内即可。为了稍微扩展一下这个例子,想象一下我们的正方形:


(0,1)+------------+(1,1)
| |
| |
| |
| |
| |
(0,0)+------------+(0,1)

我们想在正中心采样这个点:


(0,1)+------------+(1,1)
| |
| |
| * |
| |
| |
(0,0)+------------+(0,1)

我们的顶点着色器将自动从其他 4 个位置插入该位置,并将以下 vec3 传递给片段着色器:

out_vertex = vec3(0.5,0.5,0);

然后可以使用它来成功采样纹理

关于opengl - 全屏纹理采样的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23113247/

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