/*
sky reflection ao

OPTIONS LIGHTING MODES
  ORIGINAL
  BLEND
  PBR
  
put skylight in this file

put diffuse and min ambient in hete too as STRICT NEW PBR

increase gi by max of 2 material reflectivities before fresnel

*/

#define SPECULAR_STRENGTH_ 1.0 //[0.0 0.1 0.25 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.25 1.5 1.75 2.0 2.5 3.0] //Strength of shiny appearance



  #define PBR_QUALITY_CPF 4 // [0 1 2 3 4 5] // Quality of Physically Based Rendering Techniques, like Specular, Porosity, etc, THIS IS ALPHA and in PATCH FORM, IT'LL BE BETTER LATER .  0- None . 1- very basic . 2- occlude sunshine specular and rain wetness indoors . 3- also occlude sun reflections in opposing faces, and reflect sky, deepen metals. 4- specular done proper . 5- variable roughness realistic reflections

#define SUN_SPECULAR_INDOOR_FALLOFF_CPF 2.0 //[ 0.05 0.1 0.15 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.75 2.0 2.5 3.0] // PBR QUALITY 2+ . Limit Specular Sunshine highlights and sky color reflections and rain indoors by this falloff rate. 

#define PBR_AO_CPF 0.5 // [0.0 0.25 0.5 0.75 1.0 ] // Ambient Occlusion from Textures, strength of effect. Darkens crevices

#define PBR_WETNESS_CPF 1.0 // [0.0 0.25 0.5 0.75 1.0 ] // Wetness effect from rain . Darkens porous materials . Adds reflectivity

#define PBR_WETNESS_DARKENING 0.5 // [0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 ] // Wetness effect from rain to Darken porous materials .


#define PBR_SKY_REFLECTION_CPF 1.0 // [0.0 0.25 0.5 0.75 1.0 1.25 1.5 2 3 4 5 ] // strength of effect.  sky color reflected outdoors on upward facing surfaces exposed to sky

#define PBR_AO_SKY_LIGHT_CPF 1.0 // [0.0 0.25 0.5 0.75 1.0] // hide skylight in recesses in walls where occluded in pbr texture packs

#define POM_DEPTH_AS_AO 0 //[0 1]//Use POM Depth as AO

#define FRESNEL_STRENGTH_CPF 1.0 //[ 0.0 0.2 0.5 0.7 1.0 1.5 1.75 2.0] // Material reflectivity increased by viewing angle . strength of effect

#define SPECULAR_LENS_CURVATURE_CPF 0.55 //[ 0.0 0.1 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.52 0.54 0.55 0.56 0.58.6 0.65 0.7 1.0] //FOV this aligns specular highlights on screen and the width of said highlights . CHANGING THIS CAN MISALIGN REFLECTIONS . 0-no curvature to lens, super wide reflections . 0.55 recommended as standard . bigger will curve specular highlights towards off screen and make highlights smaller .

#define SUBSURFACE_SCATTERING_CPF 1.0 //[0.0 0.25 0.5 0.75 1.0]//strength of effect . if you hold a flaslight up to your hand, the red glow is subsurface scattering, it is also sunlight going through the back of leaves to make them softly lit

#define SPECULAR_STYLE_CPF 0 //[0 1 2] //SPEC8ULAR SUN STYLE . 0 - REALISTIC . 1 - STYLIZED  . etc

#define SUN_WIDTH_CPF 0.05 //[ 0.0 0.01 0.02 0.025 0.03 0.04 0.045 0.05 0.055 0.06 0.07 0.075 0.1 0.2 0.3 0.4 0.5] // width of sun in reflections

#define SUN_CRISPNESS 1.0 //[ 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0] // Crispness of sun in perfectly reflective materials, 1.0 is perfectly crisp

#define SKY_AMBIENT_LIGHT 20.0 //[ 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.25 1.5 1.75 2.0 3.0 5 5 6 7.0 8 9 10 11 12 15 20] //AMOUNT OF RAYTRACED AMBIENT SKY DIFFUSE LIGHTING


