2
votes

I'm trying to establish a full screen quad using a pass thru vertex shader in THREE.js. The quad itself is a plane geometry with dimension (2, 2) located at the origin. It is assigned the ShaderMaterial. The camera is at z = 1 aiming at the quad.

The shaders are quite simple:

Vertex Shader:

void main() {
   gl_Position = vec4( position, 1.0 );
}

Fragment Shader:

void main() {
   gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}

But nothing shows up on screen. This setup is a standard way of render-to-texture, why is it not working in THREE.js?

I've tried plane.frustumCulled = false and changing the clip planes of the camera to no avail.

Any help is appreciated.


Upon further investigation, the reason for not seeing the rendering result is more involved and pointing to some odd behavior in three.js.

I am using a PlaneGeometry with a rotation matrix applied, which is then wrapped by an Object3D with a counter rotation.

var geometry = new THREE.PlaneGeometry(2, 2);
var m4 = new THREE.Matrix4().makeRotationX(Math.PI * 0.5);
geometry.applyMatrix(m4);

var mesh = new THREE.Mesh(geometry, material);
var obj = new THREE.Object3D();
obj.add(mesh);
obj.rotation.x = -Math.PI * 0.5;
scene.add(obj);

This setup seems to throw three.js off and no rendering is shown.


Ok, the rotation got thrown away because it is a part of model view matrix that I ignored in the vertex shader. I've to refact what I'm currently doing.

1
Try making a jsfiddle! There is not enough information here to help you.Brendan Annable
Problem solved, see my comments above.user2566142

1 Answers

3
votes

I'm not sure the exact problem you're having, but here is an example of a working fullscreen quad using the same technique.

var canvas = document.getElementById('canvas');
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true});
var camera = new THREE.PerspectiveCamera(45, canvas.clientWidth / canvas.clientWidth, 1, 1000);
var clock = new THREE.Clock();

var quad = new THREE.Mesh(
  new THREE.PlaneGeometry(2, 2),
  new THREE.ShaderMaterial({
    vertexShader: document.getElementById('vertex-shader').textContent,
    fragmentShader: document.getElementById('fragment-shader').textContent,
    depthWrite: false,
    depthTest: false
  })
);
scene.add(quad);

var box = new THREE.Mesh(
  new THREE.BoxGeometry(50, 50, 50),
  new THREE.MeshBasicMaterial({color: '#000', wireframe: true})
);
scene.add(box);

camera.position.z = 200;

render();

function render() {
  requestAnimationFrame(render);
  
  if (canvas.width !== canvas.clientWidth || canvas.height !== canvas.clientHeight) {
    renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
    camera.aspect = canvas.clientWidth /  canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  
  var dt = clock.getDelta();
  box.rotation.x += dt * 2 * Math.PI / 5;
  box.rotation.y += dt * 2 * Math.PI / 7;
  box.rotation.z += dt * 2 * Math.PI / 11;
  
  renderer.render(scene, camera);
}
html, body, #canvas {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js"></script>
<canvas id="canvas"></canvas>
<script id="vertex-shader" type="x-shader/x-vertex">
  varying vec2 vUv;

  void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
  }
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
  varying vec2 vUv;

  void main() {
    gl_FragColor = vec4(vUv, 0.0, 1.0);
  }
</script>