3

使用 Three.js,我编写了一个顶点着色器,根据渲染像素的屏幕象限为平面中的每个点着色。

// vertex shader
uniform float width;
uniform float height;
varying float x;
varying float y;
void main() 
{ 
    vec4 v = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    x = v.x; 
    y = v.y;
    gl_Position = v;
}

// fragment shader
varying float x;
varying float y;
void main() 
{
    gl_FragColor = vec4(x, y, 0.0, 1.0);
}  

在此处输入图像描述

jsFiddle 上的实时示例:http: //jsfiddle.net/Stemkoski/ST4aM/

我想修改这个着色器,使其x在屏幕左侧等于 0,在屏幕右侧等于 1,同样y在顶部等于 0,在底部等于 1。我(错误地)假设这将涉及将和的值更改为和(x在哪里和存储窗口的宽度和高度)。但是,随着这种变化,在平面上放大和缩小时,每个屏幕像素的颜色似乎都会发生变化。yx = v.x / widthy = v.y / heightwidthheight

如何修复着色器代码以获得所需的效果?

4

2 回答 2

7

您的变量v在剪辑空间中。您需要应用透视除法以将其映射到标准化设备坐标 (NDC) 空间,该空间采用 [ -1, 1 ] 范围内的值。然后,您需要将该值映射到范围 [ 0, 1 ],如下所示:

    vec4 v = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    x = v.x / v.z;
    y = v.y / v.z;

    gl_FragColor = vec4( 0.5 * x + 0.5, - 0.5 * y + 0.5, 0.0, 1.0 );

小提琴:http: //jsfiddle.net/ST4aM/4/

三.js r.62

于 2013-11-05T03:24:32.750 回答
1

只是对 WestLangley 答案的补充。

我遇到了一个小错误,我的顶点位置计算得有点错误。似乎在 (-1.1, 1.1) 的范围内。因此,经过实验证明这v.z并不完全正确,它取决于近场剪辑平面,人们通常在相机设置中将其保留为 1。所以添加 2v.z似乎已经解决了它。我不明白为什么是 2 而不是 1。

x = v.x / (v.z + 2.0); // depth + 2 x near clip space plane dist (camera setting)

因此,如果您正在使用 WestLangley 示例中的大型对象,您不会注意到它,但如果您的对象很小且靠近相机,那么错误将很明显。

如果 Y 的位置不在 (0,1) 范围内,并且 X 的固定计算,我已经修改了上面的示例以剪辑颜色。平面大小为 20,相机距离为 30。

顶点位置计算错误

jsFiddle

它仍然不完美。如果物体非常靠近相机,它仍然会弄乱位置,但至少这使它适用于中等大小的物体。

超近距离错误

于 2017-10-02T22:12:34.520 回答