merge shader into one, some fixes

This commit is contained in:
Matthew 2026-02-18 06:01:57 +11:00
parent 9bfe5bdd8b
commit 958e9c86ee
8 changed files with 251 additions and 24 deletions

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
build build
include/SDL3
assets/StylizedNature/OBJ assets/StylizedNature/OBJ
assets/StylizedNature/FBX assets/StylizedNature/FBX
assets/StylizedNature/FBX (Unity) assets/StylizedNature/FBX (Unity)

View File

@ -3,3 +3,4 @@
SDL SDL
external external
build build
assets

View File

@ -1,4 +1,4 @@
const u64 IMAGE_MAX = 1024; const u64 MODEL_MAX = 2048;
#include <bit> #include <bit>
@ -42,9 +42,11 @@ struct Mesh
struct Material struct Material
{ {
TextureID textures[MMI_Max]; TextureID textures[MMI_Max];
PipelineID pipeline_id; ShaderModelState shader_state;
BufferID buffer_id; PipelineID pipeline_id;
BufferID buffer_id;
BufferID shader_state_buffer_id;
}; };
struct Model struct Model
@ -55,6 +57,8 @@ struct Model
Array<Material> materials; Array<Material> materials;
}; };
Model g_models[MODEL_MAX];
Array<u8> Array<u8>
OpenFile(String8 file_path) OpenFile(String8 file_path)
{ {
@ -233,8 +237,8 @@ LoadImage(cgltf_image *asset_image, String8 texture_path)
} }
else else
{ {
u8 buffer[512]; u8 buffer[512];
String8 file_path = SPrintf(buffer, "%s%s", texture_path.ptr, uri_path.ptr); String8 file_path = SPrintf(buffer, "%s%s", texture_path.ptr, uri_path.ptr);
Array<u8> image_file = OpenFile(file_path); Array<u8> image_file = OpenFile(file_path);
image_buffer = LoadImage(image_file.ptr, (i32)image_file.length); image_buffer = LoadImage(image_file.ptr, (i32)image_file.length);
@ -303,7 +307,8 @@ LoadImageToTexture(cgltf_image *asset_image, String8 texture_path)
return texture_id; return texture_id;
} }
TextureID FindTexture(cgltf_texture *texture, cgltf_data *data, Model *model) TextureID
FindTexture(cgltf_texture *texture, cgltf_data *data, Model *model)
{ {
TextureID result = g_renderer.default_texture; TextureID result = g_renderer.default_texture;
@ -312,6 +317,7 @@ TextureID FindTexture(cgltf_texture *texture, cgltf_data *data, Model *model)
if(texture == data->textures+i) if(texture == data->textures+i)
{ {
result = model->textures[i]; result = model->textures[i];
break;
} }
} }
@ -444,7 +450,8 @@ LoadGLTF(Arena* arena, Model* model_result, String8 file_name)
for(u64 i = 0; i < data->materials_count; i += 1) for(u64 i = 0; i < data->materials_count; i += 1)
{ {
MaterialSet material_set; MaterialSet material_set = {};
ShaderModelState shader_state = {};
TextureID *textures = model.materials[i].textures; TextureID *textures = model.materials[i].textures;
cgltf_material *material = data->materials+i; cgltf_material *material = data->materials+i;
@ -455,6 +462,7 @@ LoadGLTF(Arena* arena, Model* model_result, String8 file_name)
if(pbr_mr->base_color_texture.texture) if(pbr_mr->base_color_texture.texture)
{ {
textures[MMI_Albedo] = FindTexture(pbr_mr->base_color_texture.texture, data, &model); textures[MMI_Albedo] = FindTexture(pbr_mr->base_color_texture.texture, data, &model);
shader_state.albedo_texture = true;
} }
memcpy(material_set.maps[MMI_Albedo].color.v, pbr_mr->base_color_factor, sizeof(f32)*4); memcpy(material_set.maps[MMI_Albedo].color.v, pbr_mr->base_color_factor, sizeof(f32)*4);
@ -468,16 +476,20 @@ LoadGLTF(Arena* arena, Model* model_result, String8 file_name)
material_set.maps[MMI_Metallic].value = pbr_mr->metallic_factor; material_set.maps[MMI_Metallic].value = pbr_mr->metallic_factor;
material_set.maps[MMI_Roughness].value = pbr_mr->roughness_factor; material_set.maps[MMI_Roughness].value = pbr_mr->roughness_factor;
shader_state.metallic_roughness_texture = true;
} }
if(material->normal_texture.texture) if(material->normal_texture.texture)
{ {
textures[MMI_Normal] = FindTexture(material->normal_texture.texture, data, &model); textures[MMI_Normal] = FindTexture(material->normal_texture.texture, data, &model);
shader_state.normal_texture = true;
} }
if(material->occlusion_texture.texture) if(material->occlusion_texture.texture)
{ {
textures[MMI_Occlusion] = FindTexture(material->occlusion_texture.texture, data, &model); textures[MMI_Occlusion] = FindTexture(material->occlusion_texture.texture, data, &model);
shader_state.occlusion_texture = true;
} }
if(material->emissive_texture.texture) if(material->emissive_texture.texture)
@ -486,10 +498,13 @@ LoadGLTF(Arena* arena, Model* model_result, String8 file_name)
memcpy(material_set.maps[MMI_Emission].color.v, material->emissive_factor, sizeof(f32)*3); memcpy(material_set.maps[MMI_Emission].color.v, material->emissive_factor, sizeof(f32)*3);
material_set.maps[MMI_Emission].color.a = 1.0; material_set.maps[MMI_Emission].color.a = 1.0;
shader_state.emission_texture = true;
} }
} }
model.materials[i].buffer_id = CreateBuffer(&material_set); model.materials[i].buffer_id = CreateBuffer(&material_set);
model.materials[i].shader_state = shader_state;
model.materials[i].shader_state_buffer_id = CreateBuffer(&shader_state);
} }
u64 mesh_index = 0, point_index = 0; u64 mesh_index = 0, point_index = 0;

