// © Copyright 2023 timetravelbeard (contact: https://www.patreon.com/timetravelbeard , https://youtube.com/@timetravelbeard3588 , https://discord.gg/S6F4r6K5yU )

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//NOTE:  In case you don't know, copyright means all rights are reserved. You cannot modify, redistribute, or make derivative works of this. Do not steal any of this code or use "code snippets". 


#define RAY_BIAS -0.0001 //[-0.0001 0.0]
#define REFINER_STEPS_RAY 3 //[0 1 2 3 4 5 6 7 8 9 10] //fractal refinement of ray collission position

vec3 ray_emit= vec3(0.0);
vec3 ray_emit2= vec3(0.0);

vec3 diffuse_angle =  bumpy_orth.xyz;

#include "/settings_1.glsl"
int PBR_RAY_STEPS2 = int((float(PBR_RAY_STEPS) * PATH_TRACING_RESOLUTION)) ;//((PBR_RAY_STEPS>0)?1:0) );
PBR_RAY_STEPS2=(PBR_RAY_STEPS>0&&PBR_RAY_STEPS2==0)?1:PBR_RAY_STEPS2;
				 tangent2.xyz = normalize(cross(tangent.xyz,diffuse_angle.xyz));//*tangent.w);

				
				tangent = tangent *2-1;
				tangent2 = tangent2 *2-1;
				tangent.z*=-1;
				tangent2.z*=-1;
				
				//debug
				reflected_angle_orth.xy*=-1;
				
				
				#if SCREEN_TANGENT == 0
					tangent.xyz=vec3(1,0,0);
					tangent2.xyz=vec3(0,1,0);
					// diffuse_angle = vec3(0.0,0.0,-1.0); //bumpy_orth.xyz
					// reflected_angle_orth.xy/= texcoord.xy,-texture2D(colortex15,raypos.xy).z;
					//tangent.z*=-1;
				#endif
				reflected_angle_orth=normalize(reflected_angle_flat);
				
				
			//debug
				//debugvalue3  =.5+.5*diffuse_angle;
				//debugvalue3  =.5+.5*reflected_angle_orth;
				
				//ray trace reflections
				bool rayhit = false;
				bool oob = false;
				vec3 reflection_rgb = vec3(0.0);
				vec3 raypos;// = vec3(texcoord.xy,texture2D(depthtex0,texcoord.xy).x);//+reflected_angle;
				vec3 rayspeed ;//= reflected_angle_orth*1.0/PBR_RAY_STEPS2;
				vec3 oobrgb=vec3(0.0);
				float fadesky_complete=0;
				
				 
				 raypos = vec3(texcoord.xy,texture2D(depthtex0,texcoord.xy).x);//+reflected_angle;
				 rayspeed = reflected_angle_orth*1.0/PBR_RAY_STEPS2;
				 oobrgb=vec3(0.0);
				//raypos+=rayspeed;
						
				int raystepss = 0;
				
				
				
				for(raystepss = 0;raystepss<0&&!oob&&!rayhit;raystepss++)
				{ 
				    
					raypos+=vec3(rayspeed.xy/abs(raypos.z),.015*rayspeed.z/abs(raypos.z));
					rayspeed*=1.05;
					//rayspeed=(reflected_angle_orth*.01)*(1+.1*raystepss);
					//rayspeed.xyz/=((1+raypos.z));
					oob = raypos.x<0 || raypos.x>1 || raypos.y<0 || raypos.y> 1 || raypos.z<0? true: false;
					oobrgb.g= raypos.y<0 || raypos.y>1 ? 1:0;
					oobrgb.r= raypos.x<0 || raypos.x>1 ? 1:0;
					oobrgb.b= raypos.z<0 || raypos.z>1 ? 1:0;
					rayhit = oob? false :(texture2D(depthtex0,raypos.xy).x) <  raypos.z ? true : false;
					//reflection_rgb = rayhit? rayhit
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				float fadesky = oobrgb.r* (texcoord.x<.05?1-texcoord.x/.05: texcoord.x>.95?(texcoord.x-.95)/.05:0);
				//fade lower on screen, looking up is actually looking horizontally
				float looking_up=1-clamp(abs((distance(uppos,vec3(0.0,0.0,1.0))/(1*1.41))-1.0),0,1);
				fadesky = fadesky + looking_up* oobrgb.r*(1-raypos.y);//ffade sky lower on screen
				//fadesky = raypos.z<0? fadesky + looking_up*oobrgb.b*(1):fadesky;//ffade sky lower on screen
				fadesky = raypos.y<0?fadesky +looking_up*(1-raypos.y): fadesky;//ffade sky lower on screen
				
				fadesky =clamp(fadesky+ oobrgb.g* (texcoord.y<.05?1-texcoord.y/.05: texcoord.y>.95?(texcoord.y-.95)/.05:0) ,0.0,1.0);
				
			
				
				//raytrace reflections2
				 fadesky_complete=0;
				int numddiffrays=5;
				#if HALF_RAYS == 1
					sky_reflection = 0.0;
				#else
				vec3 reflection_color_total = vec3(0.0);
				
				
				//
				//ray cone setup
				 int w = RAY_NUM_W ;
				 int h = RAY_NUM_H ;
				 
			     float iw = 1.0/w;
			     float ih = 1.0/h;
			     
			     vec3 t1,t2;
			     
			      #if RAY_FULLY_CONVERGE == 0
			      int ray_num= 4*w*h;
			      #else
			      int ray_num= 4*w*h+1;
				 #endif
				 int NUM_RAYS_SPECULAR = ray_num;
				 
	vec3 goal = reflected_angle_orth.xyz; // or diffuse  normal
	
	float focus = mix(0.1,1.0,smoothness);;//or 0.1, etc
				
				//
				
				
				 #include "/raycone.glsl"
				  
				 rayhit = false;
				
				 raypos = vec3(texcoord.xy,-texture2D(colortex15,texcoord.xy).z);//+reflected_angle;
				
				
				 oobrgb=vec3(0.0);
				//raypos+=rayspeed;
				
				 oob = false;
				 raystepss = 0;
				 rayspeed=.25*normalize(rayspeed)/PBR_RAY_STEPS2;
				// raypos-=.5*vec3(rayspeed.xy/abs(raypos.z),rayspeed.z);
				 //raypos+=0.2*rayspeed*clamp(texture2D(noisetex, texcoord.xy).g,0.0,1.0);
				 #if NUM_RAYS_SPECULAR == 5
					 raypos+=0.3*rayspeed*blueNoise()*clamp(1.0-0.8*smoothness,0.3,1.0);
				 #else
					 raypos+=0.2*rayspeed*blueNoise()*clamp(1*1.0-smoothness,0.0,1.0);
				 #endif
				rayspeed.x*=.5;
				vec3 ray_color = vec3(0.0);
				
				//first step
				if(PBR_RAY_STEPS2<40)
				{ 
				    vec3 rayspeed2 = rayspeed * PBR_RAY_STEPS2/20;
					raypos+=vec3(rayspeed2.xy,rayspeed2.z*abs(raypos.z+1));
					//rayspeed*=1.05;
					//rayspeed=(reflected_angle_orth*.01)*(1+.1*raystepss);
					//rayspeed.xyz/=((1+raypos.z));
					oob = raypos.x<0 || raypos.x>1 || raypos.y<0 || raypos.y> 1 || raypos.z<0|| raypos.z>far? true: false;
					oobrgb.g= raypos.y<0 || raypos.y>1 ? 1:0;
					oobrgb.r= raypos.x<0 || raypos.x>1 ? 1:0;
					oobrgb.b= raypos.z<0 || raypos.z>far ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
					rayhit = oob? false :(bgdepth)-RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH) >  raypos.z  ? true : false;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				
				for(raystepss = 0;raystepss<PBR_RAY_STEPS2&&!oob&&!rayhit;raystepss++)
				{ 
				    
					raypos+=vec3(rayspeed.xy,rayspeed.z*abs(raypos.z+1));
					rayspeed*=1.05;
					//rayspeed=(reflected_angle_orth*.01)*(1+.1*raystepss);
					//rayspeed.xyz/=((1+raypos.z));
					oob = raypos.x<0 || raypos.x>1 || raypos.y<0 || raypos.y> 1 || raypos.z<0|| raypos.z>far? true: false;
					oobrgb.g= raypos.y<0 || raypos.y>1 ? 1:0;
					oobrgb.r= raypos.x<0 || raypos.x>1 ? 1:0;
					oobrgb.b= raypos.z<0 || raypos.z>far ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
					rayhit = oob? false :(bgdepth)-RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH) >  raypos.z  ? true : false;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				//
				#if SPECULAR_BOUNCE_LIGHT > 0
				if(rayhit)
				{
				//refine pos
				float reverse = -1.0;
				for(raystepss = 0;raystepss<REFINER_STEPS_RAY;raystepss++)
				{ 
				    rayspeed*=.5;
					raypos+=reverse*vec3(rayspeed.xy,rayspeed.z*abs(raypos.z+1));
					
					//rayspeed=(reflected_angle_orth*.01)*(1+.1*raystepss);
					//rayspeed.xyz/=((1+raypos.z));
					oob = raypos.x<0 || raypos.x>1 || raypos.y<0 || raypos.y> 1 || raypos.z<0|| raypos.z>far? true: false;
					oobrgb.g= raypos.y<0 || raypos.y>1 ? 1:0;
					oobrgb.r= raypos.x<0 || raypos.x>1 ? 1:0;
					oobrgb.b= raypos.z<0 || raypos.z>far ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
					reverse = oob? 1.0 :(bgdepth)-RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH) >  raypos.z  ? -1.0 : 1.0;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				
				//
					ray_color =textureLod(colortex3,raypos.xy,0).rgb; // albedo2*(shadow_info.x ) ;
					//ray_emit += albedo2*PBR_EMMISSIVE_STRENGTH*emmissiveness2;
					
				}
				#endif
				//
				reflection_color_total+=ray_color;
				 fadesky = oobrgb.r* (texcoord.x<.05?1-texcoord.x/.05: texcoord.x>.95?(texcoord.x-.95)/.05:0);
				 fadesky =clamp(fadesky+ oobrgb.g* (texcoord.y<.05?1-texcoord.y/.05: texcoord.y>.95?(texcoord.y-.95)/.05:0) ,0.0,1.0);
			    //
				 //fadesky = oobrgb.r* (texcoord.x<.05?1-texcoord.x/.05: texcoord.x>.95?(texcoord.x-.95)/.05:0);
				//fade lower on screen, looking up is actually looking horizontally
				float looking_up=1-clamp(abs((distance(uppos,vec3(0.0,0.0,1.0))/(1*1.41))-1.0),0,1);
				
				//debug
				looking_up=0.0;
				
				fadesky = fadesky + looking_up* oobrgb.r*(1-raypos.y);//ffade sky lower on screen
				//fadesky = raypos.z<0? fadesky + looking_up*oobrgb.b*(1):fadesky;//ffade sky lower on screen
				fadesky = raypos.y<0?fadesky +looking_up*(1-raypos.y): fadesky;//ffade sky lower on screen
				
				fadesky =clamp(fadesky+ oobrgb.g* (texcoord.y<.05?1-texcoord.y/.05: texcoord.y>.95?(texcoord.y-.95)/.05:0) ,0.0,1.0);
				
				
				//
				fadesky=rayhit?1.0:fadesky;
				
				
				 fadesky_complete+=fadesky;
				
				
				  }  }//xy, wh
				 }//s
				 #if RAY_FULLY_CONVERGE == 1
				  }}
				  #endif
				 //per ray
				
				
				 #endif
				 

				 reflection_color_total=reflection_color_total/(NUM_RAYS_SPECULAR);
				 ray_emit=ray_emit/(NUM_RAYS_SPECULAR);
				 fadesky_complete=clamp(fadesky_complete/(NUM_RAYS_SPECULAR),0.0,1.0);
				sky_light_cpf=sky_light_cpf*(1-fadesky_complete);
				sky_light_cpf=rayhit?sky_light_cpf*0.0:sky_light_cpf*(1-fadesky);
				
				
				//raytrace ambient
				 fadesky_complete=0;
				 numddiffrays=5;
				 vec3 reflection_color_total2 = vec3(0.0);
				 
				 
				  //
				//ray cone setup
				  w = RAY_NUM_W ;
				  h = RAY_NUM_H ;
				 
			      iw = 1.0/w;
			      ih = 1.0/h;
			     
			     
			     
			      #if RAY_FULLY_CONVERGE == 0
			       ray_num= 4*w*h;
			      #else
			       ray_num= 4*w*h+1;
				 #endif
				 int NUM_RAYS_DIFFUSE = ray_num;
				 
	 goal = diffuse_angle.xyz; // or diffuse  normal
	
	 focus = 0.1;;//or 0.1, etc
				
				//
				
		
				 
				 #include "/raycone.glsl"
				 
				
				 rayhit = false;
				
				 raypos = vec3(texcoord.xy,-texture2D(colortex15,texcoord.xy).z);//+reflected_angle;
				 
				 
			
				
				 oobrgb=vec3(0.0);
				//raypos+=rayspeed;
				 oob = false;
				 raystepss = 0;
				 #if HALF_RAYS == 1
					rayspeed= mix(rayspeed.xyz,reflected_angle_orth.xyz,smoothness);
				 #endif
				 
				 rayspeed=0.5*normalize(rayspeed)/PBR_RAY_STEPS2;
				 //raypos-=.5*vec3(rayspeed.xy/abs(raypos.z),rayspeed.z);
				 #if HALF_RAYS == 1
					 #if NUM_RAYS_DIFFUSE == 5
						 raypos+=0.3*rayspeed*blueNoise()*clamp(1.0-0.8*smoothness,0.3,1.0);
					 #else
						 raypos+=0.2*rayspeed*blueNoise()*clamp(1*1.0-smoothness,0.0,1.0);
					 #endif
				#else
				 //just diffuse
					 #if NUM_RAYS_DIFFUSE == 5
						 raypos+=0.3*rayspeed*blueNoise();//*clamp(1.0-0.8*smoothness,0.3,1.0);
					 #else
						 raypos+=0.2*rayspeed*blueNoise();//*clamp(1*1.0-smoothness,0.0,1.0);
					 #endif
				#endif
				 rayspeed.x*=.5;
				vec3 ray_color = vec3(0.0);
				
				//first step
				if(PBR_RAY_STEPS2<40)
				{ 
				    vec3 rayspeed2 = rayspeed * PBR_RAY_STEPS2/20;
					raypos+=vec3(rayspeed2.xy,rayspeed2.z*abs(raypos.z+1));
					//rayspeed*=1.05;
					//rayspeed=(reflected_angle_orth*.01)*(1+.1*raystepss);
					//rayspeed.xyz/=((1+raypos.z));
					oob = raypos.x<0 || raypos.x>1 || raypos.y<0 || raypos.y> 1 || raypos.z<0|| raypos.z>far? true: false;
					oobrgb.g= raypos.y<0 || raypos.y>1 ? 1:0;
					oobrgb.r= raypos.x<0 || raypos.x>1 ? 1:0;
					oobrgb.b= raypos.z<0 || raypos.z>far ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
					rayhit = oob? false :(bgdepth)-RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH) >  raypos.z  ? true : false;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				
				for(raystepss = 0;raystepss<PBR_RAY_STEPS2&&!oob&&!rayhit;raystepss++)
				{ 
				    
					raypos+=vec3(rayspeed.xy,rayspeed.z*abs(raypos.z+1));
					rayspeed*=1.05;
					//rayspeed=(reflected_angle_orth*.01)*(1+.1*raystepss);
					//rayspeed.xyz/=((1+raypos.z));
					oob = raypos.x<0 || raypos.x>1 || raypos.y<0 || raypos.y> 1 || raypos.z<0? true: false;
					oobrgb.g= raypos.y<0 || raypos.y>1 ? 1:0;
					oobrgb.r= raypos.x<0 || raypos.x>1 ? 1:0;
					oobrgb.b= raypos.z<0 || raypos.z>1 ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
					rayhit = oob? false :(bgdepth)-RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH) >  raypos.z  ? true : false;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				 fadesky = oobrgb.r* (texcoord.x<.05?1-texcoord.x/.05: texcoord.x>.95?(texcoord.x-.95)/.05:0);
				 fadesky =clamp(fadesky+ oobrgb.g* (texcoord.y<.05?1-texcoord.y/.05: texcoord.y>.95?(texcoord.y-.95)/.05:0) ,0.0,1.0);
			     fadesky=rayhit?1.0:fadesky;
				 fadesky_complete+=fadesky;
				 
				 #if DIFFUSE_BOUNCE_LIGHT > 0
				 if(rayhit)
				{
				//refine pos
				float reverse = -1.0;
				for(raystepss = 0;raystepss<REFINER_STEPS_RAY;raystepss++)
				{ 
				    rayspeed*=.5;
					raypos+=reverse*vec3(rayspeed.xy,rayspeed.z*abs(raypos.z+1));
					
					//rayspeed=(reflected_angle_orth*.01)*(1+.1*raystepss);
					//rayspeed.xyz/=((1+raypos.z));
					oob = raypos.x<0 || raypos.x>1 || raypos.y<0 || raypos.y> 1 || raypos.z<0|| raypos.z>far? true: false;
					oobrgb.g= raypos.y<0 || raypos.y>1 ? 1:0;
					oobrgb.r= raypos.x<0 || raypos.x>1 ? 1:0;
					oobrgb.b= raypos.z<0 || raypos.z>far ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
					reverse = oob? 1.0 :(bgdepth)-RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH) >  raypos.z  ? -1.0 : 1.0;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				
				//
					ray_color =textureLod(colortex3,raypos.xy,0).rgb; // 
					//ray_emit2 += albedo2*PBR_EMMISSIVE_STRENGTH*emmissiveness2;
					// *.01*directLightCol.rgb
				}
				#endif
				//
				reflection_color_total2+=ray_color;
				 
			  }  }//xy, wh
				 }//s
				  #if RAY_FULLY_CONVERGE == 1
				  }}
				  #endif
				 //per ray
				 
				 
				 fadesky_complete=clamp(fadesky_complete/(NUM_RAYS_DIFFUSE),0.0,1.0);
				  ray_emit2=ray_emit2/(NUM_RAYS_DIFFUSE);
				 
					sky_light_diffuse=sky_light_diffuse*(1-fadesky_complete);
							//
				 reflection_color_total2=reflection_color_total2/(NUM_RAYS_DIFFUSE);
				 	 #ifdef YOUR_MOM			
				 #endif
				 
				
				 //debugvalue3  =vec3(reflectivity_total);
				 //debugvalue3 = textureLod(colortex3,texcoord.xy,0).rgb;
				 
// © Copyright 2023 timetravelbeard (contact: https://www.patreon.com/timetravelbeard , https://youtube.com/@timetravelbeard3588 , https://discord.gg/S6F4r6K5yU )

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//NOTE:  In case you don't know, copyright means all rights are reserved. You cannot modify, redistribute, or make derivative works of this. Do not steal any of this code or use "code snippets". 

