我正在尝试在 Webgl 中创建一个 3d 立方体,但我正在制作钻石?

问题描述 投票:0回答:1

我是 Webgl 的新手,一直在遵循许多指南来创建一个具有插值颜色的 3d 立方体,颜色被插值并且动画正在运行。但是,我需要的形状是一个 3D 立方体,而不是一个 3D 金字塔,我终究无法弄清楚为什么。

这是我的代码

//Defing Vector shader
var VSHADER_SOURCE = 
'precision mediump float;\n '+
'attribute vec3 vertPosition;\n '+
'attribute vec3 vertColor;\n '+
'uniform mat4 mWorld;\n '+
'uniform mat4 mView;\n '+
'uniform mat4 mProj;\n '+
'varying  vec3 vColor;\n '+
'void main()\n '+
'{\n '+
'  vColor = vertColor;\n '+
'  gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);\n '+
'}'
//Defining Fragment Shader
var FSHADER_SOURCE =
'precision mediump float;\n '+
'varying  vec3 vColor;\n '+
'void main()\n '+
'{\n '+
'  gl_FragColor = vec4(vColor, 1.0);\n '+
'}';

//Defining vertices for rectangular cube
var boxVertices = 
[ // X, Y, Z    
// Front face
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0,

// Back face
-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0,

// Top face
-1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0,

// Bottom face
-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,

// Right face
1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0,

// Left face
-1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0,
];
//Defining indices for rectangular cube
var boxIndices =
[
    0,
    1,
    2,
    0,
    2,
    3, // front
    4,
    5,
    6,
    4,
    6,
    7, // back
    8,
    9,
    10,
    8,
    10,
    11, // top
    12,
    13,
    14,
    12,
    14,
    15, // bottom
    16,
    17,
    18,
    16,
    18,
    19, // right
    20,
    21,
    22,
    20,
    22,
    23, // left
];
//Defining colors for the color buffer
const colors = [
    1.0,1.0,1.0, //white color
    1.0,0.0,0.0, //red color
    0.0,1.0,0.0, //green color
    0.0,0.0,1.0, //blue color
    0.0,0.0,0.0, // black color
    1.0,1.0,1.0, //white color
    1.0,0.0,0.0, //red color
    0.0,1.0,0.0, //green color
    0.0,0.0,1.0, //blue color
    0.0,0.0,0.0, // black color
    1.0,1.0,1.0, //white color
    1.0,0.0,0.0, //red color
    0.0,1.0,0.0, //green color
    0.0,0.0,1.0, //blue color
    0.0,0.0,0.0, // black color
    1.0,1.0,1.0, //white color
    1.0,0.0,0.0, //red color
    0.0,1.0,0.0, //green color
    0.0,0.0,1.0, //blue color
    0.0,0.0,0.0, // black color
    1.0,0.0,0.0, //red color
    0.0,1.0,0.0, //green color
    0.0,0.0,1.0, //blue color
    0.0,0.0,0.0, // black color
];

var angle = 0;

