/*
CMYK Halftone Dot Shader

Adapted from Stefan Gustavson's GLSL shader demo for WebGL:
http://webstaff.itn.liu.se/~stegu/OpenGLinsights/shadertutorial.html

Ported to Cg shader language by hunterk

This shader is licensed in the public domain, as per S. Gustavson's original license.
Note: the MIT-licensed noise functions have been purposely removed.
*/

/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
   - FX11 compilers
*/

#pragma parameter frequency "CMYK HalfTone Dot Density" 550.0 50.0 1000.0 50.0
#ifdef PARAMETER_UNIFORM
uniform float frequency;
#else
#define frequency 550.0 // controls the density of the dot pattern
#endif

#include "../compat_includes.inc"
uniform COMPAT_Texture2D(decal) : TEXUNIT0;
uniform float4x4 modelViewProj;

struct out_vertex
{
	float4 position : COMPAT_POS;
	float2 texCoord : TEXCOORD0;
#ifndef HLSL_4
	float4 Color    : COLOR;
#endif
};

out_vertex main_vertex(COMPAT_IN_VERTEX)
{
	out_vertex OUT;
#ifdef HLSL_4
	float4 position = VIN.position;
	float2 texCoord = VIN.texCoord;
#else
	OUT.Color = color;
#endif
	OUT.position = mul(modelViewProj, position);
	OUT.texCoord = texCoord;
	
	return OUT;
}

// FRAGMENT SHADER //

float4 cmyk_halftone_dot(float2 texture_size, float2 video_size, float2 output_size, float2 texCoord, COMPAT_Texture2D(decal))
{
    // Distance to nearest point in a grid of
	// (frequency x frequency) points over the unit square
	float2x2 rotation_matrix = float2x2(0.707, 0.707, -0.707, 0.707);
	float2 st2 = mul(rotation_matrix , texCoord);
    float2 nearest = 2.0 * fract(frequency * st2) - 1.0;
    float dist = length(nearest);
    float3 texcolor = COMPAT_SamplePoint(decal, texCoord).rgb; // Unrotated coords
    float3 black = float3(0,0,0);
	
	// Perform a rough RGB-to-CMYK conversion
    float4 cmyk;
    cmyk.xyz = 1.0 - texcolor;
    cmyk.w = min(cmyk.x, min(cmyk.y, cmyk.z)); // Create K
	
	float2x2 k_matrix = float2x2(0.707, 0.707, -0.707, 0.707);
	float2 Kst = frequency * (0.48 * (texture_size / video_size)) * mul(k_matrix , texCoord);
    float2 Kuv = 2.0 * fract(Kst) - 1.0;
    float k = step(0.0, sqrt(cmyk.w) - length(Kuv));
	float2x2 c_matrix = float2x2(0.966, 0.259, -0.259, 0.966);
    float2 Cst = frequency * (0.48 * (texture_size / video_size)) * mul(c_matrix , texCoord);
    float2 Cuv = 2.0 * fract(Cst) - 1.0;
    float c = step(0.0, sqrt(cmyk.x) - length(Cuv));
	float2x2 m_matrix = float2x2(0.966, -0.259, 0.259, 0.966);
    float2 Mst = frequency * (0.48 * (texture_size / video_size)) * mul(m_matrix , texCoord);
    float2 Muv = 2.0 * fract(Mst) - 1.0;
    float m = step(0.0, sqrt(cmyk.y) - length(Muv));
    float2 Yst = frequency * (0.48 * (texture_size / video_size)) * texCoord; // 0 deg
    float2 Yuv = 2.0 * fract(Yst) - 1.0;
    float y = step(0.0, sqrt(cmyk.z) - length(Yuv));
	
	float3 rgbscreen = 1.0 - 0.9 * float3(c,m,y);
	rgbscreen = lerp(rgbscreen, black, 0.85 * k);
	
	float afwidth = 2.0 * frequency * max(length(video_size / (output_size * texture_size)), length(video_size / (output_size * texture_size)));
	float blend = smoothstep(0.0, 1.0, afwidth);
	
    float4 color = float4(lerp(rgbscreen , texcolor, blend), 1.0);
	color = (max(texcolor.r, max(texcolor.g, texcolor.b)) < 0.01) ? float4(0,0,0,0) : color; // make blacks actually black

	return color;
}

float4 main_fragment(COMPAT_IN_FRAGMENT) : COMPAT_Output
{
	return cmyk_halftone_dot(COMPAT_texture_size, COMPAT_video_size, COMPAT_output_size, VOUT.texCoord, decal);
}
COMPAT_END