From ecccc9b5c923a3d9aa9a1e69555449df9d4907eb Mon Sep 17 00:00:00 2001 From: deuxcents Date: Mon, 17 May 2021 22:40:52 +0200 Subject: [PATCH] Fux camera2D flipping textures --- gs.h | 1 + impl/gs_graphics_impl.h | 11 +++++++++++ util/gs_gfxt.h | 4 +++- util/gs_idraw.h | 30 +++++++++++++++++++++++++----- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/gs.h b/gs.h index 34ba37f3..f8d7838e 100644 --- a/gs.h +++ b/gs.h @@ -4493,6 +4493,7 @@ gs_enum_decl(gs_graphics_shader_language_type, /* Uniform Type */ gs_enum_decl(gs_graphics_uniform_type, + GS_GRAPHICS_UNIFORM_BOOL, GS_GRAPHICS_UNIFORM_FLOAT, GS_GRAPHICS_UNIFORM_INT, GS_GRAPHICS_UNIFORM_VEC2, diff --git a/impl/gs_graphics_impl.h b/impl/gs_graphics_impl.h index 1a16cc69..328110c7 100644 --- a/impl/gs_graphics_impl.h +++ b/impl/gs_graphics_impl.h @@ -34,6 +34,7 @@ gs_graphics_info_t* gs_graphics_info() typedef enum gsgl_uniform_type { + GSGL_UNIFORMTYPE_BOOL, GSGL_UNIFORMTYPE_FLOAT, GSGL_UNIFORMTYPE_INT, GSGL_UNIFORMTYPE_VEC2, @@ -420,6 +421,7 @@ gsgl_uniform_type gsgl_uniform_type_to_gl_uniform_type(gs_graphics_uniform_type gsgl_uniform_type type = GSGL_UNIFORMTYPE_FLOAT; switch (gstype) { default: + case GS_GRAPHICS_UNIFORM_BOOL: type = GSGL_UNIFORMTYPE_BOOL; break; case GS_GRAPHICS_UNIFORM_FLOAT: type = GSGL_UNIFORMTYPE_FLOAT; break; case GS_GRAPHICS_UNIFORM_INT: type = GSGL_UNIFORMTYPE_INT; break; case GS_GRAPHICS_UNIFORM_VEC2: type = GSGL_UNIFORMTYPE_VEC2; break; @@ -499,6 +501,7 @@ size_t gsgl_uniform_data_size_in_bytes(gs_graphics_uniform_type type) { size_t sz = 0; switch (type) { + case GS_GRAPHICS_UNIFORM_BOOL: sz = sizeof(bool); break; case GS_GRAPHICS_UNIFORM_FLOAT: sz = sizeof(float); break; case GS_GRAPHICS_UNIFORM_INT: sz = sizeof(int32_t); break; case GS_GRAPHICS_UNIFORM_VEC2: sz = 2 * sizeof(float); break; @@ -1571,6 +1574,14 @@ void gs_graphics_submit_command_buffer(gs_command_buffer_t* cb) // Switch on uniform type to upload data switch (u->type) { + + case GSGL_UNIFORMTYPE_BOOL: //GSGL size of bool is uint32, which is fine for a normally one byte bool in C + { + gs_assert(u->size == sizeof(bool)); + gs_byte_buffer_read_bulkc(&cb->commands, bool, v, u->size); + glUniform1f(u->location, v); + } break; + case GSGL_UNIFORMTYPE_FLOAT: { gs_assert(u->size == sizeof(float)); diff --git a/util/gs_gfxt.h b/util/gs_gfxt.h index b3c53b33..f000bc7e 100644 --- a/util/gs_gfxt.h +++ b/util/gs_gfxt.h @@ -243,6 +243,7 @@ gs_gfxt_uniform_block_t gs_gfxt_uniform_block_create(gs_gfxt_uniform_block_desc_ // Add to data offset based on type switch (ud->type) { default: + case GS_GRAPHICS_UNIFORM_BOOL: offset += sizeof(bool); break; case GS_GRAPHICS_UNIFORM_FLOAT: offset += sizeof(float); break; case GS_GRAPHICS_UNIFORM_INT: offset += sizeof(int32_t); break; case GS_GRAPHICS_UNIFORM_VEC2: offset += sizeof(gs_vec2); break; @@ -367,7 +368,8 @@ void gs_gfxt_material_set_uniform(gs_gfxt_material_t* mat, const char* name, voi switch (u->type) { - case GS_GRAPHICS_UNIFORM_FLOAT: gs_byte_buffer_write(&mat->uniform_data, float, *(float*)data); break; + case GS_GRAPHICS_UNIFORM_BOOL: gs_byte_buffer_write(&mat->uniform_data, bool, *(bool*)data); break; + case GS_GRAPHICS_UNIFORM_FLOAT: gs_byte_buffer_write(&mat->uniform_data, float, *(float*)data); break; case GS_GRAPHICS_UNIFORM_INT: gs_byte_buffer_write(&mat->uniform_data, int32_t, *(int32_t*)data); break; case GS_GRAPHICS_UNIFORM_VEC2: gs_byte_buffer_write(&mat->uniform_data, gs_vec2, *(gs_vec2*)data); break; case GS_GRAPHICS_UNIFORM_VEC3: gs_byte_buffer_write(&mat->uniform_data, gs_vec3, *(gs_vec3*)data); break; diff --git a/util/gs_idraw.h b/util/gs_idraw.h index 860ada7a..6e7395fc 100644 --- a/util/gs_idraw.h +++ b/util/gs_idraw.h @@ -84,6 +84,8 @@ typedef struct gs_immediate_cache_t gs_dyn_array(gs_mat4) projection; /* Mode stack*/ gs_dyn_array(gsi_matrix_type) modes; + /* Flip texture in fragment shader in case y axis is reversed by projection matrix*/ + bool flip_tex; /* UV */ gs_vec2 uv; /* Color */ @@ -109,6 +111,8 @@ typedef struct gs_immediate_draw_t gs_hash_table(gsi_pipeline_state_attr_t, gs_handle(gs_graphics_pipeline_t)) pipeline_table; /* Uniform buffer */ gs_handle(gs_graphics_uniform_t) uniform; + /* Uniform flip texture flag */ + gs_handle(gs_graphics_uniform_t) flip_tex; /* Uniform sampler */ gs_handle(gs_graphics_uniform_t) sampler; /* Dynamic array of vertex data to update */ @@ -234,11 +238,12 @@ GSI_GL_VERSION_STR "layout(location = 1) in vec2 a_uv;\n" "layout(location = 2) in vec4 a_color;\n" "uniform mat4 u_mvp;\n" +"uniform bool flip_tex;\n" "out vec2 uv;\n" "out vec4 color;\n" "void main() {\n" " gl_Position = u_mvp * vec4(a_position, 1.0);\n" -" uv = a_uv;\n" +" uv = flip_tex ? vec2(a_uv.s, 1.0 - a_uv.t) : a_uv;\n" " color = a_color;\n" "}\n"; @@ -278,6 +283,7 @@ void gsi_reset(gs_immediate_draw_t* gsi) gs_dyn_array_push(gsi->cache.projection, gs_mat4_identity()); gs_dyn_array_push(gsi->cache.modes, GSI_MATRIX_MODELVIEW); + gsi->cache.flip_tex = false; gsi->cache.texture = gsi->tex_default; gsi->cache.pipeline = gsi_pipeline_state_default(); gsi->cache.pipeline.prim_type = 0x00; @@ -305,6 +311,14 @@ gs_immediate_draw_t gs_immediate_draw_new() udesc.layout = &uldesc; gsi.uniform = gs_graphics_uniform_create(&udesc); + // Flip texture flag + gs_graphics_uniform_layout_desc_t fldesc = gs_default_val(); + fldesc.type = GS_GRAPHICS_UNIFORM_BOOL; + gs_graphics_uniform_desc_t fdesc = gs_default_val(); + fdesc.name = "flip_tex"; + fdesc.layout = &fldesc; + gsi.flip_tex = gs_graphics_uniform_create(&fdesc); + // Create sampler buffer gs_graphics_uniform_layout_desc_t sldesc = gs_default_val(); sldesc.type = GS_GRAPHICS_UNIFORM_SAMPLER2D; @@ -530,9 +544,10 @@ void gsi_flush(gs_immediate_draw_t* gsi) gs_graphics_bind_vertex_buffer_desc_t vbuffer = gs_default_val(); vbuffer.buffer = gsi->vbo; - gs_graphics_bind_uniform_desc_t ubinds[2] = gs_default_val(); + gs_graphics_bind_uniform_desc_t ubinds[3] = gs_default_val(); ubinds[0].uniform = gsi->uniform; ubinds[0].data = &mvp; - ubinds[1].uniform = gsi->sampler; ubinds[1].data = &gsi->cache.texture; ubinds[1].binding = 0; + ubinds[1].uniform = gsi->flip_tex; ubinds[1].data = &gsi->cache.flip_tex; + ubinds[2].uniform = gsi->sampler; ubinds[2].data = &gsi->cache.texture; ubinds[2].binding = 0; // Bindings for all buffers: vertex, uniform, sampler gs_graphics_bind_desc_t binds = gs_default_val(); @@ -642,6 +657,7 @@ void gsi_defaults(gs_immediate_draw_t* gsi) gsi_flush(gsi); // Set defaults for cache + gsi->cache.flip_tex = false; gsi->cache.texture = gsi->tex_default; gsi->cache.pipeline = gsi_pipeline_state_default(); gsi->cache.pipeline.prim_type = 0x00; @@ -821,26 +837,29 @@ void gsi_camera(gs_immediate_draw_t* gsi, gs_camera_t* cam) // Just grab main window for now. Will need to grab top of viewport stack in future gs_vec2 ws = gs_platform_window_sizev(gs_platform_main_window()); gsi_load_matrix(gsi, gs_camera_get_view_projection(cam, (s32)ws.x, (s32)ws.y)); + gsi->cache.flip_tex = false; } void gsi_camera2D(gs_immediate_draw_t* gsi) { // Flush previous gsi_flush(gsi); - // Puts the camera in center of screen, 0,0 is bottom left corner + // Puts the camera from center of screen where (-1,-1) is bottom left to screen coordinates (pixels with origin at top left, means y axis is flipped) gs_vec2 ws = gs_platform_window_sizev(gs_platform_main_window()); gs_vec2 hws = gs_vec2_scale(ws, 0.5f); gs_camera_t c = gs_camera_default(); c.transform.position = gs_vec3_add(c.transform.position, gs_v3(hws.x, hws.y, -1.f)); f32 l = -ws.x / 2.f; f32 r = ws.x / 2.f; - f32 b = ws.y / 2.f; + f32 b = ws.y / 2.f; // The sign of this line with the below line's sign flip y axis f32 tp = -ws.y / 2.f; gs_mat4 ortho = gs_mat4_transpose(gs_mat4_ortho( l, r, b, tp, 0.1f, 100.f )); ortho = gs_mat4_mul(ortho, gs_camera_get_view(&c)); gsi_load_matrix(gsi, ortho); + // Need to flip texture as y axis is now inverted with the above matrix + gsi->cache.flip_tex = true; } void gsi_camera3D(gs_immediate_draw_t* gsi) @@ -849,6 +868,7 @@ void gsi_camera3D(gs_immediate_draw_t* gsi) gsi_flush(gsi); gs_camera_t c = gs_camera_perspective(); gsi_camera(gsi, &c); + gsi->cache.flip_tex = false; } // Shape Drawing Utils