Webgl 2 中的透视投影(使用 gl-matrix)不显示任何内容,但没有显示效果很好
Perspective projection (using gl-matrix) in Webgl 2 shows nothing, but without it shows fine
我有以下 javascript 代码:
// convenience function.
function v(x, y, z){
var v = vec3.create();
vec3.set(v, x, y, z);
return v;
}
window.onload = function() {
gl = get_gl('c', {antialias: true})
var vert_shader = make_vertex_shader(gl,
`
in vec3 a_pos;
uniform mat4 u_transform;
uniform mat4 u_camera;
uniform mat4 u_projection;
void main(){
gl_Position = vec4(a_pos.xyz, 1) * u_transform * u_camera * u_projection;
}
`);
var frag_shader = make_fragment_shader(gl,
`
uniform vec4 u_color;
out vec4 frag_color;
void main(){
frag_color = u_color;
}
`)
var program = make_program(gl, vert_shader, frag_shader);
// Triangle
var points = [1, 0, 0,
-1, 0, 0,
0, 1, 0]
var pos_buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, pos_buffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(points), gl.STATIC_DRAW)
// ---------- create a transform matrix..
var point_transform = mat4.create();
mat4.scale(point_transform, point_transform, v(0.5, 1, 1))
// ---------- create a camera matrix
var camera = mat4.create();
mat4.lookAt(camera, v(0, 0, 10), v(0, 0, 0), v(0, 1, 0))
// ---------- create a projection matrix
var proj = mat4.create();
var c = document.querySelector('#c')
mat4.perspective(proj, 0.5, c.width / c.height, 1, 1000)
// ---------- set attribs
var attrib_location = gl.getAttribLocation(program, "a_pos")
gl.vertexAttribPointer(attrib_location, 3, gl.FLOAT, false, 0, 0)
// ---------- set uniforms
gl.useProgram(program)
var color_location = gl.getUniformLocation(program, "u_color")
gl.uniform4fv(color_location, new Float32Array([0.9, 0.9, 0.8, 1]))
var transform_location = gl.getUniformLocation(program, "u_transform")
gl.uniformMatrix4fv(transform_location, false, point_transform)
var camera_location = gl.getUniformLocation(program, "u_camera")
gl.uniformMatrix4fv(camera_location, false, camera)
var proj_location = gl.getUniformLocation(program, "u_projection")
gl.uniformMatrix4fv(proj_location, false, mat4.identity(mat4.create()))
// ---------- setup pre drawing
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
gl.clearColor(0, 0, 0, 0)
gl.clear(gl.COLOR_BUFFER_BIT)
// ---------- do the drawing
gl.enableVertexAttribArray(attrib_location)
gl.drawArrays(gl.TRIANGLES, 0, 3)
}
这会按预期在屏幕上正确输出一个三角形:
canvas
的截图
请注意,我实际上并没有在这里对透视矩阵进行任何乘法运算。我只是传递一个单位矩阵来表明它在没有它的情况下也能正常工作。
现在,当我更改行时:
gl.uniformMatrix4fv(proj_location, false, mat4.identity(mat4.create()))
至:
gl.uniformMatrix4fv(proj_location, false, proj)
我得到一个空 canvas。
我浏览了网上的帖子,并尝试了一些建议,比如反转 Z。摆弄近平面和远平面等。但它始终是空输出。
透视矩阵有什么问题?即这里:
mat4.perspective(proj, 0.5, c.width / c.height, 1, 1000)
注意:我使用 gl-matrix 的 mat4 和 vec3 模块进行矩阵运算。
在顶点着色器中,您必须更改以下行:
gl_Position = vec4(a_pos.xyz, 1) * u_transform * u_camera * u_projection;
至
gl_Position = u_projection * u_camera * u_transform * vec4(a_pos.xyz, 1);
因为,矩阵和向量之间的 GLSL 运算不是可交换的。
请参阅 Khronos GLSL ES Specification (chapter 5.10 Vector and Matrix Operations),其中清楚地写着:
The exceptions
are matrix multiplied by vector, vector multiplied by matrix, and matrix multiplied by matrix. These do
not operate component-wise, but rather perform the correct linear algebraic multiply
vec3 v, u;
mat3 m;
u = v * m;
is equivalent to
u.x = dot(v, m[0]); // m[0] is the left column of m
u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
u.z = dot(v, m[2]);
And
u = m * v;
is equivalent to
u.x = m[0].x * v.x + m[1].x * v.y + m[2].x * v.z;
u.y = m[0].y * v.x + m[1].y * v.y + m[2].y * v.z;
u.z = m[0].z * v.x + m[1].z * v.y + m[2].z * v.z;
另见
我有以下 javascript 代码:
// convenience function.
function v(x, y, z){
var v = vec3.create();
vec3.set(v, x, y, z);
return v;
}
window.onload = function() {
gl = get_gl('c', {antialias: true})
var vert_shader = make_vertex_shader(gl,
`
in vec3 a_pos;
uniform mat4 u_transform;
uniform mat4 u_camera;
uniform mat4 u_projection;
void main(){
gl_Position = vec4(a_pos.xyz, 1) * u_transform * u_camera * u_projection;
}
`);
var frag_shader = make_fragment_shader(gl,
`
uniform vec4 u_color;
out vec4 frag_color;
void main(){
frag_color = u_color;
}
`)
var program = make_program(gl, vert_shader, frag_shader);
// Triangle
var points = [1, 0, 0,
-1, 0, 0,
0, 1, 0]
var pos_buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, pos_buffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(points), gl.STATIC_DRAW)
// ---------- create a transform matrix..
var point_transform = mat4.create();
mat4.scale(point_transform, point_transform, v(0.5, 1, 1))
// ---------- create a camera matrix
var camera = mat4.create();
mat4.lookAt(camera, v(0, 0, 10), v(0, 0, 0), v(0, 1, 0))
// ---------- create a projection matrix
var proj = mat4.create();
var c = document.querySelector('#c')
mat4.perspective(proj, 0.5, c.width / c.height, 1, 1000)
// ---------- set attribs
var attrib_location = gl.getAttribLocation(program, "a_pos")
gl.vertexAttribPointer(attrib_location, 3, gl.FLOAT, false, 0, 0)
// ---------- set uniforms
gl.useProgram(program)
var color_location = gl.getUniformLocation(program, "u_color")
gl.uniform4fv(color_location, new Float32Array([0.9, 0.9, 0.8, 1]))
var transform_location = gl.getUniformLocation(program, "u_transform")
gl.uniformMatrix4fv(transform_location, false, point_transform)
var camera_location = gl.getUniformLocation(program, "u_camera")
gl.uniformMatrix4fv(camera_location, false, camera)
var proj_location = gl.getUniformLocation(program, "u_projection")
gl.uniformMatrix4fv(proj_location, false, mat4.identity(mat4.create()))
// ---------- setup pre drawing
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
gl.clearColor(0, 0, 0, 0)
gl.clear(gl.COLOR_BUFFER_BIT)
// ---------- do the drawing
gl.enableVertexAttribArray(attrib_location)
gl.drawArrays(gl.TRIANGLES, 0, 3)
}
这会按预期在屏幕上正确输出一个三角形:
canvas
请注意,我实际上并没有在这里对透视矩阵进行任何乘法运算。我只是传递一个单位矩阵来表明它在没有它的情况下也能正常工作。
现在,当我更改行时:
gl.uniformMatrix4fv(proj_location, false, mat4.identity(mat4.create()))
至:
gl.uniformMatrix4fv(proj_location, false, proj)
我得到一个空 canvas。
我浏览了网上的帖子,并尝试了一些建议,比如反转 Z。摆弄近平面和远平面等。但它始终是空输出。
透视矩阵有什么问题?即这里:
mat4.perspective(proj, 0.5, c.width / c.height, 1, 1000)
注意:我使用 gl-matrix 的 mat4 和 vec3 模块进行矩阵运算。
在顶点着色器中,您必须更改以下行:
gl_Position = vec4(a_pos.xyz, 1) * u_transform * u_camera * u_projection;
至
gl_Position = u_projection * u_camera * u_transform * vec4(a_pos.xyz, 1);
因为,矩阵和向量之间的 GLSL 运算不是可交换的。
请参阅 Khronos GLSL ES Specification (chapter 5.10 Vector and Matrix Operations),其中清楚地写着:
The exceptions are matrix multiplied by vector, vector multiplied by matrix, and matrix multiplied by matrix. These do not operate component-wise, but rather perform the correct linear algebraic multiply
vec3 v, u;
mat3 m;
u = v * m;
is equivalent to
u.x = dot(v, m[0]); // m[0] is the left column of m
u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
u.z = dot(v, m[2]);
And
u = m * v;
is equivalent to
u.x = m[0].x * v.x + m[1].x * v.y + m[2].x * v.z;
u.y = m[0].y * v.x + m[1].y * v.y + m[2].y * v.z;
u.z = m[0].z * v.x + m[1].z * v.y + m[2].z * v.z;
另见