2013-11-04 92 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