generated from krampus/template-godot4
	
		
			
				
	
	
		
			143 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| // Retro Post-Processing shader
 | ||
| // From https://godotshaders.com/shader/retro-post-processing/
 | ||
| 
 | ||
| shader_type canvas_item;
 | ||
| 
 | ||
| // Handles the resolution changes, color depth, and dithering
 | ||
| group_uniforms resolution_and_colors;
 | ||
| uniform bool change_color_depth = false;
 | ||
| uniform int target_color_depth : hint_range(1, 8) = 5;
 | ||
| uniform bool dithering = false;
 | ||
| uniform bool scale_resolution = false;
 | ||
| uniform int target_resolution_scale = 3;
 | ||
| 
 | ||
| // Handles the LUTish recoloring
 | ||
| group_uniforms gradient_recoloring;
 | ||
| uniform bool enable_recolor = false;
 | ||
| uniform sampler2D to_gradient: hint_default_black;
 | ||
| 
 | ||
| int dithering_pattern(ivec2 fragcoord) {
 | ||
| 	const int pattern[] = {
 | ||
| 		-4, +0, -3, +1,
 | ||
| 		+2, -2, +3, -1,
 | ||
| 		-3, +1, -4, +0,
 | ||
| 		+3, -1, +2, -2
 | ||
| 	};
 | ||
| 
 | ||
| 	int x = fragcoord.x % 4;
 | ||
| 	int y = fragcoord.y % 4;
 | ||
| 
 | ||
| 	return pattern[y * 4 + x];
 | ||
| }
 | ||
| 
 | ||
| vec3 rgb2hsv(vec3 rgb) { //Converts RGB values to HSV
 | ||
| 	float r = rgb.r;
 | ||
| 	float g = rgb.g;
 | ||
| 	float b = rgb.b;
 | ||
| 
 | ||
| 	float cmax = max(r,max(g,b));
 | ||
| 	float cmin = min(r,min(g,b));
 | ||
| 	float delta = cmax - cmin;
 | ||
| 
 | ||
| 	float h = 0.f; //hue
 | ||
| 
 | ||
| 	if (delta > 0.f){
 | ||
| 		if (cmax == r){
 | ||
| 			h = (g-b)/delta;
 | ||
| 			h = mod(h,6.f);
 | ||
| 		} else if (cmax == g){
 | ||
| 			h = ((b - r) / delta) + 2.f;
 | ||
| 		} else {
 | ||
| 			h = ((r-g)/delta) + 4.f;
 | ||
| 		}
 | ||
| 		h = h * 60.f;
 | ||
| 	}
 | ||
| 
 | ||
| 	float s = 0.f; //saturation
 | ||
| 	if (cmax > 0.f){
 | ||
| 		s = delta / cmax;
 | ||
| 	}
 | ||
| 
 | ||
| 	return vec3(h,s,cmax); // Keep original alpha value
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| vec3 hsv2rgb(vec3 hsv) { //Converts HSV values to RGB
 | ||
| 	float h = hsv.r;
 | ||
| 	float s = hsv.g;
 | ||
| 	float v = hsv.b;
 | ||
| 	float c = v * s;
 | ||
| 	//X = C × (1 - |(H / 60°) mod 2 - 1|)
 | ||
| 	float x = h / 60.f;
 | ||
| 	x = mod(x,2.f);
 | ||
| 	x = abs(x - 1.f);
 | ||
| 	x = c * (1.f - x);
 | ||
| 
 | ||
| 	float m = v - c;
 | ||
| 
 | ||
| 	vec3 rgb = vec3(0.f,0.f,0.f);
 | ||
| 
 | ||
| 	if (h < 60.f) {
 | ||
| 		rgb = vec3(c,x,0.f);
 | ||
| 	} else if (h < 120.f){
 | ||
| 		rgb = vec3(x,c,0.f);
 | ||
| 	} else if (h < 180.f){
 | ||
| 		rgb = vec3(0.f,c,x);
 | ||
| 	} else if (h < 240.f){
 | ||
| 		rgb = vec3(0.f,x,c);
 | ||
| 	} else if (h < 300.f){
 | ||
| 		rgb = vec3(x,0.f,c);
 | ||
| 	} else if (h < 360.f){
 | ||
| 		rgb = vec3(c,0.f,x);
 | ||
| 	}
 | ||
| 	rgb[0] = rgb[0] + m;
 | ||
| 	rgb[1] = rgb[1] + m;
 | ||
| 	rgb[2] = rgb[2] + m;
 | ||
| 
 | ||
| 	return rgb;
 | ||
| }
 | ||
| 
 | ||
| void fragment() {
 | ||
| 	ivec2 uv;
 | ||
| 	vec3 color;
 | ||
| 
 | ||
| 	if(scale_resolution){
 | ||
| 		uv = ivec2(FRAGCOORD.xy / float(target_resolution_scale));
 | ||
| 		color = texelFetch(TEXTURE, uv * target_resolution_scale, 0).rgb;
 | ||
| 	} else {
 | ||
| 		uv = ivec2(FRAGCOORD.xy);
 | ||
| 		color = texelFetch(TEXTURE, uv, 0).rgb;
 | ||
| 	}
 | ||
| 
 | ||
| 	if(enable_recolor){
 | ||
| 		vec3 hsv = rgb2hsv(color);
 | ||
| 		float color_pos = (hsv.x / 360.0);
 | ||
| 		vec3 new_color = texture(to_gradient, vec2((color_pos), 0.5)).rgb;
 | ||
| 		vec3 new_hsv = rgb2hsv(new_color);
 | ||
| 		hsv.x = new_hsv.x;
 | ||
| 		vec3 final_rgb = hsv2rgb(hsv);
 | ||
| 
 | ||
| 		color.rgb = final_rgb;
 | ||
| 	}
 | ||
| 
 | ||
| 
 | ||
| 	// Convert from [0.0, 1.0] range to [0, 255] range
 | ||
| 	ivec3 c = ivec3(round(color * 255.0));
 | ||
| 
 | ||
| 	// Apply the dithering pattern
 | ||
| 	if (dithering) {
 | ||
| 		c += ivec3(dithering_pattern(uv));
 | ||
| 	}
 | ||
| 
 | ||
| 	vec3 final_color;
 | ||
| 	if(change_color_depth){
 | ||
| 		// Truncate from 8 bits to color_depth bits
 | ||
| 		c >>= (8 - target_color_depth);
 | ||
| 		final_color = vec3(c) / float(1 << target_color_depth);
 | ||
| 	} else {
 | ||
| 		final_color = vec3(c) / float(1 << 8);
 | ||
| 	}
 | ||
| 
 | ||
| 	// Convert back to [0.0, 1.0] range
 | ||
| 	COLOR.rgb = final_color;
 | ||
| } |