WebGL中的平面着色

7

我正尝试在WebGL中实现平面着色。

我知道在顶点着色器中使用“varying”关键字可以插值该值并将其传递到片段着色器中。

我正在尝试禁用插值,并发现“flat”关键字可以做到这一点,但似乎无法在WebGL中使用?

flat varying vec4 fragColor;

总是出现错误:Illegal use of reserved word 'flat'

2个回答

10

请查看WebGL 2。支持平面着色。对于顶点着色器:

#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

6
我认为在WebGL中使用的GLSL版本不支持“flat”。如果您想要平滑着色,有几个选择:
1)在每个顶点复制多边形的法线。这是最简单的解决方案,但我觉得它会重复数据,有些不太令人满意。
2)在顶点着色器中,将顶点转换为视图坐标,在片段着色器中,使用计算导数的dFdx()和dFdy()函数计算法线。这些函数由扩展GL_OES_standard_derivatives支持(在使用之前需要检查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)。
参见这个问题的答案: 如何在立方体上获得平坦法线 我的实现可以在这里找到: http://alice.loria.fr/software/geogram/doc/html/index.html 一些在线Web-GL演示可以在这里找到(使用emscripten从C++转换为JavaScript): http://homepages.loria.fr/BLevy/GEOGRAM/

谢谢,通过使用dFdx / dFdy函数,我终于得到了表面法线~! - SSARCandy
2
但在WebGL中,dFdx / dFdy是一个扩展功能,因此需要先声明它。 - SSARCandy
https://developer.mozilla.org/en-US/docs/Web/API/OES_standard_derivatives - SSARCandy
2
modelview * position 不是剪裁空间,而是视图空间。 - gman
只是想让大家知道,使用dx/dy表示法线不仅效率低下,在边缘处也是不正确的,因为dFdx通常会使用中心差分(实际上我认为总是这样,但我不确定),所以每个像素需要43次约来约去,然后还要加上32次乘法计算叉积,对于每个像素(当然,对于任何小的东西你都看不到性能下降,但是),而且当然你会在边缘处遇到伪影,因为那里的位置不是模型的一部分,因此描述了其他对象或根本没有任何东西(在这种情况下远视距)。通过预先计算法线可以避免这种情况。 - LWS SWL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接