<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>

<glsl_hacker>
	
  <window name="win3d01" title="MadShaders - Shadertoy/torus journey" 
          width="800" height="400"
          gl_version_major="2" gl_version_minor="1" />
          
          
<gpu_program name="shadertoy_prog" >
	<raw_data_vs><![CDATA[	 
void main()
{	
	gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;		
}
  ]]></raw_data_vs>
  
	<raw_data_ps><![CDATA[	 

// https://www.shadertoy.com/view/MdlGzn

uniform vec3      iResolution;     // viewport resolution (in pixels)
uniform float     iGlobalTime;     // shader playback time (in seconds)
uniform vec4      iMouse;          // mouse pixel coords. xy: current (if MLB down), zw: click
//uniform sampler2D iChannel0;


  
// TorusJourney (shadertoy version) by @paulofalcao

float time=iGlobalTime+25.0;

//Util Start
float PI=3.14159265;

vec2 ObjUnion(in vec2 obj0,in vec2 obj1){
  if (obj0.x<obj1.x)
    return obj0;
  else
    return obj1;
}

vec3 sim(vec3 p,float s){
  vec3 ret=p;
  ret=p+s/2.0;
  ret=fract(ret/s)*s-s/2.0;
  return ret;
}

vec2 rot(vec2 p,float r){
  vec2 ret;
  ret.x=p.x*cos(r)-p.y*sin(r);
  ret.y=p.x*sin(r)+p.y*cos(r);
  return ret;
}

vec2 rotsim(vec2 p,float s){
  vec2 ret=p;
  ret=rot(p,-PI/(s*2.0));
  ret=rot(p,floor(atan(ret.x,ret.y)/PI*s)*(PI/s));
  return ret;
}

vec2 revolve(vec2 p){
  p.x=length(p);
  return p;
}
//Util End

//Scene Start

//IQ signed box
float sdBox(vec3 p,vec3 b){
  vec3 d=abs(p)-b;
  return min(max(d.x,max(d.y,d.z)),0.0) +
         length(max(d,0.0));
}

vec2 obj0(in vec3 p){
  p.z=p.z-3.5;
  float c1=sdBox(p,vec3(0.25,0.25,0.25));
  float c2=sdBox(p,vec3(1.5,0.15,0.15));
  float c3=sdBox(p,vec3(0.15,1.5,0.15));
  return vec2(min(min(c1,c3),c2),0);
}

vec3 obj0_c(in vec3 p){
  return vec3(0.2,0.5,1.0);
}

vec2 obj1(vec3 p){
  p.z=p.z-6.0;
  float c1=sdBox(p,vec3(1.5,0.15,0.3));
  float c2=sdBox(p,vec3(0.15,1.5,0.3));
  return vec2(min(c1,c2),1);
}

vec3 obj1_c(in vec3 p){
  return vec3(1.0,0.7,0.6);
}

vec2 obj2(vec3 p){
  vec3 op=p;
  p.xz=revolve(p.xz);
  p.x-=32.0;
  op.xz=rot(op.xz,time*0.3);
  p.xy=rot(p.xy,atan(op.z,op.x)*24.0*sin(time*0.2));
  p.x-=sin(time*2.0);
  return vec2(length(max(abs(p.xy)-vec2(0.5,0.1),0.0))-0.2,2);
}

vec3 obj2_c(in vec3 p){
  return vec3(1.0,0.5,0.2);
}


vec2 inObj(in vec3 p){
  vec3 b=p;
  p.xz=rotsim(p.xz,64.0);
  p.z=p.z-32.0;
  p.yz=rotsim(p.yz,8.0);
  return ObjUnion(ObjUnion(obj0(p),obj1(p)),obj2(b));
}

//Scene End

//tetrahedron normal
vec3 objNormal(vec3 p){
  const float n_er=0.02;
  float v1=inObj(vec3(p.x+n_er,p.y-n_er,p.z-n_er)).x;
  float v2=inObj(vec3(p.x-n_er,p.y-n_er,p.z+n_er)).x;
  float v3=inObj(vec3(p.x-n_er,p.y+n_er,p.z-n_er)).x;
  float v4=inObj(vec3(p.x+n_er,p.y+n_er,p.z+n_er)).x;
  return normalize(vec3(v4+v1-v3-v2,v3+v4-v1-v2,v2+v4-v3-v1));
}


void main(void){
  vec2 vPos=-1.0+2.0*gl_FragCoord.xy/iResolution.xy;
  
  //Camera animation
  vec3 vuv=vec3(sin(time*0.7),1.0,sin(time*0.9));
  float camSpeed=time*0.3;
  vec3 vrp=vec3(sin(camSpeed+0.2)*32.0,0,cos(camSpeed+0.2)*32.0);
  float camCenterDist=2.1+exp(-20.0*pow(sin(time*0.2)+1.0,20.0))*2.8;
  vec3 prp=vec3(sin(camSpeed)*32.0,0,cos(camSpeed)*32.0);
  mat3 camMov=mat3(normalize(prp),vec3(0,1.0,0),normalize(vrp-prp));
  camSpeed+=sin(time*0.3)*0.5;
  vrp=vec3(sin(camSpeed)*32.0,0,cos(camSpeed)*32.0);
  vec3 camMovP=vec3(sin(time)*camCenterDist,cos(time)*camCenterDist,0.0);
  prp=prp+camMovP*camMov;
  float vpd=1.5;  
 
  //Camera setup
  vec3 vpn=normalize(vrp-prp);
  vec3 u=normalize(cross(vuv,vpn));
  vec3 v=cross(vpn,u);
  vec3 scrCoord=prp+vpn*vpd+vPos.x*u*iResolution.x/iResolution.y+vPos.y*v;
  vec3 scp=normalize(scrCoord-prp);

  //Raymarching
  const vec3 e=vec3(0.1,0,0);
  float maxd=48.0; //Max depth

  vec2 s=vec2(0.1,0.0);
  vec3 c,p,n;

  float f=1.0;
  for(int i=0;i<128;i++){
    if (abs(s.x)<.001||f>maxd) break;
    f+=s.x;
    p=prp+scp*f;
    s=inObj(p);
  }
  
  if (f<maxd){
    if (s.y==0.0)
      c=obj0_c(p);
    else if (s.y==1.0)
      c=obj1_c(p);
    else
      c=obj2_c(p);
 
    n=objNormal(p);
    float b=abs(dot(n,normalize(prp-p)));
    vec3 objColor=b*c+pow(b,8.0);
  
    //reflect
    float f0=f;
    if (s.y==2.0){
      prp=p-0.02*scp;
      scp=reflect(scp,n);
      f=0.0;
      s=vec2(0.1,0.0);
      maxd=16.0;
      for(int i=0;i<64;i++){
        if (abs(s.x)<.01||f>maxd) break;
        f+=s.x;
        p=prp+scp*f;
        s=inObj(p);
      }
      if (f<maxd){
        if (s.y==0.0)
          c=obj0_c(p);
        else if (s.y==1.0)
          c=obj1_c(p);
        else
          c=obj2_c(p);
      
        n=objNormal(p);
        b=abs(dot(n,normalize(prp-p)));
        vec3 objColor2=b*c+pow(b,8.0);
        gl_FragColor=vec4((objColor*0.8+objColor2*0.2)*(1.0-f0*.03),1.0);
      } else gl_FragColor=vec4(objColor*0.8*(1.0-f0*.03),1.0);

    } else gl_FragColor=vec4(objColor*(1.0-f0*.03),1.0);
    
  } else gl_FragColor=vec4(0,0,0,1);

}
]]></raw_data_ps>