#define PBR_LIGHTING 1 //[0 1]// 0 is off, 1 is on . Physically Based Rendering . makes stuff shiny and all sorts of good lighting effects

#define PBR_RAY_STEPS 10 //[0 5 10 20 30 40 50 60 70 80 90] //lower is faster, higher is better ray tracing . 0 is off

#define SUN_COLOR_R 1.0 //[ 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0]
#define SUN_COLOR_G 0.9 //[ 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0]
#define SUN_COLOR_B 0.7 //[ 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0]

#define MOON_BRIGHTNESS 1.0 //[ 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.5 1.7 2.0 2.5 3.0 3.5 4.0] 
#define SPECULAR_LOW_END 1.0 //[ 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.5 1.7 2.0 2.5 3.0 3.5 4.0] //how shiny rough surfaces are will be multiplied by this amount

#define PBR_EMMISSIVE_STRENGTH 15 //[ 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 2 3 4 5 6 7 8 9 10 11 12 13 14 15 20 30] //how brightly glowing things glow

#if PBR_QUALITY_CPF != 0
 #define PBR_SPARKLE_CUTOFF 1 //[0 1 2 3 4 5 6 7 8 9 10 1000 ] //Experimental.  debug use , will break things but 1000 looks soft om tree leaves

//normal_target = atlas_uv_to_bilinear_data_normal(pom_target_coord,dist);
vec3 bumpy = (clamp(textureLod(colortex14,texcoord.xy,0).xyz*2.0-1.0,-1.0,1.0));;//normal_tex_to_view_cpf(normal_target.rgb,normal_target.xyz);
//vec3 world_normals = normal_tex_to_world2_cpf(normal_target.rgb);
vec3 bumpy_orth =  bumpy ;
//albedo_target = atlas_uv_to_bilinear_data(pom_target_coord,dist);
//normal_target= atlas_uv_to_bilinear_data_normal(pom_target_coord,dist);
//specular_target=atlas_uv_to_bilinear_data_specular(pom_target_coord,dist);



	
//uniform int worldTime;


//pbr stuff


//lens curvature for specular width
float screen_square = max(viewWidth,viewHeight);
vec3 screen_square_conversion = vec3(viewWidth/screen_square,viewHeight/screen_square,1.0);
vec3 curved_lens;
curved_lens.xy = vec2(gl_FragCoord.x/viewWidth,gl_FragCoord.y/viewHeight)*2-1;
//curved_lens.xy*=1;
curved_lens.z = 0.0;//-(abs(curved_lens.x)+abs(curved_lens.y));
curved_lens*=screen_square_conversion;
//curved_lens * vec2(1.0,1.0);
//curved_lens = -normalize(curved_lens);

//bumpy.x = mix(bumpy.x,0,SPECULAR_LENS_CURVATURE_CPF*abs(curved_lens.x)*(1-bumpy.z)) ;
//bumpy.y = mix(bumpy.y,0,SPECULAR_LENS_CURVATURE_CPF*abs(curved_lens.y)*(1-bumpy.z)) ;
//bumpy.xy =  mix(bumpy.xy, mix(bumpy.xy, curved_lens.xy,SPECULAR_LENS_CURVATURE_CPF*distance(curved_lens.xy,vec2(0.0))) , bumpy.z) ;
//bumpy.z = mix(bumpy.x,0,SPECULAR_LENS_CURVATURE_CPF*abs(curved_lens.x)*(1-bumpy.z)) 

bumpy = normalize(bumpy);


//debug
//sky_exposure_cpf = 1.0;
//reflectivity_angle_face = 1.0;//

