#version 330 core

in vec4 polozenie;
in vec4 kolor;
in vec2 wspTekstur;
in vec3 polozenie_scena;
in vec3 normalna_scena;
in vec2 polozenie_kamera;

//parametry zrodla swiatla
uniform vec4 Ca = vec4(1,1,1,1);
uniform vec4 Cd = vec4(1,1,1,1);
uniform vec4 Cs = vec4(1,1,1,1);
uniform vec3 PolozenieZrodlaSwiatla = vec3(5,2,1);
uniform vec3 PolozenieKamery = vec3(0,0,1);

//parametry materialu
const float wa = 0.1;
const float wd = 1.0;
//const float ws = 0.3;
uniform vec4 Wa = vec4(wa,wa,wa,1);
uniform vec4 Wd = vec4(wd,wd,wd,1);
uniform vec4 Ws = vec4(0,1,0,1);
uniform float WNs = 100.0;

uniform bool OslabienieOswietlenia = false;
uniform vec3 WspolczynnikiOslabieniaOswietlenia = vec3(1,0,0);

float Oslabienie(float odleglosc)
{
    if(!OslabienieOswietlenia) return 1;
    else return 1.0/(WspolczynnikiOslabieniaOswietlenia[0]+
                     WspolczynnikiOslabieniaOswietlenia[1]*odleglosc+
                     WspolczynnikiOslabieniaOswietlenia[2]*odleglosc*odleglosc);
}

uniform bool Teksturowanie = true;
uniform sampler2D ProbnikTekstury;

vec4 ObliczKolorPhong(vec3 polozenie,vec3 normalna,vec4 kolor)
{
	vec3 R = polozenie;
	vec3 L = PolozenieZrodlaSwiatla-R;
	float odleglosc = length(L);
	float oslabienie = Oslabienie(odleglosc);
	L=normalize(L);
	vec3 N = normalize(normalna);
	float dotLN = dot(L,N);

	vec3 O = 2.0*dotLN*N-L;	//vec3 O = reflect(-L,N);
	vec3 V = normalize(PolozenieKamery-R);
	float dotOVn = pow(max(dot(O,V),0.0),WNs);

	dotLN = max(dotLN,0.0);

	vec4 teksel = vec4(1.0f, 1.0f, 1.0f, 1.0f);
	if(Teksturowanie) teksel = texture(ProbnikTekstury, wspTekstur);

	vec4 _kolor = Wa*Ca*kolor*teksel;
	_kolor+= oslabienie*Wd*Cd*kolor*teksel*dotLN;
	_kolor+= oslabienie*Ws*Cs*dotOVn;
	//_kolor = teksel; //Test teksturowania bez o�wietlenia
	return _kolor;
}

uniform bool CelShading = false;

float DyskretyzujWartosc(float wartosc)
{
	if(wartosc>=0 && wartosc <=0.25) return 0.1;
	if(wartosc>0.25 && wartosc <=0.5) return 0.4;
	if(wartosc>0.5 && wartosc <=0.75) return 0.7;
	return 1;
}

vec4 DyskretyzujKolor(vec4 kolor) //cel-shading
{
	kolor.r = DyskretyzujWartosc(kolor.r);
	kolor.g = DyskretyzujWartosc(kolor.g);
	kolor.b = DyskretyzujWartosc(kolor.b);
	return kolor;
}

vec4 Negatyw(vec4 kolor)
{
	kolor.rgb = 1 - kolor.rgb;
	return kolor;
}

vec4 ZmianaJasnosci(vec4 kolor, float wspolczynnik)
{
	kolor.rgb *= wspolczynnik;
	return kolor;
}

float Jasnosc(vec4 kolor)
{
	return (kolor.r + kolor.g + kolor.b)/3.0;
}

vec4 SkalaSzarosci(vec4 kolor)
{
	float jasnosc = Jasnosc(kolor);
	return vec4(jasnosc, jasnosc, jasnosc, kolor.a);
}

vec4 GammaCorrection(vec4 kolor, float gamma)
{	
	if(gl_FragCoord.x > 400) //demo
		kolor.rgb = pow(kolor.rgb, vec3(1.0/gamma));
	return kolor;
}

vec4 GoochJasnosc(vec4 kolor)
{
	float jasnosc = Jasnosc(kolor);
	kolor.r = jasnosc;
	kolor.g = 0;
	kolor.b = 1 - jasnosc;
	return kolor;
}

vec4 GoochDiffuse(vec3 polozenie,vec3 normalna)
{
	vec3 R = polozenie;
	vec3 L = PolozenieZrodlaSwiatla-R;
	L=normalize(L);
	vec3 N = normalize(normalna);
	float dotLN = dot(L,N);

	float wsp = 0.5 * (1 + dotLN); //[-1,1] -> [0,1]
	vec3 kolorZimny = vec3(255.0/255, 75.0/255, 75.0/255); 	
	vec3 kolorCieply = vec3(159.0/255, 148.0/255, 255.0/255); 	

	//pozniej dodane
	vec3 kolorBazowy = vec3(0.5, 0.5, 0.0); 
	kolorZimny = kolorZimny + kolorBazowy * 0.25;
	kolorCieply = kolorCieply + kolorBazowy * 0.25;
	
	vec3 kolor = mix(kolorZimny, kolorCieply, wsp);
	return vec4(kolor, 1);
}

vec4 FiltrZielony(vec4 kolor)
{
	kolor.r *= 0.05;
	kolor.g *= 0.9;
	kolor.b *= 0.05;
	return kolor;
}

float rand(vec2 pozycja)
{
    return fract(sin(dot(pozycja.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

vec4 Szum(vec4 kolor,vec2 pozycja)
{
	kolor.r *= rand(pozycja);
	kolor.g *= rand(pozycja);
	kolor.b *= rand(pozycja);
	return kolor;
}

out vec4 kolor_out;

void main(void)
{
	kolor_out = ObliczKolorPhong(polozenie_scena,normalna_scena,kolor);
	if(CelShading) kolor_out = DyskretyzujKolor(kolor_out);

	//kolor_out = vec4(polozenie_scena.x,polozenie_scena.y,polozenie_scena.z,1.0);
	//kolor_out = Negatyw(kolor_out); //zadanie: zrobi� negatyw tylko we wskazanym prostok�cie ekranu (xmin, xmax) - (ymin, ymax)
	//kolor_out = ZmianaJasnosci(kolor_out, 0.1);
	//kolor_out = SkalaSzarosci(kolor_out);
	//kolor_out = GammaCorrection(kolor_out, 0.5);
	//kolor_out = GammaCorrection(kolor_out, 2);
	//kolor_out = GoochJasnosc(kolor_out); //uruchamiane po Phong
	//kolor_out = GoochDiffuse(polozenie_scena,normalna_scena); //samodzielny, bez Phonga

	//kolor_out = FiltrZielony(kolor_out); //zrobi� jako zadanie
	//kolor_out = Szum(kolor_out, gl_FragCoord.xy);
	kolor_out = Szum(kolor_out, polozenie_kamera); //wymaga przekazania polozenie_kamera z vertex shadera
}