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

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

// https://www.shadertoy.com/view/4sjSW1

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;
uniform vec3 iChannelResolution0;

// Created by inigo quilez - iq/2014
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

// An edge antialising experiment (not multisampling used)
//
// If slow_antialias is disabled, then only the 4 closest hit points are used for antialising, 
// otherwise all found partial-intersections are considered.

#define ANTIALIASING
//#define SLOW_ANTIALIAS

vec2 sincos( float x ) { return vec2( sin(x), cos(x) ); }

vec2 sdSegment( in vec3 p, in vec3 a, in vec3 b )
{
    vec3 pa = p-a, ba = b-a;
	float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
	return vec2( length( pa-ba*h ), h );
}

vec3 opU( vec3 d1, vec3 d2 ) { return (d1.x<d2.x) ? d1 : d2; }

vec3 map( vec3 p )
{
    vec2 id = floor( (p.xz+1.0)/2.0);
    p.xz = mod( p.xz+1.0, 2.0 ) - 1.0;
    
    float ph = sin(0.5 + 3.1*id.x + sin(7.1*id.y));
    
    p.xz += 0.5*sincos(1.0+0.5*iGlobalTime+(p.y+11.0*ph)*0.8);

    vec3 p1 = p; p1.xz += 0.15*sincos(1.0*p.y-1.0*iGlobalTime+0.0);
    vec3 p2 = p; p2.xz += 0.15*sincos(1.0*p.y-1.0*iGlobalTime+2.0);
    vec3 p3 = p; p3.xz += 0.15*sincos(1.0*p.y-1.0*iGlobalTime+4.0);
    
    vec2 h1 = sdSegment(p1, vec3(0.0,-50.0, 0.0), vec3(0.0, 50.0, 0.0) );
    vec2 h2 = sdSegment(p2, vec3(0.0,-50.0, 0.0), vec3(0.0, 50.0, 0.0) );
    vec2 h3 = sdSegment(p3, vec3(0.0,-50.0, 0.0), vec3(0.0, 50.0, 0.0) );
    
    return opU( opU( vec3(h1.x-0.12,                                         ph + 0.0/3.0, h1.y), 
                     vec3(h2.x-0.12-0.05*cos( 500.0*h2.y - iGlobalTime*4.0), ph + 1.0/3.0, h2.y) ), 
                     vec3(h3.x-0.12-0.02*cos(2000.0*h3.y - iGlobalTime*4.0), ph + 2.0/3.0, h3.y) );
}

//-------------------------------------------------------

vec3 calcNormal( in vec3 pos, in float dt )
{
    vec2 e = vec2(1.0,-1.0)*dt;
    return normalize( e.xyy*map( pos + e.xyy ).x + 
					  e.yyx*map( pos + e.yyx ).x + 
					  e.yxy*map( pos + e.yxy ).x + 
					  e.xxx*map( pos + e.xxx ).x );
}

float calcOcc( in vec3 pos, in vec3 nor )
{
    const float h = 0.15;
	float ao = 0.0;
    for( int i=0; i<8; i++ )
    {
        vec3 dir = sin( float(i)*vec3(1.0,7.13,13.71)+vec3(0.0,2.0,4.0) );
        dir = dir + 2.5*nor*max(0.0,-dot(nor,dir));            
        float d = map( pos + h*dir ).x;
        ao += max(0.0,h-d);
    }
    return clamp( 1.0 - 0.7*ao, 0.0, 1.0 );
}

//-------------------------------------------------------
vec3 shade( in float t, in float m, in float v, in vec3 ro, in vec3 rd )
{
    float px = 0.0001;//(2.0/iResolution.y)*(1.0/3.0);
    float eps = px*t;

    vec3  pos = ro + t*rd;
    vec3  nor = calcNormal( pos, eps );
    float occ = calcOcc( pos, nor );

    vec3 col = 0.5 + 0.5*cos( m*vec3(1.4,1.2,1.0) + vec3(0.0,1.0,2.0) );
    col += 0.05*nor;
    col = clamp( col, 0.0, 1.0 );
    col *= 1.0 + 0.5*nor.x;
    col += 0.2*clamp(1.0+dot(rd,nor),0.0,1.0);
    col *= 1.4;
    col *= occ;
    col *= exp( -0.15*t );
    col *= 1.0 - smoothstep( 15.0, 35.0, t );
    
    return col;
}

//-------------------------------------------------------

void main( void )
{	
	vec2 p = (-iResolution.xy+2.0*gl_FragCoord.xy)/iResolution.y;
    
	vec3 ro = 0.6*vec3(2.0,-3.0, 4.0);
	vec3 ta = 0.5*vec3(0.0, 4.0,-4.0);
    
    float fl = 1.0;
    vec3 ww = normalize( ta - ro);
    vec3 uu = normalize( cross( vec3(1.0,0.0,0.0), ww ) );
    vec3 vv = normalize( cross(ww,uu) );
    vec3 rd = normalize( p.x*uu + p.y*vv + fl*ww );
	
    float px = (2.0/iResolution.y)*(1.0/fl);
    
    vec3 col = vec3(0.0);

    //---------------------------------------------
    // raymach loop
    //---------------------------------------------
    const float maxdist = 32.0;

    vec3 res = vec3(-1.0);
    float t = 0.0;
    #ifdef ANTIALIASING
    vec3 oh = vec3(0.0);
    mat4 hit = mat4(-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0);
    #endif
    
    for( int i=0; i<128; i++ )
    {
	    vec3 h = map( ro + t*rd );
        float th1 = px*t;
        res = vec3( t, h.yz );
        if( h.x<th1 || t>maxdist ) break;

        
        #ifdef ANTIALIASING
        float th2 = px*t*3.0;
        if( (h.x<th2) && (h.x>oh.x) )
        {
            float lalp = 1.0 - (h.x-th1)/(th2-th1);
            #ifdef SLOW_ANTIALIAS
             vec3  lcol = shade( t, oh.y, oh.z, ro, rd );
             tmp.xyz += (1.0-tmp.w)*lalp*lcol;
             tmp.w   += (1.0-tmp.w)*lalp;
             if( tmp.w>0.99 ) break;
            #else
             if( hit[0].x<0.0 )
             {
             hit[0] = hit[1]; hit[1] = hit[2]; hit[2] = hit[3]; hit[3] = vec4( t, oh.yz, lalp );
             }
            #endif
        }
        oh = h;
        #endif
        
        t += min( h.x, 0.5 )*0.5;
    }
    
    if( t < maxdist )
        col = shade( res.x, res.y, res.z, ro, rd );
    
    #ifdef ANTIALIASING
    #ifdef SLOW_ANTIALIAS
	col = mix( col, tmp.xyz/(0.001+tmp.w), tmp.w );
    #else
    for( int i=0; i<4; i++ ) // blend back to front
    if( hit[3-i].x>0.0 )
        col = mix( col, shade( hit[3-i].x, hit[3-i].y, hit[3-i].z, ro, rd ), hit[3-i].w );
    #endif
    #endif
 
    //---------------------------------------------
    
    col = pow( col, vec3(0.5,0.7,0.5) );
    
    vec2 q = gl_FragCoord.xy/iResolution.xy;
    col *= pow(16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.1);
    
	gl_FragColor = vec4( col, 1.0 );
}
]]></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/antialiased worms", 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>
