WebGLFundamentals.org

Fix, Fork, Contribute

WebGL 天空盒

``````// 填充定义矩形的值给缓冲
function setGeometry(gl) {
var positions = new Float32Array(
[
-1, -1,
1, -1,
-1,  1,
-1,  1,
1, -1,
1,  1,
]);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
}
``````

``````// 告诉位置属性怎么从位置缓冲positionBuffer (ARRAY_BUFFER)中取数据
-var size = 3;          // 每次迭代提取3个单位数据
+var size = 2;          // 每次迭代提取2个单位数据
var type = gl.FLOAT;   // 数据是32位浮点型
var normalize = false; // 不归一化数据
var stride = 0;        // 0 = 移动单位数量 * 每个单位占用内存sizeof(type)
var offset = 0;        // 从缓冲起始位置开始读取
gl.vertexAttribPointer(
positionLocation, size, type, normalize, stride, offset)
``````

``````attribute vec4 a_position;
varying vec4 v_position;
void main() {
v_position = a_position;
gl_Position = a_position;
gl_Position.z = 1;
}
``````

``````precision mediump float;

uniform samplerCube u_skybox;
uniform mat4 u_viewDirectionProjectionInverse;

varying vec4 v_position;
void main() {
vec4 t = u_viewDirectionProjectionInverse * v_position;
gl_FragColor = textureCube(u_skybox, normalize(t.xyz / t.w));
}
``````

``````var skyboxLocation = gl.getUniformLocation(program, "u_skybox");
var viewDirectionProjectionInverseLocation =
gl.getUniformLocation(program, "u_viewDirectionProjectionInverse");
``````

``````// 计算投影矩阵
var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
var projectionMatrix =

// 相机在以原点为圆心直径2个单位的圆上看向原点
var cameraPosition = [Math.cos(time * .1), 0, Math.sin(time * .1)];
var target = [0, 0, 0];
var up = [0, 1, 0];
// 用look at计算相机矩阵。
var cameraMatrix = m4.lookAt(cameraPosition, target, up);

// 由相机矩阵得出视图矩阵。
var viewMatrix = m4.inverse(cameraMatrix);

// 我们只关心方向所以清除移动的部分
viewMatrix[12] = 0;
viewMatrix[13] = 0;
viewMatrix[14] = 0;

var viewDirectionProjectionMatrix =
m4.multiply(projectionMatrix, viewMatrix);
var viewDirectionProjectionInverseMatrix =
m4.inverse(viewDirectionProjectionMatrix);

// 设置全局变量
gl.uniformMatrix4fv(
viewDirectionProjectionInverseLocation, false,
viewDirectionProjectionInverseMatrix);

// 告诉着色器对于u_skybox使用纹理单元0
gl.uniform1i(skyboxLocation, 0);
``````

``````<script id="skybox-vertex-shader" type="x-shader/x-vertex">
...
...
...
...
``````

``````// 设置GLSL程序查找位置
const envmapProgramInfo = webglUtils.createProgramInfo(
const skyboxProgramInfo = webglUtils.createProgramInfo(
``````

``````// 创建缓冲并填充顶点数据
const cubeBufferInfo = primitives.createCubeBufferInfo(gl, 1);
``````

``````// 相机在以原点为圆心直径2个单位的圆上看向原点
var cameraPosition = [Math.cos(time * .1) * 2, 0, Math.sin(time * .1) * 2];
var target = [0, 0, 0];
var up = [0, 1, 0];
// 使用look at计算相机矩阵
var cameraMatrix = m4.lookAt(cameraPosition, target, up);

// 通过相机矩阵创建视图矩阵
var viewMatrix = m4.inverse(cameraMatrix);

// 以x轴旋转立方体
var worldMatrix = m4.xRotation(time * 0.11);

// 我们只关心方向所以清除移动的部分
var viewDirectionMatrix = m4.copy(viewMatrix);
viewDirectionMatrix[12] = 0;
viewDirectionMatrix[13] = 0;
viewDirectionMatrix[14] = 0;

var viewDirectionProjectionMatrix = m4.multiply(
projectionMatrix, viewDirectionMatrix);
var viewDirectionProjectionInverseMatrix =
m4.inverse(viewDirectionProjectionMatrix);
``````

``````// 绘制立方体
gl.useProgram(envmapProgramInfo.program);
webglUtils.setBuffersAndAttributes(gl, envmapProgramInfo, cubeBufferInfo);
webglUtils.setUniforms(envmapProgramInfo, {
u_world: worldMatrix,
u_view: viewMatrix,
u_projection: projectionMatrix,
u_texture: texture,
u_worldCameraPosition: cameraPosition,
});
webglUtils.drawBufferInfo(gl, cubeBufferInfo);
``````

``````// 绘制天空盒
gl.useProgram(skyboxProgramInfo.program);
webglUtils.setUniforms(skyboxProgramInfo, {
u_viewDirectionProjectionInverse: viewDirectionProjectionInverseMatrix,
u_skybox: texture,
});
``````

• 基础概念
• 图像处理
• 二维平移，旋转，缩放和矩阵运算
• 三维
• 光照
• 组织和重构
• 几何
• 纹理
• 渲染到纹理
• 阴影
• 技术
• 建议
• 优化
• 杂项
• 参考

Issue/Bug? 在GitHub上提issue.