Implement transparency (blend tables) (#280)

* support for index_blend materials

* blended materials should not write to zbuffer

* remove reliance on glsl layout qualifiers

* tidy StripBlendedFaces
This commit is contained in:
Dethrace Engineering Department 2023-01-16 16:17:52 +13:00 committed by GitHub
parent 716b98c25a
commit acd403f183
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 139 additions and 81 deletions

View File

@ -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 <math.h>
#include <stdlib.h>
#include <string.h>
@ -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) {

View File

@ -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);

View File

@ -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");

View File

@ -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) {

View File

@ -12,11 +12,8 @@
#include <stdio.h>
#include <string.h>
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, &current_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++;
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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) {