way improved post processing

This commit is contained in:
Tuomas Katajisto 2025-10-26 19:03:14 +02:00
parent eabf4bf2cf
commit 3c4bb9e100
14 changed files with 1188 additions and 685 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

View File

@ -59,6 +59,12 @@ draw_subwindow_post_process :: (state: *GR.Subwindow_State, r: GR.Rect, data: *v
file.write_entire_file("./game/resources/postprocess.json", json);
}
}
r3.y += r3.h;
r2.h -= r3.h;
r2.y += r3.h;
GR.dropdown(r3, LUT_name_list, *g_current_lut_texture_index, *theme_ptr.dropdown_theme);
autoedit(r2, *current_post_process, *theme_ptr);
}

View File

@ -121,6 +121,7 @@ init_after_asset_pack :: () {
lworlds();
init_spritesheets();
init_rendering();
load_color_lut_images();
load_post_process_from_pack();
// We want to do this last.

View File

@ -327,16 +327,10 @@ backend_process_command_buckets :: () {
// Draw the render texture and do post processing:
sg_apply_pipeline(gPipelines.postprocess.pipeline);
gPipelines.postprocess.bind.images[0] = g_postprocess_a;
gPipelines.postprocess.bind.images[1] = LUT_list[g_current_lut_texture_index].image;
sg_apply_bindings(*gPipelines.postprocess.bind);
post_process_config_uniform : Post_Process_Config;
fill_uniform_with_engine_data(*post_process_config_uniform , *current_post_process);
post_process_config_uniform.vignette_intensity = current_post_process.vignette_intensity;
post_process_config_uniform.vignette_radius = current_post_process.vignette_radius;
post_process_config_uniform.scanlines_intensity = current_post_process.scanlines_intensity;
post_process_config_uniform.scanlines_density = current_post_process.scanlines_density;
post_process_config_uniform.chromatic_aberration_intensity = current_post_process.chromatic_aberration_intensity;
post_process_config_uniform.film_grain_intensity = current_post_process.film_grain_intensity;
post_process_config_uniform.barrel_distortion_intensity = current_post_process.barrel_distortion_intensity;
sg_apply_uniforms(UB_post_process_config, *(sg_range.{ ptr = *post_process_config_uniform, size = size_of(type_of(post_process_config_uniform)) }));
sg_draw(0, 6, 1);

View File

@ -690,6 +690,13 @@ create_postprocess_pipeline :: () {
mag_filter = .NEAREST,
}));
gPipelines.postprocess.bind.samplers[1] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .LINEAR,
mag_filter = .LINEAR,
}));
}
// Takes in a texture, manipulates it and outputs it.

View File