#if PBR_QUALITY_CPF != 0 && PBR_QUALITY_CPF != 1
	//limit sunshine reflection indoors
	
	/*
		// Use the texture matrix instead of dividing by 15 to maintain compatiblity for each version of Minecraft
    vec2 LightmapCoords = mat2(gl_TextureMatrix[1]) * gl_MultiTexCoord1.st;
    // Transform them into the [0, 1] range
    LightmapCoords = (LightmapCoords * 33.05f / 32.0f) - (1.05f / 32.0f);
    [...]
	*/
	float sun_allowed_indoors = clamp(mix(1.0,sky_exposure_cpf,SUN_SPECULAR_INDOOR_FALLOFF_CPF) ,0.0,1.0) ; //limit rain to outdoors only
	
	
	float actual_wetness = sun_allowed_indoors< .9 ? 0: wetness;
	//float actual_wetness = wetness;
#else
	float actual_wetness = wetness;
#endif

//wet porosity darkening
float porosity = specular_target.b;
porosity=porosity>=64.5/255?0:porosity;

actual_wetness = actual_wetness * PBR_WETNESS_CPF;

albedo_target.rgb = mix(albedo_target.rgb,vec3(0.0),clamp(actual_wetness*porosity*PBR_WETNESS_CPF*PBR_WETNESS_DARKENING ,0.0,0.5)); //porosity*.5 is darkenning amount

float puddle_depth = actual_wetness - porosity;
//ADD WORLD XYZ NOISE FOR PUDDLE LOCATIONS, KEEP UNDER .5 maybe  SO THEY GET FULL COVERAGE in full rain, or add puddle spottiness intensity slider



//uniform int worldTime



//eye in angle
vec3 eye_in= vec3(0.0);
eye_in.b = -1.0;
#if PBR_QUALITY_CPF != 1
	//albedo_target.r = gl_FragCoord.x;
#endif

	vec3 eye_out = eye_in;
	//eye_out.b = eye_in.b *-1.0;
//bumpy.x = mix(bumpy.x,0,SPECULAR_LENS_CURVATURE_CPF*abs(curved_lens.x)*(1-bumpy.z)) ;
//bumpy.y = mix(bumpy.y,0,SPECULAR_LENS_CURVATURE_CPF*abs(curved_lens.y)*(1-bumpy.z)) ;
eye_out =   mix(eye_out, curved_lens,SPECULAR_LENS_CURVATURE_CPF);
//bumpy.z = mix(bumpy.x,0,SPECULAR_LENS_CURVATURE_CPF*abs(curved_lens.x)*(1-bumpy.z)) 

eye_out = vec3(0.0,0.0,1.0);//normalize(eye_out);


//reflection angle
vec3 reflected_angle = reflect(eye_out,bumpy); 

vec3 relative_position = texture2D(colortex15,texcoord.xy).xyz;
relative_position.z*=-1.0;
vec3 curved_lens2=relative_position;
//curved_lens2.xy*=screen_square_conversion.xy;
//curved_lens2.xy=curved_lens2.xy*2-1;
curved_lens2=normalize(curved_lens2);
bumpy_orth.z*=-1;
vec3 reflected_angle_orth = reflect(curved_lens2,bumpy_orth); //bumpy_orth
vec3 reflected_angle_flat = reflect(vec3(0.0,0.0,1.0),bumpy_orth); //bumpy_orth

//integrate
reflected_angle=reflected_angle_orth;
bumpy=-bumpy_orth;


float f0 = clamp(specular_target.g/(230.5/255),0.04,1.0);

float early_fresnel = clamp(1-distance(reflected_angle,curved_lens2),0.0,1.0);
float fresnel=early_fresnel*early_fresnel;
//fresnel=mix(fresnel*fresnel,clamp((fresnel-.95)*20,0.0,1.0),0.7);
fresnel=fresnel*FRESNEL_STRENGTH_CPF;