function main() {
    var canvas = document.getElementById('canvas');
    var gl = canvas.getContext('webgl');

    if (!gl) {
        console.log('Your browser does not support WebGL');
    }
    // Initializing shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }
    gl.clearColor(0.5, 0.5, 0.5, 0.9);
    gl.clearDepth(1.0);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    var n = initBuffers(gl,boxVertices,boxIndices,colors);

    var matWorldUniformLocation = gl.getUniformLocation(gl.program, 'mWorld');
    checkLocations(matWorldUniformLocation);
    var matViewUniformLocation = gl.getUniformLocation(gl.program, 'mView');
    checkLocations(matViewUniformLocation);
    var matProjUniformLocation = gl.getUniformLocation(gl.program, 'mProj');
    checkLocations(matProjUniformLocation);
    

    var worldMatrix = mat4.create();
    var viewMatrix = mat4.create();
    var projMatrix = mat4.create();
    
    mat4.lookAt(viewMatrix, [3, 3, 7], //x,y,z
         [0, 0, 0], [0, 1, 0]);
    mat4.perspective(projMatrix, glMatrix.toRadian(20), 1/1, 1, 100);

    gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
    gl.uniformMatrix4fv(matViewUniformLocation, gl.FALSE, viewMatrix);
    gl.uniformMatrix4fv(matProjUniformLocation, gl.FALSE, projMatrix);
    

    var xRotationMatrix = mat4.create();
    var yRotationMatrix = mat4.create();
    var identityMatrix = mat4.create(); 
    function loop() {
        angle = performance.now() / 1000 / 6 * 2 * Math.PI;
        mat4.rotate(yRotationMatrix, identityMatrix, angle, [0, 1, 0]);
        mat4.rotate(xRotationMatrix, identityMatrix, angle / 4, [1, 0, 0]);
        mat4.mul(worldMatrix, yRotationMatrix, xRotationMatrix);
        gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
        gl.clearColor(0.5, 0.5, 0.5, 0.8);
        gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
        gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
    
        requestAnimationFrame(loop);
    };
    requestAnimationFrame(loop);
};

function checkLocations(location){
    if(!location){
        console.log("ERROR: cannot find storage location of " + location);
    }
}

function initBuffers(gl,boxVertices,boxIndices,colors){

    const boxVertexBufferObject = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, boxVertexBufferObject);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(boxVertices), gl.STATIC_DRAW);

    const boxIndexBufferObject = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boxIndexBufferObject);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(boxIndices), gl.STATIC_DRAW);
 

    const colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors),gl.STATIC_DRAW);

    var positionAttribLocation = gl.getAttribLocation(gl.program, 'vertPosition');
    var colorAttribLocation = gl.getAttribLocation(gl.program, 'vertColor');
    gl.vertexAttribPointer(positionAttribLocation, // Attribute location
        3, // Number of elements per attribute
        gl.FLOAT, // Type of elements
        gl.FALSE,
        0, // Size of an individual vertex
        0 // Offset from the beginning of a single vertex to this attribute
    );
    gl.vertexAttribPointer(
        colorAttribLocation, // Attribute location
        3, // Number of elements per attribute
        gl.FLOAT, // Type of elements
        gl.FALSE,
        0,
        0  
    );

    gl.enableVertexAttribArray(positionAttribLocation);
    gl.enableVertexAttribArray(colorAttribLocation);

    // Tell OpenGL state machine which program should be active.
    gl.useProgram(gl.program);
    var n = boxIndices.length;
    return n;
}
javascript glsl webgl
1个回答
0
投票

当您调用

vertexAttribPointer
时,它会从当前绑定的
gl.ARRAY_BUFFER
中读取数据。

在你的代码中你应该绑定你的

