如何在WebGL中执行颜色素材跟踪

时间:2013-12-02 18:49:45

标签: webgl

我知道要在OpenGL中使用以下代码执行此操作:

glDisable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);

如何在WebGL中模拟它?

1 个答案:

答案 0 :(得分:0)

这是一个blinn-phong着色器,它模拟每个顶点光照的OpenGL固定功能管道。默认情况下,这相当于启用了glEnable(GL_COLOR_MATERIAL)和glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE)。您可以通过将制服设置为1.0来模拟glColorMaterial,这将导致材质参数跟踪当前颜色而不是glMaterial设置的颜色。

#version 120

////////////////////////////////////////////////////////////////////////////////
// http://www.glprogramming.com/red/chapter05.html                            //
//                                                                            //
// color = (matEmission + globalAmbient * matAmbient) +                       //
//         AttenuationFactor( 1.0 / ( Kc + Kl*d + Kq*d^2 ) ) *                //
//         [ (lightAmbient * matAmbient) +                                    //
//           (max(N.L,0) * lightDiffuse * matDiffuse) +                       //
//           (max(N.H,0)^matShininess * lightSpecular * matSpecular) ]        //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Uniforms                                                                   //
////////////////////////////////////////////////////////////////////////////////
uniform float uColorMaterialAmbient = 1.0;
uniform float uColorMaterialDiffuse = 1.0;
uniform float uColorMaterialEmission = 0.0;
uniform float uColorMaterialSpecular = 0.0;

////////////////////////////////////////////////////////////////////////////////
// Main                                                                       //
////////////////////////////////////////////////////////////////////////////////
void main(void)
{
    vec4 matAmbient = mix(gl_FrontMaterial.ambient, gl_Color, uColorMaterialAmbient);
    vec4 matDiffuse = mix(gl_FrontMaterial.diffuse, gl_Color, uColorMaterialDiffuse);
    vec4 matEmission = mix(gl_FrontMaterial.emission, gl_Color, uColorMaterialEmission);
    vec4 matSpecular = mix(gl_FrontMaterial.specular, gl_Color, uColorMaterialSpecular);

    // Transform normal into eye space. gl_NormalMatrix is the transpose of the
    // inverse of the upper leftmost 3x3 of gl_ModelViewMatrix.
    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);

    // Calculate emission and global ambient light
    vec4 emissionAmbient = matEmission + (gl_LightModel.ambient * matAmbient);

    // Calculate ambient
    vec4 lightAmbient = gl_LightSource[0].ambient * matAmbient;

    // Transform the vertex into eye space
    vec4 eyeVertex = gl_ModelViewMatrix * gl_Vertex;
    vec3 eyeLightDir = gl_LightSource[0].position.xyz - eyeVertex.xyz;
    float dist = length(eyeLightDir);
    eyeLightDir = normalize(eyeLightDir);

    // No attenuation for a directional light
    float attenuationFactor = 1.0 / (gl_LightSource[0].constantAttenuation
                                   + gl_LightSource[0].linearAttenuation * dist
                                   + gl_LightSource[0].quadraticAttenuation * dist * dist);

    // Calculate lambert term
    float NdotL = max(dot(eyeNormal, eyeLightDir), 0.0);

    // Calculate diffuse
    vec4 lightDiffuse = NdotL * (gl_LightSource[0].diffuse * matDiffuse);

    // Calculate specular
    vec4 lightSpecular = vec4(0.0);
    if ( NdotL > 0.0 )
    {
        float NdotHV = max(dot(eyeNormal, gl_LightSource[0].halfVector.xyz), 0.0);
        lightSpecular = pow(NdotHV, gl_FrontMaterial.shininess) * (gl_LightSource[0].specular * matSpecular);
    }

    gl_FrontColor = emissionAmbient + attenuationFactor * (lightAmbient + lightDiffuse + lightSpecular);
    gl_Position = ftransform();
}