<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>12_平行光和环境光</title>
<script src="../js/three.js"></script>
<!-- 顶点着色器 -->
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uNMatrix;
uniform vec3 uAmbientColor;
uniform vec3 uLightingDirection;
uniform vec3 uDirectionalColor;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
void main(void) {
gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
vec3 transformedNormal = (uNMatrix * vec4(aVertexNormal, 1.0)).xyz;
float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);
vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;
}
</script>
<!-- 片源着色器 -->
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D uSampler;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
void main(void) {
vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a);
}
</script>
<script type="text/javascript">
var start = function () {
// 上下文环境
var canvas = document.getElementById("mycanvas");
var gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
gl.viewport(0, 0, gl.viewportWidth, gl.viewportWidth);
gl.enable(gl.DEPTH_TEST);
// 顶点着色器
var shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, document.getElementById('shader-vs').textContent);
gl.compileShader(shader);
var vertexShader = shader;
// 片源着色器
var shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, document.getElementById('shader-fs').textContent);
gl.compileShader(shader);
var fragmentShader = shader;
// 着色器程序
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
// 获取参数地址
var vertexPositionAttr = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.enableVertexAttribArray(vertexPositionAttr);
var vertexNormalAttr = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(vertexNormalAttr);
var textureCoordAttr = gl.getAttribLocation(shaderProgram, 'aTextureCoord');
gl.enableVertexAttribArray(textureCoordAttr);
var nMatrixUniform = gl.getUniformLocation(shaderProgram, "uNMatrix");
var mvMatrixUniform = gl.getUniformLocation(shaderProgram, 'uMVMatrix');
var ambientColorUniform = gl.getUniformLocation(shaderProgram, 'uAmbientColor');
var lightingDirectionUniform = gl.getUniformLocation(shaderProgram, "uLightingDirection");
var directionalColorUniform = gl.getUniformLocation(shaderProgram, "uDirectionalColor");
var samplerUniform = gl.getUniformLocation(shaderProgram, 'uSampler');
// 顶点位置
var vertices = [
// 前面
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
// 后面
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5,
// 左面
-0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5, 0.5, -0.5,
// 右面
0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
0.5, 0.5, 0.5,
// 上面
-0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5,
// 下面
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, -0.5,
];
var vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// 顶点索引
var vertexIndices = [
// 前面
0, 1, 2,
0, 2, 3,
// 后面
4, 5, 6,
4, 6, 7,
// 左面
8, 9, 10,
8, 10, 11,
// 右面
12, 13, 14,
12, 14, 15,
// 上面
16, 17, 18,
16, 18, 19,
// 下面
20, 21, 22,
20, 22, 23
];
var vertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(vertexIndices), gl.STATIC_DRAW);
// 顶点法线
var vertexNormals = [
// 前面
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
// 后面
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.0, 0.0, -1.0,
// 左面
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
// 右面
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
// 上面
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
// 下面
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, -1.0, 0.0
];
var cubeVertexNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexNormalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexNormals), gl.STATIC_DRAW);
// 纹理坐标
var textureCoords = [
// 前面
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// 后面
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// 左面
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// 右面
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// 上面
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// 下面
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
];
var vertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
// 纹理
var texture = gl.createTexture();
texture.image = new Image();
texture.image.onload = function () {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D, null);
}
texture.image.src = "../image/crate.gif";
// 渲染循环
var x = 0, y = 0, z = 0;
var rotateSpeed = 0.01; // 旋转速度
var scale = 1.0; // 缩放级别
var render = function () {
// 清屏
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// 顶点
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.vertexAttribPointer(vertexPositionAttr, 3, gl.FLOAT, false, 0, 0);
// 顶点法线
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexNormalBuffer);
gl.vertexAttribPointer(vertexNormalAttr, 3, gl.FLOAT, false, 0, 0);
// 纹理坐标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTextureCoordBuffer);
gl.vertexAttribPointer(textureCoordAttr, 2, gl.FLOAT, false, 0, 0);
// 纹理
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.uniform1i(samplerUniform, 0);
// 环境光
gl.uniform3f(ambientColorUniform, 0.5, 0.5, 0.5);
// 平行光
var lightMat = new THREE.Vector3(1.0, 1.0, 1.0);
lightMat.normalize();
lightMat.multiplyScalar(-1);
gl.uniform3fv(lightingDirectionUniform, lightMat.toArray()); // 方向
gl.uniform3f(directionalColorUniform, 1.0, 1.0, 0.0); // 颜色
// 位移矩阵
var mvEuler = new THREE.Euler(x, y, z);
var mvMatrix = new THREE.Matrix4();
mvMatrix.makeRotationFromEuler(mvEuler);
// 缩放矩阵
var scaleMatrix = new THREE.Matrix4();
scaleMatrix.makeScale(scale, scale, scale);
gl.uniformMatrix4fv(mvMatrixUniform, false, scaleMatrix.multiply(mvMatrix).toArray());
// 位移矩阵法线
var normalMatrix = new THREE.Matrix4();
normalMatrix.getInverse(mvMatrix);
normalMatrix.transpose();
gl.uniformMatrix4fv(nMatrixUniform, false, normalMatrix.toArray());
// 绘制
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
x += rotateSpeed;
y += rotateSpeed;
z += rotateSpeed;
requestAnimationFrame(render);
}
// 键盘输入
document.onkeypress = function (event) {
var key = String.fromCharCode(event.keyCode).toLowerCase();
if (key == 'a') {
rotateSpeed += 0.01;
} else if (key == 's') {
rotateSpeed -= 0.01
} else if (key == 'd') {
scale += 0.1;
} else if (key == 'f') {
scale -= 0.1;
}
if (rotateSpeed <= 0.0) {
rotateSpeed = 0.0;
}
if (scale <= 0.0) {
scale = 0.0;
}
if (scale >= 2.0) {
scale = 2.0;
}
}
render();
}
</script>
</head>
<body onload="start();">
<canvas id="mycanvas" style="border: none;" width="500" height="500"></canvas>
</body>
</html>
12、平行光和环境光
创建日期:2024-07-08
更新日期:2025-01-12
简介
一个来自三线小城市的程序员开发经验总结。