</gpu_program>

 
	<script name="init_scene" run_mode="INIT" >
		<raw_data><![CDATA[	

app_dir = gh_utils.get_scripting_libs_dir() 		
dofile(app_dir .. "lua/Moon3D_v2.lua")

moon3d.init(2, 1)
moon3d.graphics.vsync(0)

bmfont = moon3d.font.create("trebuchet_20px.fnt", "data/")
bmfont_texture = moon3d.font.getTexture(bmfont)
moon3d.madshaders.setBmFontData(bmfont, bmfont_texture)

winW, winH = moon3d.window.getSize()

quad = moon3d.graphics.newQuad(winW, winH)
shadertoy_prog = moon3d.graphics.getGpuProgram("shadertoy_prog")

-- tex0 = moon3d.image.load2d("./data/tex16.png")

moon3d.madshaders.resetBenchmarkData()

		]]></raw_data>
	</script> 

  
	<script name="update_scene" run_mode="FRAME" >
		<raw_data><![CDATA[	

moon3d.startFrame(0, 0, 0, 1)

local global_time = moon3d.getTime()

moon3d.madshaders.updateBenchmarkData(global_time)

moon3d.camera.bindOrtho()

moon3d.graphics.bindGpuProgram(shadertoy_prog)
moon3d.madshaders.updateShadertoyCommonParams(shadertoy_prog, global_time)
--moon3d.madshaders.setShadertoyTexture(shadertoy_prog, tex0, 0)
moon3d.graphics.draw(quad)

moon3d.madshaders.displayBenchmarkInfoV2("Shadertoy/torus journey", global_time, 1, 1, 1, 1)

moon3d.endFrame()

		]]></raw_data>
	</script> 
	

	<script name="resize_scene" run_mode="SIZE" >
		<raw_data><![CDATA[	

moon3d.window.resize()
winW, winH = moon3d.window.getSize()
moon3d.graphics.resizeQuad(quad, winW, winH)

		]]></raw_data>
	</script> 
  
</glsl_hacker>
