From 7c1eae3b8cbcd64b8488b169bf3c13f7abd1f0e0 Mon Sep 17 00:00:00 2001 From: jacob Date: Fri, 23 May 2025 00:40:51 -0500 Subject: [PATCH] srgb aware rendering --- res/shaders/grid.hlsl | 46 +++++++++++++----------- res/shaders/triangle.hlsl | 21 ++++++----- src/ase.c | 8 +++++ src/ase.h | 1 + src/common.h | 28 +++++---------- src/draw.c | 76 +++++++++++++++++++-------------------- src/draw.h | 26 +++++++------- src/renderer.h | 13 +++---- src/renderer_d3d11.c | 63 +++++++++++++++++++------------- src/sprite.c | 7 +++- 10 files changed, 159 insertions(+), 130 deletions(-) diff --git a/res/shaders/grid.hlsl b/res/shaders/grid.hlsl index 79b968f6..151dc738 100644 --- a/res/shaders/grid.hlsl +++ b/res/shaders/grid.hlsl @@ -1,25 +1,25 @@ struct vs_input { float4 pos : POSITION; - float4 color_bg0 : COLOR_BG_A; - float4 color_bg1 : COLOR_BG_B; - float4 color_line : COLOR_LINE; - float4 color_x : COLOR_X; - float4 color_y : COLOR_Y; float line_thickness : THICKNESS; float line_spacing : SPACING; float2 offset : OFFSET; + float4 bg0_srgb : COLOR0; + float4 bg1_srgb : COLOR1; + float4 line_srgb : COLOR2; + float4 x_srgb : COLOR3; + float4 y_srgb : COLOR4; }; struct ps_input { float4 screen_pos : SV_POSITION; - float4 color_bg0 : COLOR_BG_A; - float4 color_bg1 : COLOR_BG_B; - float4 color_line : COLOR_LINE; - float4 color_x : COLOR_X; - float4 color_y : COLOR_Y; float line_thickness : THICKNESS; float line_spacing : SPACING; float2 offset : OFFSET; + float4 bg0_lin : COLOR0; + float4 bg1_lin : COLOR1; + float4 line_lin : COLOR2; + float4 x_lin : COLOR3; + float4 y_lin : COLOR4; }; cbuffer vs_constants : register(b0) @@ -27,19 +27,24 @@ cbuffer vs_constants : register(b0) float4x4 projection; }; +float4 linear_from_srgb(float4 srgb) +{ + return float4(pow(srgb.rgb, 2.2), srgb.a); +} + ps_input vs_main(vs_input input) { ps_input output; output.screen_pos = mul(projection, float4(input.pos.xy, 0.f, 1.f)); - output.color_bg0 = input.color_bg0; - output.color_bg1 = input.color_bg1; - output.color_line = input.color_line; - output.color_x = input.color_x; - output.color_y = input.color_y; output.line_thickness = input.line_thickness; output.line_spacing = input.line_spacing; output.offset = input.offset; + output.bg0_lin = linear_from_srgb(input.bg0_srgb); + output.bg1_lin = linear_from_srgb(input.bg1_srgb); + output.line_lin = linear_from_srgb(input.line_srgb); + output.x_lin = linear_from_srgb(input.x_srgb); + output.y_lin = linear_from_srgb(input.y_srgb); return output; } @@ -49,17 +54,18 @@ float4 ps_main(ps_input input) : SV_TARGET float2 grid_pos = input.screen_pos.xy + input.offset; float half_thickness = input.line_thickness / 2; float spacing = input.line_spacing; - float4 color = input.color_bg0; + + float4 color = input.bg0_lin; float2 v = abs(round(grid_pos / spacing) * spacing - grid_pos); float dist = min(v.x, v.y); if (grid_pos.y <= half_thickness && grid_pos.y >= -half_thickness) { - color = input.color_x; + color = input.x_lin; } else if (grid_pos.x <= half_thickness && grid_pos.x >= -half_thickness) { - color = input.color_y; + color = input.y_lin; } else if (dist < half_thickness) { - color = input.color_line; + color = input.line_lin; } else { bool checker = false; uint cell_x = (uint)(abs(grid_pos.x) / spacing) + (grid_pos.x < 0); @@ -70,7 +76,7 @@ float4 ps_main(ps_input input) : SV_TARGET checker = cell_y % 2 == 1; } if (checker) { - color = input.color_bg1; + color = input.bg1_lin; } } diff --git a/res/shaders/triangle.hlsl b/res/shaders/triangle.hlsl index 0abf31b2..0bf39989 100644 --- a/res/shaders/triangle.hlsl +++ b/res/shaders/triangle.hlsl @@ -9,29 +9,34 @@ cbuffer constants : register(b0) }; struct vs_input { - float4 pos : POSITION; - float2 uv : TEXCOORD; - float4 col : COLOR; + float4 pos : POSITION; + float2 uv : TEXCOORD; + float4 tint_srgb : COLOR; }; struct ps_input { - float4 pos : SV_POSITION; - float2 uv : TEXCOORD; - float4 col : COLOR; + float4 pos : SV_POSITION; + float2 uv : TEXCOORD; + float4 tint_lin : COLOR; }; +float4 linear_from_srgb(float4 srgb) +{ + return float4(pow(srgb.rgb, 2.2), srgb.a); +} + ps_input vs_main(vs_input input) { ps_input output; output.pos = mul(projection, float4(input.pos.xy, 0.f, 1.f)); output.uv = input.uv; - output.col = input.col; + output.tint_lin = linear_from_srgb(input.tint_srgb); return output; } float4 ps_main(ps_input input) : SV_TARGET { - return globals.texture0.Sample(globals.sampler0, input.uv) * input.col; + return globals.texture0.Sample(globals.sampler0, input.uv) * input.tint_lin; } diff --git a/src/ase.c b/src/ase.c index c929cdbe..f8e7cde4 100644 --- a/src/ase.c +++ b/src/ase.c @@ -705,6 +705,14 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct stri } } break; + case CHUNK_TYPE_COLOR_PROFILE: { + u16 type = br_read_ubits(&br, 16); + if (type == 1) { + res.srgb = true; + } + br_seek_to_byte(&br, chunk_end_pos); + } break; + default: { br_seek_to_byte(&br, chunk_end_pos); } break; diff --git a/src/ase.h b/src/ase.h index dd9dd87b..48d89fce 100644 --- a/src/ase.h +++ b/src/ase.h @@ -48,6 +48,7 @@ struct ase_frame { struct ase_decode_image_result { struct image_rgba image; struct ase_error_list errors; + b32 srgb; }; struct ase_decode_sheet_result { diff --git a/src/common.h b/src/common.h index f05e69b6..9b7e4280 100644 --- a/src/common.h +++ b/src/common.h @@ -290,25 +290,15 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t); #define ALPHA_F(color, a) ((color) & 0x00FFFFFF) | (_RGB_U8_FROM_F((a)) << 24) -/* Palette color defines */ -#define COLOR_WHITE RGB(0xE6, 0xE8, 0xE6) -#define COLOR_BLACK RGB(0x4C, 0x2E, 0x05) -#define COLOR_RED RGB(0x6F, 0x1D, 0x1B) -#define COLOR_GREEN RGB(0x26, 0xA9, 0x6C) -#define COLOR_BLUE RGB(0x25, 0x8E, 0xA6) -#define COLOR_YELLOW RGB(0xFC, 0xF6, 0xB1) -#define COLOR_ORANGE RGB(0xFF, 0x7F, 0x51) -#define COLOR_PURPLE RGB(0xFF, 0x57, 0xBB) - -/* True color defines */ -#define COLOR_TRUE_WHITE RGB(0xFF, 0xFF, 0xFF) -#define COLOR_TRUE_BLACK RGB(0x00, 0x00, 0x00) -#define COLOR_TRUE_RED RGB(0xFF, 0x00, 0x00) -#define COLOR_TRUE_GREEN RGB(0x00, 0xFF, 0x00) -#define COLOR_TRUE_BLUE RGB(0x00, 0x00, 0xFF) -#define COLOR_TRUE_YELLOW RGB(0xFF, 0xFF, 0x00) -#define COLOR_TRUE_ORANGE RGB(0xFF, 0xA5, 0x00) -#define COLOR_TRUE_PURPLE RGB(0xFF, 0x00, 0XFF) +/* Color defines */ +#define COLOR_WHITE RGB(0xFF, 0xFF, 0xFF) +#define COLOR_BLACK RGB(0x00, 0x00, 0x00) +#define COLOR_RED RGB(0xFF, 0x00, 0x00) +#define COLOR_GREEN RGB(0x00, 0xFF, 0x00) +#define COLOR_BLUE RGB(0x00, 0x00, 0xFF) +#define COLOR_YELLOW RGB(0xFF, 0xFF, 0x00) +#define COLOR_ORANGE RGB(0xFF, 0xA5, 0x00) +#define COLOR_PURPLE RGB(0xFF, 0x00, 0XFF) /* Barrier */ #if COMPILER_MSVC diff --git a/src/draw.c b/src/draw.c index a0a47278..936b4600 100644 --- a/src/draw.c +++ b/src/draw.c @@ -28,7 +28,7 @@ struct draw_startup_receipt draw_startup(struct renderer_startup_receipt *render * Texture * ========================== */ -void draw_quad_texture_ex(struct renderer_cmd_buffer *cmdbuff, struct renderer_texture texture, struct sprite_tag sprite, struct clip_rect clip, u32 tint0, u32 tint1, struct quad quad) +void draw_quad_texture_ex(struct renderer_cmd_buffer *cmdbuff, struct renderer_texture texture, struct sprite_tag sprite, struct clip_rect clip, u32 tint0_srgb, u32 tint1_srgb, struct quad quad) { struct renderer_cmd_parameters cmd_params = ZI; cmd_params.kind = SHADER_TRIANGLE; @@ -44,25 +44,25 @@ void draw_quad_texture_ex(struct renderer_cmd_buffer *cmdbuff, struct renderer_t vertices[0] = (struct triangle_shader_vertex) { .pos = quad.p0, .uv = { clip.p0.x, clip.p0.y }, - .color = tint0 + .tint_srgb = tint0_srgb }; /* Top right */ vertices[1] = (struct triangle_shader_vertex) { .pos = quad.p1, .uv = { clip.p1.x, clip.p0.y }, - .color = tint0 + .tint_srgb = tint0_srgb }; /* Bottom right */ vertices[2] = (struct triangle_shader_vertex) { .pos = quad.p2, .uv = { clip.p1.x, clip.p1.y }, - .color = tint1 + .tint_srgb = tint1_srgb }; /* Bottom left */ vertices[3] = (struct triangle_shader_vertex) { .pos = quad.p3, .uv = { clip.p0.x, clip.p1.y }, - .color = tint1 + .tint_srgb = tint1_srgb }; /* Top / right triangle */ @@ -85,7 +85,7 @@ void draw_quad_texture(struct renderer_cmd_buffer *cmdbuff, struct draw_texture_ * Solid fill shapes * ========================== */ -void draw_poly(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, u32 color) +void draw_poly(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, u32 srgb) { if (array.count < 3) { return; @@ -107,7 +107,7 @@ void draw_poly(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, u32 c for (u32 i = 0; i < array.count; ++i) { vertices[i] = (struct triangle_shader_vertex) { .pos = array.points[i], - .color = color + .tint_srgb = srgb }; } @@ -120,7 +120,7 @@ void draw_poly(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, u32 c } } -void draw_circle(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 color, u32 detail) +void draw_circle(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 srgb, u32 detail) { struct temp_arena scratch = scratch_begin_no_conflict(); @@ -137,39 +137,39 @@ void draw_circle(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, .points = points, .count = detail }; - draw_poly(cmdbuff, a, color); + draw_poly(cmdbuff, a, srgb); scratch_end(scratch); } -void draw_quad(struct renderer_cmd_buffer *cmdbuff, struct quad quad, u32 color) +void draw_quad(struct renderer_cmd_buffer *cmdbuff, struct quad quad, u32 srgb) { - draw_quad_texture_ex(cmdbuff, G.solid_white, sprite_tag_nil(), CLIP_ALL, color, color, quad); + draw_quad_texture_ex(cmdbuff, G.solid_white, sprite_tag_nil(), CLIP_ALL, srgb, srgb, quad); } /* ========================== * * Solid line shapes * ========================== */ -void draw_gradient_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 color_start, u32 color_end) +void draw_gradient_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 start_srgb, u32 end_srgb) { struct quad quad = quad_from_line(start, end, thickness); - draw_quad_texture_ex(cmdbuff, G.solid_white, sprite_tag_nil(), CLIP_ALL, color_start, color_end, quad); + draw_quad_texture_ex(cmdbuff, G.solid_white, sprite_tag_nil(), CLIP_ALL, start_srgb, end_srgb, quad); } -void draw_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 color) +void draw_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 srgb) { struct quad quad = quad_from_line(start, end, thickness); - draw_quad(cmdbuff, quad, color); + draw_quad(cmdbuff, quad, srgb); } -void draw_ray(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, u32 color) +void draw_ray(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, u32 srgb) { struct quad quad = quad_from_ray(pos, rel, thickness); - draw_quad(cmdbuff, quad, color); + draw_quad(cmdbuff, quad, srgb); } -void draw_poly_line(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, b32 loop, f32 thickness, u32 color) +void draw_poly_line(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, b32 loop, f32 thickness, u32 srgb) { if (array.count < 2) { return; @@ -179,17 +179,17 @@ void draw_poly_line(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, struct v2 p1 = array.points[i - 1]; struct v2 p2 = array.points[i]; struct quad q = quad_from_line(p1, p2, thickness); - draw_quad(cmdbuff, q, color); + draw_quad(cmdbuff, q, srgb); } if (loop && array.count > 2) { struct v2 p1 = array.points[array.count - 1]; struct v2 p2 = array.points[0]; struct quad q = quad_from_line(p1, p2, thickness); - draw_quad(cmdbuff, q, color); + draw_quad(cmdbuff, q, srgb); } } -void draw_circle_line(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail) +void draw_circle_line(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, f32 thickness, u32 srgb, u32 detail) { struct temp_arena scratch = scratch_begin_no_conflict(); @@ -206,19 +206,19 @@ void draw_circle_line(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 ra .points = points, .count = detail }; - draw_poly_line(cmdbuff, a, true, thickness, color); + draw_poly_line(cmdbuff, a, true, thickness, srgb); scratch_end(scratch); } -void draw_quad_line(struct renderer_cmd_buffer *cmdbuff, struct quad quad, f32 thickness, u32 color) +void draw_quad_line(struct renderer_cmd_buffer *cmdbuff, struct quad quad, f32 thickness, u32 srgb) { struct v2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 }; struct v2_array a = { .points = points, .count = ARRAY_COUNT(points) }; - draw_poly_line(cmdbuff, a, true, thickness, color); + draw_poly_line(cmdbuff, a, true, thickness, srgb); } -void draw_arrow_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color) +void draw_arrow_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 srgb) { const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */ @@ -242,19 +242,19 @@ void draw_arrow_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struc .points = head_points, .count = ARRAY_COUNT(head_points) }; - draw_poly(cmdbuff, head_points_v2_array, color); + draw_poly(cmdbuff, head_points_v2_array, srgb); struct quad line_quad = quad_from_line(start, head_start, thickness); - draw_quad(cmdbuff, line_quad, color); + draw_quad(cmdbuff, line_quad, srgb); } -void draw_arrow_ray(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color) +void draw_arrow_ray(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 srgb) { struct v2 end = v2_add(pos, rel); - draw_arrow_line(cmdbuff, pos, end, thickness, arrowhead_height, color); + draw_arrow_line(cmdbuff, pos, end, thickness, arrowhead_height, srgb); } -void draw_collider_line(struct renderer_cmd_buffer *cmdbuff, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail) +void draw_collider_line(struct renderer_cmd_buffer *cmdbuff, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 srgb, u32 detail) { struct temp_arena scratch = scratch_begin_no_conflict(); @@ -269,12 +269,12 @@ void draw_collider_line(struct renderer_cmd_buffer *cmdbuff, struct xform draw_x #if 1 struct v2_array poly = { .points = points, .count = detail }; - draw_poly_line(cmdbuff, poly, true, thickness, color); + draw_poly_line(cmdbuff, poly, true, thickness, srgb); #else for (u64 i = 0; i < detail; ++i) { struct v2 point = points[i]; (UNUSED)thickness; - draw_circle(cmdbuff, point, 3, color, 10); + draw_circle(cmdbuff, point, 3, srgb, 10); } #endif @@ -285,7 +285,7 @@ void draw_collider_line(struct renderer_cmd_buffer *cmdbuff, struct xform draw_x * Grid * ========================== */ -void draw_grid(struct renderer_cmd_buffer *cmdbuff, struct rect rect, u32 color_bg0, u32 color_bg1, u32 color_line, u32 color_x, u32 color_y, f32 thickness, f32 spacing, struct v2 offset) +void draw_grid(struct renderer_cmd_buffer *cmdbuff, struct rect rect, u32 bg0_srgb, u32 bg1_srgb, u32 line_srgb, u32 x_srgb, u32 y_srgb, f32 thickness, f32 spacing, struct v2 offset) { struct renderer_cmd_parameters cmd_params = ZI; cmd_params.kind = SHADER_GRID; @@ -298,11 +298,11 @@ void draw_grid(struct renderer_cmd_buffer *cmdbuff, struct rect rect, u32 color_ struct quad quad = quad_from_rect(rect); struct grid_shader_vertex attributes = ZI; - attributes.color_bg0 = color_bg0; - attributes.color_bg1 = color_bg1; - attributes.color_line = color_line; - attributes.color_x= color_x; - attributes.color_y = color_y; + attributes.bg0_srgb = bg0_srgb; + attributes.bg1_srgb = bg1_srgb; + attributes.line_srgb = line_srgb; + attributes.x_srgb = x_srgb; + attributes.y_srgb = y_srgb; attributes.line_thickness = thickness; attributes.line_spacing = spacing; attributes.offset = offset; diff --git a/src/draw.h b/src/draw.h index e0c985f4..06c87e34 100644 --- a/src/draw.h +++ b/src/draw.h @@ -28,21 +28,21 @@ struct draw_startup_receipt draw_startup(struct renderer_startup_receipt *render void draw_quad_texture_ex(struct renderer_cmd_buffer *cmdbuff, struct renderer_texture texture, struct sprite_tag sprite, struct clip_rect clip, u32 tint0, u32 tint1, struct quad quad); void draw_quad_texture(struct renderer_cmd_buffer *cmdbuff, struct draw_texture_params params, struct quad quad); -void draw_poly(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, u32 color); -void draw_circle(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 color, u32 detail); -void draw_quad(struct renderer_cmd_buffer *cmdbuff, struct quad quad, u32 color); +void draw_poly(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, u32 srgb); +void draw_circle(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 srgb, u32 detail); +void draw_quad(struct renderer_cmd_buffer *cmdbuff, struct quad quad, u32 srgb); -void draw_gradient_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 color_start, u32 color_end); -void draw_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 color); -void draw_ray(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 ray, f32 thickness, u32 color); -void draw_poly_line(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, b32 loop, f32 thickness, u32 color); -void draw_circle_line(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail); -void draw_quad_line(struct renderer_cmd_buffer *cmdbuff, struct quad quad, f32 thickness, u32 color); -void draw_arrow_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color); -void draw_arrow_ray(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color); -void draw_collider_line(struct renderer_cmd_buffer *cmdbuff, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail); +void draw_gradient_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 start_srgb, u32 end_srgb); +void draw_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 srgb); +void draw_ray(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 ray, f32 thickness, u32 srgb); +void draw_poly_line(struct renderer_cmd_buffer *cmdbuff, struct v2_array array, b32 loop, f32 thickness, u32 srgb); +void draw_circle_line(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, f32 thickness, u32 srgb, u32 detail); +void draw_quad_line(struct renderer_cmd_buffer *cmdbuff, struct quad quad, f32 thickness, u32 srgb); +void draw_arrow_line(struct renderer_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 srgb); +void draw_arrow_ray(struct renderer_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 srgb); +void draw_collider_line(struct renderer_cmd_buffer *cmdbuff, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 srgb, u32 detail); -void draw_grid(struct renderer_cmd_buffer *cmdbuff, struct rect rect, u32 color_bg0, u32 color_bg1, u32 color_line, u32 color_x, u32 color_y, f32 thickness, f32 spacing, struct v2 offset); +void draw_grid(struct renderer_cmd_buffer *cmdbuff, struct rect rect, u32 bg0_srgb, u32 bg1_srgb, u32 line_srgb, u32 x_srgb, u32 y_srgb, f32 thickness, f32 spacing, struct v2 offset); void draw_text(struct renderer_cmd_buffer *cmdbuff, struct font *font, struct v2 pos, struct string str); void draw_text_ex(struct renderer_cmd_buffer *cmdbuff, struct font *font, struct v2 pos, f32 scale, struct string str); diff --git a/src/renderer.h b/src/renderer.h index 5374e2c2..45de4d82 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -39,19 +39,19 @@ struct renderer_cmd_parameters { PACK(struct triangle_shader_vertex { struct v2 pos; struct v2 uv; - u32 color; + u32 tint_srgb; }); PACK(struct grid_shader_vertex { struct v2 pos; - u32 color_bg0; - u32 color_bg1; - u32 color_line; - u32 color_x; - u32 color_y; f32 line_thickness; f32 line_spacing; struct v2 offset; + u32 bg0_srgb; + u32 bg1_srgb; + u32 line_srgb; + u32 x_srgb; + u32 y_srgb; }); /* ========================== * @@ -69,6 +69,7 @@ enum renderer_texture_format { RENDERER_TEXTURE_FORMAT_NONE, RENDERER_TEXTURE_FORMAT_R8G8B8A8_UNORM, + RENDERER_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB, NUM_RENDERER_TEXTURE_FORMATS }; diff --git a/src/renderer_d3d11.c b/src/renderer_d3d11.c index 8c7adb82..e1bce9ce 100644 --- a/src/renderer_d3d11.c +++ b/src/renderer_d3d11.c @@ -30,12 +30,18 @@ #define SHADER_INFO_LOOKUP_BINS 64 /* FIXME: Enable this and resolve unreleased references */ -//#define D3D11_DEBUG RTC -#define D3D11_DEBUG 0 +#if RTC +# define D3D11_DEBUG 0 +#else +# define D3D11_DEBUG 0 +#endif #define D3D11_SHADER_DEBUG RTC -#define D3D11_SWAPCHAIN_FLAGS (DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) +#define D3D11_SWAPCHAIN_FLAGS (DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) + +#define D3D11_SWAPCHAIN_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM) +#define D3D11_SWAPCHAIN_RTV_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) struct dx11_shader { enum shader_kind kind; @@ -217,9 +223,9 @@ INTERNAL void init_shader_table(void) .name_cstr = "res/shaders/triangle.hlsl", .vertex_size = sizeof(struct triangle_shader_vertex), .input_layout_desc = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } } }; @@ -230,14 +236,14 @@ INTERNAL void init_shader_table(void) .vertex_size = sizeof(struct grid_shader_vertex), .input_layout_desc = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR_BG_A", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR_BG_B", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR_LINE", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR_X", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR_Y", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "THICKNESS", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "SPACING", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "OFFSET", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } + { "OFFSET", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 2, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 3, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 4, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } } }; @@ -445,7 +451,7 @@ struct renderer_startup_receipt renderer_startup(struct sys_window *window) } #if D3D11_DEBUG - /* Enable debug break on API errors */ + /* D3D11 Debug break */ { ID3D11InfoQueue *info; ID3D11Device_QueryInterface(device, &IID_ID3D11InfoQueue, (void **)&info); @@ -454,7 +460,7 @@ struct renderer_startup_receipt renderer_startup(struct sys_window *window) ID3D11InfoQueue_Release(info); } - /* Enable debug break for DXGI too */ + /* DXGI Debug break */ { IDXGIInfoQueue *dxgiInfo; hr = DXGIGetDebugInterface1(0, &IID_IDXGIInfoQueue, (void **)&dxgiInfo); @@ -485,19 +491,13 @@ struct renderer_startup_receipt renderer_startup(struct sys_window *window) ASSERT(SUCCEEDED(hr)); DXGI_SWAP_CHAIN_DESC1 desc = { - .Format = DXGI_FORMAT_R8G8B8A8_UNORM, + .Format = D3D11_SWAPCHAIN_FORMAT, .SampleDesc = { 1, 0 }, .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT, .BufferCount = 2, .Scaling = DXGI_SCALING_NONE, .Flags = D3D11_SWAPCHAIN_FLAGS, .AlphaMode = DXGI_ALPHA_MODE_IGNORE, - - /* More efficient FLIP presentation model. - * Windows 10 allows to use DXGI_SWAP_EFFECT_FLIP_DISCARD - * For Windows 8 compatibility use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL - * For Windows 7 compatibility use DXGI_SWAP_EFFECT_DISCARD - */ .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD, }; @@ -520,6 +520,7 @@ struct renderer_startup_receipt renderer_startup(struct sys_window *window) G.dev = device; G.devcon = context; G.swapchain = swapchain; + G.backbuffer_texture.is_backbuffer = true; struct string prof_ctx_name = LIT("D3d11 Context"); (UNUSED)prof_ctx_name; @@ -706,10 +707,10 @@ INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct renderer_cmd_bu if (texture) { /* Bind texture */ - D3D11_TEXTURE2D_DESC texture_desc = ZI; - ID3D11Texture2D_GetDesc(texture, &texture_desc); /* Create SRV */ + D3D11_TEXTURE2D_DESC texture_desc = ZI; + ID3D11Texture2D_GetDesc(texture, &texture_desc); D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = { .Format = texture_desc.Format, .ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D, .Texture2D.MipLevels = texture_desc.MipLevels, .Texture2D.MostDetailedMip = 0 }; ID3D11ShaderResourceView *texture_srv = NULL; ID3D11Device_CreateShaderResourceView(G.dev, (ID3D11Resource *)texture, &srv_desc, &texture_srv); @@ -771,6 +772,10 @@ INTERNAL struct dx11_format dx11_format_from_renderer_format(enum renderer_textu [RENDERER_TEXTURE_FORMAT_R8G8B8A8_UNORM] = { .format = DXGI_FORMAT_R8G8B8A8_UNORM, .pixel_size = 4 + }, + [RENDERER_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB] = { + .format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + .pixel_size = 4 } }; struct dx11_format res = ZI; @@ -806,7 +811,7 @@ INTERNAL struct dx11_texture *dx11_texture_alloc(enum renderer_texture_format fo if (dx11_format.format == DXGI_FORMAT_UNKNOWN) { /* Unknown format */ ASSERT(false); - dx11_format = (struct dx11_format) { .format = DXGI_FORMAT_R8G8B8A8_UNORM, .pixel_size = 4 }; + sys_panic(LIT("Unknown dx11 texture format during texture allocation")); } u32 bind_flags = D3D11_BIND_SHADER_RESOURCE; @@ -911,8 +916,16 @@ void renderer_texture_render(struct renderer_texture texture, struct renderer_cm struct dx11_texture *t = (struct dx11_texture *)texture.handle; + D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = ZI; + D3D11_RENDER_TARGET_VIEW_DESC *rtv_desc_param = NULL; + if (t->is_backbuffer) { + rtv_desc.Format = D3D11_SWAPCHAIN_RTV_FORMAT; + rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtv_desc_param = &rtv_desc; + } + ID3D11RenderTargetView *target_view = NULL; - ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, NULL, &target_view); + ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, rtv_desc_param, &target_view); if (target_view) { dx11_render(target_view, cmdbuff, view, viewport); } diff --git a/src/sprite.c b/src/sprite.c index 2d9fda4e..3dbef2d6 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -368,11 +368,16 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t decoded = ase_decode_image(scratch.arena, resource_get_data(&texture_rs)); resource_close(&texture_rs); + enum renderer_texture_format format = RENDERER_TEXTURE_FORMAT_R8G8B8A8_UNORM; + if (decoded.srgb) { + format = RENDERER_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB; + } + /* Initialize */ e->texture = arena_push(&e->arena, struct sprite_texture); e->texture->width = decoded.image.width; e->texture->height = decoded.image.height; - e->texture->texture = renderer_texture_alloc(RENDERER_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32(decoded.image.width, decoded.image.height), decoded.image.pixels); + e->texture->texture = renderer_texture_alloc(format, 0, V2I32(decoded.image.width, decoded.image.height), decoded.image.pixels); e->texture->valid = true; e->texture->loaded = true; /* TODO: Query renderer for more accurate texture size in VRAM */