Webgl раскрашивает всю геометрию?

#webgl

#webgl

Вопрос:

Я использую треугольники (используя вершины и положение граней) для рисования графики.Я сохраняю информацию о цвете для каждой вершины и применяю цвета соответствующим образом. Но проблема в том, что все геометрии в моей сцене имеют один цвет (скажем, конус = красный, цилиндр = синий). ИТАК, сохранение цвета для каждой вершины, по-видимому, бесполезно для меня.

Есть ли у них какой-либо другой подход, с помощью которого в webgl можно выполнить раскрашивание, помимо хранения информации о цвете каждой вершины в сцене. Может быть, что-то вроде раскрашивания всей геометрии (скажем, конуса).

Комментарии:

1. Что вы пробовали? Вот пример, в котором используется другой цвет для каждой грани с использованием цветов вершин , а вот другой меньший образец, который делает то же самое. Или, может быть, вам не нужны цвета вершин? Из вашего вопроса неясно. WebGL не требует ничего конкретного. Если вам не нужен цвет вершин, напишите шейдер, который их не использует, или отключите атрибут для цветов.

2. @gman ~ проблема заключается в сохранении и привязке цвета для каждой вершины. Поскольку количество вершин в любой геометрии (объекте) будет БОЛЬШИМ. И хотя каждая вершина имеет один и тот же цвет, я должен сохранить ее значение в буфере. В любом случае я использовал равномерную переменную для раскрашивания всей геометрии, и это сработало для меня.

3. Вам не нужно сохранять цвет вершины для каждой вершины. (а) вы можете просто использовать другой шейдер, который не использует цвета вершин, или (б) вы можете отключить атрибут для используется для цвета вершин с gl.disableVertexAttribArray помощью, и вы можете установить постоянное значение для атрибута с gl.vertexAttrib4f помощью .

4. Это кажется интересным, можете ли вы предоставить ссылки на любой пример. Я новичок в webgl:(.

Ответ №1:

Из вашего вопроса ясно, что вы, возможно, еще не совсем понимаете WebGL? Возможно, вы захотите ознакомиться с этими руководствами.

WebGL использует шейдеры, эти шейдеры используют любые входные данные, которые вы определяете, и выводят все, что вы им указываете для вывода. Это означает, что WebGL не требует цвета вершин. Цвета вершин — это то, что вы выбираете при написании своих шейдеров. Если вы не хотите использовать цвета вершин, не пишите шейдер, который ссылается на цвета вершин.

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

вершинный шейдер:

 attribute vec4 a_position; 
attribute vec4 a_color;     // vertex colors

varying vec4 v_color;       // so we can pass the colors to the fragment shader

uniform mat4 u_matrix;

void main() {
   gl_Position = u_matrix * a_position;
   v_color = a_color;
}
  

фрагментный шейдер:

 precision mediump float;

varying vec4 v_color;

void main() {
  gl_FragColor = v_color;
}
  

Теперь все, что вам нужно сделать, чтобы использовать постоянный цвет, это отключить атрибут for a_color и установить постоянное значение gl.vertexAttrib4f примерно так

 // at init time
var a_colorLocation = gl.getAttribLocation(program, "a_color";

// at draw time
gl.disableVertexAttribArray(a_colorLocation);    // turn off the attribute
gl.vertexAttrib4f(a_colorLocation, r, g, b, a);  // supply a constant color
  

Обратите внимание, что отключение атрибута 0 замедлит работу WebGL на настольных компьютерах, потому что если различия между OpenGL и OpenGL ES. Возможно a_colorLocation , это атрибут 0. Чтобы избежать этой проблемы, свяжите свои местоположения атрибутов ПЕРЕД тем, как связать свою программу. В частности, поскольку вы всегда будете использовать позицию (которая в приведенном выше примере называется «a_position»), просто привяжите ее к местоположению 0 следующим образом

 ..compile shaders..
..attach shaders to program..

// Must happen before you call linkProgram
gl.bindAttribLocation(program, 0, "a_position");

gl.linkProgram(program);

...check for errors, etc...
  

Это заставит атрибут для «a_position» быть атрибутом 0, поэтому вы всегда будете его включать.

Вот пример

 function main() {
  var canvas = document.getElementById("c");
  var gl = canvas.getContext("webgl");
  if (!gl) {
      alert("no WebGL");
      return;
  }

  // NOTE:! This function binds attribute locations
  // based on the indices of the second array
  var program = twgl.createProgramFromScripts(
      gl, 
      ["vshader", "fshader"], 
      ["a_position", "a_color"]);  // a_position will get location 0
                                   // a_color will get location 1

  var a_positionLoc = 0;
  var a_colorLoc = 1;
  var u_matrixLoc = gl.getUniformLocation(program, "u_matrix");

  gl.useProgram(program);

  var verts = [
        1,  1,  
       -1,  1,  
       -1, -1, 
        1,  1, 
       -1, -1, 
        1, -1,  
  ];

  var colors = [
    255, 0, 0, 255,
    0, 255, 0, 255,
    0, 0, 255, 255,

    255, 255, 0, 255,
    0, 255, 255, 255,
    255, 0, 255, 255,
  ];    

  var positionBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
  gl.enableVertexAttribArray(a_positionLoc);
  gl.vertexAttribPointer(a_positionLoc, 2, gl.FLOAT, false, 0, 0);

  var colorBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(colors), gl.STATIC_DRAW);
  gl.enableVertexAttribArray(a_colorLoc);
  gl.vertexAttribPointer(a_colorLoc, 4, gl.UNSIGNED_BYTE, true, 0, 0);

  // Draw in the bottom right corner
  gl.uniformMatrix4fv(
      u_matrixLoc,
      false,
      [0.5, 0, 0, 0,
       0, 0.5, 0, 0,
       0, 0, 1, 0,
       -0.5, -0.5, 0, 1]);

  gl.drawArrays(gl.TRIANGLES, 0, 6);


  // Now turn off the a_color attribute and supply a solid color

  gl.disableVertexAttribArray(a_colorLoc);
  var r = 0.5;
  var g = 1;
  var b = 0.5;
  var a = 1;
  gl.vertexAttrib4f(a_colorLoc, r, g, b, a); // greenish

  // Draw in the top left corner
  gl.uniformMatrix4fv(
      u_matrixLoc,
      false,
      [0.5, 0, 0, 0,
       0, 0.5, 0, 0,
       0, 0, 1, 0,
       0.5, 0.5, 0, 1]);

  gl.drawArrays(gl.TRIANGLES, 0, 6);
};
main();  
 canvas { border: 1px solid black; }  
 <script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
<script id="vshader" type="whatever">
    attribute vec4 a_position;
    attribute vec4 a_color;
    
    varying vec4 v_color;
    
    uniform mat4 u_matrix;
    
    void main() {
        gl_Position = u_matrix * a_position;
        v_color = a_color;
    }    
</script>
<script id="fshader" type="whatever">
precision mediump float;
varying vec4 v_color;
void main() {
    gl_FragColor = v_color;
}
</script>
<canvas id="c" width="300" height="300"></canvas>  

Ответ №2:

Если ваша геометрия имеет цвет для каждого объекта, который не изменяется по всей геометрии, тогда вы должны передать этот цвет в качестве переменной uniform .

Таким образом, вы получаете только один атрибут — положение вершин, несколько матриц формы — скажем, матрицы модели, представления, проекции, для вершинного шейдера и одну векторную однородную переменную для фрагментного шейдера для «затенения» объекта.