WebGL:无需THREE.JS的帮助即可添加镜面光

时间:2018-12-27 21:14:32

标签: glsl webgl shader fragment-shader vertex-shader

我正在Webgl编程中迈出第一步。在this tutorial之后创建了一个简单的设置。设法添加了一些我自己的东西,尽管偶然发现添加了光,尤其是镜面反射光。 如我所料,大多数将在片段着色器中实现,也许还会在顶点着色器和Light模块中实现。这就是我在下面提供的代码。

顶点着色器:

attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
varying vec3 vNormal;
varying vec2 vUv;

void main() {
    vUv = uv;
    vNormal = (model * vec4(normal, 0.)).xyz;
    gl_Position = projection * view * model * vec4(position, 1.);
}

片段着色器:

#ifdef GL_ES
precision highp float;
#endif

uniform vec3 lightDirection;
uniform float ambientLight;
uniform sampler2D diffuse;
varying vec3 vNormal;
varying vec2 vUv;

void main() {
    float lightness = -clamp(dot(normalize(vNormal), normalize(lightDirection)), -1., 0.);
    lightness = ambientLight + (1. - ambientLight) * lightness;
    gl_FragColor = vec4(texture2D(diffuse, vUv).rgb * lightness, 1.);
}

Light.js模块:

function Light () {
  this.lightDirection = new Vector3(-1, -1, -1)
  this.ambientLight = 0.3
}

Light.prototype.use = function (shaderProgram) {
  var dir = this.lightDirection
  var gl = shaderProgram.gl
  gl.uniform3f(shaderProgram.lightDirection, dir.x, dir.y, dir.z)
  gl.uniform1f(shaderProgram.ambientLight, this.ambientLight)
}

非常感谢您在这里提出的建议。预先感谢!

1 个答案:

答案 0 :(得分:2)

最常见和最简单的灯光模型是Phong reflection modelBlinn–Phong model模型。

以下着色器代码基于您的原始代码并实现Blinn–Phong model模型。与您的代码相比,光照计算是在视图空间中完成的,因为镜面反射高光取决于视图位置,该位置在视图空间中为(0,0,0)。因此必须将光的方向转换为可见空间。

顶点着色器

attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

uniform vec3 lightDirection;

varying vec3 vPos;
varying vec3 vNormal;
varying vec2 vUv;
varying vec3 lightDirectionView;

void main() 
{
    lightDirectionView = (view * vec4(lightDirection, 0.)).xyz;

    mat4 modelView = view * model;
    vec4 viewPos   = modelView * vec4(position, 1.0)
    vPos           = viewPos.xyz;
    vUv            = uv;
    vNormal        = (modelView * vec4(normal, 0.)).xyz;
    gl_Position    = projection * viewPos;
}

Fragemnt着色器

#ifdef GL_ES
precision highp float;
#endif

uniform float     shininess;
uniform float     ambientLight;
uniform sampler2D diffuse;

varying vec3 vPos;
varying vec3 vNormal;
varying vec2 vUv;
varying vec3 lightDirectionView;

void main()
{
    vec3  color     = texture2D(diffuse, vUv).rgb;

    vec3  N         = normalize( vNormal );
    vec3  L         = normalize( -lightDirectionView );
    vec3  V         = normalize( -vPos );
    vec3  H         = normalize( V + L );

    float NdotL     = dot(N, L);
    float NdotH     = dot(N, H);

    float kDiffuse  = max(0.0, NdotL);
    // float kSpecular = (shininess + 2.0) * pow(max(0.0, NdotH), shininess) / (2.0 * 3.14159265);
    float kSpecular = pow(max(0.0, NdotH), shininess);

    vec3 light_col  = color * (kDiffuse + kSpecular);
    gl_FragColor    = vec4(light_col, 1.0);
}

统一shininess的值必须为[1,100]范围内的正值。

另请参阅Phong and Gouraud Shading WebGL