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

<glsl_hacker>
	
  <window name="win3d01" title="MadShaders - Shadertoy/balls and occlusion" 
          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/ldX3Ws
  
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; // channel resolution (in pixels)


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

#define NUMSPHEREES 12

#define eps 0.001

vec2 hash2( float n )
{
    return fract(sin(vec2(n,n+1.0))*vec2(43758.5453123,22578.1459123));
}

vec3 hash3( float n )
{
    return fract(sin(vec3(n,n+1.0,n+2.0))*vec3(43758.5453123,22578.1459123,19642.3490423));
}

vec3 nSphere( in vec3 pos, in vec4 sph )
{
    return (pos-sph.xyz)/sph.w;
}

float iSphere( in vec3 ro, in vec3 rd, in vec4 sph )
{
	vec3 oc = ro - sph.xyz;
	float b = dot( oc, rd );
	float c = dot( oc, oc ) - sph.w*sph.w;
	float h = b*b - c;
	if( h<0.0 ) return -1.0;
	return -b - sqrt( h );
}

float sSphere( in vec3 ro, in vec3 rd, in vec4 sph )
{
    vec3 oc = ro - sph.xyz;
    float b = dot( oc, rd );
    float c = dot( oc, oc ) - sph.w*sph.w;
	
    return step( min( -b, min( c, b*b - c ) ), 0.0 );
}

vec4 sphere[NUMSPHEREES];

float intersect( in vec3 ro, in vec3 rd, out vec3 nor, out float id )
{
	float res = 1e20;
	float fou = -1.0;
	
	nor = vec3(0.0);

	for( int i=0; i<NUMSPHEREES; i++ )
	{
		vec4 sph = sphere[i];
	    float t = iSphere( ro, rd, sph ); 
		if( t>eps && t<res ) 
		{
			res = t;
			nor = nSphere( ro + t*rd, sph );
			fou = 1.0;
			id = float(i);
		}
	}
						  
    return fou * res;					  
}

float shadow( in vec3 ro, in vec3 rd )
{
	float res = 1.0;
	for( int i=0; i<NUMSPHEREES; i++ )
	{
		float id = float(i);
	    float t = sSphere( ro, rd, sphere[i] ); 
		res = min( t, res );
	}
    return res;					  
}

float getRad( float id )
{
	float rad = 0.0;
	if( id<12.5 ) rad = 1.0;
	if( id<9.5 )  rad = 0.5;
	if( id<6.5 )  rad = 0.0;
	return rad;
}

void main( void )
{
	vec2 q = gl_FragCoord.xy / iResolution.xy;
    vec2 p = -1.0 + 2.0 * q;
    p.x *= iResolution.x/iResolution.y;
    vec2 m = vec2(0.5);
	if( iMouse.z>0.0 ) m = iMouse.xy/iResolution.xy;
	
    //-----------------------------------------------------
    // animate
    //-----------------------------------------------------
	float time = iGlobalTime - 11.6;
	
	float an = 0.3*time - 7.0*m.x;

	for( int i=0; i<NUMSPHEREES; i++ )
	{
		float id  = float(i);
		float rad = getRad( id );
	    vec3  pos = 1.0*cos( 6.2831*hash3(id*37.17) + 0.5*(1.0-0.7*rad)*hash3(id*31.3+4.7)*time );
		sphere[i] = vec4( pos, (0.3+0.7 *rad) );
    }
			
    //-----------------------------------------------------
    // camera
    //-----------------------------------------------------
	vec3 ro = vec3(2.5*sin(an),1.5*cos(0.5*an),2.5*cos(an));
    vec3 ta = vec3(0.0,0.0,0.0);
    vec3 ww = normalize( ta - ro );
    vec3 uu = normalize( cross(ww,vec3(0.0,1.0,0.0) ) );
    vec3 vv = normalize( cross(uu,ww));
	vec3 rd = normalize( p.x*uu + p.y*vv + 2.0*ww );

    //-----------------------------------------------------
	// render
    //-----------------------------------------------------
	vec3 col = vec3(1.0) * (0.98+0.1*rd.y);

	// raymarch
	vec3 nor;
	float id;
	float t = intersect(ro,rd,nor, id);
	if( t>0.0 )
	{
		vec3 pos = ro + t*rd;
		
		float occ = 0.0;
		vec3  uu  = normalize( cross( nor, vec3(0.0,1.0,1.0) ) );
		vec3  vv  = normalize( cross( uu, nor ) );
        float off = texture2D( iChannel0, gl_FragCoord.xy/iChannelResolution0.xy, -100.0 ).x;
		for( int j=0; j<48; j++ )
		{
			vec2  aa = hash2( off + float(j)*203.1 );
			float ra = sqrt(aa.y);
			float rx = ra*cos(6.2831*aa.x); 
			float ry = ra*sin(6.2831*aa.x);
			float rz = sqrt( 1.0-aa.y );
			vec3  rr = vec3( rx*uu + ry*vv + rz*nor );
			occ += shadow( pos, rr );
		}
		occ /= 48.0;
				
		vec3 mate = vec3(1.0);
		mate = vec3( 1.0, 1.0, 0.6 );
		mate = mix( mate, vec3(1.0,0.4,0.1), (1.0-smoothstep(0.7,0.71,getRad( id ))) );
		mate = mix( mate, vec3(1.0,0.7,0.1), (1.0-smoothstep(0.4,0.41,getRad( id ))) );
        mate += 0.10*sin( 5.0 + vec3(0.0,1.0,2.0) + id*20.0 );
		mate *= 0.25 + 0.75*mix( 1.0, smoothstep( -0.95,-0.8,sin(pos.y*40.0) ), 1.0-pow(abs(nor.y),8.0) );
		mate *= 1.00 + 0.10*nor*nor*nor;
		
		col = mate * (occ*0.25+0.75*sqrt(occ));
		
		col += 0.25*pow( 1.0+dot(rd,nor), 5.0 )*occ*occ;
	    col *= 0.90 + 0.10*nor.y;
	}
	
	// vigneting
    col *= 1.0 - 0.3*dot((q-0.5)*(q-0.5),(q-0.5)*(q-0.5));

	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/noise_texture_0002b_256x256.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.displayBenchmarkInfoV3("Shadertoy/balls and occlusion", global_time, 1, 1, 1, 1, 3, 9)

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>
