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

<glsl_hacker>
	
  <window name="win3d01" title="MadShaders - GLSLSandbox/#6254.0" 
          width="800" height="400" 
          gl_version_major="2" gl_version_minor="1" />
          
         
<gpu_program name="glslsandbox_prog" >
	<raw_data_vs><![CDATA[	 
varying vec2 surfacePosition;
uniform vec2 resolution;
void main()
{	
	gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;		
  surfacePosition = gl_Vertex.xy / (resolution*0.5);
}
  ]]></raw_data_vs>
  
	<raw_data_ps><![CDATA[	 

// http://glsl.heroku.com/e#6254.0

// 704 Remake - @PauloFalcao
// based on Blank Slate - @P_Malin (http://glsl.heroku.com/e#2540.09)
//
// Tonight was very tired from work, and decided to do some graphics fun to clear the mind! :)
// I opened the http://glsl.heroku.com/ and saw a copy of @P_Malin framework
// I Remembered my old 704 (http://www.backtothepixel.com/demos/js/webgl/704_webgl.html)
// and thought... how it would look like if i used the 704 object...
// I loved the results!!! @P_Malin framework is awesome!!!
// Very complete, with nice variable names, really nice! :)
// Colors, and the object are the same as the original 704,
// but time is slower to give to the stuff time to cook... ;)
//

#ifdef GL_ES
precision highp float;
#endif

uniform float time;
//uniform vec2 mouse;
uniform vec2 resolution;
uniform sampler2D backbuffer;

// somehow these enable pan/zoom controls (using magic)
uniform vec2 surfaceSize;
varying vec2 surfacePosition;

float kPI = acos(0.0);
float kHalfPi = asin(1.0);
float kTwoPI = kPI * 2.0;

// Removed so that it works again
//float cos(float v) // workaround for AMD Radeon on OS X
//{ 
//	return sin(v+kHalfPi);
//}

#define ENABLE_MONTE_CARLO
#define ENABLE_REFLECTIONS
#define ENABLE_FOG
#define ENABLE_SPECULAR
#define ENABLE_POINT_LIGHT
//#define ENABLE_POINT_LIGHT_FLARE

#ifdef ENABLE_MONTE_CARLO
vec4 gPixelRandom;
vec3 gRandomNormal;

void CalcPixelRandom()
{
	// Nothing special here, just numbers generated by bashing keyboard
	vec4 s1 = sin(time * 3.3422 + gl_FragCoord.xxxx * vec4(324.324234, 563.324234, 657.324234, 764.324234)) * 543.3423;
	vec4 s2 = sin(time * 1.3422 + gl_FragCoord.yyyy * vec4(567.324234, 435.324234, 432.324234, 657.324234)) * 654.5423;
	gPixelRandom = fract(2142.4 + s1 + s2);
	gRandomNormal = normalize( gPixelRandom.xyz - 0.5);
}
#endif

struct C_Ray
{
	vec3 vOrigin;
	vec3 vDir;
};
 
struct C_HitInfo
{
	vec3 vPos;
	float fDistance;
	vec3 vObjectId;
};
 
struct C_Material
{
	vec3 cAlbedo;
	float fR0;
	float fSmoothness;
	vec2 vParam;
};
 
vec3 RotateX( const in vec3 vPos, const in float fAngle )
{
	float s = sin(fAngle);
	float c = cos(fAngle);
	
	vec3 vResult = vec3( vPos.x, c * vPos.y + s * vPos.z, -s * vPos.y + c * vPos.z);
	
	return vResult;
}
 
vec3 RotateY( const in vec3 vPos, const in float fAngle )
{
	float s = sin(fAngle);
	float c = cos(fAngle);
	
	vec3 vResult = vec3( c * vPos.x + s * vPos.z, vPos.y, -s * vPos.x + c * vPos.z);
	
	return vResult;
}
     
vec3 RotateZ( const in vec3 vPos, const in float fAngle )
{
	float s = sin(fAngle);
	float c = cos(fAngle);
	
	vec3 vResult = vec3( c * vPos.x + s * vPos.y, -s * vPos.x + c * vPos.y, vPos.z);
	
	return vResult;
}
 
vec4 DistCombineUnion( const in vec4 v1, const in vec4 v2 )
{
	//if(v1.x < v2.x) return v1; else return v2;
	return mix(v1, v2, step(v2.x, v1.x));
}
 
vec4 DistCombineIntersect( const in vec4 v1, const in vec4 v2 )
{
	return mix(v2, v1, step(v2.x,v1.x));
}
 
vec4 DistCombineSubtract( const in vec4 v1, const in vec4 v2 )
{
	return DistCombineIntersect(v1, vec4(-v2.x, v2.yzw));
}
 
vec3 DomainRepeatXZGetTile( const in vec3 vPos, const in vec2 vRepeat, out vec2 vTile )
{
	vec3 vResult = vPos;
	vec2 vTilePos = (vPos.xz / vRepeat) + 0.5;
	vTile = floor(vTilePos + 1000.0);
	vResult.xz = (fract(vTilePos) - 0.5) * vRepeat;
	return vResult;
}
 
vec3 DomainRepeatXZ( const in vec3 vPos, const in vec2 vRepeat )
{
	vec3 vResult = vPos;
	vec2 vTilePos = (vPos.xz / vRepeat) + 0.5;
	vResult.xz = (fract(vTilePos) - 0.5) * vRepeat;
	return vResult;
}
 
vec3 DomainRepeatY( const in vec3 vPos, const in float fSize )
{
	vec3 vResult = vPos;
	vResult.y = (fract(vPos.y / fSize + 0.5) - 0.5) * fSize;
	return vResult;
}
 
vec3 DomainRotateSymmetry( const in vec3 vPos, const in float fSteps )
{
	float angle = atan( vPos.x, vPos.z );

	float fScale = fSteps / (kTwoPI);
	float steppedAngle = (floor(angle * fScale + 0.5)) / fScale;

	float s = sin(-steppedAngle);
	float c = cos(-steppedAngle);

	vec3 vResult = vec3( c * vPos.x + s * vPos.z,
			     vPos.y,
			    -s * vPos.x + c * vPos.z);

	return vResult;
}
 
float GetDistanceXYTorus( const in vec3 p, const in float r1, const in float r2 )
{
	vec2 q = vec2(length(p.xy)-r1,p.z);
	return length(q)-r2;
}
float GetDistanceYZTorus( const in vec3 p, const in float r1, const in float r2 )
{
	vec2 q = vec2(length(p.yz)-r1,p.x);
	return length(q)-r2;
}
float GetDistanceCylinderY(const in vec3 vPos, const in float r)
{
	return length(vPos.xz) - r;
}
float GetDistanceBox( const in vec3 vPos, const in vec3 vSize )
{
	vec3 vDist = (abs(vPos) - vSize);
	return max(vDist.x, max(vDist.y, vDist.z));
}
 
float GetDistanceRoundedBox( const in vec3 vPos, const in vec3 vSize, float fRadius )
{
	vec3 vClosest = max(min(vPos, vSize), -vSize);
	return length(vClosest - vPos) - fRadius;
}
 
// result is x=scene distance y=material or object id; zw are material specific parameters (maybe uv co-ordinates)
vec4 GetDistanceScene( const in vec3 vPos )
{          
	vec4 vResult = vec4(10000.0, -1.0, 0.0, 0.0);
       
	float oP=length(vPos);
	vec3 vSphereDomain=vPos;
	float tt=time*0.05+10.0;
	vSphereDomain.x=sin(vSphereDomain.x)+sin(tt);
	vSphereDomain.z=sin(vSphereDomain.z)+cos(tt);

	vec4 vDistSphere = vec4( length(length(vSphereDomain))-1.5-sin(oP-tt*4.0), 2.0, vSphereDomain.xy);
       
	vResult = DistCombineUnion(vResult, vDistSphere);
		       
	vec4 vDistFloor = vec4(vPos.y + 1.0, 1.0, vPos.xz);
	vResult = DistCombineUnion(vResult, vDistFloor);
		       
	return vResult;
}

C_Material GetObjectMaterial( const in vec3 vObjId, const in vec3 vPos )
{
	C_Material mat;
		       
	if(vObjId.x < 1.5)
	{
		// floor
		mat.fR0 = 0.01;
		mat.fSmoothness = 0.0;
		if (fract(vPos.x*.5)>.5)
			if (fract(vPos.z*.5)>.5)
				mat.cAlbedo=vec3(0,0,0);
			else
				mat.cAlbedo=vec3(1,1,1);
			else
			if (fract(vPos.z*.5)>.5)
				mat.cAlbedo = vec3(1,1,1);
			else
				mat.cAlbedo = vec3(0,0,0);
	}
	else
	if(vObjId.x < 2.5)
	{
		// sphere
		mat.fR0 = 0.5;
		mat.fSmoothness = 0.9;
		float tt=time*0.05+10.0;
		float d=length(vPos);
		mat.cAlbedo = vec3((sin(d*.25-tt*4.0)+1.0)/2.0,(sin(tt)+1.0)/2.0,(sin(d-tt*4.0)+1.0)/2.0);
	}
	
	return mat;
}
vec3 GetSkyGradient( const in vec3 vDir )
{
	float fBlend = vDir.y * 0.5 + 0.5;
	return mix(vec3(0.0, 0.0, 0.0), vec3(0.5, 0.6, 0.7), fBlend);
}
vec3 GetLightPos()
{
	vec3 vLightPos = vec3(2.0, 9.0, 2.0);
	#ifdef ENABLE_MONTE_CARLO        
	vLightPos += gRandomNormal * 0.2;
	#endif
	return vLightPos;
}
vec3 GetLightCol()
{
	return vec3(32.0, 6.0, 1.0) * 10.0;
}
 
vec3 GetAmbientLight(const in vec3 vNormal)
{
	return GetSkyGradient(vNormal);
}

#define kFogDensity 0.035
void ApplyAtmosphere(inout vec3 col, const in C_Ray ray, const in C_HitInfo intersection)
{
	#ifdef ENABLE_FOG
	// fog
	float fFogAmount = exp(intersection.fDistance * -kFogDensity);
	vec3 cFog = GetSkyGradient(ray.vDir);
	col = mix(cFog, col, fFogAmount);
	#endif
       
	// glare from light (a bit hacky - use length of closest approach from ray to light)
	#ifdef ENABLE_POINT_LIGHT_FLARE
	vec3 vToLight = GetLightPos() - ray.vOrigin;
	float fDot = dot(vToLight, ray.vDir);
	fDot = clamp(fDot, 0.0, intersection.fDistance);
       
	vec3 vClosestPoint = ray.vOrigin + ray.vDir * fDot;
	float fDist = length(vClosestPoint - GetLightPos());
	col += GetLightCol() * 0.01/ (fDist * fDist);
	#endif     
}
vec3 GetSceneNormal( const in vec3 vPos )
{
	// tetrahedron normal
	float fDelta = 0.025;

	vec3 vOffset1 = vec3( fDelta, -fDelta, -fDelta);
	vec3 vOffset2 = vec3(-fDelta, -fDelta,  fDelta);
	vec3 vOffset3 = vec3(-fDelta,  fDelta, -fDelta);
	vec3 vOffset4 = vec3( fDelta,  fDelta,  fDelta);

	float f1 = GetDistanceScene( vPos + vOffset1 ).x;
	float f2 = GetDistanceScene( vPos + vOffset2 ).x;
	float f3 = GetDistanceScene( vPos + vOffset3 ).x;
	float f4 = GetDistanceScene( vPos + vOffset4 ).x;

	vec3 vNormal = vOffset1 * f1 + vOffset2 * f2 + vOffset3 * f3 + vOffset4 * f4;

	return normalize( vNormal );
}

#define kRaymarchEpsilon 0.01
#define kRaymarchMatIter 256
#define kRaymarchStartDistance 0.1
// This is an excellent resource on ray marching -> http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
void Raymarch( const in C_Ray ray, out C_HitInfo result, const float fMaxDist, const int maxIter )
{         
	result.fDistance = kRaymarchStartDistance;
	result.vObjectId.x = 0.0;
							   
	for(int i=0;i<=kRaymarchMatIter;i++)               
	{
		result.vPos = ray.vOrigin + ray.vDir * result.fDistance;
		vec4 vSceneDist = GetDistanceScene( result.vPos );
		result.vObjectId = vSceneDist.yzw;

		// abs allows backward stepping - should only be necessary for non uniform distance functions
		if((abs(vSceneDist.x) <= kRaymarchEpsilon) || (result.fDistance >= fMaxDist) || (i > maxIter))
		{
			break;
		}                         

		result.fDistance = result.fDistance + vSceneDist.x;     
	}
       
       
	if(result.fDistance >= fMaxDist)
	{
		result.vPos = ray.vOrigin + ray.vDir * result.fDistance;
		result.vObjectId.x = 0.0;
		result.fDistance = 1000.0;
	}
}

float GetShadow( const in vec3 vPos, const in vec3 vLightDir, const in float fLightDistance )
{
	C_Ray shadowRay;
	shadowRay.vDir = vLightDir;
	shadowRay.vOrigin = vPos;

	C_HitInfo shadowIntersect;
	Raymarch(shadowRay, shadowIntersect, fLightDistance, 32);
																									    
	return step(0.0, shadowIntersect.fDistance) * step(fLightDistance, shadowIntersect.fDistance );          
}

// http://en.wikipedia.org/wiki/Schlick's_approximation
float Schlick( const in vec3 vNormal, const in vec3 vView, const in float fR0, const in float fSmoothFactor)
{
	float fDot = dot(vNormal, -vView);
	fDot = min(max((1.0 - fDot), 0.0), 1.0);
	float fDot2 = fDot * fDot;
	float fDot5 = fDot2 * fDot2 * fDot;
	return fR0 + (1.0 - fR0) * fDot5 * fSmoothFactor;
}

float GetDiffuseIntensity(const in vec3 vLightDir, const in vec3 vNormal)
{
	return max(0.0, dot(vLightDir, vNormal));
}

float GetBlinnPhongIntensity(const in C_Ray ray, const in C_Material mat, const in vec3 vLightDir, const in vec3 vNormal)
{           
	vec3 vHalf = normalize(vLightDir - ray.vDir);
	float fNdotH = max(0.0, dot(vHalf, vNormal));

	float fSpecPower = exp2(4.0 + 6.0 * mat.fSmoothness);
	float fSpecIntensity = (fSpecPower + 2.0) * 0.125;

	return pow(fNdotH, fSpecPower) * fSpecIntensity;
}

// use distance field to evaluate ambient occlusion
float GetAmbientOcclusion(const in C_Ray ray, const in C_HitInfo intersection, const in vec3 vNormal)
{
	vec3 vPos = intersection.vPos;
       
	float fAmbientOcclusion = 1.0;
       
	float fDist = 0.0;
	for(int i=0; i<=5; i++)
	{
		fDist += 0.1;

		vec4 vSceneDist = GetDistanceScene(vPos + vNormal * fDist);

		fAmbientOcclusion *= 1.0 - max(0.0, (fDist - vSceneDist.x) * 0.2 / fDist );                                   
	}
       
	return fAmbientOcclusion;
}
 
vec3 GetObjectLighting(const in C_Ray ray, const in C_HitInfo intersection, const in C_Material material, const in vec3 vNormal, const in vec3 cReflection)
{
	vec3 cScene ;
	
	vec3 vSpecularReflection = vec3(0.0);
	vec3 vDiffuseReflection = vec3(0.0);
	
	float fAmbientOcclusion = GetAmbientOcclusion(ray, intersection, vNormal);
	vec3 vAmbientLight = GetAmbientLight(vNormal) * fAmbientOcclusion;
	
	vDiffuseReflection += vAmbientLight;
	
	vSpecularReflection += cReflection * fAmbientOcclusion;
		       
	#ifdef ENABLE_POINT_LIGHT
	vec3 vLightPos = GetLightPos();
	vec3 vToLight = vLightPos - intersection.vPos;
	vec3 vLightDir = normalize(vToLight);
	float fLightDistance = length(vToLight);
	
	float fAttenuation = 1.0 / (fLightDistance * fLightDistance);
	
	float fShadowBias = 0.1;             
	float fShadowFactor = GetShadow( intersection.vPos + vLightDir * fShadowBias, vLightDir, fLightDistance - fShadowBias );
	vec3 vIncidentLight = GetLightCol() * fShadowFactor * fAttenuation;
	
	vDiffuseReflection += GetDiffuseIntensity( vLightDir, vNormal ) * vIncidentLight;                                                                                 
	vSpecularReflection += GetBlinnPhongIntensity( ray, material, vLightDir, vNormal ) * vIncidentLight;
	#endif
	
	vDiffuseReflection *= material.cAlbedo;              
	
	#ifdef ENABLE_SPECULAR
	float fFresnel = Schlick(vNormal, ray.vDir, material.fR0, material.fSmoothness * 0.9 + 0.1);
	cScene = mix(vDiffuseReflection , vSpecularReflection, fFresnel);
	#else
	cScene = vDiffuseReflection;
	#endif
	
	return cScene;
}

vec3 GetSceneColourSimple( const in C_Ray ray )
{
	C_HitInfo intersection;
	Raymarch(ray, intersection, 16.0, 32);
					    
	vec3 cScene;

	if(intersection.vObjectId.x < 0.5)
	{
		cScene = GetSkyGradient(ray.vDir);
	}
	else
	{
		C_Material material = GetObjectMaterial(intersection.vObjectId, intersection.vPos);
		vec3 vNormal = GetSceneNormal(intersection.vPos);

		// use sky gradient instead of reflection
		vec3 cReflection = GetSkyGradient(reflect(ray.vDir, vNormal));

		// apply lighting
		cScene = GetObjectLighting(ray, intersection, material, vNormal, cReflection );
	}

	ApplyAtmosphere(cScene, ray, intersection);

	return cScene;
}

vec3 GetSceneColour( const in C_Ray ray )
{                                                           
	C_HitInfo intersection;
	Raymarch(ray, intersection, 60.0, 256);
			    
	vec3 cScene;
       
	if(intersection.vObjectId.x < 0.5)
	{
		cScene = GetSkyGradient(ray.vDir);
	}
	else
	{
		C_Material material = GetObjectMaterial(intersection.vObjectId, intersection.vPos);
		vec3 vNormal = GetSceneNormal(intersection.vPos);

		#ifdef ENABLE_MONTE_CARLO
		vNormal = normalize(vNormal + gRandomNormal / (5.0 + material.fSmoothness * 200.0));
		#endif

		vec3 cReflection;
		#ifdef ENABLE_REFLECTIONS    
		{
			// get colour from reflected ray
			float fSepration = 0.05;
			C_Ray reflectRay;
			reflectRay.vDir = reflect(ray.vDir, vNormal);
			reflectRay.vOrigin = intersection.vPos + reflectRay.vDir * fSepration;
															      
			cReflection = GetSceneColourSimple(reflectRay);                                                                         
		}
		#else
		cReflection = GetSkyGradient(reflect(ray.vDir, vNormal));                               
		#endif
		// apply lighting
		cScene = GetObjectLighting(ray, intersection, material, vNormal, cReflection );
	}
       
	ApplyAtmosphere(cScene, ray, intersection);
       
	return cScene;
}

void GetCameraRay( const in vec3 vPos, const in vec3 vForwards, const in vec3 vWorldUp, out C_Ray ray)
{
	vec2 vPixelCoord = gl_FragCoord.xy;
	#ifdef ENABLE_MONTE_CARLO
	vPixelCoord += gPixelRandom.zw;
	#endif
	vec2 vUV = ( vPixelCoord / resolution.xy );
	vec2 vViewCoord = vUV * 2.0 - 1.0;

	vViewCoord *= 0.75;
       
	float fRatio = resolution.x / resolution.y;

	vViewCoord.y /= fRatio;                           

	ray.vOrigin = vPos;

	vec3 vRight = normalize(cross(vForwards, vWorldUp));
	vec3 vUp = cross(vRight, vForwards);
	    
	ray.vDir = normalize( vRight * vViewCoord.x + vUp * vViewCoord.y + vForwards);        
}

void GetCameraRayLookat( const in vec3 vPos, const in vec3 vInterest, out C_Ray ray)
{
	vec3 vForwards = normalize(vInterest - vPos);
	vec3 vUp = vec3(0.0, 1.0, 0.0);

	GetCameraRay(vPos, vForwards, vUp, ray);
}

vec3 OrbitPoint( const in float fHeading, const in float fElevation )
{
	return vec3(sin(fHeading) * cos(fElevation), sin(fElevation), cos(fHeading) * cos(fElevation));
}

vec3 Gamma( const in vec3 cCol )
{
	return cCol * cCol;
}

vec3 InvGamma( const in vec3 cCol )
{
	return sqrt(cCol);
}


vec3 Tonemap( const in vec3 cCol )
{
	// simple Reinhard tonemapping operator     
	vec3 vResult = cCol / (1.0 + cCol);

	return Gamma(vResult);
}

vec3 InvTonemap( const in vec3 cCol )
{
	vec3 vResult = cCol;
	vResult = clamp(vResult, 0.01, 0.99);
	vResult = InvGamma(vResult);
	return - (vResult / (vResult - 1.0));
}

void main( void )
{

  vec2 uv = gl_TexCoord[0].xy;
  vec2 p = -1.0 + 2.0 * uv;
	//vec2 p = gl_FragCoord.xy / resolution;


	#ifdef ENABLE_MONTE_CARLO             
	CalcPixelRandom();
	#endif
       
	C_Ray ray;
       
	const float fCamreaInitialHeading = 0.5;
	const float fCamreaInitialElevation = 0.5;
	const float fCamreaInitialDist = 20.0;
	const float fCameraHeight = 0.01;
	const float fOrbitSpeed = 1.0;
	
	// This magic stolen from other 3d pan/zoom examples
	float fZoom = surfaceSize.y * 0.5 + 0.4;
	
	//vec2 vCenterPosition = (0.5 - ( gl_FragCoord.xy / resolution )) * surfaceSize + surfacePosition;
	//vec2 vCenterPosition = (0.5 - ( uv )) * surfaceSize + surfacePosition;
	vec2 vCenterPosition = p * surfaceSize + surfacePosition;
	float fHeading = vCenterPosition.x * fOrbitSpeed + fCamreaInitialHeading;
	float fElevation = (vCenterPosition.y * fOrbitSpeed + fCamreaInitialElevation);
	
	vec3 vCameraPos = OrbitPoint(fHeading, fElevation) * fCamreaInitialDist * fZoom;
	
	vCameraPos += vec3(0.0, -fCameraHeight, 0.0);
	#ifdef ENABLE_MONTE_CARLO             
	float fDepthOfField = 0.1;
	vCameraPos += gRandomNormal * fDepthOfField;
	#endif
       
	GetCameraRayLookat( vCameraPos, vec3(0.0, 0.0, 0.0), ray);
	//GetCameraRayLookat(vec3(0.0, 0.0, -5.0), vec3(0.0, 0.0, 0.0), ray);
       
	vec3 cScene = GetSceneColour( ray );   
       
	float fExposure = 3.5;
	cScene = cScene * fExposure;
       
	#ifdef ENABLE_MONTE_CARLO                              
	vec3 cPrev = texture2D(backbuffer, gl_FragCoord.xy / resolution).xyz;
	//vec3 cPrev = texture2D(backbuffer, uv).xyz;
	// add noise to pixel value (helps values converge)
	cPrev += (gPixelRandom.xyz - 0.5) * (1.0 / 255.0);
	cPrev = InvTonemap(cPrev);
	// converge speep
	float fBlend = 0.1;
	vec3 cFinal = mix(cPrev, cScene, fBlend);
	#else
	vec3 cFinal = cScene;
	#endif
	
	cFinal = Tonemap(cFinal);
       	
	float fAlpha = 1.0;
       
	gl_FragColor = vec4( cFinal, fAlpha );
}
]]></raw_data_ps>

