Converting Shadertoy Shaders to Vircadia

Hello all,

I had fun translating shadertoy shaders to vircadia. First read this topic on the docs to get a general understanding of shaders and how to use them: Procedural Shaders for Models and Avatars — Vircadia Documentation

The shadertoy shader I converted can be found here: Shader - Shadertoy BETA
notice that you can edit the shader life in shadertoy. Safest thing to do is to change numbers in the code. Make sure the number always has “.” if it is a float. for example 1.0 or 0.5 or .2. Some gpu’s wont accept floats if they dont have a decimal point.

copy paste the code from shadertoy in your favourite texteditor and start changing it. The extension is .fs

things I had to change:

iGlobalTime

this shader uses iTime for the time counter. Vircadia uses iGlobalTime. Replace all iTime in the script with iGlobalTime

Main loop

the main loop in shadertoy is something like this:

void mainImage( out vec4 fragColor, in vec2 fragCoord ) { }

it shows what goes in and out. In vircadia there are 4 different setups (see documentation.) I replaced the shadertoy main loop with:

float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition proceduralData) { }

Screen coordinates

to read the screen coordinates (the in the main loop statement) the shadertoy shader uses: fragCoord:
iResolution is the screen size:

vec2 uv = (fragCoord - iResolution.xy*.5) / iResolution.y;

vircadia uses _texCoord0.st
because we project the shader on an entity instead of a screen we will use iWorldscale. iWorldscale is a vec3 and the texture coordinates are a vec2 that is why we wil use the scale in xy iWorldscale.xy
we will end up with:

vec2 uv = (_texCoord0.st - iWorldScale.xy*.5) / iWorldScale.xy;

shader out

shadertoy outputs:

fragColor = vec4(sqrt(clamp(col, 0., 1.)), 1.);

this is a vec4, the last part is the alpha channel

Vircadia outputs diffuse data without the alpha channel which is a vec3:

proceduralData.diffuse = vec3(sqrt(clamp(col, 0., 1.)));

you need to add return 0.0; just before the last curly bracket.

those are all the changes needed for this particular shader. I have created a JSON file to see how it is setup in vircadia:
https://bas-skyspace.ams3.digitaloceanspaces.com/Shaders/shaderTest.json

it will spawn a sphere called shaderTest and a material called ShaderTestMaterial. The URL to the shader is in the material entity on the material tab.(https://bas-skyspace.ams3.digitaloceanspaces.com/Shaders/combustion.fs)

I hope this is helpful,

happy shading!

5 Likes

That’s great. Was wanting to add a shader based dance floor to madders place, so this will be extremely helpful :smile:

Well, that UV transform really does not do it for me, it’s all flipped and offset :thinking: I used:

vec2 uv = vec2(2*_texCoord0.x-1, -2*_texCoord0.y-1);

But I have no idea if it is “correct”.
Generally, for absract shaders I think it is better to use model or world space, something like:

vec2 uv = (_position.xz * iWorldScale.xz) / iWorldScale.xz;

then it can be put on any shape type without worrying about UV’s

Also, I have learned (the hard way) that iDate.w in shadertoy gives you your local time, but in Vircadia it gives you UTC. arguments can be made for both but it does mean that I can’t make a clock that shows you your time, only one that shows a specific timezone, atleast without some scripty scripting.

My solution now, is to make the clock impossible to read :grinning_face_with_smiling_eyes:
daliClock

https://silverfish-freestuff.s3.eu-north-1.amazonaws.com/index.html?prefix=Shaders/daliClock/

2 Likes