boxVertexBufferObject
缓冲区然后调用相应的
gl.vertexAttribPointer(positionAttribLocation...
.

然后你应该绑定你的

colorBuffer
,然后调用相应的
gl.vertexAttribPointer(colorAttribLocation...

您的代码中的错误是您绑定了

boxVertexBufferObject
缓冲区,然后在调用
colorBuffer
之前绑定了
gl.vertexAttribPointer
,有效地覆盖了您需要加载的数据。结果是
colorBuffer
被加载到
vertPosition
vertColor
属性中,这就是为什么你的脸加载不正确。这些面使用
colorBuffer
值作为顶点而不是
boxIndices
值。

<!DOCTYPE html>
<html>

<body>
    <canvas id="canvas"></canvas>
</body>
<script type="module">
    import { glMatrix, mat4 } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm'
    window.mat4 = mat4;
    console.log(mat4)
    //Defing Vector shader
    var VSHADER_SOURCE =
        'precision mediump float;\n ' +
        'attribute vec3 vertPosition;\n ' +
        'attribute vec3 vertColor;\n ' +
        'uniform mat4 mWorld;\n ' +
        'uniform mat4 mView;\n ' +
        'uniform mat4 mProj;\n ' +
        'varying  vec3 vColor;\n ' +
        'void main()\n ' +
        '{\n ' +
        '  vColor = vertColor;\n ' +
        '  gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);\n ' +
        '}'
    //Defining Fragment Shader
    var FSHADER_SOURCE =
        'precision mediump float;\n ' +
        'varying  vec3 vColor;\n ' +
        'void main()\n ' +
        '{\n ' +
        '  gl_FragColor = vec4(vColor, 1.0);\n ' +
        '}';

    //Defining vertices for rectangular cube
    var boxVertices =
        [ // X, Y, Z    
            // Front face
            -1.0, -1.0, 1.0,
            1.0, -1.0, 1.0,
            1.0, 1.0, 1.0,
            -1.0, 1.0, 1.0,

            // Back face
            -1.0, -1.0, -1.0,
            -1.0, 1.0, -1.0,
            1.0, 1.0, -1.0,
            1.0, -1.0, -1.0,

            // Top face
            -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0,

            // Bottom face
            -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,

            // Right face
            1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0,

            // Left face
            -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0,
        ];
    //Defining indices for rectangular cube
    var boxIndices =
        [
            0,
            1,
            2,
            0,
            2,
            3, // front
            4,
            5,
            6,
            4,
            6,
            7, // back
            8,
            9,
            10,
            8,
            10,
            11, // top
            12,
            13,
            14,
            12,
            14,
            15, // bottom
            16,
            17,
            18,
            16,
            18,
            19, // right
            20,
            21,
            22,
            20,
            22,
            23, // left
        ];

    //Defining indices for rectangular cube
    // var boxIndices =
    //     [
    //         0,
    //         1,
    //         2,
    //         // 7,
    //         // 8,
    //         // 9,
    //         4,
    //         5,
    //         6
    //     ];

    //Defining colors for the color buffer
    const colors = [
        1.0, 1.0, 1.0, //white color
        1.0, 0.0, 0.0, //red color
        0.0, 1.0, 0.0, //green color
        0.0, 0.0, 1.0, //blue color
        0.0, 0.0, 0.0, // black color
        1.0, 1.0, 1.0, //white color
        1.0, 0.0, 0.0, //red color
        0.0, 1.0, 0.0, //green color
        0.0, 0.0, 1.0, //blue color
        0.0, 0.0, 0.0, // black color
        1.0, 1.0, 1.0, //white color
        1.0, 0.0, 0.0, //red color
        0.0, 1.0, 0.0, //green color
        0.0, 0.0, 1.0, //blue color
        0.0, 0.0, 0.0, // black color
        1.0, 1.0, 1.0, //white color
        1.0, 0.0, 0.0, //red color
        0.0, 1.0, 0.0, //green color
        0.0, 0.0, 1.0, //blue color
        0.0, 0.0, 0.0, // black color
        1.0, 0.0, 0.0, //red color
        0.0, 1.0, 0.0, //green color
        0.0, 0.0, 1.0, //blue color
        0.0, 0.0, 0.0, // black color
    ];

    var angle = 0;

    function initShaders(gl, vertexSource, fragmentSource) {
        const vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, vertexSource);
        gl.compileShader(vertexShader);
        const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader, fragmentSource);
        gl.compileShader(fragmentShader);
        const program = gl.createProgram();
        gl.attachShader(program, vertexShader);
        gl.attachShader(program, fragmentShader);
        gl.linkProgram(program);
        gl.validateProgram(program);
        if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
            console.error('Link failed: ' + gl.getProgramInfoLog(program));
            console.error('vs info-log: ' + gl.getShaderInfoLog(vertexShader));
            console.error('fs info-log: ' + gl.getShaderInfoLog(fragmentShader));
        }
        gl.useProgram(program);
        gl.program = program;
        return program;
    }

    function main() {
        var canvas = document.getElementById('canvas');
        var gl = canvas.getContext('webgl');

        if (!gl) {
            console.log('Your browser does not support WebGL');
        }
        // Initializing shaders
        if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
            console.log('Failed to intialize shaders.');
            return;
        }
        gl.clearColor(0.5, 0.5, 0.5, 0.9);
        gl.clearDepth(1.0);
        gl.enable(gl.DEPTH_TEST);
        gl.depthFunc(gl.LEQUAL);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        var n = initBuffers(gl, boxVertices, boxIndices, colors);

        var matWorldUniformLocation = gl.getUniformLocation(gl.program, 'mWorld');
        checkLocations(matWorldUniformLocation);
        var matViewUniformLocation = gl.getUniformLocation(gl.program, 'mView');
        checkLocations(matViewUniformLocation);
        var matProjUniformLocation = gl.getUniformLocation(gl.program, 'mProj');
        checkLocations(matProjUniformLocation);


        var worldMatrix = mat4.create();
        var viewMatrix = mat4.create();
        var projMatrix = mat4.create();

        mat4.lookAt(viewMatrix, [3, 3, 7], //x,y,z
            [0, 0, 0], [0, 1, 0]);
        mat4.perspective(projMatrix, glMatrix.toRadian(20), 1 / 1, 1, 100);

        gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
        gl.uniformMatrix4fv(matViewUniformLocation, gl.FALSE, viewMatrix);
        gl.uniformMatrix4fv(matProjUniformLocation, gl.FALSE, projMatrix);


        var xRotationMatrix = mat4.create();
        var yRotationMatrix = mat4.create();
        var identityMatrix = mat4.create();
        function loop() {
            angle = performance.now() / 1000 / 6 * 2 * Math.PI;
            mat4.rotate(yRotationMatrix, identityMatrix, angle, [0, 1, 0]);
            mat4.rotate(xRotationMatrix, identityMatrix, angle / 4, [1, 0, 0]);
            mat4.mul(worldMatrix, yRotationMatrix, xRotationMatrix);
            gl.uniformMatrix4fv(matWorldUniformLocation, gl.FALSE, worldMatrix);
            gl.clearColor(0.5, 0.5, 0.5, 0.8);
            gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
            gl.drawElements(gl.TRIANGLES, boxIndices.length, gl.UNSIGNED_SHORT, 0);

            requestAnimationFrame(loop);
        };
        requestAnimationFrame(loop);
    };

    function checkLocations(location) {
        if (!location) {
            console.log("ERROR: cannot find storage location of " + location);
        }
    }

    function initBuffers(gl, boxVertices, boxIndices, colors) {
        gl.useProgram(gl.program);

        var positionAttribLocation = gl.getAttribLocation(gl.program, 'vertPosition');
        var colorAttribLocation = gl.getAttribLocation(gl.program, 'vertColor');

        gl.enableVertexAttribArray(positionAttribLocation);
        gl.enableVertexAttribArray(colorAttribLocation);

        const boxVertexBufferObject = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, boxVertexBufferObject);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(boxVertices), gl.STATIC_DRAW);

        gl.vertexAttribPointer(positionAttribLocation, // Attribute location
            3, // Number of elements per attribute
            gl.FLOAT, // Type of elements
            false,
            0, // Size of an individual vertex
            0 // Offset from the beginning of a single vertex to this attribute
        );


        const colorBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
        gl.vertexAttribPointer(
            colorAttribLocation, // Attribute location
            3, // Number of elements per attribute
            gl.FLOAT, // Type of elements
            false,
            0,
            0
        );
        const boxIndexBufferObject = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boxIndexBufferObject);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(boxIndices), gl.STATIC_DRAW);

        // Tell OpenGL state machine which program should be active.
        var n = boxIndices.length;
        return n;
    }
    main();
</script>

</html>
© www.soinside.com 2019 - 2024. All rights reserved.