Welcome to Fractal Forums

Fractal Software => 3D Fractal Generation => Topic started by: tryptophan on January 05, 2012, 11:19:01 PM




Title: OpenGL MengerSphonge rotation question
Post by: tryptophan on January 05, 2012, 11:19:01 PM
I'm porting an openGL MengerSphonge shader to an app I use called Touch Designer. Most of the attributes of the shader I can control except for rotation. Not rotation of the whole fractal but each iteration. I do not know a lot about fractal math so I'm hoping someone can help me add an equaton into the code so I control the rotation with a uniform variable. Any help would be greatly appreciated.

thanks
Keith

Code:

#ifdef GL_ES
precision highp float;
#endif

uniform vec4 uResolution;
uniform float time;
uniform vec4 iterations;
uniform vec3 camera;
uniform vec3 detail;
uniform vec3 rotation;
uniform vec3 offset;

float maxcomp(in vec3 p ) { return max(p.x,max(p.y,p.z));}
float sdBox( vec3 p, vec3 b )
{
  vec3  di = abs(p) - b;
  float mc = maxcomp(di);
  return min(mc,length(max(di,0.0)));
}

vec4 map( in vec3 p )
{
   float d = sdBox(p,vec3(iterations.w));
   vec4 res = vec4( d,  1.0, 0.0, 0.0 );

   float s = iterations.x;
   for( int m=0; m<3; m++ )
   {
      vec3 a = mod( p*s,2.0 )-1.0;
      s *= iterations.y;
      vec3 r = abs(1.0 - iterations.z*abs(a))+offset;
      float da = max(r.x*detail.x,r.y*detail.y)*rotation.x;
      float db = max(r.y*detail.y,r.z*detail.z);
      float dc = max(r.z*detail.z,r.x*detail.x);
      float c = (min(da,min(db,dc))-1.0)/s;

      if( c>d )
      {
          d = c;
          res = vec4( d, 0.3*da*db*dc, (1.0+float(m))/4.0, 0.0 );
       }
   }

   return res;
}

// GLSL ES doesn't seem to like loops with conditional break/return...
#if 0
vec4 intersect( in vec3 ro, in vec3 rd )
{
    float t = 0.0;
    for(int i=0;i<64;i++)
    {
        vec4 h = map(ro + rd*t);
        if( h.x<0.002 )
            return vec4(t,h.yzw);
        t += h;
    }
    return vec4(-1.0);
}
#else
vec4 intersect( in vec3 ro, in vec3 rd )
{
    float t = 0.0;
    vec4 res = vec4(-1.0);
    for(int i=0;i<64;i++)
    {
        vec4 h = map(ro + rd*t);
        if( h.x<0.002 )
        {
            if( res.x<0.0 ) res = vec4(t,h.yzw);
        }
//if( h.x>0.0 )
        t += h.x;
    }
    return res;
}
#endif

vec3 calcNormal(in vec3 pos)
{
    vec3  eps = vec3(0.001,0.0,0.0);
    vec3 nor;
    nor.x = map(pos+eps.xyy).x - map(pos-eps.xyy).x;
    nor.y = map(pos+eps.yxy).x - map(pos-eps.yxy).x;
    nor.z = map(pos+eps.yyx).x - map(pos-eps.yyx).x;
    return normalize(nor);
}

void main(void)
{
    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / uResolution.zw;
    p.x *= 1.33;

    // light
    vec3 light = normalize(vec3(1.0,0.8,-0.6));

    float ctime = time;
    // camera
    vec3 ro = 1.1*vec3(2.5*cos(0.5*ctime),1.5*cos(ctime*.23),2.5*sin(0.5*ctime));
    //vec3 ro = 1.1*vec3(2.5,1.5,2.5);
vec3 ww = normalize(vec3(0.0) - ro);
    vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), ww ));
    vec3 vv = normalize(cross(ww,uu));
    vec3 rd = normalize( p.x*uu + p.y*vv + 1.5*ww );

    vec3 col = vec3(0.0);
    vec4 tmat = intersect(ro,rd);
    if( tmat.x>0.0 )
    {
        vec3 pos = ro + tmat.x*rd;
        vec3 nor = calcNormal(pos);

        float dif1 = max(0.4 + 0.6*dot(nor,light),0.0);
        float dif2 = max(0.4 + 0.6*dot(nor,vec3(-light.x,light.y,-light.z)),0.0);

        // shadow
        float ldis = 4.0;
        vec4 shadow = intersect( pos + light*ldis, -light );
        if( shadow.x>0.0 && shadow.x<(ldis-0.01) ) dif1=0.0;

        float ao = tmat.y;
        col  = 1.0*ao*vec3(0.2,0.2,0.2);
        col += 2.0*(0.5+0.5*ao)*dif1*vec3(1.0,0.97,0.85);
        col += 0.2*(0.5+0.5*ao)*dif2*vec3(1.0,0.97,0.85);
        col += 1.0*(0.5+0.5*ao)*(0.5+0.5*nor.y)*vec3(0.1,0.15,0.2);

        // gamma lighting
        col = col*0.5+0.5*sqrt(col)*1.2;

        vec3 matcol = vec3(
            0.6+0.4*cos(5.0+6.2831*tmat.z),
            0.6+0.4*cos(5.4+6.2831*tmat.z),
            0.6+0.4*cos(5.7+6.2831*tmat.z) );
        col *= matcol;
        col *= 1.5*exp(-0.5*tmat.x);
    }


    gl_FragColor = vec4(col,1.0);
}


Title: Re: OpenGL MengerSphonge rotation question
Post by: eiffie on January 06, 2012, 10:50:18 PM
This has to be about the 5th version of a menger I have seen. Not too sure what the scale and offset are so couldn't try it but if you want to rotate a vector by the pitch, yaw, roll angles held in another vector you can use this:
Code:
mat3 matPyr(vec3 rot)
{//orient the mat3 (pitch yaw roll)
float cx=cos(rot.x),cy=cos(rot.y),cz=cos(rot.z),sx=sin(rot.x),sy=sin(rot.y),sz=sin(rot.z);
return mat3(cz*cy+sz*sx*sy,sz*cx,-cz*sy+sz*sx*cy,-sz*cy+cz*sx*sy,cz*cx,sz*sy+cz*sx*cy,cx*sy,-sx,cx*cy);
}
mat3 rmx=matPyr(rotation);
//...then inside iteration loop
p=rmx*p;


Title: Re: OpenGL MengerSphonge rotation question
Post by: tryptophan on January 07, 2012, 03:37:49 AM
thanks Eiffie. Your code worked with no errors, nice job. I'm still not getting the control I would like in comparison to other 3d fractal programs like Fragmentarium or Mandlebulber but it is working. It's rotating within the cube but the outside still has a cube shape. It seems I really need to learn some fractal math and more GLSL programming.

thanks for the help
Keith