Правильный способ манипулировать буфером глубины для InstancedBufferGeometry, используя RawShaderMaterial WITH TRANSPARENCY в three.js? - PullRequest
0 голосов
/ 30 октября 2019

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

Я пытаюсь настроить (полу) каркасная сетка ячеек (с четырехугольными ребрами, а не с тремя ребрами), которые являются правильными в направлениях x и y, но могут различаться по глубине (направление z). Я хотел бы иметь возможность отображать до 2 миллионов ячеек (это 24 миллиона треугольников, если моя математика верна), и, поскольку каждая ячейка представляет собой разновидность прямоугольной призмы, я использовал InstancedBufferGeometry от Three.js, чтобы позволитьшейдер выполняет тяжелую работу с переводом, масштабированием, цветом и т. д. Барицентрическая функция отлично работает с каркасом. Я хотел бы, чтобы ячейки были полупрозрачными (более непрозрачные провода, менее непрозрачные грани. Они кажутся правильными при просмотре с одной стороны, но непрозрачными при взгляде с другой.

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

  precision lowp float;
  uniform mat4 modelViewMatrix;
  uniform mat4 projectionMatrix;
  uniform vec3 cameraPosition;
  attribute vec3 position;
  attribute vec3 translation;
  attribute vec3 scale;
  attribute vec3 color;
  attribute float near;
  attribute float far;
  attribute vec3 center;
  attribute float colorByDepth;
  vec3 transform(inout vec3 position, vec3 T, vec3 S) {
    position *= S;
    position += T;
    return position;
  }
  varying float vDepth;
  varying vec3 vColor;
  varying vec3 vCenter;
  varying float vColorByDepth;
  void main() {
    vec3 pos = position;
    transform(pos, translation, scale);
    gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 );
    float z = distance(vec4(cameraPosition, 1.0), gl_Position);
    vDepth = (z - near) / (far - near);
    vColor = color;
    vCenter = center;
    vColorByDepth = colorByDepth;
  }

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

  #extension GL_EXT_frag_depth : enable
  precision lowp float;
  varying float vDepth;
  varying vec3 vColor;
  varying vec3 vCenter;
  varying float vColorByDepth;
  float edgeFactorTri() {
    vec3 d = fwidth(vCenter.xyz);
    vec3 a3 = smoothstep(vec3(0.0), d * 1.5, vCenter.xyz);
    return min(min(a3.x, a3.y), a3.z);
  }
  void main() {
    vec4 edgeColor = vec4(vColor, 0.1);
    vec4 faceColor = vec4(vColor, 0.01);
    float edgeFactor = edgeFactorTri();
    vec4 opaqueWhite = vec4(1.0, 1.0, 1.0, 1.0);
    vec4 opaqueBlack = vec4(0.0, 0.0, 0.0, 1.0);
    float depthFactor = vDepth;
    gl_FragColor = vColorByDepth > 0.5 ? mix(opaqueWhite, opaqueBlack, depthFactor) : mix(edgeColor, faceColor, edgeFactor);
    gl_FragDepthEXT = depthFactor;
  }

https://jsfiddle.net/hexwrench/ob04a3xp/138/

Для этой скрипки я включил небольшой примерный набор данных. Ячейки окрашены по глубине верхней части ячейки. Когдамышь находится на вращающейся сетке, ячейки окрашены по глубине от камеры. Обратите внимание, что при просмотре сетки под углом, имеющим форму буквы "c", наблюдается надлежащая прозрачность. Когда сетка просматривается с другой стороныи сетка имеет форму ɔ (спасибо Google), ячейки (неправильно) непрозрачны.

...