我使用投影的gl_Position和屏幕参数进行了一些计算,但是在靠近相机的多边形中位置看起来是扭曲的。但是当我使用...时
vec2 fragmentScreenCoordinates = vec2(gl_FragCoord.x / _ScreenParams.x, gl_FragCoord.y / _ScreenParams.y);
......我得到了相当准确的xy
结果。
漂亮的输出gl_FragCoord.xy坐标:
从投影顶点计算会在整个面上产生插值,我不能用它来对屏幕对齐纹理进行采样。
gl_Position的丑陋插值输出:
有没有办法在顶点着色器中生成这个gl_FragCoord
类似的值?我真的想在顶点着色器中计算纹理坐标,以进行独立纹理读取,手动深度测试等。
或者我在这里可以使用哪些Unity内置值?
答案 0 :(得分:7)
在顶点着色器中,设置
gl_Position = ...
在透视划分为标准化设备坐标之前,它必须位于剪辑空间中。这是因为OpenGL在4D空间中做了很多东西,并且是插值所必需的。
由于你只想在每个顶点的值而没有内插,你可以立即标准化(或者甚至可以leave out if using an orthographic projection)......
vec3 ndc = gl_Position.xyz / gl_Position.w; //perspective divide/normalize
vec2 viewportCoord = ndc.xy * 0.5 + 0.5; //ndc is -1 to 1 in GL. scale for 0 to 1
vec2 viewportPixelCoord = viewportCoord * viewportSize;
此处, viewportCoord
相当于您的fragmentScreenCoordinates
,假设视口覆盖了窗口。
注意:正如@derhass指出的那样,如果几何与w = 0
平面相交,则会失败。即可见三角形的顶点位于相机后面。
[修改]
评论讨论使用1到1像素最近邻居查找的坐标。正如@ AndonM.Coleman所说,改变坐标将起作用,但使用最近邻过滤更容易,更快捷。您还可以使用texelFetch
,它完全绕过过滤:
抓住坐标:
vec2 sampleCoord = (floor(viewportPixelCoord) + 0.5) / textureSize(mySampler);
vec4 colour = texture(mySampler, sampleCoord);
最近邻过滤(不确定这在unity3d中是什么):
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //magnification is the important one here
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
使用texelFetch
:
vec4 colour = texelFetch(mySampler, ivec2(viewportPixelCoord), 0);