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

<glsl_hacker>
	
  <window name="win3d01" title="MadShaders - Shadertoy/Hammer 2D Grid" 
          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/ld23Dm
  
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;


bool onGridline(int distFrom, int spacing);
bool onSplitline(int distFrom, int spacing, int interval);

void main(void)
{
	// Colours , used to return to gl_FragColor depending on criteria.
	const vec4 cBackground = vec4(0.0,0.0,0.0,1.0);			// Background colour.
	const vec4 cOrigin = vec4(0.0,0.392,0.392,1.0);			// Frag is directly in line with mouse's X or Y.
	const vec4 cLargeSplit = vec4(0.392,0.18,0.004,1.0);	// Frag is on a large split line.
	const vec4 cMedSplit = vec4(0.449,0.449,0.449,1.0);		// Frag is on a medium split line.
	const vec4 cGridline = vec4(0.293,0.293,0.293,1.0);		// Frag is on a grid line.
	
	// Grid lines
	const int spacingStd = 16;			// Spacing of normal grid lines
	const int intervalLargeSplit = 16;	// On how many gridlines a large split occurs.
	const int intervalMedSplit = 8;		// On how many gridlines a medium split occurs.
	const float zoom = 1.0;			// Zoom level of the grid.
	
	// Effective spacing
	// This is the standard grid spacing, as an integer, once zoom has been applied.
	// We do this here and use this value later to avoid float rounding errors.
	int effGrid = int(floor((float(spacingStd) * zoom) + 0.5));
	
	// Convenience integer values for resolution and frag position.
	int fragX = int(gl_FragCoord.x - 0.5);
	int fragY = int(gl_FragCoord.y - 0.5);
	int width = int(iResolution.x);
	int height = int(iResolution.y);
	
	// The offsets to the original mouse position were found by trial and error.
	int mouseX = int(iMouse.x);
	int mouseY = int(iMouse.y - 1.0);
	
	// Distance this frag is from the mouse position, in each axis.
	int xDistFrom = int(abs(float(mouseX - fragX)));
	int yDistFrom = int(abs(float(mouseY - fragY)));
	
	// ============================================================
	
	// If on same X or Y as mouse, paint with origin colour.
	if ( fragX == mouseX || fragY == mouseY )
	{
		gl_FragColor = cOrigin;
		return;
	}
	
	// If on grid line, decide which colour to paint.
	else if ( onGridline(xDistFrom, effGrid) || onGridline(yDistFrom, effGrid) )
	{
		// If on large split line, choose this first.
		if ( onSplitline(xDistFrom, effGrid, intervalLargeSplit) ||
		     onSplitline(yDistFrom, effGrid, intervalLargeSplit))
		{
			gl_FragColor = cLargeSplit;
			return;
		}
		
		// Then check medium split line.
		else if ( onSplitline(xDistFrom, effGrid, intervalMedSplit) ||
		     onSplitline(yDistFrom, effGrid, intervalMedSplit))
		{
			gl_FragColor = cMedSplit;
			return;
		}
		
		// Otherwise, return normal grid line colour.
		else
		{
			gl_FragColor = cGridline;
			return;
		}
	}
	
	// Fragment is not in line with any grid line - paint as background.
	gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}

// @brief Returns whether the given fragment distance from the mouse axis lies on a grid line.
// @param distFrom Units the fragment is away from the mouse axis value. 0 = on the same axis.
// @param spacing The units between each consecutive grid line.
// @return True if distFrom lies on a gridline, false otherwise.
bool onGridline(int distFrom, int spacing)
{
	return mod(float(distFrom), float(spacing)) == 0.0;
}

// @brief Returns whether the given fragment distance from the mouse axis lies on a split line.
// @param distFrom Units the fragment is away from the mouse axis value. 0 = on the same axis.
// @param spacing The units between each consecutive grid line.
// @param interval On how many gridlines a split occurs. Eg. 4 would imply a split every 4
//		  grid spacing amounts.
// @return True if distFrom lies on the split line, false otherwise.
bool onSplitline(int distFrom, int spacing, int interval)
{
	int newSpacing = spacing * interval;
	
	return mod(float(distFrom), float(newSpacing)) == 0.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.displayBenchmarkInfoV2("Shadertoy/hammer 2d grid", 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>