BIN
assets/shaders/pbr.frag.spv Normal file

Binary file not shown.

BIN
assets/shaders/pbr.vert.spv Normal file

Binary file not shown.

View File

@ -40,6 +40,8 @@ typedef double f64;
typedef uintptr_t uintptr; typedef uintptr_t uintptr;
typedef intptr_t intptr; typedef intptr_t intptr;
typedef uint32_t b32;
#ifdef __linux__ #ifdef __linux__
typedef ssize_t isize; typedef ssize_t isize;
typedef size_t usize; typedef size_t usize;
@ -265,6 +267,35 @@ typedef GLuint PipelineID;
typedef GLuint ShaderID; typedef GLuint ShaderID;
typedef GLuint BufferID; typedef GLuint BufferID;
enum PipelineFeature
{
PF_Albedo = 1<<0,
PF_Normal = 1<<1,
PF_Metallic = 1<<2,
PF_Roughness = 1<<3,
PF_Occlusion = 1<<4,
PF_Emission = 1<<5,
PF_Height = 1<<6,
PF_Cubemap = 1<<7,
PF_Irradiance = 1<<8,
PF_Prefilter = 1<<9,
PF_BRDF = 1<<10,
};
const PipelineFeature PIPELINE_FEATURES[] = {
PF_Albedo,
PF_Normal,
PF_Metallic,
PF_Roughness,
PF_Occlusion,
PF_Emission,
PF_Height,
PF_Cubemap,
PF_Irradiance,
PF_Prefilter,
PF_BRDF,
};
struct ImageBuffer struct ImageBuffer
{ {
Array<u8> data; Array<u8> data;
@ -315,6 +346,25 @@ struct ShaderGlobals
Mat4 model_matrix; Mat4 model_matrix;
}; };
struct ShaderModelState
{
b32 albedo_texture;
b32 normal_texture;
b32 metallic_roughness_texture;
b32 occlusion_texture;
b32 emission_texture;
b32 height_texture;
b32 cubemap_texture;
b32 irradiance_texture;
b32 prefilter_texture;
b32 brdf_texture;
};
struct ShaderInstanceState
{
Mat4 model_matrix;
};
struct Renderer struct Renderer
{ {
SDL_Window* window; SDL_Window* window;
@ -355,14 +405,14 @@ CreateModelBuffers()
} }
ShaderID ShaderID
CreateShader(GLenum type, char *src) CreateShader(GLenum type, Array<const char *> src)
{ {
ShaderID shader_id = glCreateShader(type); ShaderID shader_id = glCreateShader(type);
if(shader_id) if(shader_id)
{ {
GLint success; GLint success;
glShaderSource(shader_id, 1, (const char **)&src, NULL); glShaderSource(shader_id, src.length, src.ptr, NULL);
glCompileShader(shader_id); glCompileShader(shader_id);
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &success); glGetShaderiv(shader_id, GL_COMPILE_STATUS, &success);
@ -386,13 +436,26 @@ CreateShader(GLenum type, char *src)
} }
PipelineID PipelineID
CreatePipeline(Array<u8> vertex_shader_src, Array<u8> frag_shader_src) CreatePipeline(Array<u8> shader_src)
{ {
PipelineID pipeline_id; PipelineID pipeline_id;
GLint success; GLint success;
ShaderID vertex_shader_id = CreateShader(GL_VERTEX_SHADER, (char *)vertex_shader_src.ptr); const char *vertex_src[] = { "#version 460\n", "#define VERTEX_SHADER 1\n", (const char *)shader_src.ptr };
ShaderID fragment_shader_id = CreateShader(GL_FRAGMENT_SHADER, (char *)frag_shader_src.ptr); const char *fragment_src[] = { "#version 460\n", (const char *)shader_src.ptr };
Array<const char *> vertex_src_array = {
.ptr = vertex_src,
.length = Length(vertex_src),
};
Array<const char *> fragment_src_array = {
.ptr = fragment_src,
.length = Length(fragment_src),
};
ShaderID vertex_shader_id = CreateShader(GL_VERTEX_SHADER, vertex_src_array);
ShaderID fragment_shader_id = CreateShader(GL_FRAGMENT_SHADER, fragment_src_array);
if(vertex_shader_id && fragment_shader_id) if(vertex_shader_id && fragment_shader_id)
{ {
pipeline_id = glCreateProgram(); pipeline_id = glCreateProgram();
@ -570,14 +633,12 @@ Init(Renderer *renderer)
SDL_SetWindowPosition(renderer->window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_SetWindowPosition(renderer->window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(renderer->window); SDL_ShowWindow(renderer->window);
Array<u8> vertex_src = OpenFile(String8Lit("./shaders/vert.glsl")); Array<u8> shader_src = OpenFile(String8Lit("./shaders/pbr.glsl"));
Array<u8> fragment_src = OpenFile(String8Lit("./shaders/frag.glsl")); if(shader_src)
if(vertex_src.ptr && fragment_src.ptr)
{ {
renderer->pipeline_id = CreatePipeline(vertex_src, fragment_src); renderer->pipeline_id = CreatePipeline(shader_src);
Free(&vertex_src); Free(&shader_src);
Free(&fragment_src);
} }
InitCheckError(!renderer->pipeline_id, "Unable to create pipeline"); InitCheckError(!renderer->pipeline_id, "Unable to create pipeline");
@ -599,9 +660,12 @@ Init(Renderer *renderer)
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
renderer->globals.projection = IdentityMatrix(); renderer->globals.projection = IdentityMatrix();
renderer->globals.view = LookAt(Vec3(0.0f), Vec3(0.0f, 5.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f)); renderer->globals.view = LookAt(Vec3(0.0f, 5.0f, 0.0f), Vec3(0.0f, 30.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
renderer->globals.model_matrix = Translate(IdentityMatrix(), Vec3(0.0f, 0.0f, -3.0f)); renderer->globals.model_matrix = Translate(IdentityMatrix(), Vec3(0.0f, 0.0f, 20.0f));
renderer->globals_buffer_id = CreateBuffer(&renderer->globals); renderer->globals_buffer_id = CreateBuffer(&renderer->globals);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_renderer.globals_buffer_id); glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_renderer.globals_buffer_id);
@ -631,6 +695,9 @@ main(int argc, char** argv)
} }
} }
Mat4 model_matrix = IdentityMatrix();
BufferID model_matrix_buffer_id = CreateBuffer(&model_matrix);
while(running) while(running)
{ {
BeginScratch(); BeginScratch();
@ -684,6 +751,10 @@ main(int argc, char** argv)
glUniform1i(g_renderer.texture_locations[j], j); glUniform1i(g_renderer.texture_locations[j], j);
glBindTexture(GL_TEXTURE_2D, material->textures[j]); glBindTexture(GL_TEXTURE_2D, material->textures[j]);
} }
glBindBufferBase(GL_UNIFORM_BUFFER, 1, material->shader_state_buffer_id);
glBindBufferBase(GL_UNIFORM_BUFFER, 2, model_matrix_buffer_id);
glBindBufferBase(GL_UNIFORM_BUFFER, 3, material->buffer_id);
glDrawElements(GL_TRIANGLES, tree_model.meshes[i].index_length, GL_UNSIGNED_INT, (void *)(u64)(tree_model.meshes[i].index_start*sizeof(u32))); glDrawElements(GL_TRIANGLES, tree_model.meshes[i].index_length, GL_UNSIGNED_INT, (void *)(u64)(tree_model.meshes[i].index_start*sizeof(u32)));

View File

@ -1,6 +1,6 @@
#version 460 #version 460
precision highp float; precision mediump float;
#define AlbedoTexture u_texture0 #define AlbedoTexture u_texture0
#define NormalTexture u_texture1 #define NormalTexture u_texture1

141
shaders/pbr.glsl Normal file
View File

@ -0,0 +1,141 @@
precision mediump float;
#define f32 float
#define f64 double
#define u32 uint
#define i32 int
#define b32 bool
#ifdef VERTEX_SHADER
# define varying_param out
layout(location = 0) in vec4 a_color;
layout(location = 1) in vec4 a_tangent;
layout(location = 2) in vec3 a_pos;
layout(location = 3) in vec3 a_normal;
layout(location = 4) in vec2 a_uv0;
layout(location = 5) in vec2 a_uv1;
#else
# define varying_param in
layout(location = 0) out vec4 FragColor;
#define AlbedoTexture u_texture0
#define NormalTexture u_texture1
#define MetallicTexture u_texture2
#define RoughnessTexture u_texture3
#define OcclusionTexture u_texture4
#define EmissionTexture u_texture5
#define HeightTexture u_texture6
#define CubemapTexture u_texture7
#define IrradianceTexture u_texture8
#define PrefilterTexture u_texture9
#define BRDFTexture u_texture10
uniform sampler2D u_texture0;
uniform sampler2D u_texture1;
uniform sampler2D u_texture2;
uniform sampler2D u_texture3;
uniform sampler2D u_texture4;
uniform sampler2D u_texture5;
uniform sampler2D u_texture6;
uniform sampler2D u_texture7;
uniform sampler2D u_texture8;
uniform sampler2D u_texture9;
uniform sampler2D u_texture10;
#endif
#define MMI_Albedo 0
#define MMI_Normal 1
#define MMI_Metallic 2
#define MMI_Roughness 3
#define MMI_Occlusion 4
#define MMI_Emission 5
#define MMI_Height 6
#define MMI_Cubemap 7
#define MMI_Irradiance 8
#define MMI_Prefilter 9
#define MMI_BRDF 10
#define MMI_MAX 11
#define AlbedoMaterial material_maps[MMI_Albedo]
#define NormalMaterial material_maps[MMI_Normal]
#define MetallicMaterial material_maps[MMI_Metallic]
#define RoughnessMaterial material_maps[MMI_Roughness]
#define OcclusionMaterial material_maps[MMI_Occlusion]
#define EmissionMaterial material_maps[MMI_Emission]
#define HeightMaterial material_maps[MMI_Height]
#define CubemapMaterial material_maps[MMI_Cubemap]
#define IrradianceMaterial material_maps[MMI_Irradiance]
#define PrefilterMaterial material_maps[MMI_Prefilter]
#define BRDFMaterial material_maps[MMI_BRDF]
#define VertexMain main
#define FragmentMain main
struct MaterialMap
{
vec4 color;
f32 value;
};
layout(location = 0) varying_param vec2 v_uv0;
layout(location = 1) varying_param vec2 v_uv1;
layout(std140, binding = 0) uniform Globals
{
mat4 projection;
mat4 view;
};
layout(std140, binding = 1) uniform ModelState
{
bool albedo_texture;
bool normal_texture;
bool metallic_roughness_texture;
bool occlusion_texture;
bool emission_texture;
bool height_texture;
bool cubemap_texture;
bool irradiance_texture;
bool prefilter_texture;
bool brdf_texture;
};
layout(std140, binding = 2) uniform InstanceState
{
mat4 model_matrix;
};
layout(std140, binding = 3) uniform Materials
{
MaterialMap material_maps[MMI_MAX];
};
#ifdef VERTEX_SHADER
void
VertexMain()
{
gl_Position = projection * model_matrix * vec4(a_pos, 1.0);
v_uv0 = a_uv0;
}
#else
void
FragmentMain()
{
if(albedo_texture)
{
FragColor = texture(AlbedoTexture, v_uv0);
}
else
{
FragColor = AlbedoMaterial.color;
}
}
#endif