当前位置: 首页 > 知识库问答 >
问题:

体验全屏纹理的最佳方式

贺自明
2023-03-14

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

目前,我使用以下两种方法:

>

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;

也不理想,因为需要从浮动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]。这对全屏四边形效果很好(即使没有透视分割,因为坐标非常简单)。不过,我需要在延迟渲染器中绘制为灯光几何体的任意几何体存在一些问题。在顶点着色器中,我将输出为红色=x和绿色=y的颜色:

#version 150

noperspective in vec2 vVertCoord;
out vec4 colorOut;

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

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

但是,如果我靠近灯光几何体,结果是:

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

共有1个答案

曹子平
2023-03-14

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

例如,如果你画了一个简单的单位正方形,覆盖了你的屏幕,你可以,然后会收到全屏纹理,你可以这样做:

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_顶点永远只在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);

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

 类似资料:
  • 立方体纹理是放置在立方体各个表面上的六个单独的方形纹理的集合。大多数情况下,它们用于在物体上显示无限远的反射,类似于天空盒在背景中显示远处的风景。一个展开的立方体纹理可能是这样的: 在 Cocos2d-x 中,这样创建立方体纹理: // create a textureCube object with six texture assets auto textureCube = TextureCub

  • 我知道我可以写这些: 但是,如果在类中有一个字段,并且我在: 我也必须在其他两个存储库中编写这样的方法,这有点烦人…有没有更好的方法来处理这种情况? 我想指出的另一点是,应该是一个只读存储库(即扩展类),而另外两个存储库应该公开所有CRUD操作。 让我知道可能的解决办法。

  • 第五课:纹理立方体 本课学习如下几点: 什么是UV坐标 怎样自行加载纹理 怎样在OpenGL中使用纹理 什么是滤波?什么是mipmap?怎样使用? 怎样利用GLFW更加有效地加载纹理? 什么是alpha通道? 关于UV坐标 给一个模型贴纹理时,需要通过某种方式告诉OpenGL用哪一块图像来填充三角形。这是借助UV坐标来实现的。 每个顶点除了位置坐标外还有两个浮点数坐标:U和V。这两个坐标用于获取纹

  • 有了这个功能,我可以在Android系统的OpenGL ES 1.0中创建一个球体: 我现在的问题是,我想在球体上使用这个纹理,但是只创建了一个黑色的球(当然,因为右上角是黑色的)。我使用这个纹理坐标是因为我想使用整个纹理: 要正确使用纹理,我需要做什么?

  • 前因后果 问题的起因是和一个群友一起讨论,怎么让地球的背景贴上视频,而且地球展开成平面之后,可以拖动实体位置 由于之前几次示例都用了本地的图片(设置 Cesium.Viewer 的imageryProvider 属性)来作背景,这次我很自然的想到了如果使用本地mp4 作为url的值是否可行,结果实践证明这样不行,查看了一下SingleTileImageryProvider的url属性的官方文档,感

  • 目前,我的应用程序的某些部分在将大量数据加载到报告表时遇到了速度问题。报告表中的数据是从多个表中提取的,并运行一些复杂的查询,但这是必需的。 除了优化代码,我的问题是,您个人如何处理需要向用户显示的大量数据,最佳实践是什么? 目前我正在处理所有的数据,然后通过javascript库生成数据表。 我知道的事情: 用户不需要一次看到所有数据 用户需要能够搜索所有数据 用户需要能够过滤数据 最好的方法真