Embed GLSL files during build (#238)

* Embed GLSL files during build
This commit is contained in:
Dethrace Engineering Department 2022-11-11 13:18:07 +13:00 committed by GitHub
parent 73d924891e
commit 4246f66384
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 215 additions and 178 deletions

38
cmake/EmbedResource.cmake Normal file
View File

@ -0,0 +1,38 @@
# EmbedResource.cmake
####################################################################################################
# original function by amir-saniyan https://gist.github.com/amir-saniyan/de99cee82fa9d8d615bb69f3f53b6004
function(embed_resource resource_file_name source_file_name variable_name)
if(EXISTS "${source_file_name}")
if("${source_file_name}" IS_NEWER_THAN "${resource_file_name}")
return()
endif()
endif()
file(READ "${resource_file_name}" hex_content HEX)
string(REPEAT "[0-9a-f]" 32 pattern)
string(REGEX REPLACE "(${pattern})" "\\1\n" content "${hex_content}")
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " content "${content}")
string(REGEX REPLACE ", $" "" content "${content}")
set(array_definition "static const char ${variable_name}[] =\n{\n${content}\n};")
set(source "// Auto generated file.\n${array_definition}\n")
file(WRITE "${source_file_name}" "${source}")
endfunction()
####################################################################################################
if(NOT DEFINED SOURCE_DIR)
message(FATAL_ERROR "SOURCE_DIR is not set")
endif(NOT DEFINED SOURCE_DIR)
if(NOT DEFINED FILE)
message(FATAL_ERROR "FILE is not set")
endif(NOT DEFINED FILE)
string(REPLACE "." "_" generated_name "${FILE}")
string(REPLACE "/" "_" generated_name "${generated_name}")
string(TOUPPER "${generated_name}" generated_name)
embed_resource("${SOURCE_DIR}/${FILE}" "${FILE}.h" "${generated_name}")

View File

@ -6,7 +6,7 @@ if (NOT DEFINED IO_PLATFORM)
set(IO_PLATFORM "SDL_OpenGL") set(IO_PLATFORM "SDL_OpenGL")
endif() endif()
target_include_directories(harness target_include_directories(harness
PRIVATE PRIVATE
. .
${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}
@ -61,14 +61,26 @@ target_sources(harness PRIVATE
) )
if (IO_PLATFORM STREQUAL "SDL_OpenGL") if (IO_PLATFORM STREQUAL "SDL_OpenGL")
# generate embedded glsl resources
foreach(elem resources/framebuffer_vert.glsl resources/framebuffer_frag.glsl resources/3d_vert.glsl resources/3d_frag.glsl)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${elem}.h"
COMMAND "${CMAKE_COMMAND}" "-DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}" "-DFILE=${elem}" -P "${dethrace_SOURCE_DIR}/cmake/EmbedResource.cmake"
DEPENDS "${elem}"
)
endforeach()
target_sources(harness PRIVATE target_sources(harness PRIVATE
io_platforms/sdl_gl.c io_platforms/sdl_gl.c
renderers/gl/gl_renderer.c renderers/gl/gl_renderer.c
renderers/gl/gl_renderer.h renderers/gl/gl_renderer.h
renderers/gl/shaders.c
renderers/gl/shaders.h
renderers/gl/stored_context.c renderers/gl/stored_context.c
renderers/gl/stored_context.h renderers/gl/stored_context.h
resources/framebuffer_vert.glsl.h
resources/framebuffer_frag.glsl.h
resources/3d_vert.glsl.h
resources/3d_frag.glsl.h
) )
target_link_libraries(harness PRIVATE SDL2::SDL2 glad) target_link_libraries(harness PRIVATE SDL2::SDL2 glad)
endif() endif()
@ -78,9 +90,9 @@ if(WIN32)
os/windows.c os/windows.c
) )
elseif(APPLE) elseif(APPLE)
target_sources(harness PRIVATE target_sources(harness PRIVATE
os/macos.c os/macos.c
) )
else() else()
target_sources(harness PRIVATE target_sources(harness PRIVATE
os/linux.c os/linux.c

View File

@ -90,19 +90,19 @@ void Harness_DetectGameMode() {
harness_game_info.defines.INTRO_SMK_FILE = "SPLINTRO.SMK"; harness_game_info.defines.INTRO_SMK_FILE = "SPLINTRO.SMK";
harness_game_info.defines.GERMAN_LOADSCRN = "LOADSCRN.PIX"; harness_game_info.defines.GERMAN_LOADSCRN = "LOADSCRN.PIX";
harness_game_info.mode = eGame_splatpack; harness_game_info.mode = eGame_splatpack;
LOG_INFO("\"%s\"", "Splat Pack"); printf("Game mode: Splat Pack\n");
} else if (access("DATA/RACES/TINSEL.TXT", F_OK) != -1) { } else if (access("DATA/RACES/TINSEL.TXT", F_OK) != -1) {
// Only the the splat x-mas demo has the tinsel track // Only the the splat x-mas demo has the tinsel track
harness_game_info.defines.INTRO_SMK_FILE = ""; harness_game_info.defines.INTRO_SMK_FILE = "";
harness_game_info.defines.GERMAN_LOADSCRN = ""; harness_game_info.defines.GERMAN_LOADSCRN = "";
harness_game_info.mode = eGame_splatpack_demo; harness_game_info.mode = eGame_splatpack_demo;
LOG_INFO("\"%s\"", "Splat Pack X-mas demo"); printf("Game mode: Splat Pack X-mas demo\n");
} else { } else {
// Assume we're using the splatpack demo // Assume we're using the splatpack demo
harness_game_info.defines.INTRO_SMK_FILE = ""; harness_game_info.defines.INTRO_SMK_FILE = "";
harness_game_info.defines.GERMAN_LOADSCRN = ""; harness_game_info.defines.GERMAN_LOADSCRN = "";
harness_game_info.mode = eGame_splatpack_demo; harness_game_info.mode = eGame_splatpack_demo;
LOG_INFO("\"%s\"", "Splat Pack demo"); printf("Game mode: Splat Pack demo\n");
} }
} else if (access("DATA/RACES/CITYB3.TXT", F_OK) != -1) { } else if (access("DATA/RACES/CITYB3.TXT", F_OK) != -1) {
// All non-splatpack edition have the cityb3 track // All non-splatpack edition have the cityb3 track
@ -111,7 +111,7 @@ void Harness_DetectGameMode() {
harness_game_info.defines.INTRO_SMK_FILE = ""; harness_game_info.defines.INTRO_SMK_FILE = "";
harness_game_info.defines.GERMAN_LOADSCRN = "COWLESS.PIX"; harness_game_info.defines.GERMAN_LOADSCRN = "COWLESS.PIX";
harness_game_info.mode = eGame_carmageddon_demo; harness_game_info.mode = eGame_carmageddon_demo;
LOG_INFO("\"%s\"", "Carmageddon demo"); printf("Game mode: Carmageddon demo\n");
} else { } else {
goto carmageddon; goto carmageddon;
} }
@ -124,7 +124,7 @@ void Harness_DetectGameMode() {
} }
harness_game_info.defines.GERMAN_LOADSCRN = "LOADSCRN.PIX"; harness_game_info.defines.GERMAN_LOADSCRN = "LOADSCRN.PIX";
harness_game_info.mode = eGame_carmageddon; harness_game_info.mode = eGame_carmageddon;
LOG_INFO("\"%s\"", "Carmageddon"); printf("Game mode: Carmageddon\n");
} }
harness_game_info.localization = eGameLocalization_none; harness_game_info.localization = eGameLocalization_none;
@ -176,7 +176,7 @@ void Harness_DetectGameMode() {
void Harness_Init(int* argc, char* argv[]) { void Harness_Init(int* argc, char* argv[]) {
int result; int result;
LOG_INFO("version: " DETHRACE_VERSION); printf("Dethrace version: %s\n", DETHRACE_VERSION);
// disable the original CD check code // disable the original CD check code
harness_game_config.enable_cd_check = 0; harness_game_config.enable_cd_check = 0;
@ -206,7 +206,7 @@ void Harness_Init(int* argc, char* argv[]) {
if (root_dir == NULL) { if (root_dir == NULL) {
LOG_INFO("DETHRACE_ROOT_DIR is not set, assuming '.'"); LOG_INFO("DETHRACE_ROOT_DIR is not set, assuming '.'");
} else { } else {
printf("DETHRACE_ROOT_DIR: %s\n", root_dir); printf("Data directory: %s\n", root_dir);
result = chdir(root_dir); result = chdir(root_dir);
if (result != 0) { if (result != 0) {
LOG_PANIC("Failed to chdir. Error is %s", strerror(errno)); LOG_PANIC("Failed to chdir. Error is %s", strerror(errno));

View File

@ -2,7 +2,10 @@
#include "brender/brender.h" #include "brender/brender.h"
#include "harness.h" #include "harness.h"
#include "harness/trace.h" #include "harness/trace.h"
#include "shaders.h" #include "resources/3d_frag.glsl.h"
#include "resources/3d_vert.glsl.h"
#include "resources/framebuffer_frag.glsl.h"
#include "resources/framebuffer_vert.glsl.h"
#include "stored_context.h" #include "stored_context.h"
#include <glad/glad.h> #include <glad/glad.h>
@ -29,7 +32,7 @@ static br_pixelmap* last_shade_table = NULL;
static int dirty_buffers = 0; static int dirty_buffers = 0;
struct { struct {
GLuint pixels, pixels_transform; GLuint pixels, uv_transform;
GLuint shade_table; GLuint shade_table;
GLuint model, view, projection; GLuint model, view, projection;
GLuint palette_index_override; GLuint palette_index_override;
@ -46,92 +49,84 @@ struct {
GLuint pixels, palette; GLuint pixels, palette;
} uniforms_2dpp; } uniforms_2dpp;
GLuint CreateShaderFromFile(const char* filename, const char* fallback, GLenum type) { GLuint CreateShaderProgram(char* name, const char* vertex_shader, const int vertex_shader_len, const char* fragment_shader, const int fragment_shader_len) {
int success; int success;
char log_buffer[1024];
GLuint res = glCreateShader(type); GLuint program;
FILE* f = fopen(filename, "r");
if (f) {
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char* file_bytes = malloc(fsize + 1);
fsize = fread(file_bytes, fsize, 1, f);
fclose(f);
file_bytes[fsize] = 0;
const GLchar* sources[] = { file_bytes };
glShaderSource(res, 1, sources, NULL);
} else {
const GLchar* sources[] = { fallback };
glShaderSource(res, 1, sources, NULL);
}
glCompileShader(res);
glGetShaderiv(res, GL_COMPILE_STATUS, &success);
if (!success) {
char log_buffer[1024];
glGetShaderInfoLog(res, 1024, NULL, log_buffer);
LOG_PANIC("shader %s failed to compile: %s", filename, log_buffer);
}
return res;
}
GLuint CreateShaderProgram(const char* vertex_file, const char* fragment_file, const char* vertex_fallback, const char* fragment_fallback) {
GLuint program = glCreateProgram();
GLuint v_shader, f_shader; GLuint v_shader, f_shader;
v_shader = CreateShaderFromFile(vertex_file, vertex_fallback, GL_VERTEX_SHADER); program = glCreateProgram();
if (!v_shader) v_shader = glCreateShader(GL_VERTEX_SHADER);
return 0; const GLchar* vertex_sources[] = { vertex_shader };
glShaderSource(v_shader, 1, vertex_sources, &vertex_shader_len);
glCompileShader(v_shader);
glGetShaderiv(v_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(v_shader, 1024, NULL, log_buffer);
LOG_PANIC("shader %s failed to compile: %s", name, log_buffer);
}
f_shader = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* fragment_sources[] = { fragment_shader };
glShaderSource(f_shader, 1, fragment_sources, &fragment_shader_len);
glCompileShader(f_shader);
glGetShaderiv(f_shader, GL_COMPILE_STATUS, &success);
if (!success) {
char log_buffer[1024];
glGetShaderInfoLog(f_shader, 1024, NULL, log_buffer);
LOG_PANIC("shader %s failed to compile: %s", name, log_buffer);
}
glAttachShader(program, v_shader); glAttachShader(program, v_shader);
f_shader = CreateShaderFromFile(fragment_file, fragment_fallback, GL_FRAGMENT_SHADER);
if (!f_shader)
return 0;
glAttachShader(program, f_shader); glAttachShader(program, f_shader);
glLinkProgram(program); glLinkProgram(program);
glDeleteShader(v_shader); glDeleteShader(v_shader);
glDeleteShader(f_shader); glDeleteShader(f_shader);
GLint link_ok = GL_FALSE; GLint link_ok = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &link_ok); glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
if (!link_ok) { if (!link_ok) {
char log_buffer[1024];
glGetShaderInfoLog(program, 1024, NULL, log_buffer); glGetShaderInfoLog(program, 1024, NULL, log_buffer);
LOG_PANIC("shader program %s:%s failed to link: %s", vertex_file, fragment_file, log_buffer); LOG_PANIC("shader program %s failed to link: %s", name, log_buffer);
} }
return program; return program;
} }
GLint GetValidatedUniformLocation(GLuint program, char* uniform_name) {
GLint location;
location = glGetUniformLocation(program, uniform_name);
if (location == -1) {
LOG_PANIC("glGetUniformLocation(%d, %s) failed. Check the shader uniform names.", program, uniform_name);
}
return location;
}
void LoadShaders() { void LoadShaders() {
shader_program_2d = CreateShaderProgram("vertex_shader_2d.glsl", "fragment_shader_2d.glsl", vs_2d, fs_2d); shader_program_2d = CreateShaderProgram("framebuffer", RESOURCES_FRAMEBUFFER_VERT_GLSL, sizeof(RESOURCES_FRAMEBUFFER_VERT_GLSL), RESOURCES_FRAMEBUFFER_FRAG_GLSL, sizeof(RESOURCES_FRAMEBUFFER_FRAG_GLSL));
glUseProgram(shader_program_2d); glUseProgram(shader_program_2d);
uniforms_2d.pixels = glGetUniformLocation(shader_program_2d, "pixels"); uniforms_2d.pixels = GetValidatedUniformLocation(shader_program_2d, "u_pixels");
uniforms_2d.palette = glGetUniformLocation(shader_program_2d, "palette"); uniforms_2d.palette = GetValidatedUniformLocation(shader_program_2d, "u_palette");
// bind the uniform samplers to texture units: // bind the uniform samplers to texture units:
glUniform1i(uniforms_2d.pixels, 0); glUniform1i(uniforms_2d.pixels, 0);
glUniform1i(uniforms_2d.palette, 1); glUniform1i(uniforms_2d.palette, 1);
shader_program_3d = CreateShaderProgram("vertex_shader_3d.glsl", "fragment_shader_3d.glsl", vs_3d, fs_3d); shader_program_3d = CreateShaderProgram("3d", RESOURCES_3D_VERT_GLSL, sizeof(RESOURCES_3D_VERT_GLSL), RESOURCES_3D_FRAG_GLSL, sizeof(RESOURCES_3D_FRAG_GLSL));
glUseProgram(shader_program_3d); glUseProgram(shader_program_3d);
uniforms_3d.clip_plane_count = glGetUniformLocation(shader_program_3d, "clip_plane_count"); uniforms_3d.clip_plane_count = GetValidatedUniformLocation(shader_program_3d, "u_clip_plane_count");
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
char name[32]; char name[32];
sprintf(name, "clip_planes[%d]", i); sprintf(name, "u_clip_planes[%d]", i);
uniforms_3d.clip_planes[i] = glGetUniformLocation(shader_program_3d, name); uniforms_3d.clip_planes[i] = GetValidatedUniformLocation(shader_program_3d, name);
} }
uniforms_3d.model = glGetUniformLocation(shader_program_3d, "model"); uniforms_3d.model = GetValidatedUniformLocation(shader_program_3d, "u_model");
uniforms_3d.pixels = glGetUniformLocation(shader_program_3d, "pixels"); uniforms_3d.pixels = GetValidatedUniformLocation(shader_program_3d, "u_pixels");
uniforms_3d.pixels_transform = glGetUniformLocation(shader_program_3d, "pixels_transform"); uniforms_3d.uv_transform = GetValidatedUniformLocation(shader_program_3d, "u_texture_coords_transform");
uniforms_3d.shade_table = glGetUniformLocation(shader_program_3d, "shade_table"); uniforms_3d.shade_table = GetValidatedUniformLocation(shader_program_3d, "u_shade_table");
uniforms_3d.projection = glGetUniformLocation(shader_program_3d, "projection"); uniforms_3d.projection = GetValidatedUniformLocation(shader_program_3d, "u_projection");
uniforms_3d.palette_index_override = glGetUniformLocation(shader_program_3d, "palette_index_override"); uniforms_3d.palette_index_override = GetValidatedUniformLocation(shader_program_3d, "u_palette_index_override");
uniforms_3d.view = glGetUniformLocation(shader_program_3d, "view"); uniforms_3d.view = GetValidatedUniformLocation(shader_program_3d, "u_view");
uniforms_3d.light_value = glGetUniformLocation(shader_program_3d, "light_value"); uniforms_3d.light_value = GetValidatedUniformLocation(shader_program_3d, "u_light_value");
// bind the uniform samplers to texture units. palette=1, shadetable=2 // bind the uniform samplers to texture units. palette=1, shadetable=2
glUniform1i(uniforms_3d.pixels, 0); glUniform1i(uniforms_3d.pixels, 0);
@ -492,7 +487,7 @@ void setActiveMaterial(tStored_material* material) {
return; return;
} }
glUniform3fv(uniforms_3d.pixels_transform, 2, material->map_transform->v); glUniformMatrix2x3fv(uniforms_3d.uv_transform, 1, GL_TRUE, &material->map_transform.m[0][0]);
glUniform1i(uniforms_3d.palette_index_override, material->index_base); glUniform1i(uniforms_3d.palette_index_override, material->index_base);
if (material->shade_table) { if (material->shade_table) {
GLRenderer_SetShadeTable(material->shade_table); GLRenderer_SetShadeTable(material->shade_table);
@ -578,12 +573,7 @@ void GLRenderer_BufferMaterial(br_material* mat) {
strcpy(stored->identifier, mat->identifier); strcpy(stored->identifier, mat->identifier);
} }
} }
stored->map_transform[0].v[0] = mat->map_transform.m[0][0]; BrMatrix23Copy(&stored->map_transform, &mat->map_transform);
stored->map_transform[0].v[1] = mat->map_transform.m[0][1];
stored->map_transform[0].v[2] = mat->map_transform.m[2][0];
stored->map_transform[1].v[0] = mat->map_transform.m[1][0];
stored->map_transform[1].v[1] = mat->map_transform.m[1][1];
stored->map_transform[1].v[2] = mat->map_transform.m[2][1];
stored->pixelmap = mat->colour_map; stored->pixelmap = mat->colour_map;
stored->flags = mat->flags; stored->flags = mat->flags;
stored->shade_table = mat->index_shade; stored->shade_table = mat->index_shade;

View File

@ -1,87 +0,0 @@
const char* vs_2d = "#version 140\n"
"#extension GL_ARB_explicit_attrib_location : require\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"layout (location = 2) in vec2 aTexCoord;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
" TexCoord = aTexCoord;\n"
"}\0";
const char* fs_2d = "#version 140\n"
"#extension GL_ARB_explicit_attrib_location : require\n"
"in vec2 TexCoord;\n"
"uniform usampler2D pixels;\n"
"uniform sampler2D palette;\n"
"layout (location = 0) out vec4 FragColor;\n"
"void main()\n"
"{\n"
" uint palette_index = texture(pixels, TexCoord.xy).x;\n"
" vec4 texel = texelFetch(palette, ivec2(palette_index, 0), 0);\n"
" FragColor = texel;\n"
"}\n\0";
const char* vs_3d = "#version 140\n"
"#extension GL_ARB_explicit_attrib_location : require\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aNormal;\n"
"layout (location = 2) in vec2 aUV;\n"
"\n"
"out vec3 FragPos;\n"
"out vec3 Normal;\n"
"out vec2 TexCoord;\n"
"\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
" FragPos = vec3(model * vec4(aPos, 1.0));\n"
" Normal = aNormal;\n"
" TexCoord = aUV;\n"
" gl_Position = projection * view * vec4(FragPos, 1.0);\n"
"}\0";
const char* fs_3d = "#version 140\n"
"#extension GL_ARB_explicit_attrib_location : require\n"
"in vec3 Normal;\n"
"in vec3 FragPos;\n"
"in vec2 TexCoord;\n"
"\n"
"out uint palette_index;\n"
"\n"
"uniform vec3 pixels_transform[2];\n"
"uniform usampler2D pixels;\n"
"uniform usampler2D shade_table;\n"
"uniform int palette_index_override = -1;\n"
"uniform int light_value = -1;\n"
"uniform vec4 clip_planes[6];\n"
"uniform int clip_plane_count = 0;\n"
"void main()\n"
"{\n"
" for(int i=0; i<clip_plane_count; i++) {\n"
" // calculate signed plane-vertex distance\n"
" vec4 v4 = vec4(FragPos.x, FragPos.y, FragPos.z, 1);\n"
" float d = dot(clip_planes[i], v4);\n"
" if(d < 0.0) discard;\n"
" }\n"
" if (palette_index_override == -1) {"
" vec3 sample_coord = mat3(pixels_transform[0], pixels_transform[1], vec3(0, 0, 1)) * vec3(TexCoord.xy, 1);\n"
" uint texel = texture(pixels, sample_coord.xy).x;\n"
" if (light_value == -1) {\n"
" palette_index = texel;\n"
" } else {\n"
" palette_index = texelFetch(shade_table, ivec2(texel, light_value), 0).x;\n"
" }\n"
" if (palette_index == 0u) {\n"
" discard;\n"
" }\n"
" }\n"
" else {\n"
" palette_index = uint(palette_index_override);\n"
" }\n"
"}\n\0";

View File

@ -1,10 +0,0 @@
#ifndef HARNESS_GL_RENDERER_SHADERS
#define HARNESS_GL_RENDERER_SHADERS
extern const char* vs_2d;
extern const char* fs_2d;
extern const char* fs_3d;
extern const char* vs_3d;
#endif

View File

@ -18,7 +18,7 @@ typedef struct tStored_material {
br_uint_32 flags; br_uint_32 flags;
br_pixelmap* shade_table; br_pixelmap* shade_table;
br_pixelmap* pixelmap; br_pixelmap* pixelmap;
br_vector3 map_transform[2]; br_matrix23 map_transform;
char identifier[200]; char identifier[200];
} tStored_material; } tStored_material;

View File

@ -0,0 +1,46 @@
#version 140
#extension GL_ARB_explicit_attrib_location : require
in vec3 v_frag_pos;
in vec3 v_normal;
in vec2 v_tex_coord;
out uint out_palette_index;
uniform mat2x3 u_texture_coords_transform;
uniform usampler2D u_pixels;
uniform usampler2D u_shade_table;
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;
void main() {
for(int i = 0; i < u_clip_plane_count; i++) {
// 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 (u_palette_index_override >= 0) {
// force palette index, no texture lookup
out_palette_index = uint(u_palette_index_override);
} 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;
if (u_light_value >= 0) {
// shadetable is a 256x256 image which encodes 256 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;
}
}
// color 0 is always transparent
if (out_palette_index == 0u) {
discard;
}
}

View File

@ -0,0 +1,20 @@
#version 140
#extension GL_ARB_explicit_attrib_location : require
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec3 a_normal;
layout (location = 2) in vec2 a_uv;
out vec3 v_frag_pos;
out vec3 v_normal;
out vec2 v_tex_coord;
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
void main() {
v_frag_pos = vec3(u_model * vec4(a_pos, 1.0));
v_normal = a_normal;
v_tex_coord = a_uv;
gl_Position = u_projection * u_view * vec4(v_frag_pos, 1.0);
}

View File

@ -0,0 +1,15 @@
#version 140
#extension GL_ARB_explicit_attrib_location : require
in vec2 v_tex_coord;
uniform usampler2D u_pixels;
uniform sampler2D u_palette;
layout (location = 0) out vec4 out_frag_color;
void main() {
uint palette_index = texture(u_pixels, v_tex_coord.xy).r;
vec4 texel = texelFetch(u_palette, ivec2(palette_index, 0), 0);
out_frag_color = texel;
}

View File

@ -0,0 +1,13 @@
#version 140
#extension GL_ARB_explicit_attrib_location:require
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec3 a_color;
layout (location = 2) in vec2 a_uv;
out vec2 v_tex_coord;
void main() {
gl_Position = vec4(a_pos, 1.0);
v_tex_coord = a_uv;
}