2017-01-30 51 views
0

我在NTNU開設WebGL課程。我目前正在探索着色器的功能以及如何使用它們。是否可以在WebGL中每次繪製調用時運行一次代碼?

我們已經向我們展示了一個例子,我們計算投影矩陣,然後將其設置在頂點着色器中,然後進行繪製調用。我想試着在着色器中做這個矩陣計算。

這意味着我必須將代碼放在頂點着色器中的main()函數以外的位置,因爲每次繪製調用都會調用該函數多次。

頂點着色器:

uniform vec3 camRotation; 
attribute vec3 position; 
void main() { 

    // I want this code to run only once per draw call 
    float rX = camRotation[0]; 
    float rY = camRotation[1]; 
    float rZ = camRotation[2]; 
    mat4 camMatrix = mat4(
     cos(rY) * cos(rZ), cos(rZ) * sin(rX) * sin(rY) - cos(rX) * sin(rZ), sin(rX) * sin(rZ) + cos(rX) * cos(rZ) * sin(rY), 0, // 
     cos(rY) * sin(rZ), cos(rX) * cos(rZ) + sin(rX) * sin(rY) * sin(rZ), cos(rX) * sin(rY) * sin(rZ) - cos(rZ) * sin(rX), 0, // 
     -sin(rY), cos(rY) * sin(rX), cos(rX) * cos(rY), 0, // 
     0, 0, 0, 1 
    ); 
    // End of code in question 

    gl_Position = camMatrix * vec4(position, 1); 
    gl_PointSize = 5.0; 
} 

這可能嗎?我是一個傻瓜嗎?

+0

您可能會發現[這些文章有用](http://webglfundamentals.org) – gman

回答

3

AFAIK,沒有辦法做到這一點。您應該計算camMatrix在你的JS代碼,並通過統一的它傳遞到shader:

uniform mat4 camMatrix; 
attribute vec3 position; 
void main() { 
    gl_Position = camMatrix * vec4(position, 1); 
    gl_PointSize = 5.0; 
} 

現在你需要計算矩陣中的JS:

// assuming that program is your compiled shader program and 
// gl is your WebGL context. 
const cos = Math.cos; 
const sin = Math.sin; 
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'camMatrix'), [ 
    cos(rY) * cos(rZ), cos(rZ) * sin(rX) * sin(rY) - cos(rX) * sin(rZ), sin(rX) * sin(rZ) + cos(rX) * cos(rZ) * sin(rY), 0, 
    cos(rY) * sin(rZ), cos(rX) * cos(rZ) + sin(rX) * sin(rY) * sin(rZ), cos(rX) * sin(rY) * sin(rZ) - cos(rZ) * sin(rX), 0, 
    -sin(rY), cos(rY) * sin(rX), cos(rX) * cos(rY), 0, 
    0, 0, 0, 1 
]); 
+0

感謝您的答案。我知道你提供的方法,我很好奇,看看我是否可以在着色器中做這些計算(例如'cos(rY)')每次繪製調用 – gromit190

+1

@Birger我會很驚訝,因爲如何GPU運行着色器。爲了粗略地描述着色器的每一次執行(對於每個頂點,如果我們正在討論頂點着色器,並且在片段着色器的情況下針對每個像素)獲取它自己的狀態和大塊內存。同步和交換它們之間的數據會比較麻煩並且可能很慢。 –

2

沒有它不可能,着色器的整個概念是可以向量化的,所以它們可以並行運行。即使你可以在那裏獲得更多的收益,因爲GPU的速度優勢(除了其他因素)固有地基於其並行執行計算的能力。除此之外,通常您有一個組合視圖投影矩陣,在所有繪製調用(框架)期間保持靜態,並且在您繪製的每個對象上附加模型/世界矩陣。

投影矩陣的名稱意味着以任何一種透視或正交方式投影點(您可以將其視爲相機的鏡頭)。 視圖矩陣是轉換/旋轉該投影(攝像機位置和方向)的變換,而每個對象的世界/模型矩陣包含單個對象的變換(平移,旋轉和縮放)。

在你的shader你再使用每對象模型/世界矩陣變換你的頂點位置,世界空間,最後使用預乘ViewProjection矩陣將其轉換到攝像機空間:

gl_Position = matViewProjection * (matWorld * vPosition) 

正如你根據你的用例繪製點,你可以將世界矩陣簡化爲一個平移矢量。

+0

非常有啓發性,謝謝! – gromit190

相關問題