开始
- 初学webgl,刚学了纹理,然后就想像使用css制作立方体照片效果
- 开始做了六个面都是一样的,没有达到目的,然后就想做六个面不同的
- 谁知道,这一做,做完后头都晕了,但究其原因,就是那些基本的矩阵作用没搞懂,比如这个模型矩阵,就仅仅是操作传入的坐标,而且就算是绘制六个面,使用六组不同的坐标,也只需要传入一个矩阵就可以了,我之前还每次绘制都传了,反而导致了一些问题
- 再就是纹理,按照书上的做法,每次加载完图片后,然后激活纹理单元 绑定纹理对象 配置纹理对象 接着给纹理源数据u_Sampler绑定纹理单元,这一系列操作都是在imge.onload的处理函数中进行的,所以一直没有分开,这就永远没法旋转了,因为旋转必须在外部再使用该纹理对象,并绑定纹理单元,总不可能每次都重新加载图片把,那也是不可能实现的
- 最后旋转,只需要传递一次矩阵,也不知道怎么想的,之前每次绘制都传递矩阵,就出了问题,为什么会出问题之后再看看吧
效果
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>立方体纹理</title>
</head>
<body onload="init()">
<canvas id="canvas" width="600" height="600"></canvas>
<script src="../cuon-matrix.js"></script>
<script type="x-shader/x-vertex" id="shader-vs">
precision lowp float;
uniform mat4 u_MvpMatrix;
attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main(){
gl_Position = u_MvpMatrix * a_Position;
v_TexCoord = a_TexCoord;
}
</script>
<script type="x-shader/x-fragment" id="shader-fs">
precision mediump float;
varying vec2 v_TexCoord;
uniform sampler2D u_Sampler;
void main(){
gl_FragColor=texture2D(u_Sampler,v_TexCoord);
}
</script>
<script>
function init() {
startWebgl()
}
function startWebgl() {
const canvas = document.getElementById('canvas')
const gl = canvas.getContext('webgl')
if (!gl) {
alert('浏览器不支持webgl')
}
gl.enable(gl.DEPTH_TEST)
gl.enable(gl.CULL_FACE)
gl.clearColor(0, 0, 0, 1)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
const vs = document.getElementById('shader-vs').innerText;
const fs = document.getElementById('shader-fs').innerText;
const program = initProgram(gl, vs, fs)
const a_Position = gl.getAttribLocation(program, 'a_Position')
const a_TexCoord = gl.getAttribLocation(program, 'a_TexCoord')
const u_Sampler = gl.getUniformLocation(program, "u_Sampler")
const u_MvpMatrix = gl.getUniformLocation(program, 'u_MvpMatrix')
const mvpMatrix = new Matrix4()
const textureArray = [
0, 1,
0, 0,
1, 1,
1, 0,
]
const textureBuffer = initVerTexBuffer(gl, textureArray)
const indexArray = new Uint8Array([
0, 1, 2, 3,
])
const indexBuffer = gl.createBuffer()
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexArray, gl.STATIC_DRAW)
const facesBuffer = []
const facesArray = [
[
-1, 1, 1,
-1, -1, 1,
1, 1, 1,
1, -1, 1,
],
[
-1, 1, -1,
-1, -1, -1,
-1, 1, 1,
-1, -1, 1,
],
[
1, 1, 1,
1, -1, 1,
1, 1, -1,
1, -1, -1,
],
[
-1, 1, -1,
-1, 1, 1,
1, 1, -1,
1, 1, 1,
], [
-1, -1, 1,
-1, -1, -1,
1, -1, 1,
1, -1, -1,
], [
1, 1, -1,
1, -1, -1,
-1, 1, -1,
-1, -1, -1,
]
]
for (let i = 0; i < facesArray.length; i++) {
facesBuffer[i] = initVerTexBuffer(gl, facesArray[i])
}
let count = 0;
const textures = []
for (let i = 0; i < 6; i++) {
textures[i] = loadTexture(gl, `../img/${i + 1}.jpg`, facesBuffer[i])
}
initMatrix(gl, u_MvpMatrix, mvpMatrix)
let deg = 1
function rotate() {
mvpMatrix.rotate(deg, 1, 1, -1)
changeMatrix(gl, u_MvpMatrix, mvpMatrix)
drawAllTexture(textures)
requestAnimationFrame(rotate)
}
function loadTexture(gl, src, buffer) {
const texture = gl.createTexture()
const img = new Image()
img.src = src
texture.img = img
img.onload = () => {
handleTexture(gl, texture, buffer)
}
return texture
}
function handleTexture(gl, texture, buffer) {
count++
gl.bindTexture(gl.TEXTURE_2D, texture)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.img)
if (count === 6) {
console.log('count: ', count);
drawAllTexture(textures)
}
gl.bindTexture(gl.TEXTURE_2D, null)
}
function drawAllTexture(textures) {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
for (let i = 0; i < textures.length; i++) {
drawTexture(facesBuffer[i], textures[i], a_Position, a_TexCoord)
}
}
function changeMatrix(gl, u_MvpMatrix, mvpMatrix) {
gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements)
}
function drawTexture(buffer, texture, a_Position, a_TexCoord) {
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_Position)
gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer)
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_TexCoord)
gl.activeTexture(gl.TEXTURE0)
gl.bindTexture(gl.TEXTURE_2D, texture)
gl.uniform1i(u_Sampler, 0)
gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_BYTE, 0)
}
}
function initMatrix(gl, u_MvpMatrix, mvpMatrix) {
mvpMatrix.setPerspective(30, 1, 1, 100)
mvpMatrix.lookAt(6, 6, 6, 0, 0, 0, 0, 1, 0)
mvpMatrix.rotate(0, 0, 1, 0)
gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements)
}
function initVerTexBuffer(gl, bufferArray) {
const buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(bufferArray), gl.STATIC_DRAW)
return buffer
}
function initProgram(gl, vs, fs) {
const shaderVs = gl.createShader(gl.VERTEX_SHADER)
const shaderFs = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(shaderVs, vs)
gl.compileShader(shaderVs)
const successVs = gl.getShaderParameter(shaderVs, gl.COMPILE_STATUS)
if (!successVs) {
const error = gl.getShaderInfoLog(shaderVs)
console.log('error: ', error);
alert('shaderVs 创建失败: ', error)
return;
}
gl.shaderSource(shaderFs, fs)
gl.compileShader(shaderFs)
const successFs = gl.getShaderParameter(shaderFs, gl.COMPILE_STATUS)
if (!successFs) {
const error = gl.getShaderInfoLog(shaderFs)
console.log('error: ', error);
alert('shaderFs 创建失败: ', error)
return;
}
const program = gl.createProgram()
gl.attachShader(program, shaderVs)
gl.attachShader(program, shaderFs)
gl.linkProgram(program)
const successPm = gl.getProgramParameter(program, gl.LINK_STATUS)
if (!successPm) {
alert('program 创建失败')
return;
}
gl.useProgram(program)
gl.program = program
return program;
}
</script>
</body>
</html>