2

I'm trying to generate a textue using a Three.WebGLRenderTarget and then access it in a fragment shader in the next stage.

The idea is to run the first stage once to generate a complex and expensive SDF map and then access it in later stages as needed.

At the moment I can generate the test texture if I send it straight to the screen but when i send it to a texture and try to read it I just get a black screen.

I'm guessing it's something simple and appreciate any help.

The test code:

import * as Three from 'three'

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


const buffer = new Three.WebGLRenderTarget(window.innerWidth, window.innerHeight, {
    minFilter: Three.LinearFilter,
    magFilter: Three.LinearFilter,
    stencilBuffer: false,
    depthBuffer: false,
    type: Three.UnsignedByteType
});
buffer.texture.needsUpdate = false;

const camera = new Three.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
)
camera.position.set(0, 0, 1000);

//Buffer scene
const bufferScene = new Three.Scene()

const bufferQuad = new Three.Mesh(
    new Three.PlaneGeometry(2, 2),
    new Three.ShaderMaterial({
        uniforms: {
            u_resolution: { value: new Three.Vector2(window.innerWidth, window.innerHeight) }
        },
        blending: Three.NoBlending,
        vertexShader: vertShader,
        fragmentShader: bufferShader,
        depthWrite: false,
        depthTest: false,
    })
);

bufferScene.add(bufferQuad);


//Screen Scene
const screenScene = new Three.Scene()

const screenQuad = new Three.Mesh(
    new Three.PlaneGeometry(2, 2),
    new Three.ShaderMaterial({
        uniforms: {
            buffer: { value: buffer.texture }
        },
        blending: Three.NoBlending,
        vertexShader: vertShader,
        fragmentShader: screenShader,
        depthWrite: false,
        depthTest: false,

    })
);

screenScene.add(screenQuad);


window.addEventListener('resize', onWindowResize, false)

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
    render(screenScene)
}

function loop() {
    requestAnimationFrame(loop)
    render(screenScene)
}

function render(scene) {
    renderer.render(scene, camera)
}

function main() {
    render(bufferScene);
    loop();
}

main()

And the shaders

const vertShader = `
varying vec2 vUv;

void main(){
    
    vUv=position.xy*.5+.5;
    gl_Position=vec4(position.xy,1.,1.);
}`;

const bufferShader = `
precision highp float;

uniform vec2 u_resolution;

void main(){
    vec2 uv=gl_FragCoord.xy/u_resolution.xy;
    gl_FragColor=vec4(uv,0.,1.);
}`;

const screenShader = `
precision highp float;

uniform sampler2D buffer;
varying vec2 vUv;

void main(){
    
    vec4 texel=texture2D(buffer,vUv);
    gl_FragColor=texel;
}`;

1 Answer 1

1

It seems you set the render target in the renderer. Try to rewrite your main() function like so:

function main() {
    renderer.setRenderTarget(buffer);
    render(bufferScene);
    renderer.setRenderTarget(null);
    loop();
}

Full code:

const vertShader = `
varying vec2 vUv;

void main(){
    
    vUv=position.xy*.5+.5;
    gl_Position=vec4(position.xy,1.,1.);
}`;

const bufferShader = `
precision highp float;

uniform vec2 u_resolution;

void main(){
    vec2 uv=gl_FragCoord.xy/u_resolution.xy;
    gl_FragColor=vec4(uv,0.,1.);
}`;

const screenShader = `
precision highp float;

uniform sampler2D buffer;
varying vec2 vUv;

void main(){
    
    vec4 texel=texture2D(buffer,vUv);
    gl_FragColor=texel;
}`;

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


const buffer = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, {
  minFilter: THREE.LinearFilter,
  magFilter: THREE.LinearFilter,
  stencilBuffer: false,
  depthBuffer: false,
  type: THREE.UnsignedByteType
});
buffer.texture.needsUpdate = false;

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
)
camera.position.set(0, 0, 1000);

//Buffer scene
const bufferScene = new THREE.Scene()

const bufferQuad = new THREE.Mesh(
  new THREE.PlaneGeometry(2, 2),
  new THREE.ShaderMaterial({
    uniforms: {
      u_resolution: {
        value: new THREE.Vector2(window.innerWidth, window.innerHeight)
      }
    },
    blending: THREE.NoBlending,
    vertexShader: vertShader,
    fragmentShader: bufferShader,
    depthWrite: false,
    depthTest: false,
  })
);

bufferScene.add(bufferQuad);


//Screen Scene
const screenScene = new THREE.Scene()

const screenQuad = new THREE.Mesh(
  new THREE.PlaneGeometry(2, 2),
  new THREE.ShaderMaterial({
    uniforms: {
      buffer: {
        value: buffer.texture
      }
    },
    blending: THREE.NoBlending,
    vertexShader: vertShader,
    fragmentShader: screenShader,
    depthWrite: false,
    depthTest: false,

  })
);

screenScene.add(screenQuad);


window.addEventListener('resize', onWindowResize, false)

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
  render(screenScene)
}

function loop() {
  requestAnimationFrame(loop)
  render(screenScene)
}

function render(scene) {
  renderer.render(scene, camera)
}

function main() {
  renderer.setRenderTarget(buffer);
  render(bufferScene);
  renderer.setRenderTarget(null);
  loop();
}

main()
body {
      margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Mugen87, That fixed the test code. Im just trying to plug it into my main code to see if it fixes the problem.
Mugen87 - Still not working in my main code, but that is a lot more complex and atleat the test works now so, Thanks again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.