ShaderToy using BufferA as input to Buffer A

I’m trying to port a Shader Toy example over to Babylon JS.
I’ve had a lot of success generally, but the ones that I fail with are where you have Buffer chaining AND the Buffer is used as an input to iteself

Example: Shader - Shadertoy BETA

glDrawElements: Source and destination textures of the draw are the same.

Questions: How in Babylon, can I use the output of a shader as input to itself? Do I have to write/copy to a different buffer each time?

Yes and this is a webgl limitation. You have to copy it first

Can you point me to some key functions or examples that might shed some light for me on this?

The overall idea would be to have 2 textures. One source and one destination. At the end of each frame you copy destination to source. You can then always render to destination and always read from source

I think you can avoid the copy by doing a ping pong between 2 buffers A1 and A2: first write to A2 and use A1 as input, next frame write to A1 and use A2 as input. Rinse and repeat.

Thanks for the feedback again.

Can someone just give me a finger hold here, how to gain access to a PostProcess 's output buffer and to bind it to a standalone buffer?

Do you use effect.setTextureFromPostProcess?
or
effect.bindUniformBuffer
?

You should use setTextureFromPostProcess.

Thanks for the help so far. I’m really flunking out however.
I’m trying the ping pong approach, but frequently still getting the same error
Source and destination textures of the draw are the same

Some questions about how I should have this setup:
Is this whats being recommended with two Post process shaders that I try and ping pong?

const shader1 = new BABYLON.PostProcess("BufferA", `fragment`, [], ['iChannel0'], ratio, camera)
const shader2 = new BABYLON.PostProcess("BufferA", `fragment`, [], ['iChannel0'], ratio, camera)

shader1.onApply = (effect) => {
    effect.setTextureFromPostProcess("iChannel0", shader2);
}

shader2.onApply = (effect) => {
    effect.setTextureFromPostProcess("iChannel0", shader1);
}

const final = new BABYLON.PostProcess("ImageA", `final`, [], ['iChannel0'], ratio, camera)
let index = 0
final.onApply = (effect) => {

    effect.setTextureFromPostProcess("iChannel0", index === 0 ? shader1 : shader2);
    index = index == 0 ? 1 : 0
}

or I’m wondering is an alternative is to use the BABYLON.PassPostProcess


const shader1 = new BABYLON.PostProcess("BufferA", `fragment`, [], ['iChannel0'], ratio, camera)
const shaderPassThru = new BABYLON.PassPostProcess("Passthrough", ratio, camera)

shader1.onApply = (effect) => {
    effect.setTextureFromPostProcess("iChannel0", shaderPassThru);
}

const final = new BABYLON.PostProcess("ImageA", `final`, [], ['iChannel0'], ratio, camera)
final.onApply = (effect) => {
    effect.setTextureFromPostProcess("iChannel0", shaderPassThru);
}

You don’t have to use post processes for the ping pong textures, you can use regular textures (RenderTargetTexture). See for eg:

2 Likes

Yummy!

I think I’m really close. Thanks for the help.
playground: https://playground.babylonjs.com/#4C900K#13
original: Shader - Shadertoy BETA

Its really dark (blue on black), but can see the cracks split and separate out. Not sure why the bright components aren’t showing through (I don’t actually understand this shader) but I’ve got some traction at least.

Thanks again.

ShaderToy is using float textures whereas by default RenderTargetTexture are unsigned byte textures. If you use float textures it does work:

3 Likes

Thats a huge unlock for me. Thanks for all your help @Evgeni_Popov :ninja:

1 Like

Hello @Evgeni_Popov and @asdf989

Based on what you said and your playgrounds, I am trying to reproduce this other ShaderToy: Shader - Shadertoy BETA

This is what I did so far and I can’t find out what is wrong or missing:

Can you take a look please?
Have a great day! :wink:

fragCoord is really gl_FragCoord, not vUV. Also, you can replace fragCoord.xy/iResolution.xy by vUV:

2 Likes

I thought I was getting good at shader and for me, it was obvious that fragCoord equals vUV.
I guess I still have things to learn.

To thank you, here is the shader with follow mouse :wink:

So Long, and Thanks for All the Fix

Hi again :wave:

I am now trying to make this effect works with a ShaderMaterial but I can’t manage to have the same result: https://playground.babylonjs.com/#4C900K#34

It should be doable right? :wink:

Here are some typo fixes https://playground.babylonjs.com/#4C900K#36 @PichouPichou you should use spector to troubleshoot some of those :slight_smile:

Also you will need to convert from screen position to texture position for it to work.

1 Like

Thanks @sebavan, Ok I see I forgot the worldViewProjection in the attributes.

I am not familiar with Spector. I am used to debugging shaders with the console errors I have.
How can I open it in the playground, is there documentation?

Spector.js - Chrome Web Store :slight_smile: