--[[--/* ExtrudedFibonacciZoom.fuse Based on https://www.shadertoy.com/view/sfVGDG a WebGL shader created by Shane. Converted to DCTL and embeddet into a Lua Fuse by JiPi (https://www.youtube.com/c/JiPi_YT). Place this file in your Fusion's and/or DaVinci Resolve's 'Fuses/' folder to use it. */--]]-- -- /* local ShaderFuse = require("Shaderfuse/ShaderFuse") ShaderFuse.init() -- // ------------------------------------------------------------------------ -- // Registry declaration -- // ------------------------------------------------------------------------ FuRegisterClass(ShaderFuse.FuRegister.Name, CT_SourceTool, { ShaderFuse.FuRegister.Attributes, REG_NoObjMatCtrls = true, REG_NoMotionBlurCtrls = true, REG_Source_GlobalCtrls = false, REG_Source_SizeCtrls = true, REG_Source_AspectCtrls = true, REG_Source_DepthCtrls = true, REG_OpNoMask = true, REG_TimeVariant = true, }) -- // ------------------------------------------------------------------------ -- // DCTL kernel parameters -- // ------------------------------------------------------------------------ -- */ ShaderParameters = [[ float iResolution[2]; float iTime; float iMouse[4]; int iFrame; bool DarkEdges; bool CamOpt; bool CamForward; bool TexCol; bool OptCurvature; bool Tex2; bool CurveOn; bool AMB; float Color1[4]; float Color2[4]; float Color3[4]; float Roughness[4]; float Color4[4]; float ViewDXY[2]; float ViewDZ; float ViewXY[2]; float ViewZ; float TexXY[2]; float TexScale; float Type; float Rough; float FresRef; float OverallColor; float Glow; int width,height; int compOrder; ]] -- /* -- // ------------------------------------------------------------------------ -- DCTL kernel compatibility code -- // ------------------------------------------------------------------------ -- */ ShaderCompatibilityCode = [[ #if defined(DEVICE_IS_METAL) #define in #define out thread #define inout thread #else #define in #define out #define inout #endif #undef USE_NATIVE_METAL_IMPL #undef USE_NATIVE_CUDA_IMPL #undef USE_NATIVE_OPENCL_IMPL // 0 to use the generic implementations; 1 for Metal, OpenCL, Cuda specific code if existing #if 1 #if defined(DEVICE_IS_METAL) #define USE_NATIVE_METAL_IMPL 1 #elif defined(DEVICE_IS_CUDA) #define USE_NATIVE_CUDA_IMPL 1 #elif defined(DEVICE_IS_OPENCL) #define USE_NATIVE_OPENCL_IMPL 1 #endif #endif #if defined(USE_NATIVE_METAL_IMPL) #define swi2(A,a,b) (A).a##b #define swi3(A,a,b,c) (A).a##b##c #define swi2S(a,b,c,d) a.b##c = d #else #define swi2(A,a,b) to_float2((A).a,(A).b) #define swi3(A,a,b,c) to_float3((A).a,(A).b,(A).c) #define swi2S(a,b,c,d) {float2 tmp = d; (a).b = tmp.x; (a).c = tmp.y;} #endif // ---------------------------------------------------------------------------------------------------------- // mat2 implementation // ---------------------------------------------------------------------------------------------------------- #if defined(USE_NATIVE_METAL_IMPL) typedef float2x2 mat2; #define to_mat2(A,B,C,D) mat2((A),(B),(C),(D)) #define mul_mat2_mat2(A,B) ((A)*(B)) #define mul_f2_mat2(A,B) ((A)*(B)) #define mul_mat2_f2(A,B) ((A)*(B)) #else typedef struct { float2 r0; float2 r1; } mat2; __DEVICE__ inline mat2 to_mat2 ( float a, float b, float c, float d) { mat2 t; t.r0.x = a; t.r0.y = b; t.r1.x = c; t.r1.y = d; return t; } __DEVICE__ inline mat2 mul_mat2_mat2( mat2 a, mat2 b) { mat2 t; t.r0.x = a.r0.x * b.r0.x + a.r0.y * b.r1.x; t.r0.y = a.r0.x * b.r0.y + a.r0.y * b.r1.y; t.r1.x = a.r1.x * b.r0.x + a.r1.y * b.r1.x; t.r1.y = a.r1.x * b.r0.y + a.r1.y * b.r1.y; return t; } __DEVICE__ inline float2 mul_f2_mat2( float2 v, mat2 m ) { float2 t; t.x = v.x*m.r0.x + v.y*m.r0.y; t.y = v.x*m.r1.x + v.y*m.r1.y; return t; } __DEVICE__ inline float2 mul_mat2_f2( mat2 m, float2 v ) { float2 t; t.x = v.x*m.r0.x + v.y*m.r1.x; t.y = v.x*m.r0.y + v.y*m.r1.y; return t; } #endif // end of mat2 implementation // ---------------------------------------------------------------------------------------------------------- // mat3 implementation // ---------------------------------------------------------------------------------------------------------- #if defined(USE_NATIVE_METAL_IMPL) typedef float3x3 mat3; __DEVICE__ inline mat3 to_mat3( float a, float b, float c, float d, float e, float f, float g, float h, float i) { return mat3(a,b,c,d,e,f,g,h,i); } __DEVICE__ inline mat3 to_mat3_f3( float3 a, float3 b, float3 c ) { return mat3(a,b,c); } __DEVICE__ inline float3 mul_mat3_f3( mat3 B, float3 A) { return (B*A); } __DEVICE__ inline mat3 mul_mat3_mat3( mat3 A, mat3 B) { return (A*B); } #else typedef struct { float3 r0; float3 r1; float3 r2; } mat3; __DEVICE__ inline mat3 to_mat3( float a, float b, float c, float d, float e, float f, float g, float h, float i) { mat3 t; t.r0.x = a; t.r0.y = b; t.r0.z = c; t.r1.x = d; t.r1.y = e; t.r1.z = f; t.r2.x = g; t.r2.y = h; t.r2.z = i; return t; } __DEVICE__ inline mat3 to_mat3_f3( float3 A, float3 B, float3 C) { mat3 D; D.r0 = A; D.r1 = B; D.r2 = C; return D; } __DEVICE__ inline float3 mul_mat3_f3( mat3 B, float3 A) { float3 C; C.x = A.x * B.r0.x + A.y * B.r1.x + A.z * B.r2.x; C.y = A.x * B.r0.y + A.y * B.r1.y + A.z * B.r2.y; C.z = A.x * B.r0.z + A.y * B.r1.z + A.z * B.r2.z; return C; } __DEVICE__ mat3 mul_mat3_mat3( mat3 B, mat3 A) { float r[3][3]; float a[3][3] = {{A.r0.x, A.r0.y, A.r0.z}, {A.r1.x, A.r1.y, A.r1.z}, {A.r2.x, A.r2.y, A.r2.z}}; float b[3][3] = {{B.r0.x, B.r0.y, B.r0.z}, {B.r1.x, B.r1.y, B.r1.z}, {B.r2.x, B.r2.y, B.r2.z}}; for( int i = 0; i < 3; ++i) { for( int j = 0; j < 3; ++j) { r[i][j] = 0.0f; for( int k = 0; k < 3; ++k) { r[i][j] = r[i][j] + a[i][k] * b[k][j]; } } } mat3 R = to_mat3(r[0][0], r[0][1], r[0][2], r[1][0], r[1][1], r[1][2], r[2][0], r[2][1], r[2][2]); return R; } #endif // end of mat3 implementation #if defined(USE_NATIVE_METAL_IMPL) #define fract_f2(A) fract(A) #define fract_f3(A) fract(A) #define mod_f(a,b) fmod((a),(b)) #define sin_f3(i) sin(i) #define cos_f3(i) cos(i) #define tanh_f3(i) tanh(i) #define abs_f2(a) _fabs(a) #define abs_f3(a) _fabs(a) #define pow_f3(a,b) pow(a,b) #else #if defined(USE_NATIVE_OPENCL_IMPL) #define reflect(I,N) (I-2.0f*dot(N,I)*N) #define fract(a) ((a)-_floor(a)) // oder Pointer bauen: gentype fract(gentype x, gentype *itpr) #define fract_f2(A) to_float2(fract((A).x),fract((A).y)) #define fract_f3(A) to_float3(fract((A).x),fract((A).y),fract((A).z)) #define mod_f(a,b) _fmod(a,b) #define sin_f3(i) sin(i) #define cos_f3(i) cos(i) #define tanh_f3(i) tanh(i) #define abs_f2(a) fabs(a) #define abs_f3(a) fabs(a) #define pow_f3(a,b) pow(a,b) #else // Generic #if defined(DEVICE_IS_OPENCL) __DEVICE__ float3 reflect(float3 I, float3 N) {return I - 2.0f * dot(N, I) * N;} #endif #define fract(a) ((a)-_floor(a)) #define fract_f2(A) to_float2(fract((A).x),fract((A).y)) #define fract_f3(A) to_float3(fract((A).x),fract((A).y),fract((A).z)) #define mod_f(a,b) ((a)-(b)*_floor((a)/(b))) #define sin_f3(i) to_float3( _sinf((i).x), _sinf((i).y), _sinf((i).z)) #define cos_f3(i) to_float3( _cosf((i).x), _cosf((i).y), _cosf((i).z)) #define tanh_f3(i) to_float3(_tanhf((i).x), _tanhf((i).y), _tanhf((i).z)) #define abs_f2(a) to_float2(_fabs((a).x), _fabs((a).y)) #define abs_f3(a) to_float3(_fabs((a).x), _fabs((a).y),_fabs((a).z)) #define pow_f3(a,b) to_float3(_powf((a).x,(b).x),_powf((a).y,(b).y),_powf((a).z,(b).z)) #endif #endif __DEVICE__ float4 decube_f3(__TEXTURE2D__ t, float3 xyz) { float ax=_fabs(xyz.x); float ay=_fabs(xyz.y); float az=_fabs(xyz.z); if (xyz.x>0.0f && ax>=ay && ax>=az) // +X, Face 0, right return _tex2DVecN(t,(-xyz.z/ax+1.0f)/8.0f + 0.5f,(xyz.y/ax+1.0f)/6.0f + (1.0f/3.0f),15); if (xyz.y>0.0f && ay>=ax && ay>=az) // +Y, Face 2, top return _tex2DVecN(t,(xyz.x/ay+1.0f)/8.0f + 0.25f,(-xyz.z/ay+1.0f)/6.0f + (2.0f/3.0f),15); if (xyz.z>0.0f && az>=ax && az>=ay) // +Z, Face 4, front return _tex2DVecN(t,(xyz.x/az+1.0f)/8.0f + 0.25f,(xyz.y/az+1.0f)/6.0f + (1.0f/3.0f),15); if (xyz.x<0.0f && ax>=ay && ax>=az) // -X, Face 1, left return _tex2DVecN(t,(xyz.z/ax+1.0f)/8.0f,(xyz.y/ax+1.0f)/6.0f + (1.0f/3.0f),15); if (xyz.y<0.0f && ay>=ax && ay>=az) // -Y, Face 3, bottom return _tex2DVecN(t,(xyz.x/ay+1.0f)/8.0f + 0.25f,(xyz.z/ay+1.0f)/6.0f,15); if (xyz.z<0.0f && az>=ax && az>=ay) // -Z, Face 5, back return _tex2DVecN(t,(-xyz.x/az+1.0f)/8.0f + 0.75f,(xyz.y/az+1.0f)/6.0f + (1.0f/3.0f),15); return to_float4(1.0f,0.0f,0.0f,1.0f); // error } ]] -- /* -- // ------------------------------------------------------------------------ -- DCTL kernel implementation -- // ------------------------------------------------------------------------ -- */ ShaderKernelCode = [[ // ---------------------------------------------------------------------------------- // - Common - // ---------------------------------------------------------------------------------- #define texture(ch,uv) _tex2DVecN(ch, (uv).x, (uv).y, 15) union A2F { float4 F; //32bit float float A[4]; //32bit Array }; // PI and 2PI. #define PI 3.14159265358979f #define TAU 6.28318530718f // The so-called golden ratio. #define PHI ((1.0f + _sqrtf(5.0f))/2.0f) // Standard 2D rotation formula. __DEVICE__ mat2 rot2(in float a){ float c = _cosf(a), s = _sinf(a); return to_mat2(c, s, -s, c); } // Hash without Sine -- Dave Hoskins // https://www.shadertoy.com/view/4djSRW // 1 out, 2 in... __DEVICE__ float hash21(float2 p) { p = fract_f2(p*to_float2(623.34f, 456.21f)); p += dot(p, p + 145.123f); return fract(p.x*p.y); } // A slight variation on one of Dave Hoskins's hash functions, // which you can find here: // // Hash without Sine -- Dave Hoskins // https://www.shadertoy.com/view/4djSRW // 1 out, 3 in... __DEVICE__ float hash31(float3 p3) { p3 = fract_f3(p3*to_float3(0.6031f, 0.5030f, 0.4973f)); p3 += dot(p3, swi3(p3,z,y,x) + 43.527f); return fract((p3.x + p3.y) * p3.z); } //////////////// // Unsigned distance to the segment joining "a" and "b". __DEVICE__ float distLine(float2 p, float2 a, float2 b){ p -= a; b -= a; float h = clamp(dot(p, b)/dot(b, b), 0.0f, 1.0f); return length(p - b*h); } // IQ's 2D box formula. __DEVICE__ float sBoxS(in float2 p, in float2 b, in float rf){ float2 d = abs_f2(p) - b + rf; return _fminf(_fmaxf(d.x, d.y), 0.0f) + length(_fmaxf(d, to_float2_s(0.0f))) - rf; } // Commutative smooth maximum function. Provided by Tomkh, and taken // from Alex Evans's (aka Statix) talk: // http://media.lolrus.mediamolecule.com/AlexEvans_SIGGRAPH-2015.pdf // Credited to Dave Smith @media molecule. __DEVICE__ float smax(float a, float b, float k){ float f = _fmaxf(0.0f, 1.0f - _fabs(b - a)/k); return _fmaxf(a, b) + k*0.25f*f*f; } #ifdef GLOB ///////////////////////// // Global scale. Not absolutely necessary to have one, but // it's here. The ratio doesn't have to be 1 to 1, but I // think it looks neater this way. const float2 gSc = to_float2(1, 1); // Vertex holder. Not used here. //mat4x2 vP; // Iteration number and quad number. int gI, quad; // Global zoom. float gZoom; // Cell coordinates and a final scale value that I've hacked //in at the last minute... I'll tidy up the logic later. :) float2 gP, gSc2; // This is a copy of the direction ray. If you create a pattern that // relies on rotating coordinates, the direction ray needs to rotate // in unison. Traversals can be annoying to code sometimes, but the // benefits are worth the effort. float2 svRd; #endif // The Fibonacci routine. This is very similar to a regular Fibonacci rectangle // partitioning; The only difference is that four rectangles are joined together // to give the impression that you're zooming toward a central inflection point. // __DEVICE__ float3 distField(float2 p, inout int *quad, inout int *gI, inout float2 *svRd, inout float2 *gP, inout float2 *gSc2, float2 gSc, float gZoom){ // 2D coordinate copy. float2 svP = p; //Get the quadrant. Clockwise from the bottom left. *quad = p.x<0.0f? p.y<0.0f? 0 : 1 : p.y<0.0f? 3 : 2; // The following is just some space manipulation to rotate on rectangle // around itself four times. Each rectangle is then subdivided to // produce the pattern you see. // Central coordinate ID, of sorts. float2 ip = to_float2(-1, -1)*gSc*0.5f*to_float2(_sqrtf(5.0f), 1); // Rotating space and shifting coordinates.. p = mul_mat2_f2(rot2( PI/2.0f*(float)(*quad)),p); ip = mul_mat2_f2(rot2(-PI/2.0f*(float)(*quad)),ip); // Rotating the direction ray to match the rotating coordinates. *svRd = mul_mat2_f2(rot2(PI/2.0f*(float)(*quad)), *svRd); // Shifing back. p -= to_float2(-1, -1)*gSc*0.5f*to_float2(_sqrtf(5.0f), 1); // Global cell coordinate copy. *gP = p; //////////// // Subdivsion of rectangles. Because we're used repeat space tricks // above, we only need subdivide one rectangle, and not all four. // Staring scale. float2 sc = gSc; // Distance variable. float d = 1e5f; // Initializing the iteration variable to zero. *gI = 0; // Direction and translation variables. float2 dir = to_float2(0, 0); float2 ph2 = to_float2(PHI/2.0f, PHI/2.0f - 1.0f); // Subdivision: Perform the minimum you can get away with. // This is a pretty common fractal-like subdivision. Partition, // rotate, scale, then continue the process. for(int i = 0; i<16; i++){ // The rectangle (square) distance for this cell. float2 ap = abs_f2(p) - sc/2.0f; float dI = _fmaxf(ap.x, ap.y); // If we're inside this rectangle, obtain the distance, // then set the required variables, such as scale, local // coordinates, ID, vertices, and so forth. if(dI<0.0f){ d = sBoxS(p, sc/2.0f - 0.0f, sc.x*0.2f); // Box distance. *gI = i; // Iteration number. *gSc2 = sc; // Overall scale for this object. *gP = p; // Cell coordinates. // Vertices. Not used here. //vP = mat4x2(to_float2(-0.5f)*sc, to_float2(-0.5f, 0.5f)*sc, // to_float2_s(0.5f)*sc, to_float2(0.5f, -0.5f)*sc); break; } // If we're not inside the cell we need, keep subdividing. // Turn the direction each iteration. dir = mul_mat2_f2(rot2(PI/2.0f*(float)(i%4)),to_float2(1, 1)); dir *= sc*ph2; // Translate and rotate the ID to match. ip += mul_mat2_f2(rot2(-PI/2.0f*(float)(*quad)),dir); // Quarter spiral turn each iteration. ph2 = swi2(ph2,y,x)*to_float2(-1, 1); // Translate. p -= dir; // Reduce the scale by the golder ratio factor. sc /= PHI; ////////////// } // Return the distance value of the closed rectangular block // and it's cell center, which doubles as a unique ID. By the // way, you could also return the the tile center and dimensions, // if you wished to render other things. d /= gZoom; return to_float3(d, ip.x, ip.y); } //////////////////////////////// // Bidirectional Reflectance Distribution Function (BRDF). // // If you want a quick crash course in BRDF, see the following: // Microfacet BRDF: Theory and Implementation of Basic PBR Materials // https://www.youtube.com/watch?v=gya7x9H3mV0&t=730s // // Surface geometry function. __DEVICE__ float GGX_Schlick(float nv, float rough) { //float r = rough; // original float r = 0.5f + 0.5f*rough; // Disney remapping. float k = (r*r)/2.0f; float denom = nv*(1.0f - k) + k; return _fmaxf(nv, 0.001f)/denom; } // Specular calculation. __DEVICE__ float3 getSpec(float3 FS, float nh, float nr, float nl, float rough){ // Microfacet distribution... Most dominant term. // Microfaceted normal distribution function. float alpha = _powf(rough, 4.0f); float b = (nh*nh*(alpha - 1.0f) + 1.0f); float D = alpha/(PI*b*b); // Geometry self shadowing term. // G_Smith calculations. float g1_l = GGX_Schlick(nl, rough); float g1_v = GGX_Schlick(nr, rough); float G = g1_l*g1_v; // Combining the terms above. return FS*D*G/(4.0f*_fmaxf(nr, 0.001f))*PI; } __DEVICE__ float3 getDiff(float3 FS, float nl, float type){ // Diffuse calculations. float3 diff = nl*(1.0f - FS); // If not specular, use as diffuse (optional) return diff*(1.0f - type); // No diffuse for metals. } ////////////////////////////////////// // ---------------------------------------------------------------------------------- // - Image - // ---------------------------------------------------------------------------------- // Connect Image 'Texture: Rusty Metal' to iChannel0 // Connect Image 'Cubemap: Forest_0' to iChannel1 // Connect Image 'Texture: Picture' to iChannel2 /* Extruded Fibonacci Zoom ----------------------- I like perusing through simple looped animations. The standard single-rectangle Fibonacci zoom comes up every now and again -- The most common form consists of a single golden-ratio rectangle subdivided into self similar squares that traverse a golden spiral pattern. The less common variation involves subdividing the base rectangles in such a way as to create a vanishing point in one of the corners. Four of these base rectangles are then rotated around one another, effectively creating a vanishing point in the center. This particular example involves the latter arrangement. Objects exhibiting the required symmetry and self similarity can be used to create infinite fractal zoom effects. From a math and coding perspective, I know how infinite zooms work, but they still really mess with my sense of perception. :) Most of the Fibonacci zoom effects I see occur in flat 2D form. In fact, I prefer them this way. However, just to be different, I've produced this one in extruded traversal form. Related examples: // I've always been a fan of this example. Elegantly written and // presented... which is just another way to say that IQ wrote it. :) // Anyway, if you want to understand the Fibonacci zoom effect, // I'd recommend this. Golden Ratio and Spiral -- iq https://www.shadertoy.com/view/fslyW4 // Here's a much cleaner version of the four pronged // Fibonacci square zoom. I really like examples like these. fibonacci windmill -- ufffd https://www.shadertoy.com/view/tcVBzK Reference: Golden Spiral https://en.wikipedia.org/wiki/Golden_spiral */ // Max ray distance. #define FAR 20.0f // Scene object ID. //int objID; // Tri-Planar blending function: Based on an old Nvidia writeup: // GPU Gems 3 - Ryan Geiss: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html __DEVICE__ float3 tex3D(__TEXTURE2D__ tex, in float3 p, in float3 n){ // Abosolute normal with a bit of tightning. n = _fmaxf(abs_f3(n), to_float3_s(0.001f)); // _fmaxf(n*n - 0.1f,, 0.001f), etc. n /= dot(n, to_float3_s(1)); //n /= length(n); // Texure samples. One for each plane. float3 tx = swi3(texture(tex, swi2(p,z,y)),x,y,z); float3 ty = swi3(texture(tex, swi2(p,x,z)),x,y,z); float3 tz = swi3(texture(tex, swi2(p,x,y)),x,y,z); // Multiply each texture plane by its normal dominance factor.... or however you wish // to describe it. For instance, if the normal faces up or down, the "ty" texture // sample, represnting the XZ plane, will be used, which makes sense. // Textures are stored in sRGB (I think), so you have to convert them to linear space // (squaring is a rough approximation) prior to working with them... or something like // that. :) Once the final color value is gamma corrected, you should see correct // looking colors. return mul_mat3_f3(to_mat3_f3(tx*tx, ty*ty, tz*tz),n); } // IQ's extrusion formula. __DEVICE__ float opExtrusion(in float sdf, in float pz, in float h){ float2 w = to_float2( sdf, _fabs(pz) - h ); return _fminf(_fmaxf(w.x, w.y), 0.0f) + length(_fmaxf(w, to_float2_s(0.0f))); /* // Slight rounding. A little nicer, but slower. const float sf = 0.004f; float2 w = to_float2( sdf, _fabs(pz) - h - sf/2.0f); return _fminf(_fmaxf(w.x, w.y), 0.0f) + length(_fmaxf(w + sf, to_float2_s(0.0f))) - sf; */ } // Ray origin, ray direction, point on the line, normal. __DEVICE__ float rayLine(float2 ro, float2 rd, float2 p, float2 n){ // This it trimmed down, and can be trimmed done more, but it isn't // a GPU intensive example, so it'll do. float s = dot(p - ro, n)/dot(rd, n); return s<0.0f ? 1e8f : s; } // Some hacky 2D symbols. I put this together pretty quickly. There'd // be nicer ways to get the job done, but this will do. __DEVICE__ float getLetter(float2 gP, float2 gSc2, float val0, float zoom){ float d; // Random number. float rnd = hash21(to_float2_s(val0) + 0.22f); float sc = gSc2.x*0.1f; if(rnd<0.25f){ // Box. d = sBoxS(gP, to_float2_s(sc), sc*0.35f); } else if(rnd<0.5f){ // Cross. d = distLine(abs_f2(gP), to_float2_s(-sc), to_float2_s(sc));// } else if(rnd<0.75f){ // Triangle. float2 q = gP; float2 pnt[3]; float2 dir = to_float2(0, sc); pnt[0] = dir; pnt[1] = mul_mat2_f2(rot2(-TAU/3.0f),dir); pnt[2] = mul_mat2_f2(rot2( TAU/3.0f),dir); d = distLine(q, pnt[0], pnt[1]);// d = _fminf(d, distLine(q, pnt[1], pnt[2])); d = _fminf(d, distLine(q, pnt[2], pnt[0])); } else { // Circle. d = length(gP) - sc; } return _fabs(d) - 0.014f*zoom; } #ifdef GLOB float3 gRd; // Global ray direction. float3 gDir; // Global step direction. float gCD; // Global cell wall distance. // There are too many global hacked in here. I'll // tidy them up later. // Object distances and stored values. float4 vObj, gVal; // Zoomed based ID value. float gVal0; // Object border flag. int gBord; // Glow color. float3 gGlow; #endif // The extruded image. __DEVICE__ float map(float3 p3, float iTime, inout float *gZoom, float3 gRd, inout int *quad, inout int *gI, inout float2 *svRd, inout float2 *gP, inout float2 *gSc2, float2 gSc, inout float *gVal0, inout int *gBord, inout float3 *gGlow, inout float *gCD, inout float4 *vObj, inout float4 *gVal ){ // Floor. float fl = p3.y; // Fairly standard zoom setup. // // Cycle time. float t = iTime/2.0f; float iT = _floor(t); // Number of cycles. // Fractional time component. t = t - (iT + 0.5f); // We want each object to expand (or contract) to the size of // the next object each time that the fractional time scale // loops back to zero. float zoom = _powf(PHI, t*4.0f); // Scale and smoothing factor. float sc = 1.0f/4.0f/zoom; *gZoom = sc; // Saving the scale to use elsewhere. /////////// // Scaling and translation. float2 p = sc*swi2(p3,x,z); // Spiral rotation: You can do this elsewhere, but I find // this easier. mat2 rM = rot2(mod_f(iTime/4.0f, TAU)); p = mul_f2_mat2(p,rM); // The direction ray. *svRd = swi2(gRd,x,z); *svRd = mul_f2_mat2(*svRd,rM); // Rotating to match the local rotation. // Scene object. float3 d3 = distField(p, quad, gI, svRd, gP, gSc2, gSc, *gZoom); float d2 = d3.x; // Distance. float2 id = swi2(d3,y,z); // ID. // Creating some space around the objects. d2 += 0.005f; // A random value based on the Fibonacci quadrant // and zoom factor. float quadF = (float)(*quad); float val = mod_f(iT*4.0f + (float)(*gI), 16.0f)/16.0f;// val += quadF/4.0f; float val0 = val; *gVal0 = val0; val = (*gSc2).x/ *gZoom; // Creating some ring symbols. They're a bit of cliche, but they // look interesting. // 2D leters. float ring = getLetter(*gP, *gSc2, val0, *gZoom); ring /= *gZoom; // Factor in the zoom. ring = _fmaxf(ring, d2 + 0.002f); // Cap the ring object to the box. // CSG on various panels. float ew = 0.01f; // Hollowing out random boxes, then adding the ring object. float oD2 = d2; float bord = (_fabs(d2 + ew*2.0f) - ew*1.0f); d2 = _fmaxf(d2, -bord); *gBord = d2ew) *gBord = 0; } // Giving the 2D objects some depth -- based on the random zoom value. float h = 0.2f*val + 0.02f; float d = opExtrusion(d2, p3.y - h/2.0f, h/2.0f); // The ring object. ring = opExtrusion(ring, p3.y - h/2.0f, 0.005f); // Apply glow to the ring objects. if(ring<_fminf(d, fl) && ring<0.1f){ float rnd = hash21(to_float2(val0, 43)); float3 gCol = 0.5f + 0.45f*cos_f3(TAU*rnd/16.0f + to_float3(0, PI/2.0f*1.4f, PI)); gCol = _mix(gCol, swi3(gCol,x,z,y), length(*gP)/ *gZoom*4.0f); *gGlow += gCol/(0.0035f + ring)/800.0f; } // Using the 2D distance to distort the face distances. if(*gBord==0) d += d2*0.25f; else d += _fmaxf(d2, -0.01f)*0.25f; // Minimum cell wall distance. Used as a ray delimiter. // // Rectangle. // float2 n1 = to_float2(0, 1); // Top face, or line. float2 n2 = to_float2(1, 0); // Righ face, or line. // If the cell wall is behind ray (or the ray is facing the opposing cell // wall, if you prefer), use the normal from the back back cell wall. n1 = dot(*svRd, n1)<0.0f? -n1 : n1; n2 = dot(*svRd, n2)<0.0f? -n2 : n2; float2 ip = swi2(d3,y,z); float t1 = rayLine(*gP, *svRd, (n1* *gSc2*0.5f), -n1); float t2 = rayLine(*gP, *svRd, (n2* *gSc2*0.5f), -n2); *gCD = _fminf(t1, t2) + 0.0005f; *gCD /= *gZoom; // Save values for later. *gVal = to_float4(d2, id.x, id.y, h); // Object IDs. *vObj = to_float4(fl, d, ring, 1e5f); // Minimum scene distance. return _fminf(_fminf(fl, d), ring); } // Basic raymarcher. __DEVICE__ float trace(in float3 ro, in float3 rd, float iTime, inout float *gZoom, inout float3 *gRd, inout int *quad, inout int *gI, inout float2 *svRd, inout float2 *gP, inout float2 *gSc2, float2 gSc, inout float *gVal0, inout int *gBord, inout float3 *gGlow, inout float *gCD, inout float4 *vObj, inout float4 *gVal, inout float3 *gDir){ // Overall ray distance and scene distance. // // IQ's suggestion: Moving the ray's jump-off point closer to the // surface plane to gain some extra speed, especially when in // fullscreen mode. float t = hash31(ro + rd)*0.25f, d;//(0.35f - ro.y)/rd.y, d; *gRd = rd; // Global ray direction. *gDir = step(to_float3_s(0.0f), *gRd) - 0.5f; // Step direction. *gGlow = to_float3_s(0); //for(int i = _fminf(0, iFrame); i<128; i++){ for(int i = 0; i<128; i++){ d = map(ro + rd*t, iTime, gZoom, *gRd, quad, gI, svRd, gP, gSc2, gSc, gVal0, gBord, gGlow, gCD, vObj, gVal); if(_fabs(d)<0.001f || t>FAR) break; // Limit the ray jump distance to ensure that it // doesn't go any further than the next cell. t += _fminf(d*0.7f, *gCD); } return _fminf(t, FAR); } // Normal function. It's not as fast as the tetrahedral calculation, but more symmetrical. __DEVICE__ float3 normal(in float3 p, float iTime, inout float *gZoom, float3 gRd, inout int *quad, inout int *gI, inout float2 *svRd, inout float2 *gP, inout float2 *gSc2, float2 gSc, inout float *gVal0, inout int *gBord, inout float3 *gGlow, inout float *gCD, inout float4 *vObj, inout float4 *gVal) { //return normalize(to_float3(m(p + swi3(e,x,y,y)) - m(p - swi3(e,x,y,y)), m(p + swi3(e,y,x,y)) - m(p - swi3(e,y,x,y)), // m(p + swi3(e,y,y,x)) - m(p - swi3(e,y,y,x)))); // This mess is an attempt to speed up compiler time by contriving a break... It's // based on a suggestion by IQ. I think it works, but I really couldn't say for sure. float sgn = 1.0f; float3 e = to_float3(0.002f, 0.0f, 0.0f), mp = swi3(e,z,z,z); // Spalmer's clever zeroing. //for(int i = _fminf(iFrame, 0); i<6; i++){ for(int i = 0; i<6; i++){ mp.x += map(p + sgn*e, iTime, gZoom, gRd, quad, gI, svRd, gP, gSc2, gSc, gVal0, gBord, gGlow, gCD, vObj, gVal)*sgn; sgn = -sgn; if((i&1)==1){ mp = swi3(mp,y,z,x); e = swi3(e,z,x,y); } } return normalize(mp); } // Cheap shadows are hard. In fact, I'd almost say, shadowing particular scenes with // limited iterations is impossible... However, I'd be very grateful if someone could // prove me wrong. :) __DEVICE__ float softShadow(float3 ro, float3 rd, float3 n, float lDist, float k, float iTime, inout float *gZoom, inout float3 *gRd, inout int *quad, inout int *gI, inout float2 *svRd, inout float2 *gP, inout float2 *gSc2, float2 gSc, inout float *gVal0, inout int *gBord, inout float3 *gGlow, inout float *gCD, inout float4 *vObj, inout float4 *gVal, inout float3 *gDir){ // Initialize the shade and ray distance. float shade = 1.0f; float t = 0.0f; // Coincides with the hit condition in the "trace" function. I've added in // a touch of jittering to alleviate banding. ro += n*0.0015f + rd*hash31(ro + rd + n)*0.005f; *gRd = rd; // Global ray direction. *gDir = step(to_float3_s(0.0f), *gRd) - 0.5f; // Step direction. // Max shadow iterations - More iterations make nicer shadows, but slow things down. // Obviously, the lowest number to give a decent shadow is the best one to choose. //for (int i = _fminf(0, iFrame); i<48; i++){ for (int i = 0; i<48; i++){ float d = map(ro + rd*t, iTime, gZoom, *gRd, quad, gI, svRd, gP, gSc2, gSc, gVal0, gBord, gGlow, gCD, vObj, gVal); shade = _fminf(shade, k*d/t); //shade = _fminf(shade, smoothstep(0.0f, 1.0f, k*d/t)); // Thanks to IQ for this tidbit. // Early exit, if necessary. if (d<0.0f || t>lDist) break; // So many options here, and none are perfect: dist += clamp(d, 0.01f, stepDist), etc. t += clamp(_fminf(d, *gCD), 0.005f, 0.25f); } // Shadow. return _fmaxf(shade, 0.0f); } // I keep a collection of occlusion routines... OK, that sounded really nerdy. :) // Anyway, I like this one. I'm assuming it's based on IQ's original. __DEVICE__ float calcAO(in float3 p, in float3 n, float iTime, inout float *gZoom, float3 gRd, inout int *quad, inout int *gI, inout float2 *svRd, inout float2 *gP, inout float2 *gSc2, float2 gSc, inout float *gVal0, inout int *gBord, inout float3 *gGlow, inout float *gCD, inout float4 *vObj, inout float4 *gVal){ float sca = 3.0f, occ = 0.0f; for( int i = 0; i<6; i++ ){ float hr = 0.01f + (float)(i)*0.2f/6.0f; float d = map(p + n*hr, iTime, gZoom, gRd, quad, gI, svRd, gP, gSc2, gSc, gVal0, gBord, gGlow, gCD, vObj, gVal); occ += (hr - d)*sca; sca *= 0.75f; } return clamp(1.0f - occ, 0.0f, 1.0f); } // The normal function is just an application of the finite (central, forward) // difference method. The less used curvature function is a second derivative // extension of the former -- In fact, you can derive the curvature function // from it. // // I think it's technically called a discrete finite difference approximation to // the continuous Laplace differential operator? Either way, it gives you the // curvature of a surface, which is pretty handy. // // Original pixelshader usage (I think?) - Cheap curvature: // https://www.shadertoy.com/view/Xts3WM // // Other usage: Xyptonjtroz: https://www.shadertoy.com/view/4ts3z2 // // spr: sample spread, amp: amplitude, offs: offset. __DEVICE__ float curve(in float3 p, in float spr, in float amp, in float offs, float iTime, inout float *gZoom, float3 gRd, inout int *quad, inout int *gI, inout float2 *svRd, inout float2 *gP, inout float2 *gSc2, float2 gSc, inout float *gVal0, inout int *gBord, inout float3 *gGlow, inout float *gCD, inout float4 *vObj, inout float4 *gVal){ spr /= 450.0f; float sgn = 1.0f; float3 e = to_float3(spr, 0, 0); float d = -map(p, iTime, gZoom, gRd, quad, gI, svRd, gP, gSc2, gSc, gVal0, gBord, gGlow, gCD, vObj, gVal)*6.0f; //for(int i = _fminf(iFrame, 0); i<6; i++){ for(int i = 0; i<6; i++){ d += map(p + sgn*e, iTime, gZoom, gRd, quad, gI, svRd, gP, gSc2, gSc, gVal0, gBord, gGlow, gCD, vObj, gVal); sgn = -sgn; if((i&1)==1){ e = swi3(e,z,x,y); } } // By the way, I take a lot of liberties with this part of the formula. // Dividing by the sample spread squared (e.x*e.x) is technically correct, // but I'll sometimes divide by other things to get the result I want. // return clamp(d/e.x/e.x*amp/16.0f + offs, -1.0f, 1.0f)*0.5f + 0.5f; //return smoothstep(-1.0f, 1.0f, d/e.x/e.x*amp/16.0f + offs); } __KERNEL__ void ExtrudedFibonacciZoomFuse(__CONSTANTREF__ Params* params, __TEXTURE2D__ iChannel0, __TEXTURE2D__ iChannel1, __TEXTURE2D__ iChannel2, __TEXTURE2D_WRITE__ destinationTexture) { DEFINE_KERNEL_ITERATORS_XY(fusion_x, fusion_y); if (fusion_x >= params->width || fusion_y >= params->height) return; float2 iResolution = to_float2(params->iResolution[0], params->iResolution[1]); float iTime = params->iTime; float4 iMouse = to_float4(params->iMouse[0],params->iMouse[1],params->iMouse[2],params->iMouse[3]); int iFrame = params->iFrame; float4 fragColor = to_float4_s(0.0f); float2 fragCoord = to_float2(fusion_x,fusion_y); bool DarkEdges = params->DarkEdges; bool CamOpt = params->CamOpt; bool CamForward = params->CamForward; bool TexCol = params->TexCol; bool OptCurvature = params->OptCurvature; bool Tex2 = params->Tex2; bool CurveOn = params->CurveOn; bool AMB = params->AMB; float4 Color1 = to_float4(params->Color1[0], params->Color1[1], params->Color1[2], params->Color1[3]); float4 Color2 = to_float4(params->Color2[0], params->Color2[1], params->Color2[2], params->Color2[3]); float4 Color3 = to_float4(params->Color3[0], params->Color3[1], params->Color3[2], params->Color3[3]); float4 Roughness = to_float4(params->Roughness[0], params->Roughness[1], params->Roughness[2], params->Roughness[3]); float4 Color4 = to_float4(params->Color4[0], params->Color4[1], params->Color4[2], params->Color4[3]); float2 ViewDXY = to_float2(params->ViewDXY[0], params->ViewDXY[1]); float ViewDZ = params->ViewDZ; float2 ViewXY = to_float2(params->ViewXY[0], params->ViewXY[1]); float ViewZ = params->ViewZ; float2 TexXY = to_float2(params->TexXY[0], params->TexXY[1]); float TexScale = params->TexScale; float Type = params->Type; float Rough = params->Rough; float FresRef = params->FresRef; float OverallColor = params->OverallColor; float Glow = params->Glow; // -------- float ratio = iResolution.y/iResolution.x; ///////////////////////// // Global scale. Not absolutely necessary to have one, but // it's here. The ratio doesn't have to be 1 to 1, but I // think it looks neater this way. const float2 gSc = to_float2(1, 1); // Vertex holder. Not used here. //mat4x2 vP; // Iteration number and quad number. int gI, quad; // Global zoom. float gZoom; // Cell coordinates and a final scale value that I've hacked //in at the last minute... I'll tidy up the logic later. :) float2 gP, gSc2; // This is a copy of the direction ray. If you create a pattern that // relies on rotating coordinates, the direction ray needs to rotate // in unison. Traversals can be annoying to code sometimes, but the // benefits are worth the effort. float2 svRd; int objID; float3 gRd; // Global ray direction. float3 gDir; // Global step direction. float gCD; // Global cell wall distance. // There are too many global hacked in here. I'll // tidy them up later. // Object distances and stored values. float4 gVal; //vObj, union A2F vObj; // Zoomed based ID value. float gVal0; // Object border flag. int gBord; // Glow color. float3 gGlow; // Screen coordinates. float2 uv = (fragCoord - iResolution*0.5f)/iResolution.y; // Camera Setup. float3 ro = to_float3(0, 0.8f, 0.6f)+to_float3_aw(ViewXY, ViewZ); // Camera position, or ray origin. float3 lk = to_float3(0, 0, 0);//to_float3(0, -0.25f, iTime); // "Look At" position. // Light positioning. float3 lp = ro + to_float3(0.5f, 0.25f, 1);// Put it a bit in front of the camera. // Using the above to produce the unit ray-direction vector. float FOV = 1.0f; // FOV - Field of view. float3 fwd = normalize(lk - ro); // Forward. if(dot(fwd, to_float3(fwd.z, 0, -fwd.x))==0.0f && CamForward) fwd = normalize(fwd - to_float3(0, 0, 0.00001f)); float3 rgt = normalize(cross(to_float3(0, 1, 0), fwd));// Right. // "right" and "forward" are perpendicular normals, so the result is normalized. float3 up = cross(fwd, rgt); // Up. // Camera. mat3 mCam = to_mat3_f3(rgt, up, fwd); // rd - Ray direction. float3 rd = normalize(uv.x*rgt + uv.y*up + fwd/FOV+to_float3_aw(ViewDXY, ViewDZ)); if(CamOpt) rd = mul_mat3_f3(mCam , normalize(to_float3_aw(uv, 1.0f/FOV)));// //############### 3D Mouse-Rotation des Objektes ############## float crz = (iMouse.x - iResolution.x / 2.0f) / iResolution.x * PI; float crx = (iMouse.y - iResolution.y / 2.0f) / iResolution.y * PI; mat3 m = mul_mat3_mat3(to_mat3(_cosf(crz), 0.0f, _sinf(crz), 0.0f, 1.0f, 0.0f, -_sinf(crz), 0.0f, _cosf(crz)) , to_mat3(1.0f, 0.0f, 0.0f, 0.0f, _cosf(crx), _sinf(crx), 0.0f, -_sinf(crx), _cosf(crx))); if(iMouse.z > 0.0f) { ro = mul_mat3_f3(m , ro); rd = mul_mat3_f3(m , rd); } //############################################################# // Raymarch to the scene. float t = trace(ro, rd, iTime, &gZoom, &gRd, &quad, &gI, &svRd, &gP, &gSc2, gSc, &gVal0, &gBord, &gGlow, &gCD, &vObj.F, &gVal, &gDir); // Save the object ID. // Object ID. objID = 0; float minDist = 1e5f; // Sorting more objects. for(int i = 0; i<4; i++){ if(vObj.A[i]= 1) then if (InSize:GetValue(req).Value == 2) then if (InChannel0:GetValue(req) ~= nil) then Width = InChannel0:GetValue(req).Width Height = InChannel0:GetValue(req).Height end else Width = InWidth:GetValue(req).Value Height = InHeight:GetValue(req).Value end end -- Alle ( int und float ) if (InDepth:GetValue(req).Value > 0) then if InDepth:GetValue(req).Value == 1 then SourceDepth = 5 else if InDepth:GetValue(req).Value == 2 then SourceDepth = 6 else if InDepth:GetValue(req).Value == 3 then SourceDepth = 7 else SourceDepth = 8 end end end end local imgattrs = { IMG_Document = self.Comp, { IMG_Channel = "Red", }, { IMG_Channel = "Green", }, { IMG_Channel = "Blue", }, { IMG_Channel = "Alpha", }, IMG_Width = Width, IMG_Height = Height, IMG_XScale = XAspect, IMG_YScale = YAspect, IMAT_OriginalWidth = realwidth, -- nil !?! IMAT_OriginalHeight = realheight, -- nil !?! IMG_Quality = not req:IsQuick(), IMG_MotionBlurQuality = not req:IsNoMotionBlur(), IMG_DeferAlloc = true, IMG_ProxyScale = ( (not req:IsStampOnly()) and 1 or nil), IMG_Depth = ( (SourceDepth~=0) and SourceDepth or nil ) } local dst = Image(imgattrs) local black = Pixel({R=0,G=0,B=0,A=0}) dst:Fill(black) if req:IsPreCalc() then local out = Image({IMG_Like = dst, IMG_NoData = true}) OutImage:Set(req, out) return end node = DVIPComputeNode(req, "ExtrudedFibonacciZoomFuse", ShaderCompatibilityCode..ShaderKernelCode, "Params", ShaderParameters ) -- Extern texture or create a new one iChannel0 = InChannel0:GetValue(req) if iChannel0==nil then iChannel0 = Image(imgattrs) iChannel0:Fill(black) end iChannel1 = InChannel1:GetValue(req) if iChannel1==nil then iChannel1 = Image(imgattrs) iChannel1:Fill(black) end iChannel2 = InChannel2:GetValue(req) if iChannel2==nil then iChannel2 = Image(imgattrs) iChannel2:Fill(black) end -- DCTL parameters local framerate = self.Comp:GetPrefs("Comp.FrameFormat.Rate") local params = {} params = node:GetParamBlock(ShaderParameters) params.iResolution[0] = dst.Width params.iResolution[1] = dst.Height params.iTime = (req.Time / framerate) * InFrequency:GetValue(req).Value -- iMouse local mouse_xy = InMouseXY:GetValue(req) local mouse_zw = InMouseZW:GetValue(req) params.iMouse[0] = mouse_xy.X params.iMouse[1] = mouse_xy.Y params.iMouse[2] = mouse_zw.X params.iMouse[3] = mouse_zw.Y if InMouseDrag:GetValue(req).Value ~= 0 then if params.iMouse[2]==-1 and params.iMouse[3]==-1 then params.iMouse[2]=params.iMouse[0] params.iMouse[3]=params.iMouse[1] end else params.iMouse[2] = -1 params.iMouse[3] = -1 end if mouse_zw.X ~= params.iMouse[2] or mouse_zw.Y ~= params.iMouse[3] then InMouseZW:SetAttrs({INP_Disabled=false}) InMouseZW:SetSource(Point(params.iMouse[2],params.iMouse[3]),0,0) InMouseZW:SetAttrs({INP_Disabled=true}) end params.iMouse[0] = params.iMouse[0] * Width params.iMouse[1] = params.iMouse[1] * Height if params.iMouse[2] == -1 and params.iMouse[3] == -1 then params.iMouse[2] = 0 params.iMouse[3] = 0 else params.iMouse[2] = params.iMouse[2] * Width params.iMouse[3] = params.iMouse[3] * Height end params.iFrame = req.Time params.DarkEdges = InDarkEdgesCheckbox:GetValue(req).Value params.CamOpt = InCamOptCheckbox:GetValue(req).Value params.CamForward = InCamForwardCheckbox:GetValue(req).Value params.TexCol = InTexColCheckbox:GetValue(req).Value params.OptCurvature = InOptCurvatureCheckbox:GetValue(req).Value params.Tex2 = InTex2Checkbox:GetValue(req).Value params.CurveOn = InCurveOnCheckbox:GetValue(req).Value params.AMB = InAMBCheckbox:GetValue(req).Value params.Color1 = { InColor1ColorR:GetValue(req).Value, InColor1ColorG:GetValue(req).Value, InColor1ColorB:GetValue(req).Value,InColor1ColorA:GetValue(req).Value } params.Color2 = { InColor2ColorR:GetValue(req).Value, InColor2ColorG:GetValue(req).Value, InColor2ColorB:GetValue(req).Value,InColor2ColorA:GetValue(req).Value } params.Color3 = { InColor3ColorR:GetValue(req).Value, InColor3ColorG:GetValue(req).Value, InColor3ColorB:GetValue(req).Value,InColor3ColorA:GetValue(req).Value } params.Roughness = { InRoughnessColorR:GetValue(req).Value, InRoughnessColorG:GetValue(req).Value, InRoughnessColorB:GetValue(req).Value,InRoughnessColorA:GetValue(req).Value } params.Color4 = { InColor4ColorR:GetValue(req).Value, InColor4ColorG:GetValue(req).Value, InColor4ColorB:GetValue(req).Value,InColor4ColorA:GetValue(req).Value } params.ViewDXY = {InViewDXYPoint:GetValue(req).X,InViewDXYPoint:GetValue(req).Y} params.ViewDZ = InViewDZSlider:GetValue(req).Value params.ViewXY = {InViewXYPoint:GetValue(req).X,InViewXYPoint:GetValue(req).Y} params.ViewZ = InViewZSlider:GetValue(req).Value params.TexXY = {InTexXYPoint:GetValue(req).X,InTexXYPoint:GetValue(req).Y} params.TexScale = InTexScaleSlider:GetValue(req).Value params.Type = InTypeSlider:GetValue(req).Value params.Rough = InRoughSlider:GetValue(req).Value params.FresRef = InFresRefSlider:GetValue(req).Value params.OverallColor = InOverallColorSlider:GetValue(req).Value params.Glow = InGlowSlider:GetValue(req).Value -- Resolution params.width = dst.Width params.height = dst.Height -- Per channel time and resolution local edges = InEdges:GetValue(req).Value -- Set parameters and add I/O node:SetParamBlock(params) --node:AddSampler("RowSampler", TEX_FILTER_MODE_LINEAR,TEX_ADDRESS_MODE_MIRROR, TEX_NORMALIZED_COORDS_TRUE) DefineEdges(edges, node) node:AddInput("iChannel0",iChannel0) -- TODO: add a better channel name node:AddInput("iChannel1",iChannel1) -- TODO: add a better channel name node:AddInput("iChannel2",iChannel2) -- TODO: add a better channel name node:AddOutput("dst", dst) local ok = node:RunSession(req) if (not ok) then dst = nil dump(node:GetErrorLog()) end OutImage:Set(req,dst) collectgarbage(); end -- // ------------------------------------------------------------------------ -- // Callback -- // ------------------------------------------------------------------------ function NotifyChanged(inp, param, time) if (param ~= nil) then if inp == InSize then if param.Value == 1 then InWidth:SetAttrs({ IC_Visible = true }) InHeight:SetAttrs({ IC_Visible = true }) else InWidth:SetAttrs({ IC_Visible = false }) InHeight:SetAttrs({ IC_Visible = false }) end if param.Value == 3 then --1920x1080 InWidth:SetSource(Number(1920),0,0) InHeight:SetSource(Number(1080),0,0) end if param.Value == 4 then --1200x675 InWidth:SetSource(Number(1200),0,0) InHeight:SetSource(Number(675),0,0) end if param.Value == 5 then --800x450 InWidth:SetSource(Number(800),0,0) InHeight:SetSource(Number(450),0,0) end if param.Value == 6 then --640x360 InWidth:SetSource(Number(640),0,0) InHeight:SetSource(Number(360),0,0) end end end end -- */