我想为每个面部着色编写一个GLSL着色器程序。我的第一次尝试使用flat
插值限定符和激发顶点。我对正常和位置顶点属性使用平面插值,这为我提供了实心绘制表面所需的老式效果。
虽然渲染看起来正确,但着色器程序实际上并没有做正确的工作:
是否可以将照明方程一次应用于三角形的质心,然后将计算出的颜色值用于整个基元?怎么做?
答案 0 :(得分:2)
使用几何着色器,其输入为三角形,其输出为三角形。从顶点着色器传递法线和位置,自己计算质心(通过平均位置),并执行照明,将输出颜色作为输出变量传递给片段着色器,片段着色器只读取并写出来。
答案 1 :(得分:1)
另一种简单的方法是使用屏幕空间位置的导数计算片段着色器中的(屏幕空间)面法线。它实现起来非常简单,甚至表现良好。
我写了一个例子here(需要支持WebGL的浏览器):
顶点:
attribute vec3 vertex;
uniform mat4 _mvProj;
uniform mat4 _mv;
varying vec3 fragVertexEc;
void main(void) {
gl_Position = _mvProj * vec4(vertex, 1.0);
fragVertexEc = (_mv * vec4(vertex, 1.0)).xyz;
}
片段:
#ifdef GL_ES
precision highp float;
#endif
#extension GL_OES_standard_derivatives : enable
varying vec3 fragVertexEc;
const vec3 lightPosEc = vec3(0,0,10);
const vec3 lightColor = vec3(1.0,1.0,1.0);
void main()
{
vec3 X = dFdx(fragVertexEc);
vec3 Y = dFdy(fragVertexEc);
vec3 normal=normalize(cross(X,Y));
vec3 lightDirection = normalize(lightPosEc - fragVertexEc);
float light = max(0.0, dot(lightDirection, normal));
gl_FragColor = vec4(normal, 1.0);
gl_FragColor = vec4(lightColor * light, 1.0);
}