diff --git a/src/DETHRACE/common/brucetrk.c b/src/DETHRACE/common/brucetrk.c index 6fc5d137..7f92a97d 100644 --- a/src/DETHRACE/common/brucetrk.c +++ b/src/DETHRACE/common/brucetrk.c @@ -6,9 +6,9 @@ #include "globvrbm.h" #include "harness/trace.h" #include "init.h" +#include "pd/sys.h" #include "utility.h" #include "world.h" -#include "pd/sys.h" #include #include #include @@ -98,9 +98,10 @@ void StripBlendedFaces(br_actor* pActor, br_model* pModel) { LOG_TRACE("(%p, %p)", pActor, pModel); changed_one = 0; - face = &pModel->faces[0]; - for (i = 0; i < pModel->nfaces; i++, face++) { - if (face->material != NULL && face->material->identifier != NULL && ((face->material->identifier[0] == '!' && face->material->identifier[1] == '!' && gDefault_blend_pc != 0) || face->material->identifier[1] == '\\' )) { + + for (i = 0; i < pModel->nfaces; i++) { + face = &pModel->faces[i]; + if (face->material != NULL && face->material->identifier != NULL && ((face->material->identifier[0] == '!' && face->material->identifier[1] != '!' && gDefault_blend_pc != 0) || face->material->identifier[1] == '\\')) { if (gMr_blendy == NULL) { gMr_blendy = BrActorAllocate(BR_ACTOR_MODEL, NULL); gMr_blendy->render_style = BR_RSTYLE_NONE; @@ -119,8 +120,10 @@ void StripBlendedFaces(br_actor* pActor, br_model* pModel) { } else { BlendifyMaterial(face->material, 50); } - BrMaterialUpdate(face->material, BR_MATU_ALL); + } else { + BlendifyMaterial(face->material, gDefault_blend_pc); } + BrMaterialUpdate(face->material, BR_MATU_ALL); } if (nfaces_allocated <= gMr_blendy->model->nfaces) { PDFatalError("Perfectly understandable error by Batwick, thank you very much Bruce."); @@ -133,7 +136,6 @@ void StripBlendedFaces(br_actor* pActor, br_model* pModel) { pModel->nfaces--; changed_one = 1; i--; - face = &pModel->faces[i]; } } if (changed_one) { diff --git a/src/DETHRACE/common/graphics.c b/src/DETHRACE/common/graphics.c index caf6af1b..87c7a18a 100644 --- a/src/DETHRACE/common/graphics.c +++ b/src/DETHRACE/common/graphics.c @@ -176,16 +176,16 @@ int gArrows[2][4][60] = { 11, 0, 0, -1, 0, 1, 0, 0, -1, 1, -1, 1, -2, -2, 1, -1, 1, 0, 1, 1, 1, 1, 2, }, { 9, 0, 0, -2, 0, -1, 0, 1, 0, 0, -1, 1, -1, 2, -2, 0, 1, 0, 2, }, { 11, 0, 0, -1, 0, 1, 0, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, -1, 1, 0, 1, -1, 2, }, - }, + }, { // outer arrow (=border) - { 26, 1, -3, 1, -2, 1, -1, 2, -1, 2, 0, 2, 1, 3, 1, 3, 2, 3, 3, 2, 3, 1, 3, 1, 2, 0, 2, -1, 2, + { 26, 1, -3, 1, -2, 1, -1, 2, -1, 2, 0, 2, 1, 3, 1, 3, 2, 3, 3, 2, 3, 1, 3, 1, 2, 0, 2, -1, 2, -1, 3, -2, 3, -3, 3, -3, 2, -3, 1, -2, 1, -2, 0, -2, -1, -1, -1, -1, -2, -1, -3, 0, -3, }, { 22, 0, -3, 1, -3, 2, -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 3, 1, 3, 0, 3, 0, 2, -1, 2, -2, 2, -3, 2, -3, 1, -3, 0, -2, 0, -2, -1, -1, -1, -1, -2, 0, -2, }, { 24, 1, -3, 2, -3, 3, -3, 3, -2, 3, -1, 2, -1, 2, 0, 2, 1, 1, 1, 1, 2, 1, 3, 0, 3, -1, 3, -1, 2, - -1, 1, -2, 1, -3, 1, -3, 0, -3, -1, -2, -1, -1, -1, -1, -2, 0, -2, 1, -2, }, - { 22, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 3, -2, 3, -1, 3, 0, 2, 0, 2, 1, 1, 1, 1, 2, 0, 2, + -1, 1, -2, 1, -3, 1, -3, 0, -3, -1, -2, -1, -1, -1, -1, -2, 0, -2, 1, -2, }, + { 22, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 3, -2, 3, -1, 3, 0, 2, 0, 2, 1, 1, 1, 1, 2, 0, 2, 0, 3, -1, 3, -2, 3, -2, 2, -2, 1, -2, 0, -3, 0, -3, -1, }, }, }; @@ -1616,7 +1616,7 @@ void RenderAFrame(int pDepth_mask_on) { ProcessTrack(gUniverse_actor, &gProgram_state.track_spec, gCamera, &gCamera_to_world, 1); } RenderSplashes(); - Harness_Hook_FlushRenderer(); /* Dethrace. Flush buffers into memory. */ + Harness_Hook_FlushRenderer(); /* Dethrace. Flush buffers into memory. */ RenderSmoke(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period); RenderSparks(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period); RenderProximityRays(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period); diff --git a/src/DETHRACE/common/pedestrn.c b/src/DETHRACE/common/pedestrn.c index 8b4cf631..2718ccab 100644 --- a/src/DETHRACE/common/pedestrn.c +++ b/src/DETHRACE/common/pedestrn.c @@ -376,10 +376,10 @@ int BurstPedestrian(tPedestrian_data* pPedestrian, float pSplattitudinalitude, i tU32 the_time; LOG_TRACE("(%p, %f, %d)", pPedestrian, pSplattitudinalitude, pAllow_explosion); - #if defined(DETHRACE_FIX_BUGS) - min_speed = 0; - max_speed = 0; - #endif +#if defined(DETHRACE_FIX_BUGS) + min_speed = 0; + max_speed = 0; +#endif exploded = 0; for (i = 0; i < COUNT_OF(gPed_gib_counts); i++) { for (j = 0; j < gPed_size_counts[i]; j++) { @@ -3400,11 +3400,11 @@ void DropPedPoint() { void DropInitPedPoint() { LOG_TRACE("()"); - #if defined(DETHRACE_FIX_BUGS) - if (gPath_actor == NULL) { - return; - } - #endif +#if defined(DETHRACE_FIX_BUGS) + if (gPath_actor == NULL) { + return; + } +#endif gInit_ped_instruc = gPed_instruc_count; DropPedPoint2(); NewTextHeadupSlot(4, 0, 2000, -1, "Dropped initial pedestrian point"); diff --git a/src/harness/harness.c b/src/harness/harness.c index 4ff2d719..6bd51222 100644 --- a/src/harness/harness.c +++ b/src/harness/harness.c @@ -20,8 +20,6 @@ harness_br_renderer* renderer_state; br_pixelmap* last_dst = NULL; br_pixelmap* last_src = NULL; -br_pixelmap *last_colour_buffer, *last_depth_buffer; - unsigned int last_frame_time = 0; int force_nullrenderer = 0; @@ -371,9 +369,7 @@ int Harness_CalculateFrameDelay() { // Begin 3d scene void Harness_Hook_BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) { - last_colour_buffer = colour_buffer; - last_depth_buffer = depth_buffer; - renderer->BeginScene(camera, colour_buffer); + renderer->BeginScene(camera, colour_buffer, depth_buffer); } void Harness_Hook_BrZbSceneRenderAdd(br_actor* tree) { @@ -384,7 +380,7 @@ void Harness_Hook_renderFaces(br_actor* actor, br_model* model, br_material* mat } void Harness_Hook_BrZbSceneRenderEnd() { - renderer->FlushBuffers(last_colour_buffer, last_depth_buffer); + renderer->FlushBuffers(); renderer->EndScene(); } @@ -415,7 +411,7 @@ void Harness_Hook_PDSetKeyArray() { } void Harness_Hook_FlushRenderer() { - renderer->FlushBuffers(last_colour_buffer, last_depth_buffer); + renderer->FlushBuffers(); } void Harness_Hook_BrMaterialUpdate(br_material* mat, br_uint_16 flags) { diff --git a/src/harness/renderers/gl/gl_renderer.c b/src/harness/renderers/gl/gl_renderer.c index 9fc3737a..41f2ad6f 100644 --- a/src/harness/renderers/gl/gl_renderer.c +++ b/src/harness/renderers/gl/gl_renderer.c @@ -12,11 +12,8 @@ #include #include -extern float gCamera_hither; -extern float gCamera_yon; - static GLuint screen_buffer_vao, screen_buffer_ebo; -static GLuint screen_texture, palette_texture, depth_texture; +static GLuint fullscreen_quad_texture, palette_texture, depth_texture; static GLuint shader_program_2d; static GLuint shader_program_3d; @@ -28,29 +25,33 @@ static uint16_t* depth_buffer_flip_pixels; static int window_width, window_height, render_width, render_height; static int vp_x, vp_y, vp_width, vp_height; -static br_pixelmap* last_shade_table = NULL; +static br_pixelmap *last_colour_buffer, *last_depth_buffer, *last_shade_table; static int dirty_buffers = 0; -tStored_material* current_material; +static GLuint current_framebuffer_texture; +static int generated_current_framebuffer_for_this_frame = 0; + +static tStored_material* current_material; struct { - GLuint pixels, uv_transform; + GLuint texture_pixelmap; + GLuint uv_transform; GLuint shade_table; + GLuint blend_table; + GLuint blend_enabled; + GLuint current_framebuffer; GLuint model, view, projection; GLuint palette_index_override; GLuint clip_plane_count; GLuint clip_planes[6]; GLuint light_value; + GLuint viewport_height; } uniforms_3d; struct { GLuint pixels, palette; } uniforms_2d; -struct { - GLuint pixels, palette; -} uniforms_2dpp; - GLuint CreateShaderProgram(char* name, const char* vertex_shader, const int vertex_shader_len, const char* fragment_shader, const int fragment_shader_len) { int success; char log_buffer[1024]; @@ -122,17 +123,23 @@ void LoadShaders() { uniforms_3d.clip_planes[i] = GetValidatedUniformLocation(shader_program_3d, name); } uniforms_3d.model = GetValidatedUniformLocation(shader_program_3d, "u_model"); - uniforms_3d.pixels = GetValidatedUniformLocation(shader_program_3d, "u_pixels"); + uniforms_3d.texture_pixelmap = GetValidatedUniformLocation(shader_program_3d, "u_texture_pixelmap"); uniforms_3d.uv_transform = GetValidatedUniformLocation(shader_program_3d, "u_texture_coords_transform"); uniforms_3d.shade_table = GetValidatedUniformLocation(shader_program_3d, "u_shade_table"); + uniforms_3d.blend_table = GetValidatedUniformLocation(shader_program_3d, "u_blend_table"); + uniforms_3d.blend_enabled = GetValidatedUniformLocation(shader_program_3d, "u_blend_enabled"); + uniforms_3d.current_framebuffer = GetValidatedUniformLocation(shader_program_3d, "u_current_framebuffer"); uniforms_3d.projection = GetValidatedUniformLocation(shader_program_3d, "u_projection"); uniforms_3d.palette_index_override = GetValidatedUniformLocation(shader_program_3d, "u_palette_index_override"); uniforms_3d.view = GetValidatedUniformLocation(shader_program_3d, "u_view"); uniforms_3d.light_value = GetValidatedUniformLocation(shader_program_3d, "u_light_value"); + uniforms_3d.viewport_height = GetValidatedUniformLocation(shader_program_3d, "u_viewport_height"); - // bind the uniform samplers to texture units. palette=1, shadetable=2 - glUniform1i(uniforms_3d.pixels, 0); + // bind the uniform samplers to texture units + glUniform1i(uniforms_3d.texture_pixelmap, 0); glUniform1i(uniforms_3d.shade_table, 2); + glUniform1i(uniforms_3d.blend_table, 3); + glUniform1i(uniforms_3d.current_framebuffer, 4); } void SetupFullScreenRectGeometry() { @@ -221,10 +228,11 @@ void GLRenderer_Init(int width, int height, int pRender_width, int pRender_heigh glCullFace(GL_BACK); // textures - glGenTextures(1, &screen_texture); + glGenTextures(1, &fullscreen_quad_texture); glGenTextures(1, &palette_texture); glGenTextures(1, &framebuffer_texture); glGenTextures(1, &depth_texture); + glGenTextures(1, ¤t_framebuffer_texture); // setup framebuffer glGenFramebuffers(1, &framebuffer_id); @@ -234,15 +242,25 @@ void GLRenderer_Init(int width, int height, int pRender_width, int pRender_heigh glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glBindTexture(GL_TEXTURE_2D, fullscreen_quad_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, palette_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, framebuffer_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, render_width, render_height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer_texture, 0); - glBindTexture(GL_TEXTURE_2D, depth_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, current_framebuffer_texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, depth_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, render_width, render_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0); @@ -272,8 +290,6 @@ void GLRenderer_SetPalette(uint8_t* rgba_colors) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, palette_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gl_palette); // reset active texture back to default @@ -283,30 +299,48 @@ void GLRenderer_SetPalette(uint8_t* rgba_colors) { } void GLRenderer_SetShadeTable(br_pixelmap* table) { - if (last_shade_table == table) { return; } + // shade table uses texture unit 2 glActiveTexture(GL_TEXTURE2); tStored_pixelmap* stored = table->stored; glBindTexture(GL_TEXTURE_2D, stored->id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // reset active texture back to default glActiveTexture(GL_TEXTURE0); - last_shade_table = table; } +void GLRenderer_SetBlendTable(br_pixelmap* table) { + + if (!generated_current_framebuffer_for_this_frame) { + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, current_framebuffer_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, render_width, render_height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, last_colour_buffer->pixels); + generated_current_framebuffer_for_this_frame = 1; + } + + // blend table uses texture unit 3 + glActiveTexture(GL_TEXTURE3); + tStored_pixelmap* stored = table->stored; + glBindTexture(GL_TEXTURE_2D, stored->id); + + // reset active texture back to default + glActiveTexture(GL_TEXTURE0); +} + extern br_v1db_state v1db; -void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer) { - glViewport(colour_buffer->base_x, render_height - colour_buffer->height - colour_buffer->base_y, colour_buffer->width, colour_buffer->height); +void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) { + last_colour_buffer = colour_buffer; + last_depth_buffer = depth_buffer; - glEnable(GL_DEPTH_TEST); + glViewport(colour_buffer->base_x, render_height - colour_buffer->height - colour_buffer->base_y, colour_buffer->width, colour_buffer->height); glUseProgram(shader_program_3d); + glEnable(GL_DEPTH_TEST); + glUniform1i(uniforms_3d.viewport_height, colour_buffer->height); int enabled_clip_planes = 0; for (int i = 0; i < v1db.enabled_clip_planes.max; i++) { @@ -344,34 +378,34 @@ void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer) { p.m[2][2] *= -1; glUniformMatrix4fv(uniforms_3d.projection, 1, GL_FALSE, &p.m[0][0]); - // DebugCamera_Update(); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id); } void GLRenderer_EndScene() { - // switch back to default fb + // switch back to default fb and reset glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDepthMask(GL_TRUE); - CHECK_GL_ERROR("GLRenderer_RenderFullScreenQuad"); + generated_current_framebuffer_for_this_frame = 0; + CHECK_GL_ERROR("GLRenderer_EndScene"); } void GLRenderer_FullScreenQuad(uint8_t* screen_buffer) { + glViewport(vp_x, vp_y, vp_width, vp_height); glBindFramebuffer(GL_FRAMEBUFFER, 0); glDisable(GL_DEPTH_TEST); - glUseProgram(shader_program_2d); - glBindTexture(GL_TEXTURE_2D, screen_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - + glBindTexture(GL_TEXTURE_2D, fullscreen_quad_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, render_width, render_height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, screen_buffer); + glBindVertexArray(screen_buffer_vao); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, screen_buffer_ebo); + glUseProgram(shader_program_2d); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); + CHECK_GL_ERROR("GLRenderer_RenderFullScreenQuad"); } @@ -383,6 +417,7 @@ void GLRenderer_ClearBuffers() { // clear real framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + CHECK_GL_ERROR("GLRenderer_ClearBuffers"); } @@ -494,6 +529,16 @@ void setActiveMaterial(tStored_material* material) { GLRenderer_SetShadeTable(material->shade_table); } + if (material->index_blend) { + glUniform1i(uniforms_3d.blend_enabled, 1); + GLRenderer_SetBlendTable(material->index_blend); + // materials with index_blend do not write to depth buffer (https://www.cwaboard.co.uk/viewtopic.php?p=105846&sid=58ad8910238000ca14b01dad85117175#p105846) + glDepthMask(GL_FALSE); + } else { + glUniform1i(uniforms_3d.blend_enabled, 0); + glDepthMask(GL_TRUE); + } + if ((material->flags & BR_MATF_LIGHT) && !(material->flags & BR_MATF_PRELIT) && material->shade_table) { // TODO: light value shouldn't always be 0? Works for shadows, not sure about other things. glUniform1i(uniforms_3d.light_value, 0); @@ -585,6 +630,7 @@ void GLRenderer_BufferMaterial(br_material* mat) { stored->flags = mat->flags; stored->shade_table = mat->index_shade; stored->index_base = mat->index_base; + stored->index_blend = mat->index_blend; } void GLRenderer_BufferTexture(br_pixelmap* pm) { @@ -614,7 +660,7 @@ void GLRenderer_BufferTexture(br_pixelmap* pm) { CHECK_GL_ERROR("GLRenderer_BufferTexture"); } -void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer) { +void GLRenderer_FlushBuffers() { if (!dirty_buffers) { return; @@ -626,7 +672,7 @@ void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffe // flip texture to match the expected orientation int dest_y = render_height; - uint8_t* pm_pixels = color_buffer->pixels; + uint8_t* pm_pixels = last_colour_buffer->pixels; uint8_t new_pixel; for (int y = 0; y < render_height; y++) { dest_y--; @@ -642,13 +688,13 @@ void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffe glBindTexture(GL_TEXTURE_2D, depth_texture); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depth_buffer_flip_pixels); - dest_y = color_buffer->height; - int src_y = render_height - color_buffer->base_y - color_buffer->height; - uint16_t* depth_pixels = depth_buffer->pixels; - for (int y = 0; y < color_buffer->height; y++) { + dest_y = last_depth_buffer->height; + int src_y = render_height - last_depth_buffer->base_y - last_depth_buffer->height; + uint16_t* depth_pixels = last_depth_buffer->pixels; + for (int y = 0; y < last_depth_buffer->height; y++) { dest_y--; - for (int x = 0; x < color_buffer->width; x++) { - depth_pixels[dest_y * render_width + x] = depth_buffer_flip_pixels[src_y * render_width + color_buffer->base_x + x]; + for (int x = 0; x < last_depth_buffer->width; x++) { + depth_pixels[dest_y * render_width + x] = depth_buffer_flip_pixels[src_y * render_width + last_depth_buffer->base_x + x]; } src_y++; } diff --git a/src/harness/renderers/gl/gl_renderer.h b/src/harness/renderers/gl/gl_renderer.h index d1c07446..f0369554 100644 --- a/src/harness/renderers/gl/gl_renderer.h +++ b/src/harness/renderers/gl/gl_renderer.h @@ -43,7 +43,7 @@ void GLRenderer_Init(int width, int height, int render_width, int render_height); void GLRenderer_SetPalette(uint8_t* rgba_colors); -void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer); +void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer); void GLRenderer_EndScene(); void GLRenderer_FullScreenQuad(uint8_t* screen_buffer); void GLRenderer_Model(br_actor* actor, br_model* model, br_matrix34 model_matrix); @@ -51,7 +51,7 @@ void GLRenderer_BufferTexture(br_pixelmap* pm); void GLRenderer_BufferMaterial(br_material* mat); void GLRenderer_BufferModel(br_model* model); void GLRenderer_ClearBuffers(); -void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer); +void GLRenderer_FlushBuffers(); void GLRenderer_GetRenderSize(int* width, int* height); void GLRenderer_GetWindowSize(int* width, int* height); void GLRenderer_SetWindowSize(int width, int height); diff --git a/src/harness/renderers/gl/stored_context.c b/src/harness/renderers/gl/stored_context.c index 3bdf2ce7..9115f680 100644 --- a/src/harness/renderers/gl/stored_context.c +++ b/src/harness/renderers/gl/stored_context.c @@ -41,6 +41,7 @@ tStored_material* NewStoredMaterial() { ctx->index_base = -1; ctx->pixelmap = NULL; ctx->shade_table = NULL; + ctx->index_blend = NULL; ctx->identifier[0] = '\0'; return ctx; } @@ -49,4 +50,4 @@ tStored_pixelmap* NewStoredPixelmap() { tStored_pixelmap* ctx = malloc(sizeof(tStored_pixelmap)); ctx->id = 0; return ctx; -} \ No newline at end of file +} diff --git a/src/harness/renderers/gl/stored_context.h b/src/harness/renderers/gl/stored_context.h index 22377b00..ffc6a50c 100644 --- a/src/harness/renderers/gl/stored_context.h +++ b/src/harness/renderers/gl/stored_context.h @@ -18,6 +18,7 @@ typedef struct tStored_material { br_uint_32 flags; br_pixelmap* shade_table; br_pixelmap* pixelmap; + br_pixelmap* index_blend; br_matrix23 map_transform; char identifier[200]; } tStored_material; diff --git a/src/harness/renderers/null.h b/src/harness/renderers/null.h index a87fb41b..82b4d068 100644 --- a/src/harness/renderers/null.h +++ b/src/harness/renderers/null.h @@ -1,7 +1,7 @@ #include "renderer.h" void Null_Init() {} -void Null_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer) {} +void Null_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) {} void Null_EndFrame() {} void Null_SetPalette(uint8_t* palette) {} void Null_RenderFullScreenQuad(uint8_t* src) {} @@ -11,7 +11,7 @@ void Null_ClearBuffers() {} void Null_BufferTexture(br_pixelmap* pm) {} void Null_BufferMaterial(br_material* mat) {} void Null_BufferModel(br_model* model) {} -void Null_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer) {} +void Null_FlushBuffers() {} void Null_GetRenderSize(int* width, int* height) { *width = 640; *height = 480; diff --git a/src/harness/renderers/renderer.h b/src/harness/renderers/renderer.h index a960cc70..6ed98098 100644 --- a/src/harness/renderers/renderer.h +++ b/src/harness/renderers/renderer.h @@ -5,7 +5,7 @@ typedef struct tRenderer { void (*Init)(int width, int height, int pRender_width, int pRender_height); - void (*BeginScene)(br_actor* camera, br_pixelmap* colour_buffer); + void (*BeginScene)(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer); void (*EndScene)(); void (*SetPalette)(uint8_t* palette); void (*FullScreenQuad)(uint8_t* src); @@ -14,7 +14,7 @@ typedef struct tRenderer { void (*BufferTexture)(br_pixelmap* pm); void (*BufferMaterial)(br_material* mat); void (*BufferModel)(br_model* model); - void (*FlushBuffers)(br_pixelmap* color_buffer, br_pixelmap* depth_buffer); + void (*FlushBuffers)(); void (*GetRenderSize)(int* width, int* height); void (*GetWindowSize)(int* width, int* height); void (*SetWindowSize)(int width, int height); diff --git a/src/harness/resources/3d_frag.glsl b/src/harness/resources/3d_frag.glsl index 3692ee5b..89c8d506 100644 --- a/src/harness/resources/3d_frag.glsl +++ b/src/harness/resources/3d_frag.glsl @@ -8,12 +8,16 @@ in vec2 v_tex_coord; out uint out_palette_index; uniform mat2x3 u_texture_coords_transform; -uniform usampler2D u_pixels; +uniform usampler2D u_texture_pixelmap; uniform usampler2D u_shade_table; +uniform usampler2D u_blend_table; +uniform usampler2D u_current_framebuffer; uniform int u_palette_index_override = -1; uniform int u_light_value = -1; uniform vec4 u_clip_planes[6]; uniform int u_clip_plane_count = 0; +uniform int u_blend_enabled = 0; +uniform int u_viewport_height; void main() { @@ -21,7 +25,7 @@ void main() { // calculate signed plane-vertex distance vec4 v4 = vec4(v_frag_pos.x, v_frag_pos.y, v_frag_pos.z, 1); float d = dot(u_clip_planes[i], v4); - if(d < 0.0) discard; + if (d < 0.0) discard; } if (u_palette_index_override >= 0) { @@ -30,14 +34,22 @@ void main() { } else { // calculate texture uv coordinates vec2 sample_coord = vec3(v_tex_coord.xy, 1) * u_texture_coords_transform; - uint texel = texture(u_pixels, sample_coord.xy).r; + uint texel = texture(u_texture_pixelmap, sample_coord.xy).r; if (u_light_value >= 0) { - // shadetable is a 256x256 image which encodes 256 shades for each color + // shade_table is a 256x256 image which encodes 256 lit shades for each color out_palette_index = texelFetch(u_shade_table, ivec2(texel, u_light_value), 0).r; } else { // no shadetable out_palette_index = texel; } + + if (u_blend_enabled == 1 && out_palette_index != 0u) { + // blend_table is a 256x256 image which encodes 256 values of blending between texture and existing screen pixel for each color + // current_framebuffer is upside down from opengl perspective. We need to sample it upside down. + uint fb_color = texelFetch(u_current_framebuffer, ivec2(gl_FragCoord.x, u_viewport_height - gl_FragCoord.y), 0).r; + uint blended_color = texelFetch(u_blend_table, ivec2(out_palette_index, fb_color), 0).r; + out_palette_index = blended_color; + } } // color 0 is always transparent if (out_palette_index == 0u) {