@ -1,8 +1,8 @@
Post_Process :: struct {
exposure : float = 0.0; @Slider,-1,1,0.1;
contrast : float = 1.0; @Slider,0.1,4.0,0.1;
exposure : float = 0.0; @Slider,0,3,0.1;
contrast : float = 1.0; @Slider,0,6,0.1;
saturation : float = 1.0; @Slider,0.0,2.0,0.1;
gamma : float = 1.0; @Slider,0.3,3.0,0.1;
gamma : float = 2.2; @Slider,0.3,3.0,0.1;
tonemap : float = 1.0; @Slider,0,1,1;
ssao : float = 1.0; @Slider,0,5,0.1;
ssao_size : s32 = 1; @Slider,0,5,1;
@ -16,8 +16,9 @@ Post_Process :: struct {
dof_point : float = 5.0; @Slider,0,30,1;
bloom_size : s32 = 5; @Slider,0,10,1;
bloom_separation : float = 3.0; @Slider,0,10,1;
bloom_treshold : float = 0.4; @Slider,0,1,0.1;
bloom_treshold : float = 0.4; @Slider,0,1,0.1;
bloom_amount : float = 1.0; @Slider,0,5,0.1;
vignette_intensity: float = 0.5; @Slider,0,1,0.1;
vignette_radius: float = 0.5; @Slider,0,1,0.1;
scanlines_intensity: float = 0.1; @Slider,0,1,0.1;
@ -25,8 +26,10 @@ Post_Process :: struct {
chromatic_aberration_intensity: float = 0.0; @Slider,0,0.05,0.001;
film_grain_intensity: float = 0.0; @Slider,0,0.5,0.001;
barrel_distortion_intensity: float = 0.0; @Slider,-2,2,0.1;
lut_mode: s32 = 0; @Slider,0,2,1; // 0 -> no LUT, 1 -> LUT with interpolation 2 -> LUT no iterpolate
}
current_post_process : Post_Process;
load_post_process_from_pack :: () {
@ -40,3 +43,29 @@ load_post_process_from_pack :: () {
reset_post_process :: () {
load_post_process_from_pack();
} @Command
Color_LUT :: struct {
name: string;
image: sg_image;
}
LUT_list : [..]Color_LUT;
LUT_name_list : [..]string;
g_current_lut_texture_index : s32 = 0;
load_color_lut_images :: () {
for v : g_asset_pack.lookup {
isSpritesheet := String.contains(v.name, ".colorgrade.png");
noop, remainder := String.contains(v.name, "/resources/");
if isSpritesheet {
print("Adding LUT: %\n", remainder);
img, w, h := create_texture_from_pack(v.name);
newSheet := Color_LUT.{
name = remainder,
image = img,
};
array_add(*LUT_list, newSheet);
array_add(*LUT_name_list, newSheet.name);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,8 @@ out vec4 frag_color;
layout(binding = 0) uniform texture2D pptex;
layout(binding = 0) uniform sampler ppsmp;
layout(binding = 1) uniform texture2D lut;
layout(binding = 1) uniform sampler lut_linear;
layout(binding=0) uniform post_process_config {
float exposure;
@ -30,6 +32,7 @@ layout(binding=0) uniform post_process_config {
float chromatic_aberration_intensity;
float film_grain_intensity;
float barrel_distortion_intensity;
int lut_mode;
};
vec3 aces(vec3 x) {
@ -59,37 +62,66 @@ void main() {
}
}
vec4 sampled = vec4(0.0);
float r = texture(sampler2D(pptex, ppsmp), distorted_texcoord + vec2(chromatic_aberration_intensity, 0.0)).r;
float g = texture(sampler2D(pptex, ppsmp), distorted_texcoord).g;
float b = texture(sampler2D(pptex, ppsmp), distorted_texcoord - vec2(chromatic_aberration_intensity, 0.0)).b;
sampled = vec4(r, g, b, 1.0);
vec3 sampled_color_hdr = vec4(r, g, b, 1.0).rgb;
vec3 tonemapped = aces(sampled.xyz);
vec3 color_hdr = sampled_color_hdr * exposure;
vec3 color_ldr_linear;
if(tonemap > 0.5) {
tonemapped = aces(sampled.xyz);
color_ldr_linear = aces(color_hdr);
} else {
tonemapped = sampled.xyz;
color_ldr_linear = color_hdr;
}
// tonemapped *= pow(2.0, exposure);
vec3 gammaCorrected = pow(tonemapped, vec3(1.0/gamma));
gammaCorrected.rgb = ((gammaCorrected.rgb - 0.5f) * max(contrast, 0)) + 0.5f;
gammaCorrected.rgb += exposure;
float lum = (0.2125 * gammaCorrected.r) + (0.7154 * gammaCorrected.g) + (0.0721 * gammaCorrected.b);
color_ldr_linear = ((color_ldr_linear - 0.5f) * max(contrast, 0)) + 0.5f;
float lum = dot(color_ldr_linear, vec3(0.2125, 0.7154, 0.0721));
vec3 brtColor = vec3(lum, lum, lum);
gammaCorrected.rgb = mix(brtColor, gammaCorrected.rgb, saturation);
color_ldr_linear = mix(brtColor, color_ldr_linear, saturation);
color_ldr_linear = clamp(color_ldr_linear, 0.0, 1.0);
if(lut_mode != 0) {
if(lut_mode == 2) {
float u = floor(color_ldr_linear.b * 15.0) * (1.0/16.0);
u = u + floor(color_ldr_linear.r * 15.0) * (1.0/256.0);
float v = floor(color_ldr_linear.g * 15.0) * (1.0 / 16.0);
vec3 left = texture(sampler2D(lut, ppsmp), vec2(u, v)).rgb;
color_ldr_linear = left;
} else {
float b_scaled = color_ldr_linear.b * 15.0;
float b_floor = floor(b_scaled);
float b_fract = b_scaled - b_floor; // fract(b_scaled)
float v = (color_ldr_linear.g * 15.0 + 0.5) / 16.0;
float u1 = (b_floor * 16.0 + color_ldr_linear.r * 15.0 + 0.5) / 256.0;
vec3 sample1 = texture(sampler2D(lut, lut_linear), vec2(u1, v)).rgb;
float b_ceil = min(b_floor + 1.0, 15.0); // Clamp to last slice
float u2 = (b_ceil * 16.0 + color_ldr_linear.r * 15.0 + 0.5) / 256.0;
vec3 sample2 = texture(sampler2D(lut, lut_linear), vec2(u2, v)).rgb;
color_ldr_linear = mix(sample1, sample2, b_fract);
}
}
vec3 color_srgb = pow(color_ldr_linear, vec3(1.0 / gamma));
float vignette = 1.0 - smoothstep(0.0, vignette_radius, length(texcoord - vec2(0.5))) * vignette_intensity;
gammaCorrected.rgb *= vignette;
color_srgb *= vignette;
float scanline = 1.0 - (sin(texcoord.y * textureSize(sampler2D(pptex, ppsmp), 0).y * scanlines_density) * 0.5 + 0.5) * scanlines_intensity;
gammaCorrected.rgb *= scanline;
color_srgb *= scanline;
float grain = (rand(texcoord) - 0.5) * film_grain_intensity;
gammaCorrected.rgb += grain;
color_srgb += grain;
frag_color = vec4(gammaCorrected, 1.0);
frag_color = vec4(clamp(color_srgb, 0.0, 1.0), 1.0);
}
@end

View File

@ -82,6 +82,9 @@ World_Config :: struct {
waterColor : Vector3 = .{1.0, 1.0, 1.0}; @Color // @ToDo: sensible default values.
deepColor : Vector3 = .{1.0, 1.0, 1.0}; @Color // @ToDo: sensible default values.
// ambientColor : Vector3 = .{1.0, 1.0, 1.0}; @Color
// ambientIntensity : float = 0.3; @Slider,0,3,0.1
}
// Copies over all the fields of our world config into a given shader type.