[SOLVED] Swapping render targets with GPUComputationRenderer

Hi everyone!

First post, but I’ve been a lurker for years. I’m pretty new to GPGPU in general, and hoping I can get a few things cleared up.

First of all, I’m using GPUComputationRenderer to recreate Conways Game of Life, and hopefully from there begin some experimentation with automata. I am following and adapting this tutorial:

https://nullprogram.com/blog/2014/06/10/

So I have my computation renderer working fine, I can confirm fragment shader output from my GPGPU variable. My confusion is focused around utilizing the multiple render targets to achieve the front/back buffer technique described in the above tutorial. I’ve managed to do this in the past using ping-ponging, but it feels like I’m missing something this time around.

Does anyone have some advice or guidance?

Thanks!

 ...

  initComputeRenderer(){
    /*
      the GPUComputationRenderer has two render targets.

      this.gpuCompute.getCurrentRenderTarget(variable)
      this.gpuCompute.getAlternateRenderTarget(variable)
    */
    
    this.gpuCompute = new GPUComputationRenderer(this.GPUWIDTH, this.GPUWIDTH,
      this.manager.renderer);

    let dtautomata = this.gpuCompute.createTexture();
    this.fillAutomataTexture(dtautomata);

    this.automataVariable = this.gpuCompute.addVariable('textureautomata',
      automataShader.frag, dtautomata);

    this.automataUniforms = this.automataVariable.material.uniforms;

    this.automataUniforms['time'] = { value: 0.0 };
    this.automataUniforms['delta'] = { value: 0.0 };
    this.automataUniforms['state'] = { value: null }; 

    this.automataVariable.wrapS = THREE.RepeatWrapping;
    this.automataVariable.wrapT = THREE.RepeatWrapping;

    let error = this.gpuCompute.init();
    if (error !== null) {
      console.error(error);
    }
  }

  setupDebug(){
    this.automata_debug_material = new THREE.MeshBasicMaterial();
    let geometry = new THREE.PlaneBufferGeometry(250, 250, 1);
    let a_mesh = new THREE.Mesh(geometry, this.automata_debug_material);
    this.manager.scene.add(a_mesh);

    this.automata_alt_debug_material = new THREE.MeshBasicMaterial();
    let a_alt_mesh = new THREE.Mesh(geometry, this.automata_alt_debug_material);
    this.manager.scene.add(a_alt_mesh);

    a_mesh.position.x = - 135;
    a_alt_mesh.position.x = 135;
  }

  update(){
    let now = performance.now();
    let delta = (now - this.last) / 1000;

    if(delta > 1) delta = 1;
    this.last = now;

    this.automataUniforms['time'].value = now;
    this.automataUniforms['delta'].value = delta;

    this.gpuCompute.compute();

    let automata_texture = this.gpuCompute.getCurrentRenderTarget(
      this.automataVariable).texture;
    this.automata_debug_material.map = automata_texture;

    let automata_alt_texture = this.gpuCompute.getAlternateRenderTarget(
      this.automataVariable).texture;
    this.automata_alt_debug_material.map = automata_alt_texture;


    // what do I pass for 'state'?
    // this.automataUniforms['state'].value = automata_alt_texture; 
  }

Shader:

const frag = `
  uniform sampler2D state;

  int get(int x, int y) {
    return int(texture2D(state, (gl_FragCoord.xy + vec2(x, y)) / resolution.xy).r);
  }

  void main() {
    int sum = get(-1, -1) +
              get(-1,  0) +
              get(-1,  1) +
              get( 0, -1) +
              get( 0,  1) +
              get( 1, -1) +
              get( 1,  0) +
              get( 1,  1);
    if (sum == 3) {
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    } else if (sum == 2) {
        float current = float(get(0, 0));
        gl_FragColor = vec4(current, current, current, 1.0);
    } else {
        gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
    }
  }
`;

Unfortunately as a new user, I’m unable to delete this post, but I have apparently stumbled into my solution:

  update(){
    let now = performance.now();
    let delta = (now - this.last) / 1000;

    if(delta > 1) delta = 1;
    this.last = now;

    let automata_texture = this.gpuCompute.getCurrentRenderTarget(
      this.automataVariable).texture;
    this.automata_debug_material.map = automata_texture;

    let automata_alt_texture = this.gpuCompute.getAlternateRenderTarget(
      this.automataVariable).texture;
    this.automata_alt_debug_material.map = automata_alt_texture;

    this.automataUniforms['time'].value = now;
    this.automataUniforms['delta'].value = delta;
    this.automataUniforms['state'].value = automata_texture;

    this.gpuCompute.compute();
  }
2 Likes