2013-11-04 58 views
1

使用Three.js,我写了一个顶点着色器,它根据像素呈现的屏幕的哪个象限为平面上的每个点着色。在的jsfiddleThree.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); 
} 

enter image description here

直播例如:http://jsfiddle.net/Stemkoski/ST4aM/

我想使得x等于修改此着色器0在屏幕的左侧和1上的右侧屏幕上,同样y等于顶部0和底部1。我(错误地)认为这将涉及将xy的值更改为x = v.x/widthy = v.y/height(其中widthheight存储窗口的宽度和高度)。然而,随着这种改变,在平面上放大和缩小时,每个屏幕像素处的颜色似乎都会改变。

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

+0

这对我来说不是很清楚你的意思是这是它吗? http://jsfiddle.net/ST4aM/2/ – WestLangley

+0

我也没有很多线索,但atm,你的x已经在左边是零,在右边是1,不是吗?由于颜色是黑色和红色?如果你想让y在顶部为0,只需反转y-分量?顺便说一句。至于性能,将两个花车组合成一个vec2? :) btw:我在这里留下了一个关于你最后一个问题的“评论问题”,如果你能回答它,它会很酷:) – GuyGood

+0

对不起,我似乎没有解释得这么好。 @WestLangley:你的改变可以修正飞机上的着色,但是我正在寻找相对于窗口/屏幕(而不是飞机)固定的模式。例如,屏幕右下角像素的颜色应该是r = 1,g = 0,b = 0,无论平面网格的哪个点位于其之外。基本上与我发布的jsFiddle效果相同,但屏幕上的颜色应该有平滑的渐变。 –

回答

4

您的变量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/

three.js所r.62

+0

不错,挺有意思,谢谢:) – GuyGood

+0

正是我在找的东西。谢谢! –

1

只是一个除了WestLangley的答案。

我遇到了一个小错误,我的顶点位置计算有点不对。看起来它在(-1.1,1.1)的范围内。因此经过试验发现v.z并不完全正确,它依赖于近场剪辑平面,人们通常在摄像机设置中将其留作1。所以加入2到v.z似乎已经修复它。我不明白为什么2,而不是1

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

所以,如果你正在使用大型对象在WestLangley的例子那样工作,你不会注意到它,但如果你的对象是小的,靠近摄像头则错误将会引人注目。

我修改示例上述夹颜色如果位置不在内(0,1)为Y和固定计算X.平面尺寸是20,照相机距离是30。

vertex position calculation error

jsFiddle

这还不完美。如果物体距离摄像机非常近,它仍然会弄乱位置,但至少可以让它适用于中等尺寸的物体。

error in super close proximity