2015-10-18 3 views
2

Я начинаю WebGL и пытаюсь нарисовать несколько объектов, я уже отобрал один, теперь перейдя на несколько. Есть очень меньше учебника для рендеринга нескольких объектов, то один, что я смог найти по этой ссылке http://webglfundamentals.org/webgl/lessons/webgl-drawing-multiple-things.htmlРисование нескольких объектов в webgl

Я попытался изменить код в соответствии с ним, но он не работает, Может кто-то пожалуйста исправить проблемы и дать решение с объяснением что что-то не так в моей попытке?

Мой полный код:

<!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> 

Пожалуйста, объясните мне решение, так что я буду понимать, и это останется со мной на будущее. Благодаря

ответ

1

GLSL шейдеры имеют 3 типа переменных:

  • Обмундирование устанавливаются принимающим приложением и остаются неизменными во всех вершин/фрагментов в одном вызове отрисовки.
  • Атрибуты устанавливаются per-vertex приложением-хозяином и читаются только в вершинном шейдере.
  • Varyings только написан на вершинным шейдером и считывается фрагментарным шейдером после интерполяции в растеризаторе.

Так вот некоторые проблемы, я могу пятно в вашем коде:

  • Вы пытаетесь читать «меняющийся» в вершинном шейдере, использовать вершину атрибут.
  • Вы вызываете такие функции, как makeIdentity, но я не вижу их объявленных, отредактируйте вашу страницу, чтобы потянуть в соответствующую библиотеку матриц для предоставления этих функций.
  • Я не вижу никаких фактических данных вершин, передаваемых здесь в WebGL. Ничего не будет представлено без данных вершин.

В статье вы связаны в вашем вопросе есть standalone demo, что вы можете View source на, чтобы увидеть полный рабочий пример. Обратите внимание, что он втягивает некоторые библиотеки математических вспомогательных матриц вверху и вызывает функции типа createCubeVertices для создания данных вершин.

Также обратите внимание на lesson 2 of Learning WebGL, где они применяют цвета вершин к некоторым полигонам. Вы можете проделать свой путь через all of the lessons.

Кроме того, большинство разработчиков считают, что им не нужно создавать собственный 3D-движок с нуля. Рассмотрите возможность изучения одного из existing WebGL frameworks, который может скрывать детали WebGL на низком уровне. Из них Three.js - популярное место для начала. Если вам не нужно глубокое понимание всех деталей низкого уровня, это сэкономит вам много времени и сил.