我的属性包含像素值。我想用这个属性值来偏移我的gl_vertex。
问题是我的gl_vertex是世界单位而offset \ attribute是像素。
如果我将屏幕尺寸作为制服发送,然后将像素转换为-1到1的值,并将其添加到最终的gl_Position,我就能做到。但是我现在不想管理屏幕尺寸事件并且无论如何每次使用每个着色器发送它。
有什么方法可以用一些矩阵游戏或它们的反转来做到这一点?
为了更容易,我想将gl_Position设置为像素50,50。
vec4 myPixelValue = vec4(50,50,1,1);
gl_Position = <Something> * myPixelValue;
---- ADDITION ----
在我明白如果不发送着色器窗口大小就无法做到这一点我决定发送大小。我创建了以下顶点着色器代码
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值,但不知道如何。
任何人?
答案 0 :(得分:4)
来自keltars评论:
尝试计算标准化设备坐标而不是剪辑 空间。 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);