如何在WebGL中使用Phong Shader?

时间:2017-12-07 00:47:14

标签: javascript webgl shader lighting shading

我正在尝试使用Phong着色照亮基于地球的场景。我目前正在使用Gouraud阴影,这并没有像预期的那样产生球体的真实感。除此之外,我还会看到一个突出显示在顶点,如图所示

here

以下是我场景的相关代码。

照明计算;



<script id="shader-vs" type="x-shader/x-vertex">

attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoordinates;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;

varying vec2 vTextureCoordinates;
varying vec3 vNormalEye;
varying vec4 vPosition;

void main() {
  vNormalEye = normalize(uNMatrix * aVertexNormal);

  vPosition = uMVMatrix * vec4(aVertexPosition,1.0);
  gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition,1.0);
  vTextureCoordinates = aTextureCoordinates;
}

</script>

<script id="shader-fs" type="x-shader/x-fragment">

precision mediump float;

varying vec2 vTextureCoordinates;
varying vec3 vNormalEye;
varying vec4 vPosition;

uniform sampler2D uSampler;

uniform vec3 uAmbientLightColor;
uniform vec3 uLightPosition;
uniform vec3 uDiffuseLightColor;
uniform vec3 uSpecularLightColor;

const float shine = 32.0;

void main() {

  vec3 direction = normalize(-vPosition.xyz + uLightPosition);
  vec3 reflection = reflect(-direction,vNormalEye);

  float rdotv = max(dot(reflection,direction),0.0);
  float specularLightWeighting = pow(rdotv,shine);

  float directionalLightWeighting = max(dot(vNormalEye,uLightPosition),0.0);
  vec3 vLightWeighting = uAmbientLightColor + uDiffuseLightColor * directionalLightWeighting + uSpecularLightColor * specularLightWeighting;

  vec4 textureColor = texture2D(uSampler,vec2(vTextureCoordinates.s,vTextureCoordinates.t));
  gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a);
}
</script>
&#13;
&#13;
&#13;

照明配置;

&#13;
&#13;
function setupLights() {

  var angleDegree = 60;
  var lightDistance = 3.5;//Light intensity
  var angleRadian = angleDegree * Math.PI / 180; //Work out 60 degrees from180 degress
  var xDir = Math.cos(angleRadian);
  var yDir = Math.sin(angleRadian);

  gl.uniform3fv(pwgl.uniformLightPositionLoc, [lightDistance * xDir, lightDistance * yDir, 0.0]);
  gl.uniform3fv(pwgl.uniformAmbientLightColorLoc, [0.4, 0.4, 0.4]);
  gl.uniform3fv(pwgl.uniformDiffuseLightColorLoc, [0.7, 0.7, 0.7]);
  gl.uniform3fv(pwgl.uniformSpecularLightColorLoc, [0.8, 0.8, 0.8]);
}
&#13;
&#13;
&#13;

最好的方法是什么?我需要实施哪种照明计算?

此外,什么类型的阴影最适合球体的真实感?

1 个答案:

答案 0 :(得分:0)

片段着色器

void main() {

// Calculate the vector (L) to the light source
vec3 vectorToLightSource = normalize(uLightPosition - vPositionEye3);
// Calculate N dot L for diffuse lighting
float diffuseLightWeighting = max(dot(vNormalEye,
         vectorToLightSource), 0.0);
// Calculate the reflection vector (R) that is needed for specular light
vec3 reflectionVector = normalize(reflect(
       -vectorToLightSource, vNormalEye));
// Calculate viewVector (v) in eye coordinates as
// (0.0, 0.0, 0.0) - vPositionEye3
vec3 viewVectorEye = -normalize(vPositionEye3);
float rdotv = max(dot(reflectionVector, viewVectorEye), 0.0);
float specularLightWeighting = pow(rdotv, shininess);

// Sum up all three reflection components
vec3 lightWeighting =
			uAmbientLightColor +
			uDiffuseLightColor * diffuseLightWeighting +
			uSpecularLightColor * specularLightWeighting;

// Sample the texture
vec4 texelColor = texture2D(uSampler, vTextureCoordinates);
// modulate texel color with lightweigthing and write as final color
gl_FragColor = vec4(lightWeighting.rgb * texelColor.rgb,
				texelColor.a);
}

顶点着色器

void main() {
// Get vertex position in eye coordinates and send to the fragment shader
vec4 vertexPositionEye4 = uMVMatrix * vec4(aVertexPosition,
					1.0);
vPositionEye3 = vertexPositionEye4.xyz /
					vertexPositionEye4.w;
// Transform the normal to eye coordinates and send to fragment shader
vNormalEye = normalize(uNMatrix * aVertexNormal);

// Transform the geometry
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition,
					1.0);
vTextureCoordinates = aTextureCoordinates;
}