After very deep conversation with @ProjectileObjects I was able to figure out how to get smooth speed. Here is the first shader. I also want to mention that Shaders with Persistent buffers will not render properly in https://isf.video
/*{
"CATEGORIES": [
"Generator",
"Animation"
],
"CREDIT": "Converted from Shadertoy by Igor Molochevski with added controls, Smooth speed sollution based on ProjectileObjects advise",
"DESCRIPTION": "Please use DekstopApp, Web ISF App cant render thisFractal Torus with Neon Colors and Rotation Controls",
"INPUTS": [
{
"DEFAULT": [
1,
0,
0,
1
],
"NAME": "color1",
"TYPE": "color"
},
{
"DEFAULT": [
0,
1,
0,
1
],
"NAME": "color2",
"TYPE": "color"
},
{
"DEFAULT": 0.5,
"MAX": 3,
"MIN": -3,
"NAME": "rotateSpeedX",
"TYPE": "float"
},
{
"DEFAULT": 0.3,
"MAX": 3,
"MIN": -3,
"NAME": "rotateSpeedY",
"TYPE": "float"
},
{
"DEFAULT": 0.4,
"MAX": 3,
"MIN": -3,
"NAME": "rotateSpeedZ",
"TYPE": "float"
},
{
"DEFAULT": 1,
"LABEL": "Animation Speed",
"MAX": 10,
"MIN": 0,
"NAME": "speedControl",
"TYPE": "float"
}
],
"ISFVSN": "2",
"PASSES": [
{
"FLOAT": true,
"HEIGHT": 1,
"PERSISTENT": true,
"TARGET": "timeBuffer",
"WIDTH": 1
},
{
"FLOAT": true,
"HEIGHT": 1,
"PERSISTENT": true,
"TARGET": "rotateXBuffer",
"WIDTH": 1
},
{
"FLOAT": true,
"HEIGHT": 1,
"PERSISTENT": true,
"TARGET": "rotateYBuffer",
"WIDTH": 1
},
{
"FLOAT": true,
"HEIGHT": 1,
"PERSISTENT": true,
"TARGET": "rotateZBuffer",
"WIDTH": 1
},
{
"TARGET": "finalOutput"
}
]
}
*/
#define PI 3.14159265359
mat2 rot(float a) {
float s = sin(a), c = cos(a);
return mat2(c, s, -s, c);
}
float sdTorus(vec3 p, vec2 t) {
vec2 q = vec2(length(p.xz) - t.x, p.y);
return length(q) - t.y;
}
float de(vec3 p, float effectiveTime, float effectiveRotX, float effectiveRotY, float effectiveRotZ) {
float t = -sdTorus(p, vec2(2.3, 2.));
p.y += 1.;
float d = 100., s = 2.;
p *= 0.5;
// Modified rotation with XYZ controls using effective rotation values
for(int i = 0; i < 6; i++) {
p.xz *= rot(effectiveRotX);
p.xy *= rot(effectiveRotY);
p.yz *= rot(effectiveRotZ);
p.xz = abs(p.xz);
float inv = 1.0 / clamp(dot(p, p), 0.0, 1.0);
p = p * inv - 1.0;
s *= inv;
d = min(d, length(p.xz) + fract(p.y * 0.05 + effectiveTime * 0.2) - 0.1);
}
return min(d / s, t);
}
float march(vec3 from, vec3 dir, float effectiveTime, float effectiveRotX, float effectiveRotY, float effectiveRotZ) {
float td = 0.0, g = 0.0;
vec3 p;
for(int i = 0; i < 100; i++) {
p = from + dir * td;
float d = de(p, effectiveTime, effectiveRotX, effectiveRotY, effectiveRotZ);
if(d < 0.002) break;
g++;
td += d;
}
float glow = exp(-0.07 * td * td) * sin(p.y * 10.0 + effectiveTime * 10.0);
float pattern = smoothstep(0.3, 0.0, abs(0.5 - fract(p.y * 15.0)));
return mix(pattern * glow, g * g * 0.00008, 0.3);
}
void main() {
vec4 fragColor = vec4(0.0);
if (PASSINDEX == 0) {
// First pass: Update the accumulated time in the persistent buffer
vec4 prevData = texture2D(timeBuffer, vec2(0.5, 0.5));
// Extract previous accumulated time
float accumulatedTime = prevData.r;
// Calculate new accumulated time
float newTime;
if (FRAMEINDEX == 0) {
// Initialize time on first frame
newTime = 0.0;
} else {
// Accumulate time based on speed and frame delta
newTime = accumulatedTime + speedControl * TIMEDELTA;
}
// Store the accumulated time
fragColor = vec4(newTime, 0.0, 0.0, 1.0);
}
else if (PASSINDEX == 1) {
// Second pass: Update the accumulated X rotation
vec4 prevData = texture2D(rotateXBuffer, vec2(0.5, 0.5));
vec4 timeData = texture2D(timeBuffer, vec2(0.5, 0.5));
// Extract previous accumulated rotation
float accumulatedRot = prevData.r;
float effectiveTime = timeData.r;
// Calculate new accumulated rotation
float newRot;
if (FRAMEINDEX == 0) {
// Initialize on first frame
newRot = 0.0;
} else {
// Accumulate rotation based on speed and frame delta
newRot = accumulatedRot + rotateSpeedX * TIMEDELTA * speedControl;
}
// Store the accumulated rotation
fragColor = vec4(newRot, 0.0, 0.0, 1.0);
}
else if (PASSINDEX == 2) {
// Third pass: Update the accumulated Y rotation
vec4 prevData = texture2D(rotateYBuffer, vec2(0.5, 0.5));
vec4 timeData = texture2D(timeBuffer, vec2(0.5, 0.5));
// Extract previous accumulated rotation
float accumulatedRot = prevData.r;
float effectiveTime = timeData.r;
// Calculate new accumulated rotation
float newRot;
if (FRAMEINDEX == 0) {
// Initialize on first frame
newRot = 0.0;
} else {
// Accumulate rotation based on speed and frame delta
newRot = accumulatedRot + rotateSpeedY * TIMEDELTA * speedControl;
}
// Store the accumulated rotation
fragColor = vec4(newRot, 0.0, 0.0, 1.0);
}
else if (PASSINDEX == 3) {
// Fourth pass: Update the accumulated Z rotation
vec4 prevData = texture2D(rotateZBuffer, vec2(0.5, 0.5));
vec4 timeData = texture2D(timeBuffer, vec2(0.5, 0.5));
// Extract previous accumulated rotation
float accumulatedRot = prevData.r;
float effectiveTime = timeData.r;
// Calculate new accumulated rotation
float newRot;
if (FRAMEINDEX == 0) {
// Initialize on first frame
newRot = 0.0;
} else {
// Accumulate rotation based on speed and frame delta
newRot = accumulatedRot + rotateSpeedZ * TIMEDELTA * speedControl;
}
// Store the accumulated rotation
fragColor = vec4(newRot, 0.0, 0.0, 1.0);
}
else if (PASSINDEX == 4) {
// Final pass: Render the fractal using the accumulated values
vec4 timeData = texture2D(timeBuffer, vec2(0.5, 0.5));
vec4 rotXData = texture2D(rotateXBuffer, vec2(0.5, 0.5));
vec4 rotYData = texture2D(rotateYBuffer, vec2(0.5, 0.5));
vec4 rotZData = texture2D(rotateZBuffer, vec2(0.5, 0.5));
// Get the accumulated values
float effectiveTime = timeData.r;
float effectiveRotX = rotXData.r;
float effectiveRotY = rotYData.r;
float effectiveRotZ = rotZData.r;
vec2 uv = (gl_FragCoord.xy / RENDERSIZE.xy) - 0.5;
uv.x *= RENDERSIZE.x / RENDERSIZE.y;
float t = effectiveTime * 0.5;
vec3 from = vec3(cos(t), 0.0, -3.3);
vec3 dir = normalize(vec3(uv, 0.7));
// Apply rotation controls to camera using effectiveRotX
dir.xy *= rot(0.5 * sin(effectiveRotX));
float intensity = march(from, dir, effectiveTime, effectiveRotX, effectiveRotY, effectiveRotZ);
// Color blending with neon effect - properly using color2
vec3 finalColor = mix(
color1.rgb * intensity * 2.0,
color2.rgb * (1.0 - intensity) * 1.5,
smoothstep(0.2, 0.8, intensity)
);
// Add glow based on color2
finalColor += color2.rgb * 0.5 * pow(intensity, 3.0);
fragColor = vec4(finalColor, 1.0);
}
// Output the final color
gl_FragColor = fragColor;
}