纹理与光照
纹理映射
纹理映射是将2D图像应用到3D模型表面的技术。
加载纹理
JAVASCRIPT1function loadTexture(gl, url) { 2 const texture = gl.createTexture(); 3 gl.bindTexture(gl.TEXTURE_2D, texture); 4 5 // 设置默认像素(在图片加载前显示) 6 const level = 0; 7 const internalFormat = gl.RGBA; 8 const width = 1; 9 const height = 1; 10 const border = 0; 11 const srcFormat = gl.RGBA; 12 const srcType = gl.UNSIGNED_BYTE; 13 const pixel = new Uint8Array([0, 0, 255, 255]); 14 15 gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, 16 width, height, border, srcFormat, srcType, 17 pixel); 18 19 const image = new Image(); 20 image.onload = function() { 21 gl.bindTexture(gl.TEXTURE_2D, texture); 22 gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, 23 srcFormat, srcType, image); 24 25 // 检查图片尺寸是否为2的幂 26 if (isPowerOf2(image.width) && isPowerOf2(image.height)) { 27 gl.generateMipmap(gl.TEXTURE_2D); 28 } else { 29 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 30 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 31 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 32 } 33 }; 34 image.src = url; 35 36 return texture; 37} 38 39function isPowerOf2(value) { 40 return (value & (value - 1)) == 0; 41}
光照模型
Phong光照模型
Phong光照模型包含三个分量:
- 环境光(Ambient): 模拟间接光照
- 漫反射(Diffuse): 模拟直接光照
- 镜面反射(Specular): 模拟高光
GLSL1// 顶点着色器 2attribute vec3 aPosition; 3attribute vec3 aNormal; 4attribute vec2 aTexCoord; 5 6uniform mat4 uModelViewMatrix; 7uniform mat4 uProjectionMatrix; 8uniform mat4 uNormalMatrix; 9 10varying vec3 vNormal; 11varying vec3 vPosition; 12varying vec2 vTexCoord; 13 14void main() { 15 vec4 position = uModelViewMatrix * vec4(aPosition, 1.0); 16 vPosition = position.xyz; 17 vNormal = mat3(uNormalMatrix) * aNormal; 18 vTexCoord = aTexCoord; 19 gl_Position = uProjectionMatrix * position; 20}
GLSL1// 片段着色器 2precision mediump float; 3 4varying vec3 vNormal; 5varying vec3 vPosition; 6varying vec2 vTexCoord; 7 8uniform sampler2D uTexture; 9uniform vec3 uLightPosition; 10uniform vec3 uAmbientLight; 11uniform vec3 uDiffuseLight; 12uniform vec3 uSpecularLight; 13 14void main() { 15 vec3 normal = normalize(vNormal); 16 vec3 lightDir = normalize(uLightPosition - vPosition); 17 vec3 viewDir = normalize(-vPosition); 18 vec3 reflectDir = reflect(-lightDir, normal); 19 20 // 环境光 21 vec3 ambient = uAmbientLight; 22 23 // 漫反射 24 float diff = max(dot(normal, lightDir), 0.0); 25 vec3 diffuse = diff * uDiffuseLight; 26 27 // 镜面反射 28 float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0); 29 vec3 specular = spec * uSpecularLight; 30 31 vec3 lighting = ambient + diffuse + specular; 32 vec4 texColor = texture2D(uTexture, vTexCoord); 33 34 gl_FragColor = vec4(texColor.rgb * lighting, texColor.a); 35}
多重纹理
GLSL1uniform sampler2D uBaseTexture; 2uniform sampler2D uDetailTexture; 3 4void main() { 5 vec4 baseColor = texture2D(uBaseTexture, vTexCoord); 6 vec4 detailColor = texture2D(uDetailTexture, vTexCoord * 2.0); 7 gl_FragColor = baseColor * detailColor; 8}