//basic reflectivity
float reflectivity = clamp(f0 + actual_wetness + fresnel,0.04,1);
//smoothness, clarity of reflection, puddle edges
float smoothness = min(specular_target.r + clamp(puddle_depth*10,0.0,1.0),0.0);

 #if SPECULAR_STYLE_CPF == 1 
	reflectivity = smoothness;
	#endif
	//reflectivity = 1;//debug

	//angle's reflectivity of sun
	vec3 sun_angle = normalize(sunPosition);
	sun_angle.z*=-1;
	sun_angle=worldTime>13000? -1*sun_angle:sun_angle;//nighttime moon fix
	 float reflectivity_angle = clamp(1-distance(sun_angle,reflected_angle)/1.41,0,1);
	 
	 
	 //pointy reflections vs diffuse, sun
	 #if SPECULAR_STYLE_CPF == 1 
		reflectivity_angle = mix(reflectivity_angle*0.1,clamp((reflectivity_angle*reflectivity_angle),0,1),smoothness);//pointy reflections vs diffuse
	#else
		float low = reflectivity_angle*.2* SPECULAR_LOW_END;
		float mid = reflectivity_angle*reflectivity_angle *0.5;
		
		//widen sun in storms
		float sun_width = SUN_WIDTH_CPF*(1+	rainStrength);
		float sun_crispness =	SUN_CRISPNESS *(1-rainStrength);
		float steep =reflectivity_angle < 1-sun_width * sun_crispness  ? clamp(max(2*(reflectivity_angle*reflectivity_angle-0.5), (reflectivity_angle-(1-sun_width)) /(1-sun_crispness  )),-0.5,1.0) : 1.0 ; //CRISPNESS * reflectivity anhle to siften it
	//	float steep = clamp(max((reflectivity_angle-(1-SUN_WIDTH_CPF))* SUN_CRISPNESS /SUN_WIDTH_CPF,mid-0.5),-0.5,1.0);
		
		 #if SPECULAR_STYLE_CPF == 2 
		 reflectivity_angle = clamp( reflectivity_angle< 0.5? mix(low,mid,2*reflectivity_angle) : mix(mid,steep,2*(reflectivity_angle-.5)) ,0.0,1.0)  ;//pointy reflections vs diffuse
		
		 #else
		 reflectivity_angle = clamp( smoothness< 0.5? mix(low,mid,2*smoothness) : mix(mid,steep,2*(smoothness-.5)) ,0.0,1.0)  ;//pointy reflections vs diffuse
		
	 #endif
	
#endif


#if PBR_QUALITY_CPF == 1
	//just sun, no sky reflection
	reflectivity = reflectivity *  (reflectivity_angle);
	
#endif



#if PBR_QUALITY_CPF == 4
//diffuse lighting, maybe reverse sun (as below) first 
float diffuse_lighting = clamp(distance(sun_angle,bumpy),0.0,2.0);
float diffuse_lighting2=clamp(diffuse_lighting,0.,1.);
float sss = specular_target.b > 63.5/255.0 ? (specular_target.b-63.5/255.0)*.749: 0;
float subsurface_lighting = 1-(diffuse_lighting*(1)*.71);
diffuse_lighting = 1-(diffuse_lighting*(1-.3*sss)*.71);   //sss/1.41
subsurface_lighting = clamp(diffuse_lighting-subsurface_lighting,0.0,1.0);
//subsurface_lighting*=1*SUBSURFACE_SCATTERING_CPF;

float back_lighting = 1*1 *sss ;//* clamp(1.0 - distance(sun_angle,-1*bumpy),0.0,1.0);

#endif

reflectivity=clamp(reflectivity,0,1);

//reflection color
//sun
float moon_light = worldTime<13000 ? 0.0: worldTime>13000 && worldTime< 23000 ? clamp((worldTime-13000)/500.0,0.0,1.0): clamp(1.0-(worldTime- 23000)/100.0,0.0,1.0);
float sunset = clamp((worldTime-12000)/1000.0,0.0,1.0);
vec3 sun_color =   mix( vec3(SUN_COLOR_R,SUN_COLOR_G,SUN_COLOR_B)*(1-sunset) ,vec3(0.07,.07,0.15) * MOON_BRIGHTNESS ,moon_light) ;//sun_color.g = 0.9;sun_color.b = 0.7;


