From 958e9c86ee05120f9289236e8268625d41769a22 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 18 Feb 2026 06:01:57 +1100 Subject: [PATCH] merge shader into one, some fixes --- .gitignore | 1 - .ignore | 1 + assets.cpp | 33 ++++++--- assets/shaders/pbr.frag.spv | Bin 0 -> 2348 bytes assets/shaders/pbr.vert.spv | Bin 0 -> 2620 bytes main.cpp | 97 +++++++++++++++++++++---- shaders/frag.glsl | 2 +- shaders/pbr.glsl | 141 ++++++++++++++++++++++++++++++++++++ 8 files changed, 251 insertions(+), 24 deletions(-) create mode 100644 assets/shaders/pbr.frag.spv create mode 100644 assets/shaders/pbr.vert.spv create mode 100644 shaders/pbr.glsl diff --git a/.gitignore b/.gitignore index 24f15cc..9549556 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ build -include/SDL3 assets/StylizedNature/OBJ assets/StylizedNature/FBX assets/StylizedNature/FBX (Unity) diff --git a/.ignore b/.ignore index de735a6..032d927 100644 --- a/.ignore +++ b/.ignore @@ -3,3 +3,4 @@ SDL external build +assets diff --git a/assets.cpp b/assets.cpp index 3e56d77..9511649 100644 --- a/assets.cpp +++ b/assets.cpp @@ -1,4 +1,4 @@ -const u64 IMAGE_MAX = 1024; +const u64 MODEL_MAX = 2048; #include @@ -42,9 +42,11 @@ struct Mesh struct Material { - TextureID textures[MMI_Max]; - PipelineID pipeline_id; - BufferID buffer_id; + 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 materials; }; +Model g_models[MODEL_MAX]; + Array OpenFile(String8 file_path) { @@ -233,8 +237,8 @@ LoadImage(cgltf_image *asset_image, String8 texture_path) } else { - u8 buffer[512]; - String8 file_path = SPrintf(buffer, "%s%s", texture_path.ptr, uri_path.ptr); + u8 buffer[512]; + String8 file_path = SPrintf(buffer, "%s%s", texture_path.ptr, uri_path.ptr); Array image_file = OpenFile(file_path); 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; } -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].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; diff --git a/assets/shaders/pbr.frag.spv b/assets/shaders/pbr.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..0dec751928a03aee28774b649dd0286167d89cb0 GIT binary patch literal 2348 zcmZ9M>rWFw6vanM3qAos#diS(p9sE<(OAl|ZL(0(NA%kUp)oaul2TB=`3L$3`NhQZ z+wGK_UNX!*=iJ$OooQxdVa&NR?!3F`p1Cxp+=v(_E|>ISREw66dV9++U#(Da$z_s4 zY9`#c8&yx+-)S8noK>4rd!#n0TC{PsjQ&Q{|Ixrvcg}@T99Ak}6vVrShw)MGSGyUv zTL;Z}uhnht_F5-R>c&l7>tMHiyk`rts<3lsT{fA2qr3C1*lBmVnh)-x`s29Q{MkG1 zHnj`JvBs15_=HVmwbv`^3(;DzUWx0$mwKZbr2JL!Tb1f&A+r3KyC!}!s28HBTs&16 zGv;QcRV$6Kv=!89Mnt~HKg5;7HpPlLsGK7o6<@_IV{yr2eIy3;){*7 zV6(725SZt-_;R&cST7g0iorli)^|tRb~V^2NA;k3DkbyWm9|!0-!QcJtjmiZoZ%|_ z%(^+tJx{rL%e_ds1UCKSQ-0F%}Jev5D zd)F2c{6u}&?tI;8AL%r64on<&JKynPN3PDP5+2W=w3eK%n2}l{ zWOcCB@s`!WR>x;n2U{J_SsiS3{AYEr)$yX$!B)qYRtH<1-%fwVp>EOptfaH_{^agT zeP1d~?rL&~<6HFf4$K|fad3?Lq~^zsD7WLl!{gu>_gjrS$NzSZ;CVG-T27^Y zPJ7F!C%>u;|K-)LX*}Nt8gS###;yvnFzYULXs`9)9>iFJ;ei0ns z1M@Bk=ATf{_gEYCoDtuGryk5Zg_}{;jQUm0LC<^jId9eHyi=d^Mt#ov^f_)ajTF>i+Om^VUryqLlPUK+x9p78Z}oB(rn zc$~AF6@ILqd*!b0^gRvd8|VL2n7hFLd;^T9;9hGCJ>v;H@mCC<{UDY*zNE(eg1N)X aYTVyvRWbLp8a41A^#!~I_fM;QtM(ty*T@0@ literal 0 HcmV?d00001 diff --git a/assets/shaders/pbr.vert.spv b/assets/shaders/pbr.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..9f346560abb36fdc1b3af38adcb589e33aa9023c GIT binary patch literal 2620 zcmZ9NZFAdH5QRlzJEf&9eJ@Z_r{T4M&_Y`ZrD+sfwKb!}sqHZRrV);&BSx`3wi8}H z^)JBh;s^1C8P0R9bu_t|_1$xJ@4dTMN6PZj`ikeh<6ZDBdOO~HT=AB~c;aeqZbiLl zb2>ZReDwGM8JE0emq^ZK?|tW2^m~+KL%>DZ$FeVF8?ql|&tyNzp3Amm+cICatiL7A z|7f#{ciwA7ajVm5ML|3mkK^g=k35a@Y?#J}*(4pzvXhj&bEUj&ILMC=%L!FwlMza;ro>uL@Y8&5{R(x=K0TXj5joMh>5#5td} zoPRVrO!N3CnN2d+4`*B>NrN+Z21z^~O$*HPIEjx>c!aPO)G&?41d@Ivy$34#HNuf4YeJ9*b`r>;$|1{vyCRPsE4auHOv(y+*JIx%$3W zY`+`445NO~Jq@{Yo+`G}ZN4ng;ww(aNjw$YXKjvCABz-QON zvF@#`r8?33nv7xi-W)p2JFqHa9dX_PFax}y89cv(ihBpBjX@mkgE26g$G81>hG6cJ zINAo=e&`uYU&PTcxK?1a3#L!vXcl~~z~~hGZh_Gz_)W>f`$h zwtBV-Z28;5Xu{%tfvNYJx~A_n?Z$riH{}tl%WmmB`T*1a4gJzbUB=ibFuicz9bx() zA8u71XWJgcu)6Zz)6AK~pB0$zDIDiq(p;CZFXw|BhzrfoDH3dbAqJy({y)w=c;5R32-oll?x| zOpcxZg?!@h><32AcHVvY>}_!{`i8r%UB1@*P}$6U>&-{w=07O;Xxn&nZ9bYdA3d9o zmd!`U=A&Wr(J#IJpqaYpm0rMT8O|_THq70jWyAD_mJM?kXxZ-KMG->>><8X1IKzH{ zpGXhfG1_3T$G>8D2YmhV+;7Ox0-AcROf+y)25&jH<&%RZEawCH@PBI`)_f>q9XvT` zgZB|#yiyL&yDo!c7`G-Lj(&~1S8&w6ubbp9*JX7X`NYxJU)q=0Co;|_hnmsbXENR+ a`r1 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 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 vertex_shader_src, Array frag_shader_src) +CreatePipeline(Array 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 vertex_src_array = { + .ptr = vertex_src, + .length = Length(vertex_src), + }; + + Array 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 vertex_src = OpenFile(String8Lit("./shaders/vert.glsl")); - Array fragment_src = OpenFile(String8Lit("./shaders/frag.glsl")); - if(vertex_src.ptr && fragment_src.ptr) + Array 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(); @@ -684,6 +751,10 @@ main(int argc, char** argv) glUniform1i(g_renderer.texture_locations[j], 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))); diff --git a/shaders/frag.glsl b/shaders/frag.glsl index ffb8e17..2e60f78 100644 --- a/shaders/frag.glsl +++ b/shaders/frag.glsl @@ -1,6 +1,6 @@ #version 460 -precision highp float; +precision mediump float; #define AlbedoTexture u_texture0 #define NormalTexture u_texture1 diff --git a/shaders/pbr.glsl b/shaders/pbr.glsl new file mode 100644 index 0000000..244449e --- /dev/null +++ b/shaders/pbr.glsl @@ -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