</gpu_program>


<gpu_program name="viewer_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[	 
uniform sampler2D tex0;
void main(void)
{
  gl_FragColor = texture2D(tex0, gl_TexCoord[0].xy).rgba;
}
  ]]></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()



PF_U8_RGB = 1
PF_U8_BGR = 2
PF_U8_RGBA = 3
PF_U8_BGRA = 4
PF_F32_RGB = 5
PF_F32_RGBA = 6
PF_F32_R = 7

buffer_rt1 = gh_render_target.create_ex(winW, winH, PF_U8_RGBA, 1, 0)
buffer_rt2 = gh_render_target.create_ex(winW, winH, PF_U8_RGBA, 1, 0)
back_buffer_rt = buffer_rt1
front_buffer_rt = buffer_rt2

gh_render_target.bind(back_buffer_rt)
gh_renderer.set_depth_test_state(1)
gh_renderer.set_scissor_state(0) 
gh_renderer.clear_color_depth_buffers(0.0, 0.0, 0.0, 0.0, 1.0)
gh_render_target.bind(0)

gh_render_target.bind(front_buffer_rt)
gh_renderer.set_depth_test_state(1)
gh_renderer.set_scissor_state(0) 
gh_renderer.clear_color_depth_buffers(0.0, 0.0, 0.0, 0.0, 1.0)
gh_render_target.bind(0)


