2016-10-18 154 views
1

我試圖在webgl中實現平面着色,
我知道varying關鍵字在頂點着色器中會內插該值並將其傳遞給片段着色器。webGL中的平面着色

我試圖禁用插值,並且我發現flat關鍵字可以做到這一點,但它似乎不能在WebGL的使用?

flat varying vec4 fragColor;

總是收到錯誤:Illegal use of reserved word 'flat'

回答

4

我認爲, '平' 不是由WebGL的使用的版本GLSL的支持。如果你想扁的陰影,有幾個選項:

1)複製多邊形的正常每個頂點。這是最簡單的解決方案,但我發現複製數據有點令人不滿意。

2)在頂點着色器,變換頂點視圖座標,並在片段着色器,使用dFdx()和dFdy(),其計算衍生物函數計算正常。擴展GL_OES_standard_derivatives支持這些函數(在使用GPU之前需要檢查GPU是否支持這些函數),但大多數GPU(包括智能手機中的GPU)都支持該擴展。

我的頂點着色器如下:

struct VSUniformState {    
    mat4 modelviewprojection_matrix; 
    mat4 modelview_matrix;   
}; 

uniform VSUniformState GLUP_VS;  

attribute vec4 vertex_in; 
varying vec3 vertex_view_space; 

    void main() {           
     vertex_view_space = (GLUP_VS.modelview_matrix * vertex_in).xyz; 
     gl_Position = GLUP_VS.modelviewprojection_matrix * vertex_in; 
    }   

,並在相關的片段着色器:

#extension GL_OES_standard_derivatives : enable 

varying vec3 vertex_view_space; 
... 
    vec3 U = dFdx(vertex_view_space);      
    vec3 V = dFdy(vertex_view_space);     
    N = normalize(cross(U,V)); 
    ... do the lighting with N  

我喜歡這個解決方案,因爲它使設置代碼更簡單。一個缺點可能是它爲片段着色器提供了更多的工作(但是對於今天的GPU,它應該不成問題)。如果表現是一個問題,衡量它可能是一個好主意。

3)的另一種可能性是具有幾何着色器(如果支持的話),該計算法線。一般來說,它速度較慢(但同樣,測量性能可能是一個好主意,它可能取決於特定的GPU)。

又見這個問題的答案: How to get flat normals on a cube

我的實現可以在這裏找到: http://alice.loria.fr/software/geogram/doc/html/index.html

一些在線網絡-GL演示在這裏(使用emscripten轉換從C++到JavaScript的): http://homepages.loria.fr/BLevy/GEOGRAM/

+0

感謝,通過使用dFdx/dFdy功能,我終於得到了表面法線〜! – SSARCandy

+2

但在webGL中,dFdx/dFdy是擴展名,所以需要先聲明它。 – SSARCandy

+0

https://developer.mozilla.org/en-US/docs/Web/API/OES_standard_derivatives – SSARCandy

2

退房的WebGL 2.平面着色支持。 頂點shadder:

#version 300 es 
in vec4 vPos; //vertex position from application 
flat out vec4 vClr;//color sent to fragment shader 
void main(){ 
    gl_Position = vPos; 
    vClr = gl_Position;//for now just using the position as color 
}//end main 

對於片段着色器

#version 300 es 
precision mediump float; 
flat in vec4 vClr; 
out vec4 fragColor; 
void main(){ 
    fragColor = vClr; 
}//end main