//sun_color*=3;//

vec3 reflection_color = sun_color;

#if PBR_QUALITY_CPF != 1



	//for sky reflection_color
	vec3 sky_color = vec3(0.1);
	sky_color.b=1.0;
	

	
	//sky reflection angle

	//angle's reflectivity of sky
	vec3 uppos = normalize(upPosition)*vec3(0,0,-1);
	
	 float sky_reflectivity_angle = clamp(1-distance(uppos,reflected_angle)/(2*1.41),0,1) ;
	//sky_reflectivity_angle=sky_reflectivity_angle*sky_reflectivity_angle*.35 * PBR_SKY_REFLECTION_CPF ;
	
	//sky_color = mix(vec3(0.0),sky_color, sky_reflectivity_angle);
	
	
	

	#if PBR_QUALITY_CPF != 2 && PBR_QUALITY_CPF != 1 
		//sun occluded by face normal
		//vec3 face_normals = normal_tex_to_view_cpf(vec3(0.5,0.5,1.0));
		//face_normals= (face_normals+1)*.5;
		
		
		#if PBR_QUALITY_CPF == 4
			//sky reflection angle
			//vec3 reflected_angle_face = reflect(normalize(sunPosition),face_normals); 
			//angle's reflectivity of sky
		//	float reflectivity_angle_face = clamp(distance(normalize(-upPosition),face_normals),0,1);
			sky_reflectivity_angle = reflectivity_angle_face <= 0.2 ? sky_reflectivity_angle * reflectivity_angle_face*5  : sky_reflectivity_angle;
		#else
		//sun reflection angle
	//	vec3 reflected_angle_face = reflect(normalize(sunPosition),face_normals); 
				//angle's reflectivity of sun
	//		float reflectivity_angle_face = (dot( eye_in,reflected_angle_face));
	//		reflectivity_angle = reflectivity_angle_face <= 0.2 ? reflectivity_angle * reflectivity_angle_face*5  : reflectivity_angle;
		#endif
		

	#endif

	
	sky_reflectivity_angle = mix( sky_reflectivity_angle, sky_reflectivity_angle *sky_reflectivity_angle,smoothness);//pointy reflections vs diffuse
	sky_reflectivity_angle*= min(reflectivity,reflectivity)* PBR_SKY_REFLECTION_CPF;
	reflectivity_angle = mix( reflectivity_angle,0.0,rainStrength*.5);
	
	#if PBR_QUALITY_CPF != 0 && PBR_QUALITY_CPF != 1

	//no reflections ofvsun and sky indoors
	reflectivity_angle*=sun_allowed_indoors;
	sky_reflectivity_angle*= clamp(1-2*(1-sun_allowed_indoors),0.0,1.0);
	#endif
	
	#if PBR_QUALITY_CPF == 4
		//defer sky light 
		sky_reflection = sky_reflectivity_angle ;
		sky_reflectivity_angle=0;
	#endif
	
	reflectivity= reflectivity*clamp(max(reflectivity_angle,sky_reflectivity_angle),0,1);
	reflection_color=sun_color;//mix(sky_color,clamp(sky_color+sun_color,0,1), reflectivity_angle);
	
	
#endif

float emmissiveness = specular_target.a < 254.5/255.0 ? specular_target.a : 0;

float tex_ao_light_allowed=normal_target.b>0.5/255.0?normal_target.b:1.0;

//diffuse sky ambient
	 float sky_difffuse_angle = clamp(1-.75*distance(uppos,bumpy),0,1);// * PBR_SKY_REFLECTION_CPF;
float diffuse_sky_ambient = reflectivity_angle_face *sun_allowed_indoors* sky_difffuse_angle;
//diffuse_sky_ambient=  mix( diffuse_sky_ambient, diffuse_sky_ambient * tex_ao_light_allowed , PBR_AO_SKY_LIGHT_CPF);
 
 
//grey out sun and sky during rain
reflection_color=mix(reflection_color,vec3(0.5),rainStrength);





