Philipp
Philipp

Reputation: 731

How to avoid rendering artifacts due to imprecise world coordinates in WebGL?

Problem:

I'm experiencing rendering artifacts when using the world coordinates within the fragment shader to render a grid. When moving the plane onto which is rendered, the grid does not move uniformly (one "half" moves, while the other doesn't).

See gif: Rendering artifacts

I assume that the "move value" of 0.05 is too small which triggers imprecisions and thus the rendering artifacts. However, I'm not sure how to constrain the value so that it doesn't cause artifacts, because the move values depends on a number of other factors (zoom of the camera into the scene, user defined move speed etc.).

It would be perfectly fine, if the grid only moved on every second move-tick as long as it moves uniformly.

Is there a best practice to avoid such rendering artifacts reliably?

Context:

I'm developing an application which renders image data onto a plane. For each texel of the rendered plane, the corresponding world coordinate is looked up to render the data. The camera is orthographic and looks directly on said plane. When I noticed "wobbling" rendering artifacts, I traced the origin back to (what I assume) to be imprecision in the world coordinates (?).

Minimal code to reproduce

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>

Upvotes: 4

Views: 285

Answers (1)

manthrax
manthrax

Reputation: 5016

I think you may be experiencing a form of "aliasing".

You might find this article useful:

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

and this:

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

Upvotes: 1

Related Questions