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);
}
}
`;