Как я могу нарисовать несколько фигур в WebGL

#javascript #webgl

#javascript #webgl

Вопрос:

Привет, я пытался одновременно рисовать разные фигуры в WebGL, однако он рисует только первую. Я действительно новичок в WebGL. Я не знаю, проблема в том, что я не использую буферы, поскольку я должен это делать, или шейдеры.

Но я думаю, что я использую разные буферы для каждой фигуры, потому что я передаю функцию «модель», а затем делаю модель.Idbuffer… Поэтому я думаю, что создаю буфер для каждого из них.

Любая помощь приветствуется, спасибо.

Это мой код.

 var gl = null;
var program;

var x = 0;
var y = 0;
var z = 0;
var radi = 0;
var nombre_costats = 100;

var figura = {

  "vertices" : [-0.2, -0.2 , 0.0,
                -0.2, -0.1, 0.0,
                -0.4, -0.1, 0.0,
                -0.4, -0.2, 0.0,
                -0.5, -0.2, 0.0,
                -0.5, 0.0, 0.0,
                -0.2, 0.0, 0.0,
                -0.2, 0.2, 0.0,
                0.3, 0.2, 0.0,
                0.3, 0.0, 0.0,
                0.4, 0.0, 0.0,
                0.4, -0.2, 0.0,
                0.3, -0.2, 0.0,
                0.3, -0.1, 0.0,
                0.1, -0.1, 0.0,
                0.1, -0.2, 0.0,],

  "indices" : [0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 0]

};

var poligon = {

  "vertices" : [],

  "indices" : []

};

function dibuixar_cercle(x, y, z, radi, nombre_costats, poligon){
  
  var nombre_vertex = nombre_costats   2;
  poligon.vertices.push(0);
  poligon.vertices.push(0);
  poligon.vertices.push(0);

  for (var i = 1; i<nombre_vertex; i  ){
    poligon.vertices.push(x   radi * Math.cos( i * (2 * Math.PI) / nombre_costats));
    poligon.vertices.push(y   radi * Math.sin( i * (2 * Math.PI) / nombre_costats));
    poligon.vertices.push(0);
    if (i>=2){
      poligon.indices.push(0);
      poligon.indices.push(i-1);
      poligon.indices.push(i);
    }
  }

}

function getWebGLContext() {

  var canvas = document.getElementById("myCanvas");

  try {
    return canvas.getContext("webgl2");
  }
  catch(e) {
  }

  return null;

}

function initShaders() {

  // paso 1
  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vertexShader, document.getElementById('myVertexShader').text);
  gl.compileShader(vertexShader);

  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fragmentShader, document.getElementById('myFragmentShader').text);
  gl.compileShader(fragmentShader);
  
  // paso 2
  program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  
  // paso 3
  gl.linkProgram(program);

  gl.useProgram(program);

  program.vertexPositionAttribute = gl.getAttribLocation( program, "VertexPosition");
  gl.enableVertexAttribArray(program.vertexPositionAttribute);

}

function initRendering() {

  gl.clearColor(0.0,0.0,1.0,1.0);

}
  
function initBuffers(model) {

  model.idBufferVertices = gl.createBuffer ();
  gl.bindBuffer (gl.ARRAY_BUFFER, model.idBufferVertices);
  gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(model.vertices), gl.STATIC_DRAW);

  model.idBufferIndices = gl.createBuffer ();
  gl.bindBuffer (gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
  gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW);

}

function draw(model) {

  gl.bindBuffer(gl.ARRAY_BUFFER, model.idBufferVertices);
  gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
  gl.drawElements(gl.LINE_LOOP, 32, gl.UNSIGNED_SHORT, 0);
  
}

function draw2(model) {

  gl.bindBuffer(gl.ARRAY_BUFFER, model.idBufferVertices);
  gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
  gl.drawElements(gl.TRIANGLE, nombre_costats*3 , gl.UNSIGNED_SHORT, 0);
  
}

function drawScene() {

  gl.clear(gl.COLOR_BUFFER_BIT);

  draw(figura);
  draw2(poligon);
}

function initWebGL() {
      
  var costats = 100;
  var radi = 0.1;
  var x_centre = 0;
  var y_centre = 0;
  var z_centre = 0;

  gl = getWebGLContext();

  if (!gl) {
    alert("WebGL 2.0 no está disponible");
    return;
  }


  initShaders();
  dibuixar_cercle(x_centre, y_centre, z_centre, radi, costats, poligon);
  console.log(figura);
  initBuffers(figura);
  initBuffers(poligon);
  console.log(poligon);
  
  initRendering();
  
  requestAnimationFrame(drawScene);

}

