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
include/SDL3
assets/StylizedNature/OBJ
assets/StylizedNature/FBX
assets/StylizedNature/FBX (Unity)

View File

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

View File

@ -1,4 +1,4 @@
const u64 IMAGE_MAX = 1024;
const u64 MODEL_MAX = 2048;
#include <bit>
@ -43,8 +43,10 @@ struct Mesh
struct Material
{
TextureID textures[MMI_Max];
ShaderModelState shader_state;
PipelineID pipeline_id;
BufferID buffer_id;
BufferID shader_state_buffer_id;
};
struct Model
@ -55,6 +57,8 @@ struct Model
Array<Material> materials;
};
Model g_models[MODEL_MAX];
Array<u8>
OpenFile(String8 file_path)
{
@ -303,7 +307,8 @@ LoadImageToTexture(cgltf_image *asset_image, String8 texture_path)
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;
@ -312,6 +317,7 @@ TextureID FindTexture(cgltf_texture *texture, cgltf_data *data, Model *model)
if(texture == data->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)
{
MaterialSet material_set;
MaterialSet material_set = {};
ShaderModelState shader_state = {};
TextureID *textures = model.materials[i].textures;
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)
{
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);
@ -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_Roughness].value = pbr_mr->roughness_factor;
shader_state.metallic_roughness_texture = true;
}
if(material->normal_texture.texture)
{
textures[MMI_Normal] = FindTexture(material->normal_texture.texture, data, &model);
shader_state.normal_texture = true;
}
if(material->occlusion_texture.texture)
{
textures[MMI_Occlusion] = FindTexture(material->occlusion_texture.texture, data, &model);
shader_state.occlusion_texture = true;
}
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);
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].shader_state = shader_state;
model.materials[i].shader_state_buffer_id = CreateBuffer(&shader_state);
}
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 intptr_t intptr;
typedef uint32_t b32;
#ifdef __linux__
typedef ssize_t isize;
typedef size_t usize;
@ -265,6 +267,35 @@ typedef GLuint PipelineID;
typedef GLuint ShaderID;
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
{
Array<u8> data;
@ -315,6 +346,25 @@ struct ShaderGlobals
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
{
SDL_Window* window;
@ -355,14 +405,14 @@ CreateModelBuffers()
}
ShaderID
CreateShader(GLenum type, char *src)
CreateShader(GLenum type, Array<const char *> src)
{
ShaderID shader_id = glCreateShader(type);
if(shader_id)
{
GLint success;
glShaderSource(shader_id, 1, (const char **)&src, NULL);
glShaderSource(shader_id, src.length, src.ptr, NULL);
glCompileShader(shader_id);
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &success);
@ -386,13 +436,26 @@ CreateShader(GLenum type, char *src)
}
PipelineID
CreatePipeline(Array<u8> vertex_shader_src, Array<u8> frag_shader_src)
CreatePipeline(Array<u8> shader_src)
{
PipelineID pipeline_id;
GLint success;
ShaderID vertex_shader_id = CreateShader(GL_VERTEX_SHADER, (char *)vertex_shader_src.ptr);
ShaderID fragment_shader_id = CreateShader(GL_FRAGMENT_SHADER, (char *)frag_shader_src.ptr);
const char *vertex_src[] = { "#version 460\n", "#define VERTEX_SHADER 1\n", (const char *)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)
{
pipeline_id = glCreateProgram();
@ -570,14 +633,12 @@ Init(Renderer *renderer)
SDL_SetWindowPosition(renderer->window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(renderer->window);
Array<u8> vertex_src = OpenFile(String8Lit("./shaders/vert.glsl"));
Array<u8> fragment_src = OpenFile(String8Lit("./shaders/frag.glsl"));
if(vertex_src.ptr && fragment_src.ptr)
Array<u8> shader_src = OpenFile(String8Lit("./shaders/pbr.glsl"));
if(shader_src)
{
renderer->pipeline_id = CreatePipeline(vertex_src, fragment_src);
renderer->pipeline_id = CreatePipeline(shader_src);
Free(&vertex_src);
Free(&fragment_src);
Free(&shader_src);
}
InitCheckError(!renderer->pipeline_id, "Unable to create pipeline");
@ -599,9 +660,12 @@ Init(Renderer *renderer)
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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.model_matrix = Translate(IdentityMatrix(), Vec3(0.0f, 0.0f, -3.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, 20.0f));
renderer->globals_buffer_id = CreateBuffer(&renderer->globals);
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)
{
BeginScratch();
@ -685,6 +752,10 @@ main(int argc, char** argv)
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)));
glActiveTexture(GL_TEXTURE0);

View File

@ -1,6 +1,6 @@
#version 460
precision highp float;
precision mediump float;
#define AlbedoTexture u_texture0
#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