flat shading in webGL

2020-07-17 05:48发布

I'm trying to implement flat-shading in webgl,
I knew that varying keyword in vertex shader will interpolation that value and pass it to fragment shader.

I'm trying to disable interpolation, and I found that flat keyword can do this, but it seems cannot use in webgl?

flat varying vec4 fragColor;

always getting error: Illegal use of reserved word 'flat'

标签: glsl webgl
2条回答
放荡不羁爱自由
2楼-- · 2020-07-17 06:33

I think 'flat' is not supported by the version of GLSL used in WebGL. If you want flat shading, there are several options:

1) replicate the polygon's normal in each vertex. It is the simplest solution, but I find it a bit unsatisfactory to duplicate data.

2) in the vertex shader, transform the vertex in view coordinates, and in the fragment shader, compute the normal using the dFdx() and dFdy() functions that compute derivatives. These functions are supported by the extension GL_OES_standard_derivatives (you need to check whether it is supported by the GPU before using it), most GPUs, including the ones in smartphones, support the extension.

My vertex shader is as follows:

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;  
    }          

and in the associated fragment shader:

#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    

I like this solution because it makes the setup code simpler. A drawback may be that it gives more work to the fragment shader (but with today's GPUs it should not be a problem). If performance is an issue, it may be a good idea to measure it.

3) another possibility is to have a geometry shader (if supported) that computes the normals. In general it is slower (but again, it may be a good idea to measure performance, it may depend on the specific GPU).

See also answers to this question: How to get flat normals on a cube

My implementation is available here: http://alice.loria.fr/software/geogram/doc/html/index.html

Some online web-GL demos are here (converted from C++ to JavaScript using emscripten): http://homepages.loria.fr/BLevy/GEOGRAM/

查看更多
戒情不戒烟
3楼-- · 2020-07-17 06:37

Check out webGL 2. Flat shading is supported. For vertex 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

For fragment shader

#version 300 es
precision mediump float;
flat in vec4 vClr;
out vec4 fragColor;
void main(){
    fragColor = vClr;
}//end main
查看更多
登录 后发表回答