将gl_Position或gl_Vertex的偏移量设置为像素值。

3

我有一个包含像素值的属性。我想用这个属性值来偏移我的gl_vertex。

问题在于我的gl_vertex是以世界单位为单位的,而偏移\属性是以像素为单位的。

如果我将屏幕大小作为uniform发送,并将像素转换为-1到1的值,然后添加到最终的gl_Position中,我就可以做到这一点。但是我现在不想管理屏幕大小事件,并且每次绘制时都要发送它,每个着色器都要这样做。

有没有办法通过矩阵计算或它们的逆来实现呢?

为了简化问题,我想将gl_Position设置为像素50,50。

vec4 myPixelValue = vec4(50,50,1,1);
gl_Position = <Something> * myPixelValue;

---- 补充 ----

在理解无法在不向着色器发送窗口大小的情况下完成此操作后,我决定发送大小。我创建了以下顶点着色器代码:

attribute vec2 spriteOffset;

uniform vec2 screenSize;

void main() 
{    
    vec2 screenConvert = vec2(2.0 / screenSize.x, -2.0 / screenSize.y);
    vec2 convertedPix = spriteOffset * screenConvert;

    gl_Position = (gl_ModelViewProjectionMatrix * gl_Vertex) + vec4(convertedPix, 0.0, 0.0);
}

这段代码仅适用于2D(正交投影),而不适用于3D。现在我遇到了问题。我知道我需要考虑Z值,但不知道该如何处理。

有人可以帮忙吗?


视口变换不是由矩阵执行的。它超出了着色器的范围。 - keltar
那么,为了实现我想要的功能,我必须将视口发送到着色器中。对吗?你是说没有其他方法了吗? - Raziza O
是的,你必须设置uniform。 - keltar
在二维正交投影模式下成功完成了它。在三维模式下做起来有困难。我已经更新了我的问题。 - Raziza O
1
尝试在标准化设备坐标中进行计算,而不是剪裁空间。例如:vec4 clip = gl_ModelViewProjectionMatrix * gl_Vertex; gl_Position = vec4(clip.xyz / clip.w + vec3(convertexPix, 0.0), 1.0); - keltar
完美运行!!!非常感谢。现在我只需要理解为什么它能工作 :) - Raziza O
1个回答

5

来自keltars评论:

Try calculating in normalised device coordinates instead of clip space. E.g.

vec4 clip = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = vec4(clip.xyz / clip.w + vec3(convertexPix, 0.0), 1.0);
你在另一个评论中已经说过它“完美运行”。我认为keltar的一般方法在这里是绝对正确的,但这种实现存在一些问题,至少在一般情况下不会正常工作。
问题在于这个着色器手动执行了透视除法,但剪裁(在着色器之后完成)必须在除法之前完成。如果你有与近平面相交的基元,或者物体位于相机后面(现在甚至可能出现在你的前面),这将特别给你带来错误的结果。
这也将破坏透视修正插值。
因此,更好的方法是修改原始w并使用类似以下内容的东西:
vec4 clip = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = vec4(clip.xyz + vec3(clip.w * convertexPix, 0.0), clip.w);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接