//vec3 reflection2 = reflect(eye_out,world_normals);
// reflectivity_angle = clamp(dot( eye_in,reflected_angle),0,1);



//metalness color
float metalness = specular_target.g>=(229.5/255)?1.0 : 0.0;

reflection_color = metalness <1.0 ? reflection_color : reflection_color * albedo_target.rgb;

vec3 metal_color = metalness <1.0 ? vec3(0.5) : mix(albedo_target.rgb*0.5,albedo_target.rgb,early_fresnel);

albedo_target.rgb = metalness>=1.0? mix(albedo_target.rgb,metal_color, clamp(metalness,0.0,1.0)) : albedo_target.rgb ;

//deep black down when not fresnel
//...
//sky reflection
//...







#if POM_DEPTH_AS_AO == 1
tex_ao_light_allowed = min(tex_ao_light_allowed,  normal_target.a);
#endif

//AO: texture ao on sparkle
// reflectivity = (specular_target.b > 0.5 / 255) ? mix( reflectivity, reflectivity * tex_ao_light_allowed , PBR_AO_CPF): reflectivity;
 
//albedo_target.rgb*=color.rgb;//grass



	#if PBR_QUALITY_CPF == 4
		//add diffyse, spec,  no sky light if defering for shadow map
		vec4 highlights;
		highlights.rgb = clamp( albedo_target.rgb* (subsurface_lighting ) *SUBSURFACE_SCATTERING_CPF *sun_color  + reflectivity*reflection_color ,0.0,2.0);
		//AO: texture ao sky light
		  sky_reflectivity_angle=  mix( sky_reflectivity_angle, sky_reflectivity_angle * tex_ao_light_allowed , PBR_AO_SKY_LIGHT_CPF);
	#else
	
		//add specular light and reflections
		albedo_target.rgb=clamp( albedo_target.rgb *(1-reflectivity) + reflectivity*reflection_color ,0,1);
	#endif


//AO: texture ao
  albedo_target.rgb =mix( albedo_target.rgb, albedo_target.rgb * tex_ao_light_allowed , PBR_AO_CPF);

//DEBUG SCREEN CURVATURE
//albedo_target.r = gl_FragCoord.x;///gl_FragCoord.w;
//albedo_target.g = gl_FragCoord.y;///gl_FragCoord.w;

float emmisivity = specular_target.a<1.0/254.5? specular_target.a:0 ;

//fresnel debugging
/*
albedo_target.rgb = vec3(fresnel);
highlights  = vec4(0.0);
sky_reflection = 0.0;
*/

//gl_FragData[1].rgba = vec4(highlights.rgb,emmisivity);
//specular_target= highlights;


//reflectivity_angle_face= (reflectivity_angle_face+1)*.5;

//albedo_target.rgb = vec3((reflectivity_angle_face+1)*.5);
//face_normals= (face_normals+1)*.5;
//albedo_target.rgb = vec3((bumpy+1)*.5);
//albedo_target.rgb = vec3(reflectivity_angle);//ace_normals;//vec3(fresnel);
//albedo_target.rgb = vec3(sun_allowed_indoors);

//albedo_target.rgb = vec3(sky_reflectivity_angle);
//albedo_target.rgb = vec3(normalize(upPosition)*.5+.5);


//albedo_target.rgb=clamp( vec3(0.0) *(1-reflectivity) + reflectivity*reflection_color ,0,1);

//albedo_target.rgb =  reflected_angle *.5 +.5;

//albedo_target.rgb = vec3(.5 + .5*reflectivity_angle_face);

//albedo_target.rg = ((curved_lens.xy+1)*.5);
#if PBR_QUALITY_CPF == 3
//albedo_target.rgb = fract(vec3((gl_FragCoord.x/viewWidth),gl_FragCoord.y/viewHeight,0.5));//;



#endif

//albedo_target.rgb  = vec3(diffuse_lighting);

#if PBR_QUALITY_CPF == 9
#endif

#endif
