// © 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". 

float raylod3 = log2(float(textureSize(colortex3, 0).x));
float raylod10 = log2(float(textureSize(colortex10, 0).x));
				 
/*
vec3 projectAndDivide(mat4 projectionMatrix, in vec3 position)
{
	position= projectionMatrix*vec4(position,1.);
	return position.xyz/position.w;
}
*/


#define DH_RAY_M 2.0 //[1.0 1.2 1.5 1.7 2.0 2.5 3.0]ray multiplier for step size dynamic assumed depth
#define DIFFUSE_RAY_SMOOTHNESS 0.1 //[0.0 0.01 0.02 0.03 0.04 0.05 0.06 .07 0.08 0.09 0.1 0.11 0.12 0.15 0.17 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0] 

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

	//include "/settings_1.glsl"

#if defined IS_IRIS && defined DISTANT_HORIZONS
float far_adjusted = dhFarPlane;
#else
float far_adjusted = far;
#endif

//float skydist = far_adjusted*2.9;

float ASSUMED_DEPTH2 =  ASSUMED_DEPTH ;

		
#if NOISE_AMOUNT_IN_RAYS > 0 
	 float noise_ray_amount_specular =0.1*NOISE_AMOUNT_IN_RAYS* randomfast(texcoord.x+texcoord.y*1000.)*clamp(1*1.0-smoothness,0.0,1.0);
	float noise_ray_amount_diffuse = 0.1*NOISE_AMOUNT_IN_RAYS*randomfast(texcoord.x+texcoord.y*1000.);			
#else
	float noise_ray_amount_specular = 0.0;
	float noise_ray_amount_diffuse = 0.0;
#endif

#if KILL_SWITCH > 0

int Kill_switch_multiplier = (1.0/frameTime < KILL_SWITCH) ? 0 : 1;
//steps *=Kill_switch_multiplier;
#else
int Kill_switch_multiplier = 1;
#endif

vec3 diffuse_angle =  bumpy_orth.xyz;

 
				tangent = tangent *2-1;
			//	tangent2 = tangent2 *2-1;
				tangent.z*=-1;
		
		
			//in jank tracing or pbr
//vec3 normals_face = texture2D(colortex2, texcoord.xy).xyz*2.-1.;



//tangent2.xyz = normalize(cross( tangent.xyz,normals_face));// *tangent.w);
	
	//old compat
					tangent = tangent *2-1;
			//	tangent2 = tangent2 *2-1;
				tangent.z*=-1;
		
				tangent2.xyz = normalize(cross(tangent.xyz,diffuse_angle.xyz));//*tangent.w);
		
		
		//		tangent2.xyz = normalize(cross(tangent.xyz,diffuse_angle.xyz));// *tangent.w);
				
		//		tangent2.z*=-1;
				
					#if CATCH_COLOR == 0
					int Steps_to_start = PBR_RAY_STEPS_SKY;
					#else
					int Steps_to_start = PBR_RAY_STEPS;
					#endif
			
			
int PBR_RAY_STEPS2 = Kill_switch_multiplier *  int( (float(Steps_to_start) * PATH_TRACING_RESOLUTION)) ;//((Steps_to_start>0)?1:0) );
PBR_RAY_STEPS2=(Steps_to_start>0&&PBR_RAY_STEPS2==0)?1:PBR_RAY_STEPS2;
//int PBR_RAY_STEPS2 = PBR_RAY_STEPS2;// * PATH_TRACING_RESOLUTION;// min(PBR_RAY_STEPS2 * PATH_TRACING_RESOLUTION,((PBR_RAY_STEPS2>0)?1:0) );
				
				
				#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_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
				#if CATCH_COLOR > 0
				 int w = RAY_NUM_W ;
				 int h = RAY_NUM_H ;
				#else
				 int w = SKY_RAY_NUM_W ;
				 int h = SKY_RAY_NUM_H ;
				 #endif 
				 
				 #if KILL_SWITCH > 0