initWebGL();
```
  

Ответ №1:

В общем, вы должны включить свои шейдеры для вопросов WebGL. Но в любом случае проблема в том, что это gl.TRIANGLES не gl.TRIANGLE

 var gl = null;
var program;

var x = 0;
var y = 0;
var z = 0;
var radi = 0;
var nombre_costats = 100;

var figura = {

  "vertices" : [-0.2, -0.2 , 0.0,
                -0.2, -0.1, 0.0,
                -0.4, -0.1, 0.0,
                -0.4, -0.2, 0.0,
                -0.5, -0.2, 0.0,
                -0.5, 0.0, 0.0,
                -0.2, 0.0, 0.0,
                -0.2, 0.2, 0.0,
                0.3, 0.2, 0.0,
                0.3, 0.0, 0.0,
                0.4, 0.0, 0.0,
                0.4, -0.2, 0.0,
                0.3, -0.2, 0.0,
                0.3, -0.1, 0.0,
                0.1, -0.1, 0.0,
                0.1, -0.2, 0.0,],

  "indices" : [0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 0]

};

var poligon = {

  "vertices" : [],

  "indices" : []

};

function dibuixar_cercle(x, y, z, radi, nombre_costats, poligon){
  
  var nombre_vertex = nombre_costats   2;
  poligon.vertices.push(0);
  poligon.vertices.push(0);
  poligon.vertices.push(0);

  for (var i = 1; i<nombre_vertex; i  ){
    poligon.vertices.push(x   radi * Math.cos( i * (2 * Math.PI) / nombre_costats));
    poligon.vertices.push(y   radi * Math.sin( i * (2 * Math.PI) / nombre_costats));
    poligon.vertices.push(0);
    if (i>=2){
      poligon.indices.push(0);
      poligon.indices.push(i-1);
      poligon.indices.push(i);
    }
  }

}

function getWebGLContext() {

  var canvas = document.getElementById("myCanvas");

  try {
    return canvas.getContext("webgl2");
  }
  catch(e) {
  }

  return null;

}

function initShaders() {

  // paso 1
  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vertexShader, document.getElementById('myVertexShader').text);
  gl.compileShader(vertexShader);

  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fragmentShader, document.getElementById('myFragmentShader').text);
  gl.compileShader(fragmentShader);
  
  // paso 2
  program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  
  // paso 3
  gl.linkProgram(program);

  gl.useProgram(program);

  program.vertexPositionAttribute = gl.getAttribLocation( program, "VertexPosition");
  gl.enableVertexAttribArray(program.vertexPositionAttribute);

}

function initRendering() {

  gl.clearColor(0.0,0.0,1.0,1.0);

}
  
function initBuffers(model) {

  model.idBufferVertices = gl.createBuffer ();
  gl.bindBuffer (gl.ARRAY_BUFFER, model.idBufferVertices);
  gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(model.vertices), gl.STATIC_DRAW);

  model.idBufferIndices = gl.createBuffer ();
  gl.bindBuffer (gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
  gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW);

}

function draw(model) {

  gl.bindBuffer(gl.ARRAY_BUFFER, model.idBufferVertices);
  gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
  gl.drawElements(gl.LINE_LOOP, 32, gl.UNSIGNED_SHORT, 0);
  
}

function draw2(model) {

  gl.bindBuffer(gl.ARRAY_BUFFER, model.idBufferVertices);
  gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
  gl.drawElements(gl.TRIANGLES, nombre_costats*3 , gl.UNSIGNED_SHORT, 0);
  
}

function drawScene() {

  gl.clear(gl.COLOR_BUFFER_BIT);

  draw(figura);
  draw2(poligon);
}

function initWebGL() {
      
  var costats = 100;
  var radi = 0.1;
  var x_centre = 0;
  var y_centre = 0;
  var z_centre = 0;

  gl = getWebGLContext();

  if (!gl) {
    alert("WebGL 2.0 no está disponible");
    return;
  }


  initShaders();
  dibuixar_cercle(x_centre, y_centre, z_centre, radi, costats, poligon);
  //console.log(figura);
  initBuffers(figura);
  initBuffers(poligon);
  //console.log(poligon);
  
  initRendering();
  
  requestAnimationFrame(drawScene);

}

initWebGL();  
 <canvas id="myCanvas"></canvas>
<script id="myVertexShader" type="whatever">
attribute vec4 VertexPosition;
void main() {
  gl_Position = VertexPosition;
}
</script>
<script id="myFragmentShader" type="whatever">
precision highp float;
void main() {
  gl_FragColor = vec4(1, 1, 0, 1);
}
</script>  

Несколько заметок:

  • Нет причин использовать try / catch around canvas.getContext . Эта функция не будет генерировать исключение. Он вернется только null при сбое

  • не принято включать атрибуты вершин во время инициализации.

  • в следующий раз попробуйте опубликовать рабочий фрагмент

  • этот скрипт может помочь найти ошибки. Он бы нашел эту.

    ошибка в drawElements(/UNKNOWN WebGL ENUM/ undefined, 300, UNSIGNED_SHORT, 0): аргумент 0 не определен

    Причина отсутствия ошибок заключается в том, что gl.TRIANGLE не существует, поэтому он заканчивается передачей undefined gl.drawElements . undefined автоматически преобразуется в . 0 0 это то же значение, gl.POINTS что и допустимое значение. Причина, по которой вы ничего не видите, заключается в том, что вам нужно установить gl_PointSize вершинный шейдер, чтобы видеть точки.

    Это приводит к подсказке, которой я часто следую. Никогда не выбирайте 0 в качестве допустимого значения enum. Для чего-то слишком легко случайно передать 0, поэтому, если 0 является допустимым значением, то случайность будет трудно найти. К сожалению, OpenGL выбирает 0 для gl.POINTS и точная проблема потратила впустую время 10 тысяч программистов.

  • Вы можете найти эти статьи полезными.