Windows WebGL3DRenderTarget

by Cody Bennett

CSS

body {
  margin: 0;
}

canvas {
  display: block;
}

JavaScript

import * as THREE from 'https://cdn.skypack.dev/[email protected]'

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

const camera = new THREE.Camera()

const geometry = new THREE.BufferGeometry()
geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array([-1, -1, 3, -1, -1, 3]), 2))
geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array([0, 0, 2, 0, 0, 2]), 2))

const layerMaterial = new THREE.ShaderMaterial({
  fragmentShader: /* glsl */ `
    void main() {
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
  `,
})

const mesh = new THREE.Mesh(geometry, layerMaterial)
mesh.frustumCulled = false

let layerTexture

const gpuGeneration = true

if (gpuGeneration) {
  const rt = new THREE.WebGL3DRenderTarget(1, 1, 1)
  layerTexture = rt.texture

  renderer.setRenderTarget(rt, 0)
  renderer.render(mesh, camera)
  renderer.setRenderTarget(null)
} else {
  const rt = new THREE.WebGLRenderTarget(1, 1)
  const data = new Uint8Array(4)

  renderer.setRenderTarget(rt)
  renderer.render(mesh, camera)
  renderer.readRenderTargetPixels(rt, 0, 0, 1, 1, data)
  renderer.setRenderTarget(null)

  layerTexture = new THREE.Data3DTexture(data, 1, 1, 1)
  layerTexture.needsUpdate = true
}

layerTexture.format = THREE.RedFormat
layerTexture.minFilter = THREE.LinearFilter
layerTexture.magFilter = THREE.LinearFilter

const material = new THREE.ShaderMaterial({
  uniforms: {
    layerTexture: { value: layerTexture },
  },
  vertexShader: /* glsl */ `
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = vec4(position, 1);
    }
  `,
  fragmentShader: /* glsl */ `
    precision highp sampler3D;

    varying vec2 vUv;
    uniform sampler3D layerTexture;

    void main() {
      float dist = texture(layerTexture, vec3(vUv, 0.0)).r;
      gl_FragColor.rgb = dist > 0.0 ? vec3(0, dist, 0) : vec3(-dist, 0, 0);
      gl_FragColor.a = 1.0;
    }
 ...