Как избежать артефактов рендеринга из-за неточных мировых координат в WebGL?

#javascript #three.js #webgl

#javascript #three.js #webgl

Вопрос:

Проблема:

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

Смотрите gif: Артефакты рендеринга

Я предполагаю, что «значение перемещения» 0.05 слишком мало, что вызывает неточности и, следовательно, артефакты рендеринга. Однако я не уверен, как ограничить значение, чтобы оно не вызывало артефактов, потому что значения перемещения зависят от ряда других факторов (масштабирование камеры в сцене, определяемая пользователем скорость перемещения и т.д.).

Было бы прекрасно, если бы сетка перемещалась только при каждом втором перемещении — отметьте, пока она перемещается равномерно.

Есть ли лучшая практика, позволяющая надежно избегать таких артефактов рендеринга?

Контекст:

Я разрабатываю приложение, которое отображает данные изображения на плоскости. Для каждого текселя отображаемой плоскости для рендеринга данных ищется соответствующая мировая координата. Камера ортогональна и смотрит прямо на указанную плоскость. Когда я заметил «колеблющиеся» артефакты рендеринга, я проследил происхождение до (как я предполагаю) неточности в мировых координатах (?).

Минимальный код для воспроизведения

 const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(window.innerWidth / -50, window.innerWidth / 20, window.innerHeight / 50, window.innerHeight / -20, 1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const geometry = new THREE.PlaneGeometry(100, 100, 1, 1);
const material = new THREE.ShaderMaterial({
  vertexShader: `
precision highp float;

varying vec4 worldCoord;

void main() {
  worldCoord = modelMatrix * vec4(position, 1.0);
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
  fragmentShader: `
varying vec4 worldCoord;
void main() {
  gl_FragColor = mod(floor(worldCoord), 2.0) / 2.0; 
}
`
});

const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 5;

let i = 0;
let moveValue = 0.05;
let render = function() {
  i  ;
  if (i % 5 === 0) {
    moveValue *= -1.0;
  }

  cube.position.x  = moveValue;
  camera.position.x  = moveValue;
  
  renderer.render(scene, camera);
};

setInterval(render, 400);  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js"></script>  

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

1. меняется: const renderer = new THREE. WebGLRenderer({antialias: true}); помогает ситуации?

2. К сожалению, нет. Ни одна из antialias явных настроек для true или false не изменяет артефакты.

Ответ №1:

Я думаю, вы можете столкнуться с формой «сглаживания».

Возможно, вы найдете эту статью полезной:

http://madebyevan.com/shaders/grid/

и это:

https://fgiesen.wordpress.com/2011/07/10/a-trip-through-the-graphics-pipeline-2011-part-8/