3

我有以下 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)

}

这会按预期在屏幕上正确输出一个三角形:

画布截图
画布截图

请注意,我实际上并没有在这里与透视矩阵进行任何乘法运算。我只是传递一个单位矩阵以表明没有它它可以正常工作。

现在当我换行时:

gl.uniformMatrix4fv(proj_location, false, mat4.identity(mat4.create()))

至:

gl.uniformMatrix4fv(proj_location, false, proj)

我得到一个空的画布。

我浏览了网上的帖子,并尝试了一些建议,比如反转 Z。并摆弄近平面和远平面等。但它总是空输出。

透视矩阵有什么问题?即这里:

mat4.perspective(proj, 0.5, c.width / c.height, 1, 1000)

注意:我使用gl-matrix的 mat4 和 vec3 模块进行矩阵运算。

4

1 回答 1

2

在顶点着色器中,您必须更改行:

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 规范(第 5.10 章向量和矩阵运算),其中明确指出:

例外是矩阵乘以向量、向量乘以矩阵和矩阵乘以矩阵。这些不按分量操作,而是执行正确的线性代数乘法

vec3 v, u;
mat3 m;
u = v * m;

相当于

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]);

u = m * v;

相当于

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;

也可以看看

于 2017-09-25T17:00:22.800 回答