local cam_persp = moon3d.camera.getDefaultPersp()
moon3d.camera.setPosition(cam_persp, 0, 0, 20)

--[[
local aspect = winW / winH
camera = gh_camera.create_persp(60, aspect, 0.1, 1000.0)
gh_camera.set_viewport(camera, 0, 0, winW, winH)
gh_camera.setpos(camera, 0, 0, 20)
gh_camera.setlookat(camera, 0, 0, 0)
gh_camera.setupvec(camera, 0, 1, 0, 0)
--]]

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

viewer_prog = gh_node.getid("viewer_prog")

moon3d.madshaders.resetBenchmarkData()

		]]></raw_data>
	</script> 

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

moon3d.startFrame_v2()

local global_time = moon3d.getTime()

moon3d.madshaders.updateBenchmarkData(global_time)


if (back_buffer_rt == buffer_rt2) then
  back_buffer_rt = buffer_rt1
  front_buffer_rt = buffer_rt2
else  
  back_buffer_rt = buffer_rt2
  front_buffer_rt = buffer_rt1
end

gh_render_target.bind(front_buffer_rt)

gh_renderer.set_depth_test_state(0)
gh_renderer.set_scissor_state(0) 

moon3d.camera.bindPersp()
--moon3d.camera.bind(camera)