w*=Kill_switch_multiplier;
h*=Kill_switch_multiplier;
#endif

				 
			     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;
				 
				 	  #if CURVE_LENS == 2
		reflected_angle_orth = (vec3(reflected_angle_orth.xy-	curved_lens2.xy	 ,reflected_angle_orth.z));
				  #endif
				   #if CURVE_LENS == 0
				   eye_out = vec3(0.0,0.0,1.0);
				  // bumpy_orth.xy+=	curved_lens2.xy;
				   reflected_angle_orth = reflect(eye_out,bumpy_orth); //bumpy_orth
				   #endif
				    #if CURVE_LENS == 3
					 eye_out = vec3(0.0,0.0,1.0);
				  // bumpy_orth.xy+=	curved_lens2.xy;
				   reflected_angle_orth = reflect(eye_out,bumpy_orth); //bumpy_orth
				 reflected_angle_orth.x*=2.0;
					//  reflected_angle_orth.xy-=	curved_lens2.xy;
					//reflected_angle_orth=mix(reflected_angle_orth,reflected_angle_orth,0.5);
				   #endif
				  
				 
	vec3 goal = reflected_angle_orth.xyz; // or diffuse  normal
	//goal.z=0.-goal.z;//2024-2
	float focus = mix(0.1,1.0,smoothness);;//or 0.1, etc
				
				//
				
	#if FAST_PTX == 1	
		//2024
		goal = mix(diffuse_angle.xyz,reflected_angle_orth.xyz,smoothness); // or diffuse  normal
		focus = mix(0.1,1.0,smoothness);//or 0.1, etc	
	 #endif		
				
		
				 
				 #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;
				 
				 
				 
				 
				  //ortho reflections 2024-2
				  #define RAY_ACCURACY 3
				  #if RAY_ACCURACY == 3
				  rayspeed.z=0.-rayspeed.z;
				 
	 			//vec3 reflected_angle_orth = reflect(curved_lens2,bumpy_orth); //bumpy_orth
				  raypos = texture2D(colortex15,texcoord.xy).xyz;//+reflected_angle;
				  //raypos.z*=-1.; 
				  vec3 ray_start =  raypos;//vec3(texcoord.xy,raypos.z);
				  vec4 ray_goal = vec4((normalize(rayspeed)),1.);// /PBR_RAY_STEPS2;
				  vec3 close_step =ray_start;
				  vec3 far_step =ray_start;
				  float RAY_DIST2 = rayspeed.z > 0.? max(-ray_start.z,RAY_DIST) : mix(max(RAY_DIST*10.,0.),far_adjusted+ray_start.z,pow(ray_goal.z,2.));// *clamp((-ray_start.z/50.-.5)*2.,0.,1.));//far_adjusted
				 //ray_goal.xyz*= ray_goal.z<near ? 1.-(distance(ray_start,ray_goal.z)-near)/(ray_goal.z-ray_start.z) : 1.;
				  //float goalz = ray_goal.z;
				  #endif
			
				  
				#if DEBUG_VIEWS == 33
				//
					  ray_goal.z*=-1.;
						//to pers
						vec4 raypos2=gbufferProjection*vec4(ray_start,1.);
						//raypos.xy*=raypos.z>near? 1.:-1.;
						raypos2.xy/=raypos2.w;
						 
						  raypos2.xy=raypos2.xy*.5+.5;
						  //raypos2.z*=-1.;
						  raypos=raypos2.xyz;
					//
					debugvalue3=ray_start;
					debugvalue3=raypos2.xyz;
					debugvalue3.b = fract(raypos2.z);//distance(ray_start.xy,ray_goal.xy);
					//albedo  = ray_start, ray_goal.xyz
				#endif
			
				
	
				 
				// raypos-=.5*vec3(rayspeed.xy/abs(raypos.z),rayspeed.z);
				 //raypos+=0.2*rayspeed*clamp(texture2D(noisetex, texcoord.xy).g,0.0,1.0);
			
				//rayspeed.x*=.5; // ortho disable 2024-2
					 #if NOISE_AMOUNT_IN_RAYS > 0 
				    raypos+=rayspeed*noise_ray_amount_specular/PBR_RAY_STEPS2;//2024-2 ortho FIX

				 #endif
				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*CURVE_ASPECT*abs(raypos.z+1));
					raypos = (ray_start+ ray_goal.xyz*.5);//ortho 2024-2
				#if RAY_ACCURACY == 3
					raypos = (ray_start+ ray_goal.xyz*.01);//ortho 2024-2
					far_step=raypos;
					//
					
					  //raypos.z*=-1.;
						//to pers
						vec4 raypos2=gbufferProjection*vec4(raypos.xyz,1.);
						//raypos.xy*=raypos.z>near? 1.:-1.;
						raypos2.xy/=raypos2.w;
						// raypos2.z*=-1.;
						  raypos2.xy=raypos2.xy*.5+.5;
						  raypos=raypos2.xyz;
						  // raypos.z*=-1.;
					//
					#endif
					
					
					//raypos.z=0.-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|| raypos.z>far_adjusted? 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_adjusted ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
						#if ASSUMED_DEPTH_DYNAMIC == 1 
						ASSUMED_DEPTH2 = max(DH_RAY_M*abs(close_step.z-far_step.z),max(bgdepth,ASSUMED_DEPTH));
					#endif
					rayhit = oob? false :(bgdepth)+RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH2) >  raypos.z  ? true : false;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
					close_step=rayhit? close_step:far_step;//far_step=raypos;
					
				}
				
				
				for(raystepss = 1;raystepss<=PBR_RAY_STEPS2&&!oob&&!rayhit;raystepss++)
				{ 
				    
					//raypos+=vec3(rayspeed.xy,rayspeed.z*CURVE_ASPECT*abs(raypos.z+1));
					#if RAY_ACCURACY == 3
					raypos = (ray_start+ ray_goal.xyz*RAY_DIST2*pow(float(raystepss)/float(PBR_RAY_STEPS2),2.));//ortho 2024-2
					//
					far_step=raypos;
					  //raypos.z*=-1.;
						//to pers
						vec4 raypos2=gbufferProjection*vec4(raypos.xyz,1.);
						//raypos.xy*=raypos.z>near? 1.:-1.;
						raypos2.xy/=raypos2.w;
						// raypos2.z*=-1.;
						  raypos2.xy=raypos2.xy*.5+.5;
						  raypos=raypos2.xyz;
						  // raypos.z*=-1.;
					//
					#endif
					
					//raypos.z=0.-raypos.z;
					
					rayspeed*=(1.0+ RAY_ACCELERATION);
					//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_adjusted? 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_adjusted ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
						#if ASSUMED_DEPTH_DYNAMIC == 1 
						ASSUMED_DEPTH2 = max(DH_RAY_M*abs(close_step.z-far_step.z),max(bgdepth,ASSUMED_DEPTH));
					#endif
					rayhit = oob? false :(bgdepth)+RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH2) >  raypos.z  ? true : false;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
					
					close_step=rayhit? close_step:far_step;
					
				}
				
					//
				#if DEBUG_VIEWS == 34
					debugvalue3=vec3(ray_goal.xy,(ray_goal.z));
				#endif	
					
					
				#if CATCH_COLOR > 0
				
				
				if(rayhit)
				{
				
				//int raylod = DIFFUSE_THE_RAYS_SPEC == 0 ? 0: //int((1.0-smoothness)*(DIFFUSE_THE_RAYS_SPEC*raystepss*RAY_DIST)/PBR_RAY_STEPS2);
				
				int raylod = DIFFUSE_THE_RAYS_SPEC == 0 ? 0: //(DIFFUSE_THE_RAYS_SPEC*raystepss*int(min(RAY_DIST2,1.)*DIFFUSE_RAY_SMOOTHNESS))/PBR_RAY_STEPS2 ;
				 //int(4.*DIFFUSE_RAY_SMOOTHNESS); //turbo
				 int(DIFFUSE_THE_RAYS_SPEC*mix(1.0,RAY_DIST2*10.,DIFFUSE_RAY_SMOOTHNESS)*pow(raystepss/PBR_RAY_STEPS2,2.)) ;
				// float raylod_f = DIFFUSE_THE_RAYS_SPEC == 0 ? 0.: fract( (DIFFUSE_THE_RAYS_SPEC*raystepss*mix(,1.0,RAY_DIST2,DIFFUSE_RAY_SMOOTHNESS))/PBR_RAY_STEPS2) ;
				 
				
				
				//refine pos
				float reverse = -1.0;
				float refined = 1.0;
				float rrayspeed = 1.0;
				for(raystepss = 0;raystepss<REFINER_STEPS_RAY*1.;raystepss++)
				{ 
				    rrayspeed*=.5;
					refined+=rrayspeed*reverse;
					
					#if RAY_ACCURACY == 3
					raypos = mix(close_step, far_step,refined);//ortho 2024-2
					//
					
					  //raypos.z*=-1.;
						//to pers
						vec4 raypos2=gbufferProjection*vec4(raypos.xyz,1.);
						//raypos.xy*=raypos.z>near? 1.:-1.;
						raypos2.xy/=raypos2.w;
						// raypos2.z*=-1.;
						  raypos2.xy=raypos2.xy*.5+.5;
						  raypos=raypos2.xyz;
						  // raypos.z*=-1.;
					//
					#endif
				
					
					
					oob = raypos.x<0 || raypos.x>1 || raypos.y<0 || raypos.y> 1 || raypos.z<0|| raypos.z>far_adjusted? 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_adjusted ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
						#if ASSUMED_DEPTH_DYNAMIC == 1 
						ASSUMED_DEPTH2 = max(DH_RAY_M*abs(close_step.z-far_step.z),max(bgdepth,ASSUMED_DEPTH));
					#endif
					reverse = oob? 1.0 :(bgdepth)+RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH2) >  raypos.z  ? -1.0 : 1.0;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				
				//
				
				#if CATCH_COLOR >1 
					ray_color =textureLod(colortex10,raypos.xy,raylod).rgb; // albedo2*(shadow_info.x ) ;
					#else
					ray_color =textureLod(colortex3,raypos.xy,raylod).rgb; // albedo2*(shadow_info.x ) ;
					#endif
					
					
					//ray_emit += albedo2*PBR_EMMISSIVE_STRENGTH*emmissiveness2;
					
				}
				#endif
				//
				reflection_color_total+=ray_color;
				
				#if VIGNETTE_PTX == 1
				 fadesky = oobrgb.r* (texcoord.x<.05?1-texcoord.x/.05: texcoord.x>.95?(texcoord.x-.95)/.05:0);
				 #endif
				 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
				
				#if VIGNETTE_PTX == 1
				fadesky =clamp(fadesky+ oobrgb.g* (texcoord.y<.05?1-texcoord.y/.05: texcoord.y>.95?(texcoord.y-.95)/.05:0) ,0.0,1.0);
				#endif
				
				//
				fadesky=rayhit?1.0:fadesky;
				 //fadesky=raypos.z>=skydist? 0.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);
				
				
				
				
				
	#if FAST_PTX == 0	
				
				
				
				
				//raytrace ambient
				 fadesky_complete=0;
				 numddiffrays=5;
				 vec3 reflection_color_total2 = vec3(0.0);
				 
				 //
				//ray cone setup

			     
			     
			     
			      #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
	//goal.z=0.-goal.z;//2024-2
	 focus = 0.1;;//or 0.1, etc
				
				
				#if NARROW_DIFFUSE_CONE_BY_SMOOTHNESS == 1
				//2024
	  goal = mix(diffuse_angle.xyz,reflected_angle_orth.xyz,smoothness); // or diffuse  normal

	 focus = mix(0.1,1.0,smoothness);//or 0.1, etc
				//
				 #endif
		
				 
				 #include "/raycone.glsl"
				 
				 
				
				 rayhit = false;
				
				 
				 
			
				
				 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=RAY_DIST*0.25*normalize(rayspeed)/PBR_RAY_STEPS2;
				 //raypos-=.5*vec3(rayspeed.xy/abs(raypos.z),rayspeed.z);
		
				// rayspeed.x*=.5;
				 
	  //ortho reflections 2024-2
 #if RAY_ACCURACY == 3
				  rayspeed.z=0.-rayspeed.z;
				 
	 			//vec3 reflected_angle_orth = reflect(curved_lens2,bumpy_orth); //bumpy_orth
				  raypos = texture2D(colortex15,texcoord.xy).xyz;//+reflected_angle;
				  
				  //raypos.z*=-1.; 
				  vec3 ray_start =  raypos;//vec3(texcoord.xy,raypos.z);
				  vec4 ray_goal = vec4((normalize(rayspeed)),1.);// /PBR_RAY_STEPS2;
				  vec3 close_step =ray_start;
				  vec3 far_step =ray_start;
				  float RAY_DIST2 = rayspeed.z > 0.? min(-ray_start.z,RAY_DIST) : mix(max(RAY_DIST*10.,0.),far_adjusted+ray_start.z,
				  0.
					//pow(ray_goal.z,2.)
				  );// *clamp((-ray_start.z/50.-.5)*2.,0.,1.));//far_adjusted
				 //ray_goal.xyz*= ray_goal.z<near ? 1.-(distance(ray_start,ray_goal.z)-near)/(ray_goal.z-ray_start.z) : 1.;
				  //float goalz = ray_goal.z;
				  #endif
				
				 
				 		 #if HALF_RAYS == 1
		
				    	 #if NOISE_AMOUNT_IN_RAYS > 0 
				    raypos+=rayspeed*noise_ray_amount_specular;

				 #endif
					
					
				#else
				 //just diffuse
					 #if NOISE_AMOUNT_IN_RAYS > 0 
				    raypos+=rayspeed*noise_ray_amount_diffuse;

				 #endif
				#endif
				 
				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*CURVE_ASPECT*abs(raypos.z+1));
					//raypos = mix(ray_start, ray_goal.xyz,1./(PBR_RAY_STEPS2*1.));//ortho 2024-2
					
					#if RAY_ACCURACY == 3
					raypos = (ray_start+ ray_goal.xyz*.01);//ortho 2024-2
					far_step=raypos;
					
					//raypos = (ray_start+ ray_goal.xyz*RAY_DIST*raystepss/PBR_RAY_STEPS2);//ortho 2024-2
					//
					
					  //raypos.z*=-1.;
						//to pers
						vec4 raypos2=gbufferProjection*vec4(raypos.xyz,1.);
						//raypos.xy*=raypos.z>near? 1.:-1.;
						raypos2.xy/=raypos2.w;
						// raypos2.z*=-1.;
						  raypos2.xy=raypos2.xy*.5+.5;
						  raypos=raypos2.xyz;
						  // raypos.z*=-1.;
					//
					#endif
					
					
					
					//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_adjusted? 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_adjusted ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
							#if ASSUMED_DEPTH_DYNAMIC == 1 
						ASSUMED_DEPTH2 = max(DH_RAY_M*abs(close_step.z-far_step.z),max(bgdepth,ASSUMED_DEPTH));
					#endif
					rayhit = oob? false :(bgdepth)+RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH2) >  raypos.z  ? true : false;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
					close_step=rayhit? close_step:far_step;//far_step=raypos;
				}
				
				for(raystepss = 1;raystepss<=PBR_RAY_STEPS2&&!oob&&!rayhit;raystepss++)
				{ 
				    
					//raypos+=vec3(rayspeed.xy,rayspeed.z*CURVE_ASPECT*abs(raypos.z+1));
					//raypos = mix(ray_start, ray_goal.xyz,raystepss/(PBR_RAY_STEPS2));//ortho 2024-2
					
					//raypos.z=0.-raypos.z;
					#if RAY_ACCURACY == 3
					raypos = (ray_start+ ray_goal.xyz*RAY_DIST2*pow(float(raystepss)/float(PBR_RAY_STEPS2),2.));//ortho 2024-2
					//
					far_step=raypos;
					
					  //raypos.z*=-1.;
						//to pers
						vec4 raypos2=gbufferProjection*vec4(raypos.xyz,1.);
						//raypos.xy*=raypos.z>near? 1.:-1.;
						raypos2.xy/=raypos2.w;
						// raypos2.z*=-1.;
						  raypos2.xy=raypos2.xy*.5+.5;
						  raypos=raypos2.xyz;
						  // raypos.z*=-1.;
					//
					#endif
					
					
					rayspeed*=(1.0+ RAY_ACCELERATION);
					//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>far_adjusted ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
						#if ASSUMED_DEPTH_DYNAMIC == 1 
						ASSUMED_DEPTH2 = max(DH_RAY_M*abs(close_step.z-far_step.z),max(bgdepth,ASSUMED_DEPTH));
					#endif
					rayhit = oob? false :(bgdepth)+RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH2) >  raypos.z  ? true : false;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
					close_step=rayhit? close_step:far_step;//far_step=raypos;
					
				}
				
				 int raylod = DIFFUSE_THE_RAYS == 0 ? 0: //(DIFFUSE_THE_RAYS*raystepss*int(min(RAY_DIST2,1.)*DIFFUSE_RAY_SMOOTHNESS))/PBR_RAY_STEPS2 ;
				 int(DIFFUSE_THE_RAYS*mix(1.0,RAY_DIST2*10.,DIFFUSE_RAY_SMOOTHNESS)*pow(raystepss/PBR_RAY_STEPS2,2.)) ;
				// float raylod_f = DIFFUSE_THE_RAYS == 0 ? 0.: fract((DIFFUSE_THE_RAYS*raystepss*mix(,1.0,RAY_DIST2,DIFFUSE_RAY_SMOOTHNESS))/PBR_RAY_STEPS2) ;
				 
				
				#if VIGNETTE_PTX == 1
				 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);
			    #endif
				 
				 fadesky=rayhit?1.0:fadesky;
				// fadesky=raypos.z>=skydist? 0.0:fadesky;
				 fadesky_complete+=fadesky;
				 
				
				//
				#if CATCH_COLOR > 0
				if(rayhit)
				{
				//refine pos
				float reverse = -1.0;
				float refined = 1.0;
				float rrayspeed = 1.0;
				for(raystepss = 0;raystepss<REFINER_STEPS_RAY*0.;raystepss++)
				{ 
				    rrayspeed*=.5;
					refined+=rrayspeed*reverse;
					
					#if RAY_ACCURACY == 3
					raypos = mix(close_step, far_step,refined);//ortho 2024-2
					//
					
					  //raypos.z*=-1.;
						//to pers
						vec4 raypos2=gbufferProjection*vec4(raypos.xyz,1.);
						//raypos.xy*=raypos.z>near? 1.:-1.;
						raypos2.xy/=raypos2.w;
						// raypos2.z*=-1.;
						  raypos2.xy=raypos2.xy*.5+.5;
						  raypos=raypos2.xyz;
						  // raypos.z*=-1.;
					//
					#endif
					//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_adjusted? 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_adjusted ? 1:0;
					// bgdepth = texture2D(depthtex0,raypos.xy).x;
					float bgdepth=-texture2D(colortex15,raypos.xy).z;
						#if ASSUMED_DEPTH_DYNAMIC == 1 
						ASSUMED_DEPTH2 = max(DH_RAY_M*abs(close_step.z-far_step.z),max(bgdepth,ASSUMED_DEPTH));
					#endif
					reverse = oob? 1.0 :(bgdepth)+RAY_BIAS <  raypos.z && (bgdepth+ASSUMED_DEPTH2) >  raypos.z  ? -1.0 : 1.0;
					//rayhit = oob? false : -texture2D(colortex15,raypos.xy).z <  raypos.z ? true : false;
				}
				
				//
				#if CATCH_COLOR >1 
					ray_color =textureLod(colortex10,raypos.xy,min(raylod,raylod10)).rgb; // albedo2*(shadow_info.x ) ;
					//ray_color =mix(ray_color,textureLod(colortex10,raypos.xy,min(raylod+1,raylod10)).rgb, raylod_f);
					#else
					ray_color =textureLod(colortex3,raypos.xy,min(raylod,raylod3)).rgb; // albedo2*(shadow_info.x ) ;
					//ray_color =mix(ray_color,textureLod(colortex3,raypos.xy,min(raylod+1,raylod3)).rgb, raylod_f);
					#endif
					//ray_emit += albedo2*PBR_EMMISSIVE_STRENGTH*emmissiveness2;
					
				}
				#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);
		 #endif
		 
				 
	 
				 
// © 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". 

