在 webgl 中绘制多个对象

Drawing multiple objects in webgl

我是 WebGL 初学者,正在尝试绘制多个对象,我已经渲染了一个,现在要绘制多个。 多对象渲染的教程非常少,我能找到的是这个 link http://webglfundamentals.org/webgl/lessons/webgl-drawing-multiple-things.html

我尝试根据它更改代码但是它不起作用,请有人纠正问题并给出解决方案并解释 那我的尝试有什么问题吗?

我的完整代码是:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script class="WebGL">
        var gl;
        function createProgram(gl, vertexShader, fragmentShader)
        {
            var vs = gl.createShader(gl.VERTEX_SHADER);
            gl.shaderSource(vs, vertexShader);
            gl.compileShader(vs);

            if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
                alert(gl.getShaderInfoLog(vs));
            //////
            var fs = gl.createShader(gl.FRAGMENT_SHADER);
            gl.shaderSource(fs, fragmentShader);
            gl.compileShader(fs);

            if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
                alert(gl.getShaderInfoLog(fs));
            program = gl.createProgram();
            gl.attachShader(program, vs);
            gl.attachShader(program, fs);
            gl.linkProgram(program);
            if (!gl.getProgramParameter(program, gl.LINK_STATUS))
                alert(gl.getProgramInfoLog(program));
            return program;
        }
        function createShaderFromScriptElement(gl , shaderName)
        {
            var Shader = document.getElementById(shaderName).firstChild.nodeValue;
            return Shader;
        }
        function start()
        {
            var canvas = document.getElementById("canvas");
            gl = canvas.getContext("experimental-webgl");
            if (!gl) { alert("error while GL load"); }

              var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
              var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");

              var program = createProgram(gl, vertexShader, fragmentShader);

            gl.useProgram(program);
            var colorMult = gl.getAttribLocation(program, "u_colorMult");
            var colorLocation = gl.getUniformLocation(program, "u_color");


            // Our uniforms for each thing we want to draw
            var sphereUniforms = {
                u_colorMult: [0.5, 1, 0.5, 1],
                u_matrix: makeIdentity(),
            };
            var cubeUniforms = {
                u_colorMult: [1, 0.5, 0.5, 1],
                u_matrix: makeIdentity(),
            };
            var coneUniforms = {
                u_colorMult: [0.5, 0.5, 1, 1],
                u_matrix: makeIdentity(),
            };

            // The translation for each object.
            var sphereTranslation = [0, 0, 0];
            var cubeTranslation = [-40, 0, 0];
            var coneTranslation = [40, 0, 0];


            var sphereXRotation = time;
            var sphereYRotation = time;
            var cubeXRotation = -time;
            var cubeYRotation = time;
            var coneXRotation = time;
            var coneYRotation = -time;

            // ------ Draw the sphere --------

            gl.useProgram(programInfo.program);

            // Setup all the needed attributes.
            setBuffersAndAttributes(gl, programInfo.attribSetters, sphereBufferInfo);

            sphereUniforms.u_matrix = computeMatrix(
                viewMatrix,
                projectionMatrix,
                sphereTranslation,
                sphereXRotation,
                sphereYRotation);

            // Set the uniforms we just computed
            setUniforms(programInfo.uniformSetters, sphereUniforms);

            gl.drawArrays(gl.TRIANGLES, 0, sphereBufferInfo.numElements);

            // ------ Draw the cube --------

            // Setup all the needed attributes.
            setBuffersAndAttributes(gl, programInfo.attribSetters, cubeBufferInfo);

            cubeUniforms.u_matrix = computeMatrix(
                viewMatrix,
                projectionMatrix,
                cubeTranslation,
                cubeXRotation,
                cubeYRotation);

            // Set the uniforms we just computed
            setUniforms(programInfo.uniformSetters, cubeUniforms);

            gl.drawArrays(gl.TRIANGLES, 0, cubeBufferInfo.numElements);

            // ------ Draw the cone --------

            // Setup all the needed attributes.
            setBuffersAndAttributes(gl, programInfo.attribSetters, coneBufferInfo);

            coneUniforms.u_matrix = computeMatrix(
                viewMatrix,
                projectionMatrix,
                coneTranslation,
                coneXRotation,
                coneYRotation);

            // Set the uniforms we just computed
            setUniforms(programInfo.uniformSetters, coneUniforms);

            gl.drawArrays(gl.TRIANGLES, 0, coneBufferInfo.numElements);
        }
    </script>
    <script id="2d-vertex-shader" type="x-shader/x-vertex">
        // Passed in from the vertex shader.
        varying vec4 v_color;
        uniform vec4 u_colorMult;

        void main() 
        {
            gl_FragColor = v_color * u_colorMult;
        }
    </script>

    <script id="2d-fragment-shader" type="x-shader/x-fragment">
        precision mediump float;
        uniform vec4 u_color;

        void main()
        {
        gl_FragColor = u_color;  // green
        }
    </script>
</head>
<body onload="start()">
    <div style="text-align: center">

    </div>
    <table style="width:100%; height: 10%;">       
        <tr>
            <td style="width:200px; max-width:200px; ">
                <canvas id="canvas" width="300" height="300"></canvas>
            </td>
            <td style="width:200px; max-width:200px; background-color:gray; ">
                <canvas id="canvas2" width="300" height="300"></canvas>
            </td>
        </tr>
    </table>
</body>
</html> 

请向我解释解决方案,以便我理解并在未来继续使用。谢谢

GLSL 着色器有 3 种类型的变量:

  • Uniforms 由主机应用程序设置,并在单个绘制调用中在所有 vertices/fragments 中保持不变。
  • 属性 由主机应用按顶点设置,并且只在顶点着色器中读取。
  • Varyings 只会在光栅化器中进行插值后,由顶点着色器写入,并由片段着色器读取。

所以我可以在您的代码中发现一些问题:

  • 您正试图在顶点着色器中读取 "varying",请改用顶点属性。
  • 您正在调用类似 makeIdentity 的函数,但我没有看到它们已声明,请编辑您的页面以引入适当的矩阵库来提供这些函数。
  • 我在这里没有看到任何实际的顶点数据被传递到 WebGL。没有顶点数据什么都不会渲染。

您在问题中链接到的文章有一个 standalone demo,您可以 View source 查看完整的工作示例。请注意,它在顶部引入了一些矩阵数学辅助库,并调用 createCubeVertices 等函数来创建顶点数据。

也可以在那里查看 lesson 2 of Learning WebGL where they apply vertex colors to some polygons. You may want to work your way through all of the lessons

此外,大多数开发人员发现他们不需要从头开始构建自己的 3D 引擎。考虑学习其中一个 existing WebGL frameworks that can hide the low-level details of WebGL. Of these, Three.js 是一个受欢迎的起点。如果您不需要深入了解所有底层细节,这将为您节省大量时间和精力。