gh_renderer.clear_color_depth_buffers(0.0, 0.0, 0.0, 1.0, 1.0)

gh_texture.rt_color_bind(back_buffer_rt, 0)

moon3d.graphics.bindGpuProgram(glslsandbox_prog)
moon3d.madshaders.setGLSLSandboxBackBuffer(glslsandbox_prog, 0)
moon3d.madshaders.updateGLSLSandboxCommonParams(glslsandbox_prog, global_time)

gh_gpu_program.uniform2f(glslsandbox_prog, "surfaceSize", winW/winH, 1.0)

moon3d.graphics.draw(quad)



gh_render_target.bind(0)
moon3d.camera.bindOrtho()
gh_renderer.set_viewport(0, 0, winW, winH)
gh_renderer.clear_color_buffer(0.0, 0.0, 0.0, 1.0, 1.0)
gh_renderer.set_depth_test_state(0)
gh_texture.rt_color_bind(back_buffer_rt, 0)
moon3d.graphics.bindGpuProgram(viewer_prog)
moon3d.graphics.draw(quad)


moon3d.madshaders.displayBenchmarkInfoV2("GLSLSandbox/#6254.0", 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)
--moon3d.camera.updatePerspectiveProjection(camera, 60, winW/winH, 1.0, 1000.0)

gh_render_target.resize(buffer_rt1, winW, winH)
gh_render_target.resize(buffer_rt2, winW, winH)

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