【发布时间】:2021-08-19 17:12:43
【问题描述】:
在css中我可以使用perspective + matrix3d来实现3d变换的透视效果。
例如:
transform: perspective(500px) rotateY(45deg);
等于
matrix3d(0.707107, 0, -0.707107, 0.00141421, 0, 1, 0, 0, 0.707107, 0, 0.707107, -0.00141421, 0, 0, 0, 1)
<div style="display:inline-block;background: linear-gradient(#F00, #00F);width:100px;height:100px;transform:perspective(300px)rotateY(45deg)"></div>
<div style="display:inline-block;background: linear-gradient(#F00, #00F);width:100px;height:100px;transform:matrix3d(0.707107, 0, -0.707107, 0.00141421, 0, 1, 0, 0, 0.707107, 0, 0.707107, -0.00141421, 0, 0, 0, 1)"></div>
同样在webgl中使用这个矩阵,渲染了一个矩形(2个三角形),但是没有透视的效果。
function initShaders(gl, vshader, fshader) {
let program = createProgram(gl, vshader, fshader);
if (!program) {
return false;
}
gl.useProgram(program);
gl.program = program;
return true;
}
function createProgram(gl, vshader, fshader) {
let vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
let fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
if (!vertexShader || !fragmentShader) {
return null;
}
let program = gl.createProgram();
if (!program) {
return null;
}
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
let linked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linked) {
let error = gl.getProgramInfoLog(program);
gl.deleteProgram(program);
gl.deleteShader(fragmentShader);
gl.deleteShader(vertexShader);
return null;
}
return program;
}
function loadShader(gl, type, source) {
let shader = gl.createShader(type);
if (shader == null) {
return null;
}
gl.shaderSource(shader, source);
gl.compileShader(shader);
let compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compiled) {
let error = gl.getShaderInfoLog(shader);
console.error('Failed to compile shader: ' + error);
gl.deleteShader(shader);
return null;
}
return shader;
}
let canvas = document.querySelector('#canvas');
let gl = canvas.getContext('webgl');
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
let vSource = `attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_color;
uniform mat4 u_matrix;
void main() {
gl_Position = u_matrix * a_position;
v_color = a_color;
}`;
let fSource = `precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}`;
if (!initShaders(gl, vSource, fSource)) {
console.error('init error');
}
let pointBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
0.5, -0.5,
-0.5, 0.5,
0.5, 0.5,
]), gl.STATIC_DRAW);
let a_position = gl.getAttribLocation(gl.program, 'a_position');
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_position);
let colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0, 0, 1, 1,
0, 0, 1, 1,
1, 0, 0, 1,
0, 0, 1, 1,
1, 0, 0, 1,
1, 0, 0, 1,
]), gl.STATIC_DRAW);
let a_color = gl.getAttribLocation(gl.program, 'a_color');
gl.vertexAttribPointer(a_color, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_color);
let u_matrix = gl.getUniformLocation(gl.program, 'u_matrix');
// same matrix as css above
gl.uniformMatrix4fv(u_matrix, false, new Float32Array([
0.707107, 0, -0.707107, 0.00141421, 0, 1, 0, 0, 0.707107, 0, 0.707107, -0.00141421, 0, 0, 0, 1
]));
gl.drawArrays(gl.TRIANGLES, 0, 6);
<canvas id="canvas" style="height: 200px;width: 200px"></canvas>
我应该如何在webgl中获得一个与css变换矩阵具有等效效果的矩阵?
最后,我应该注意到我已经阅读了WebGL 3D Perspective,但毕竟,我仍然对这个问题感到困惑。
【问题讨论】:
标签: javascript html css webgl css-transforms