WebGL окрашивает только самую дальнюю сторону, а не ближайшую - PullRequest
0 голосов
/ 26 января 2019

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

result

Вот так это выглядит. Обратите внимание, что меньшая поверхность находится ближе к глазам, а большие - дальше от глаз. Не обманывайтесь этим изображением. Похоже, шейдер выбрал цвет краев, наиболее удаленных от глаз, и игнорирует лицевые стороны спереди.

Как мне правильно настроить эту работу?

Ниже приведены настройки моего шейдера: Буфер глубины очищается во время инициализации и никогда не используется.

function init(){
  // Retrieve <canvas> element
  var canvas = document.getElementById('webgl');

  // Get the rendering context for WebGL
  gl = getWebGLContext(canvas);
  if (!gl) {
    console.log("lib1.js: init() failed to get WebGL rendering context 'gl'\n");
    console.log("from the HTML-5 Canvas object named 'canvas'!\n\n");
    return;
  }

  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('lib1.js: init() failed to intialize shaders.');
    return;
  }

  bufferSetup(gl);

  // Set the background-clearing color and enable the depth test
  gl.clearColor(0.0, 0.0, 0.0, 1.0);  // black!
  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.CULL_FACE);   // draw the back side of triangles
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}

Спасибо, что Денис указал на это! Я также попытался включить и выключить gl.CULL_FACE, и попытался gl.BACK и gl.FRONT. Ни один из них не работает правильно.

  gl.disable(gl.CULL_FACE);
  // gl.cullFace(gl.BACK)

1 Ответ

0 голосов
/ 27 января 2019

Мы знаем, что система координат CVV, нетрансформированные оси рисования (CVV == объем канонического вида, объем куба +/- 1, который мы изображаем на экране), имеют ПРАВИЛЬНЫЕ координаты с началом координат в центре.куба CVV, x увеличивается вправо, y увеличивается вверх, а z увеличивается наружу по направлению к вашему глазу.Но не обязательно, чтобы фрагменты с БОЛЬШОЙ, БОЛЕЕ ПОЗИТИВНОЙ Z глубиной в CVV рисовались как «ближе» к нам, а фрагменты с МАЛЕНЬКИМ, БОЛЕЕ НЕГАТИВНЫМ Z в том же месте экрана перекрывались.Почему?

WebGL (и OpenGL-ES, и OpenGL) имеет историческую причуду в иначе чувствительном методе для трехмерного рисования: он определяет «глубину» как вычисленное значение в диапазоне от 0,0 до 1,0, и это НЕпросто значение z в координатах CVV.

По умолчанию WebGL определяет глубину как:

  • 0,0 для «наименьшей» глубины, ближайшей к экрану или камере;(z = +1 в CVV)
  • 1.0 для «самой большой» глубины, наиболее удаленной от экрана или камеры;(z = -1 в CVV)

В то время как графический процессор вычисляет глубину автоматически, для правильных результатов требуются вершины, которые были преобразованы с помощью проекционной матрицы 3D-камеры для имитации объектива камеры.Иногда, если мы не определяем или не используем матрицу проекции, вычисление глубины графического процессора уменьшается до:

depth = 0.5 + 0.5*(gl_position.z / gl.position.w);

Другими словами, без этой матрицы «проецирование камеры»GPU вычисляет «глубину» в обратном направлении - вершины at z = -1 получают глубину 0, когда она ДОЛЖНА быть 1. Для получения дополнительной информации о том, как GPU вычисляет глубину, см .: Как WebGL устанавливает значения в буфере глубины?

Известно, что мы могли бы легко это исправить:1030 *;Тогда все значения z, которые мы вычисляем, будут иметь обратный знак.(Это немного грязно в сочетании со сложным графом сцены ...).

Мы могли бы оставить значения z без изменений и вместо этого сказать WebGL применять другие правила для использования буфера глубины.;это более приемлемое решение.Попробуйте добавить эти строки кода
gl.enable(gl.DEPTH_TEST); // enabled by default, but let's be SURE.
gl.clearDepth(0.0);       // each time we 'clear' our depth buffer, set all
                          // pixel depths to 0.0  (1.0 is DEFAULT)
gl.depthFunc(gl.GREATER); // gl.LESS is DEFAULT; reverse it!
                          // draw a pixel only if its depth value is GREATER
                          // than the depth buffer's stored value.

Благодарю моего профессора по компьютерной графике - Джона Э. Тумблина

...