diff --git a/src/pc/gfx/gfx_cc.h b/src/pc/gfx/gfx_cc.h index 5a5df0490..3eb9f67cd 100644 --- a/src/pc/gfx/gfx_cc.h +++ b/src/pc/gfx/gfx_cc.h @@ -88,6 +88,7 @@ struct CombineMode { uint8_t use_dither : 1; uint8_t use_2cycle : 1; uint8_t light_map : 1; + uint8_t tex_persp : 1; uint8_t world_geometry : 1; }; u32 flags; diff --git a/src/pc/gfx/gfx_direct3d11.cpp b/src/pc/gfx/gfx_direct3d11.cpp index d07499ed2..664d9d118 100644 --- a/src/pc/gfx/gfx_direct3d11.cpp +++ b/src/pc/gfx/gfx_direct3d11.cpp @@ -621,13 +621,13 @@ static void gfx_d3d11_shader_get_info(struct ShaderProgram *prg, uint8_t *num_in used_textures[1] = p->used_textures[1]; } -static void gfx_d3d11_create_framebuffer(UNUSED u32 *fbo, UNUSED u32 *depthBuffer, UNUSED u32 *tex, UNUSED u32 width, UNUSED u32 height) { +static void gfx_d3d11_create_framebuffer(UNUSED struct FramePass *framePass) { } -static void gfx_d3d11_delete_framebuffer(UNUSED u32 fbo, UNUSED u32 depthBuffer, UNUSED u32 tex) { +static void gfx_d3d11_delete_framebuffer(UNUSED struct FramePass *framePass) { } -static void gfx_d3d11_set_framebuffer(UNUSED u32 fbo, UNUSED u32 width, UNUSED u32 height) { +static void gfx_d3d11_set_framebuffer(UNUSED struct FramePass *framePass) { } static void gfx_d3d11_reset_framebuffer(void) { @@ -950,7 +950,13 @@ static void gfx_d3d11_start_frame(void) { d3d.context->OMSetRenderTargets(1, d3d.backbuffer_view.GetAddressOf(), d3d.depth_stencil_view.Get()); // Clear render targets - const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + struct FramePass *framePass = gfx_get_current_frame_pass(); + const float clearColor[] = { + framePass->clearColor[0] / 255.0f, + framePass->clearColor[1] / 255.0f, + framePass->clearColor[2] / 255.0f, + framePass->clearColor[3] / 255.0f + }; d3d.context->ClearRenderTargetView(d3d.backbuffer_view.Get(), clearColor); d3d.context->ClearDepthStencilView(d3d.depth_stencil_view.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0); diff --git a/src/pc/gfx/gfx_dummy.c b/src/pc/gfx/gfx_dummy.c index d5de28f79..d782dae28 100644 --- a/src/pc/gfx/gfx_dummy.c +++ b/src/pc/gfx/gfx_dummy.c @@ -154,13 +154,13 @@ static void gfx_dummy_renderer_shader_get_info(UNUSED struct ShaderProgram *prg, used_textures[1] = false; } -static void gfx_dummy_renderer_create_framebuffer(UNUSED u32 *fbo, UNUSED u32 *depthBuffer, UNUSED u32 *tex, UNUSED u32 width, UNUSED u32 height) { +static void gfx_dummy_renderer_create_framebuffer(UNUSED struct FramePass *framePass) { } -static void gfx_dummy_renderer_delete_framebuffer(UNUSED u32 fbo, UNUSED u32 depthBuffer, UNUSED u32 tex) { +static void gfx_dummy_renderer_delete_framebuffer(UNUSED struct FramePass *framePass) { } -static void gfx_dummy_renderer_set_framebuffer(UNUSED u32 fbo, UNUSED u32 width, UNUSED u32 height) { +static void gfx_dummy_renderer_set_framebuffer(UNUSED struct FramePass *framePass) { } static void gfx_dummy_renderer_reset_framebuffer(void) { diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c index d8ee58427..1b85d201f 100644 --- a/src/pc/gfx/gfx_opengl.c +++ b/src/pc/gfx/gfx_opengl.c @@ -561,24 +561,24 @@ static void gfx_opengl_shader_get_info(struct ShaderProgram *prg, uint8_t *num_i used_textures[1] = prg->used_textures[1]; } -static void gfx_opengl_create_framebuffer(u32 *fbo, u32 *depthBuffer, u32 *tex, u32 width, u32 height) { - glGenFramebuffers(1, fbo); - glBindFramebuffer(GL_FRAMEBUFFER, *fbo); +static void gfx_opengl_create_framebuffer(struct FramePass *framePass) { + glGenFramebuffers(1, &framePass->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, framePass->fbo); - glGenTextures(1, tex); - glBindTexture(GL_TEXTURE_2D, *tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glGenTextures(1, &framePass->passTexture); + glBindTexture(GL_TEXTURE_2D, framePass->passTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, framePass->width, framePass->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tex, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framePass->passTexture, 0); // create depth buffer - glGenRenderbuffers(1, depthBuffer); - glBindRenderbuffer(GL_RENDERBUFFER, *depthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *depthBuffer); + glGenRenderbuffers(1, &framePass->depthBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, framePass->depthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, framePass->width, framePass->height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, framePass->depthBuffer); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { LOG_ERROR("Framebuffer is not complete!"); @@ -587,15 +587,15 @@ static void gfx_opengl_create_framebuffer(u32 *fbo, u32 *depthBuffer, u32 *tex, glBindFramebuffer(GL_FRAMEBUFFER, 0); } -static void gfx_opengl_delete_framebuffer(u32 fbo, u32 depthBuffer, u32 tex) { - if (fbo > 0) glDeleteFramebuffers(1, &fbo); - if (depthBuffer > 0) glDeleteRenderbuffers(1, &depthBuffer); - if (tex > 0) glDeleteTextures(1, &tex); +static void gfx_opengl_delete_framebuffer(struct FramePass *framePass) { + if (framePass->fbo > 0) { glDeleteFramebuffers(1, &framePass->fbo); } + if (framePass->depthBuffer > 0) { glDeleteRenderbuffers(1, &framePass->depthBuffer); } + if (framePass->passTexture > 0) { glDeleteTextures(1, &framePass->passTexture); } } -static void gfx_opengl_set_framebuffer(u32 fbo, u32 width, u32 height) { - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glViewport(0, 0, width, height); +static void gfx_opengl_set_framebuffer(struct FramePass *framePass) { + glBindFramebuffer(GL_FRAMEBUFFER, framePass->fbo); + glViewport(0, 0, framePass->width, framePass->height); } static void gfx_opengl_reset_framebuffer(void) { @@ -777,7 +777,15 @@ static void gfx_opengl_start_frame(void) { glDisable(GL_SCISSOR_TEST); glDepthMask(GL_TRUE); // Must be set to clear Z-buffer - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + struct FramePass *framePass = gfx_get_current_frame_pass(); + glClearColor( + framePass->clearColor[0] / 255.0f, + framePass->clearColor[1] / 255.0f, + framePass->clearColor[2] / 255.0f, + framePass->clearColor[3] / 255.0f + ); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_SCISSOR_TEST); } diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index 730317432..00df1ef7f 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -1108,12 +1108,13 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t struct CombineMode* cm = &rdp.combine_mode; - cm->use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0; - cm->texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA; - cm->use_dither = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER; - cm->use_2cycle = (rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) == G_CYC_2CYCLE; - cm->use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG; - cm->light_map = (rsp.geometry_mode & G_LIGHT_MAP_EXT) == G_LIGHT_MAP_EXT; + cm->use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0; + cm->texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA; + cm->use_dither = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER; + cm->use_2cycle = (rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) == G_CYC_2CYCLE; + cm->use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG; + cm->light_map = (rsp.geometry_mode & G_LIGHT_MAP_EXT) == G_LIGHT_MAP_EXT; + cm->tex_persp = (rdp.other_mode_h & G_TP_PERSP) == G_TP_PERSP; cm->world_geometry = gShaderFlagsEnabled && (v1->world_geometry && v2->world_geometry && v3->world_geometry); if (cm->texture_edge) { @@ -2095,6 +2096,14 @@ void gfx_start_frame(void) { gfx_current_dimensions.x_adjust_ratio = (4.0f / 3.0f) / gfx_current_dimensions.aspect_ratio; } +struct FramePass *gfx_get_current_frame_pass(void) { + if (gCurrentFramePassIndex < 0) { + return &gDefaultGeoFramePass; + } else { + return &gFramePasses[gCurrentFramePassIndex]; + } +} + static void gfx_process_lua_passes(Gfx *commands, bool *isLuaPassesActive) { for (int i = 0; i < MAX_CUSTOM_FRAME_PASSES; i++) { struct FramePass *framePass = &gFramePasses[i]; @@ -2103,7 +2112,7 @@ static void gfx_process_lua_passes(Gfx *commands, bool *isLuaPassesActive) { // remove default frame pass if we have lua frame pass if (gDefaultGeoFramePass.active) { - gfx_rapi->delete_framebuffer(gDefaultGeoFramePass.fbo, gDefaultGeoFramePass.depthBuffer, gDefaultGeoFramePass.passTexture); + gfx_rapi->delete_framebuffer(&gDefaultGeoFramePass); memset(&gDefaultGeoFramePass, 0, sizeof(struct FramePass)); } @@ -2111,9 +2120,9 @@ static void gfx_process_lua_passes(Gfx *commands, bool *isLuaPassesActive) { // setup framebuffer if (framePass->fbo == 0) { - gfx_rapi->create_framebuffer(&framePass->fbo, &framePass->depthBuffer, &framePass->passTexture, framePass->width, framePass->height); + gfx_rapi->create_framebuffer(framePass); } - gfx_rapi->set_framebuffer(framePass->fbo, framePass->width, framePass->height); + gfx_rapi->set_framebuffer(framePass); gfx_rapi->start_frame(); // resets color and depth @@ -2167,6 +2176,7 @@ void gfx_run_basic(Gfx *commands) { // for dummy frames we don't want to do a mu } void gfx_run(Gfx *commands) { + // Shader TODO: Give directx support for frame passes if (gRenderApi == &gfx_direct3d11_api) { gfx_run_basic(commands); return; @@ -2189,16 +2199,17 @@ void gfx_run(Gfx *commands) { memset(&gDefaultGeoFramePass, 0, sizeof(struct FramePass)); gDefaultGeoFramePass.active = true; gDefaultGeoFramePass.drawWorldGeometry = true; + gDefaultGeoFramePass.clearColor[3] = 255; } // create/update fbo if (gDefaultGeoFramePass.fbo == 0 || gDefaultGeoFramePass.width != gfx_current_dimensions.width || gDefaultGeoFramePass.height != gfx_current_dimensions.height) { - gfx_rapi->delete_framebuffer(gDefaultGeoFramePass.fbo, gDefaultGeoFramePass.depthBuffer, gDefaultGeoFramePass.passTexture); + gfx_rapi->delete_framebuffer(&gDefaultGeoFramePass); gfx_get_dimensions(&gDefaultGeoFramePass.width, &gDefaultGeoFramePass.height); - gfx_rapi->create_framebuffer(&gDefaultGeoFramePass.fbo, &gDefaultGeoFramePass.depthBuffer, &gDefaultGeoFramePass.passTexture, gDefaultGeoFramePass.width, gDefaultGeoFramePass.height); + gfx_rapi->create_framebuffer(&gDefaultGeoFramePass); } - gfx_rapi->set_framebuffer(gDefaultGeoFramePass.fbo, gDefaultGeoFramePass.width, gDefaultGeoFramePass.height); + gfx_rapi->set_framebuffer(&gDefaultGeoFramePass); gfx_rapi->start_frame(); // resets color and depth diff --git a/src/pc/gfx/gfx_pc.h b/src/pc/gfx/gfx_pc.h index a8c7c3f6f..59e419c26 100644 --- a/src/pc/gfx/gfx_pc.h +++ b/src/pc/gfx/gfx_pc.h @@ -55,6 +55,7 @@ struct FramePass { u32 height; bool active; bool drawWorldGeometry; + u8 clearColor[4]; }; extern struct RSP rsp; @@ -84,6 +85,7 @@ extern "C" { void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, const char *window_title); struct GfxRenderingAPI *gfx_get_current_rendering_api(void); void gfx_start_frame(void); +struct FramePass *gfx_get_current_frame_pass(void); void gfx_run_basic(Gfx *commands); void gfx_run(Gfx *commands); void gfx_end_frame_render(void); diff --git a/src/pc/gfx/gfx_rendering_api.h b/src/pc/gfx/gfx_rendering_api.h index 2705e8f48..828b32934 100644 --- a/src/pc/gfx/gfx_rendering_api.h +++ b/src/pc/gfx/gfx_rendering_api.h @@ -21,9 +21,9 @@ struct GfxRenderingAPI { struct ShaderProgram *(*lookup_shader)(struct ColorCombiner* cc); struct ShaderProgram *(*lookup_shader_using_index)(uint8_t shaderIndex, uint8_t framePassIndex); void (*shader_get_info)(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]); - void (*create_framebuffer)(uint32_t *fbo, uint32_t *depthBuffer, uint32_t *tex, uint32_t width, uint32_t height); - void (*delete_framebuffer)(uint32_t fbo, uint32_t depthBuffer, uint32_t tex); - void (*set_framebuffer)(uint32_t fbo, uint32_t width, uint32_t height); + void (*create_framebuffer)(struct FramePass *framePass); + void (*delete_framebuffer)(struct FramePass *framePass); + void (*set_framebuffer)(struct FramePass *framePass); void (*reset_framebuffer)(void); void (*set_uniform)(struct ShaderProgram *prg, const char *name, ShaderUniformType type, const void *data, uint32_t numElements); uint32_t (*new_texture)(void); diff --git a/src/pc/gfx/gfx_shader.c b/src/pc/gfx/gfx_shader.c index 8e5043e32..2f5bb137d 100644 --- a/src/pc/gfx/gfx_shader.c +++ b/src/pc/gfx/gfx_shader.c @@ -210,6 +210,7 @@ char *gfx_generate_default_fragment_shader_from_cc(struct ColorCombiner *cc) { bool opt_texture_edge = cc->cm.texture_edge; bool opt_2cycle = cc->cm.use_2cycle; bool opt_light_map = cc->cm.light_map; + bool opt_tex_persp = cc->cm.tex_persp; bool world_geometry = cc->cm.world_geometry; bool opt_dither = cc->cm.use_dither; @@ -219,6 +220,7 @@ char *gfx_generate_default_fragment_shader_from_cc(struct ColorCombiner *cc) { append_line(fs_buf, &fs_len, "#version 410 core"); append_line(fs_buf, &fs_len, "out vec4 fragColor;"); for (int t = 0; t < 2; t++) { + if (!opt_tex_persp) { append_str(fs_buf, &fs_len, "noperspective "); } fs_len += sprintf(fs_buf + fs_len, "in vec2 vTexCoord%d;\n", t); } append_line(fs_buf, &fs_len, "in vec4 vFog;"); @@ -549,9 +551,20 @@ void gfx_init_shaders() { } static void process_shader_line(struct Shader *shader, struct ShaderInput *referenceInputs, char *output, const char *line) { - char type[32], name[MAX_SHADER_VARIABLE_NAME]; + char qualifier[32] = { 0 }, type[32] = { 0 }, name[MAX_SHADER_VARIABLE_NAME] = { 0 }; // parse inputs for inputs equivalent to reference inputs + if (sscanf(line, "%31s in %31s %31[^; \t\n]", qualifier, type, name) == 3) { + for (int i = 0; i < MAX_SHADER_INPUTS; i++) { + if (referenceInputs[i].name[0] != '\0' && strcmp(referenceInputs[i].name, name) == 0) { + char layoutLine[sizeof(type) + MAX_SHADER_VARIABLE_NAME + 64]; + snprintf(layoutLine, sizeof(layoutLine), "%s layout(location=%d) in %s %s", qualifier, referenceInputs[i].location, type, name); + strncat(output, layoutLine, MAX_SHADER_CODE - strlen(output) - 1); + return; + } + } + } + if (sscanf(line, " in %31s %31[^; \t\n]", type, name) == 2) { for (int i = 0; i < MAX_SHADER_INPUTS; i++) { if (referenceInputs[i].name[0] != '\0' && strcmp(referenceInputs[i].name, name) == 0) { @@ -564,6 +577,19 @@ static void process_shader_line(struct Shader *shader, struct ShaderInput *refer } // look for and parse outputs + if (sscanf(line, "%31s out %31s %31[^; \t\n]", qualifier, type, name) == 3) { + // add name to our shader outputs + if (shader) { + snprintf(shader->shaderOutputs[sShaderOutputCount].name, MAX_SHADER_VARIABLE_NAME, "%s", name); + shader->shaderOutputs[sShaderOutputCount].location = sShaderOutputCount; + } + char layoutLine[sizeof(type) + MAX_SHADER_VARIABLE_NAME + 64]; + snprintf(layoutLine, sizeof(layoutLine), "%s layout(location=%d) out %s %s", qualifier, sShaderOutputCount, type, name); + strncat(output, layoutLine, MAX_SHADER_CODE - strlen(output) - 1); + if (sShaderOutputCount < MAX_SHADER_OUTPUTS - 1) { sShaderOutputCount++; } + return; + } + if (sscanf(line, " out %31s %31[^; \t\n]", type, name) == 2) { // add name to our shader outputs if (shader) { diff --git a/src/pc/lua/utils/smlua_gfx_utils.c b/src/pc/lua/utils/smlua_gfx_utils.c index 5bf92fc32..294dcd2b1 100644 --- a/src/pc/lua/utils/smlua_gfx_utils.c +++ b/src/pc/lua/utils/smlua_gfx_utils.c @@ -460,6 +460,7 @@ int gfx_shader_create_frame_pass() { // set default values framePass->active = true; gfx_get_dimensions(&framePass->width, &framePass->height); + framePass->clearColor[3] = 255; // clear color is black from memset, set alpha to 255 return i; } @@ -474,7 +475,7 @@ void gfx_shader_remove_frame_pass(int framePassIndex) { struct FramePass *framePass = &gFramePasses[framePassIndex]; if (!framePass->active) return; - gfx_get_current_rendering_api()->delete_framebuffer(framePass->fbo, framePass->depthBuffer, framePass->passTexture); + gfx_get_current_rendering_api()->delete_framebuffer(framePass); memset(framePass, 0, sizeof(struct FramePass)); } @@ -488,7 +489,7 @@ void gfx_shader_set_frame_pass_viewport(int framePassIndex, int width, int heigh framePass->height = height; // needs to be recreated - gfx_get_current_rendering_api()->delete_framebuffer(framePass->fbo, framePass->depthBuffer, framePass->passTexture); + gfx_get_current_rendering_api()->delete_framebuffer(framePass); framePass->fbo = 0; framePass->depthBuffer = 0; framePass->passTexture = 0;