diff options
-rw-r--r-- | LICENSE | 21 | ||||
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | assets/shaders/pbr_textured.frag | 134 | ||||
-rw-r--r-- | assets/shaders/pbr_textured.vert | 28 | ||||
-rw-r--r-- | examples/pbr_textured/ex_pbr_textured.c | 135 | ||||
-rw-r--r-- | src/maths/maths.h | 3 | ||||
-rw-r--r-- | src/renderer/backends/opengl/backend_opengl.c | 7 | ||||
-rw-r--r-- | src/renderer/builtin_materials.h | 53 | ||||
-rw-r--r-- | src/renderer/immediate.c | 50 | ||||
-rw-r--r-- | src/renderer/immediate.h | 21 | ||||
-rw-r--r-- | src/renderer/render_types.h | 6 | ||||
-rw-r--r-- | src/resources/gltf.c | 33 | ||||
-rw-r--r-- | src/transform_hierarchy.c | 1 | ||||
-rw-r--r-- | xmake.lua | 7 |
14 files changed, 439 insertions, 68 deletions
diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 21f18ca..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Joshua Rowe - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. @@ -7,6 +7,14 @@ All third-party dependencies are licensed under their own license. +## "Modules" + +| prefix | module | Description | +| --------- | ----------- | ----------- | +| `gpu` | RAL | | +| `plat` | Platforn | | +| `phys` | Physics | | + ## Notes * Check symbols in an 'archive' (static library) diff --git a/assets/shaders/pbr_textured.frag b/assets/shaders/pbr_textured.frag new file mode 100644 index 0000000..132c449 --- /dev/null +++ b/assets/shaders/pbr_textured.frag @@ -0,0 +1,134 @@ +#version 410 core + +out vec4 FragColor; + +in vec3 fragWorldPos; +in vec3 fragNormal; +in vec2 fragTexCoords; + +struct PointLight { + vec4 position; + vec4 color; +}; + +// --- Uniforms + +// Lights data +#define NUM_POINT_LIGHTS 4 +uniform Scene_Lights { + PointLight pointLights[NUM_POINT_LIGHTS]; + vec4 viewPos; +} scene; + +// Material Textures +uniform sampler2D albedoMap; +uniform sampler2D metallicRoughnessMap; +// uniform sampler2D roughnessMap; +uniform sampler2D aoMap; +uniform sampler2D normalMap; + +const float PI = 3.14; + +// Forward declarations +vec3 fresnelSchlick(float cosTheta, vec3 F0); +float DistributionGGX(vec3 N, vec3 H, float roughness); +float GeometrySchlickGGX(float NdotV, float roughness); +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness); + +void main() { + vec3 albedo = pow(texture(albedoMap, fragTexCoords).rgb, vec3(2.2)); + // vec3 normal = getNormalFromNormalMap(); + float metallic = texture(metallicRoughnessMap, fragTexCoords).g; + float roughness = texture(metallicRoughnessMap, fragTexCoords).b; + float ao = texture(aoMap, fragTexCoords).r; + + vec3 norm = normalize(fragNormal); // N + vec3 N = norm; + vec3 viewDir = normalize(vec3(scene.viewPos) - fragWorldPos); // V + vec3 V = viewDir; + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + vec3 Lo = vec3(0.0); + for (int i = 0; i < 4; ++i) { + vec3 lightVec = normalize(vec3(scene.pointLights[i].position) - fragWorldPos); // L + vec3 L = lightVec; + vec3 halfway = normalize(viewDir + lightVec); // H + vec3 H = halfway; + float distance = length(vec3(scene.pointLights[i].position) - fragWorldPos); + float attenuation = 1.0 / (distance * distance); + vec3 radiance = vec3(scene.pointLights[i].color) * attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(norm, halfway, roughness); + float G = GeometrySmith(norm, viewDir, lightVec, roughness); + // vec3 F = fresnelSchlick(max(dot(halfway, viewDir), 0.0), F0); + vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; + vec3 specular = numerator / denominator; + + vec3 kS = F; + + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + // Lo += radiance; + } + + vec3 ambient = vec3(0.03) * albedo * ao; + vec3 color = ambient + Lo; //ambient + Lo; + + color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + + FragColor = vec4(color, 1.0); + // FragColor = vec4(1.0); + // FragColor = vec4(scene.pointLights[0].position); + FragColor = vec4(albedo, 1.0); + // FragColor = vec4(pbr.metallic, pbr.roughness, pbr.ao, 1.0); + // FragColor = scene.viewPos; +} + +/* The below are from https://learnopengl.com/PBR/Lighting */ + +vec3 fresnelSchlick(float cosTheta, vec3 F0) { + return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); +} +float DistributionGGX(vec3 N, vec3 H, float roughness) { + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float num = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return num / denom; +} + +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float num = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return num / denom; +} +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} diff --git a/assets/shaders/pbr_textured.vert b/assets/shaders/pbr_textured.vert new file mode 100644 index 0000000..40a6f29 --- /dev/null +++ b/assets/shaders/pbr_textured.vert @@ -0,0 +1,28 @@ +#version 410 core + +// Vertex attributes +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec2 inTexCoords; + +// Uniforms +uniform MVP_Matrices { + mat4 model; // TODO: make model a push constant/raw uniform + mat4 view; + mat4 proj; +} mvp; + +// Outputs +layout(location = 0) out vec3 fragWorldPos; +layout(location = 1) out vec3 fragNormal; +layout(location = 2) out vec2 fragTexCoords; + +void main() { + fragWorldPos = vec3(mvp.model * vec4(inPosition, 1.0)); + fragNormal = mat3(transpose(inverse(mvp.model))) * inNormal; + // fragNormal = inNormal; + + fragTexCoords = inTexCoords; + + gl_Position = mvp.proj * mvp.view * mvp.model * vec4(inPosition, 1.0); +} diff --git a/examples/pbr_textured/ex_pbr_textured.c b/examples/pbr_textured/ex_pbr_textured.c new file mode 100644 index 0000000..a28d3fb --- /dev/null +++ b/examples/pbr_textured/ex_pbr_textured.c @@ -0,0 +1,135 @@ +#include <glfw3.h> +#include <stdbool.h> + +#include "builtin_materials.h" +#include "camera.h" +#include "colours.h" +#include "core.h" +#include "loaders.h" +#include "log.h" +#include "maths.h" +#include "maths_types.h" +#include "primitives.h" +#include "ral.h" +#include "render.h" +#include "render_types.h" +#include "str.h" + +extern core g_core; + +#define MODEL_GET(h) (model_pool_get(&g_core.models, h)) + +const vec3 pointlight_positions[4] = { + { 10.0 / 1., 10.0 / 1., 10.0 }, + { -10.0 / 1., 10.0 / 1., 10.0 }, + { 10.0 / 1., -10.0 / 1., 10.0 }, + { -10.0 / 1., -10.0 / 1., 10.0 }, +}; +pbr_point_light point_lights[4]; + +int main() { + core_bringup(); + + arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); + + for (int i = 0; i < 4; i++) { + point_lights[i].pos = pointlight_positions[i]; + point_lights[i].color = vec3(300.0, 300.0, 300.0); + } + + vec3 camera_pos = vec3(5., 0., 0.); + vec3 camera_front = vec3_normalise(vec3_negate(camera_pos)); + camera cam = camera_create(camera_pos, camera_front, VEC3_NEG_Z, deg_to_rad(45.0)); + + shader_data pbr_uniforms = { .data = NULL, .shader_data_get_layout = &pbr_textured_shader_layout }; + + // Make the pipeline + gpu_renderpass_desc pass_description = {}; + gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); + str8 vert_path = str8lit("assets/shaders/pbr_textured.vert"); + str8 frag_path = str8lit("assets/shaders/pbr_textured.frag"); + str8_opt vertex_shader = str8_from_file(&scratch, vert_path); + str8_opt fragment_shader = str8_from_file(&scratch, frag_path); + if (!vertex_shader.has_value || !fragment_shader.has_value) { + ERROR_EXIT("Failed to load shaders from disk") + } + + struct graphics_pipeline_desc pipeline_description = { + .debug_name = "Basic Pipeline", + .vertex_desc = static_3d_vertex_description(), + .data_layouts = { pbr_uniforms }, + .data_layouts_count = 1, + .vs = { .debug_name = "PBR (textured) Vertex Shader", + .filepath = vert_path, + .code = vertex_shader.contents, + .is_spirv = false }, + .fs = { .debug_name = "PBR (textured) Fragment Shader", + .filepath = frag_path, + .code = fragment_shader.contents, + .is_spirv = false }, + .renderpass = renderpass, + .wireframe = false, + .depth_test = false + }; + gpu_pipeline* pbr_pipeline = gpu_graphics_pipeline_create(pipeline_description); + + // Model + model_handle helmet_handle = + model_load_gltf("assets/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf", false); + INFO("GLTF loaded successfully!"); + model* helmet = MODEL_GET(helmet_handle); + + pbr_textured_bindgroup pbr_bind_data; + + while (!should_exit()) { + input_update(&g_core.input); + + if (!gpu_backend_begin_frame()) { + continue; + } + gpu_cmd_encoder* enc = gpu_get_default_cmd_encoder(); + // Begin recording + gpu_cmd_encoder_begin(*enc); + gpu_cmd_encoder_begin_render(enc, renderpass); + encode_bind_pipeline(enc, PIPELINE_GRAPHICS, pbr_pipeline); + encode_set_default_settings(enc); + + mat4 model_affine = mat4_ident(); + mat4 view, proj; + camera_view_projection(&cam, 1000, 1000, &view, &proj); + + // Feed shader data + pbr_bind_data.mvp_matrices = + (mvp_matrix_uniforms){ .model = model_affine, .view = view, .projection = proj }; + pbr_bind_data.lights = (pbr_params_light_uniforms){ + .viewPos = vec4(cam.position.x, cam.position.y, cam.position.z, 1.0), + .pointLights = { point_lights[0], point_lights[1], point_lights[2], point_lights[3] } + }; + pbr_bind_data.textures = (pbr_textures){ + .albedo_tex = helmet->materials->data[0].mat_data.pbr.albedo_map, + .metal_roughness_tex = helmet->materials->data[0].mat_data.pbr.metallic_map, + .ao_tex = helmet->materials->data[0].mat_data.pbr.ao_map, + .normal_tex = helmet->materials->data[0].mat_data.pbr.normal_map, + }; + pbr_uniforms.data = &pbr_bind_data; + encode_bind_shader_data(enc, 0, &pbr_uniforms); + + // Record draw calls + mesh m = helmet->meshes->data[0]; + encode_set_vertex_buffer(enc, m.vertex_buffer); + encode_set_index_buffer(enc, m.index_buffer); + encode_draw_indexed(enc, m.geometry->indices->len); + + // End recording + gpu_cmd_encoder_end_render(enc); + + gpu_cmd_buffer buf = gpu_cmd_encoder_finish(enc); + gpu_queue_submit(&buf); + // Submit + gpu_backend_end_frame(); + } + + renderer_shutdown(&g_core.renderer); + + return 0; +}
\ No newline at end of file diff --git a/src/maths/maths.h b/src/maths/maths.h index fa58088..7c0e06e 100644 --- a/src/maths/maths.h +++ b/src/maths/maths.h @@ -314,7 +314,8 @@ static inline mat4 transform_to_mat(transform *tf) { mat4 scale = mat4_scale(tf->scale); mat4 rotation = mat4_rotation(tf->rotation); mat4 translation = mat4_translation(tf->position); - return mat4_mult(mat4_mult(scale, rotation), translation); + return mat4_mult(translation, mat4_mult(rotation, scale)); + // return mat4_mult(mat4_mult(scale, rotation), translation); } // --- Sizing asserts diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index d9859b2..18cd7ee 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -207,16 +207,11 @@ void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* d glBindBuffer(GL_UNIFORM_BUFFER, ubo_buf->id.ubo); glBindBufferBase(GL_UNIFORM_BUFFER, ubo_buf->ubo_binding_point, ubo_buf->id.ubo); - if (i == 2) { - // pbr_params_light_uniforms* u = binding.data.bytes.data; - // vec4* v = &u->viewPos; - } glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo_buf->size, binding.data.bytes.data); } else if (binding.type == SHADER_BINDING_TEXTURE) { gpu_texture* tex = TEXTURE_GET(binding.data.texture.handle); - glActiveTexture(GL_TEXTURE0); - // glActiveTexture(GL_TEXTURE0 + i); + glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, tex->id); } } diff --git a/src/renderer/builtin_materials.h b/src/renderer/builtin_materials.h index 7748599..1a04f32 100644 --- a/src/renderer/builtin_materials.h +++ b/src/renderer/builtin_materials.h @@ -102,3 +102,56 @@ static void* shader_layout_get_binding(shader_data_layout* layout, u32 nth_bindi assert(nth_binding < layout->bindings_count); return &layout->bindings[nth_binding].data; } + +typedef struct pbr_textures { + texture_handle albedo_tex; + texture_handle metal_roughness_tex; + texture_handle ao_tex; + texture_handle normal_tex; +} pbr_textures; + +typedef struct pbr_textured_bindgroup { + mvp_matrix_uniforms mvp_matrices; + pbr_params_light_uniforms lights; + pbr_textures textures; +} pbr_textured_bindgroup; + +static shader_data_layout pbr_textured_shader_layout(void* data) { + pbr_textured_bindgroup* d = (pbr_textured_bindgroup*)data; + bool has_data = data != NULL; + + shader_binding b1 = { .label = "MVP_Matrices", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = { .bytes = { .size = sizeof(mvp_matrix_uniforms) } } }; + + shader_binding b2 = { .label = "Scene_Lights", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = { .bytes = { .size = sizeof(pbr_params_light_uniforms) } } }; + + shader_binding b3 = {.label = "Albedo", + .type = SHADER_BINDING_TEXTURE, + .stores_data = has_data }; + shader_binding b4 = {.label = "Metallic Roughness", + .type = SHADER_BINDING_TEXTURE, + .stores_data = has_data }; + shader_binding b5 = {.label = "Ambient Occlusion", + .type = SHADER_BINDING_TEXTURE, + .stores_data = has_data }; + shader_binding b6 = {.label = "Normal Vectors", + .type = SHADER_BINDING_TEXTURE, + .stores_data = has_data }; + + if (has_data) { + b1.data.bytes.data = &d->mvp_matrices; + b2.data.bytes.data = &d->lights; + b3.data.texture.handle = d->textures.albedo_tex; + b4.data.texture.handle = d->textures.metal_roughness_tex; + b5.data.texture.handle = d->textures.ao_tex; + b6.data.texture.handle = d->textures.normal_tex; + } + + return (shader_data_layout){ .name = "pbr_params", .bindings = { b1, b2, b3, b4, b5, b6 }, .bindings_count = 6 + }; +}
\ No newline at end of file diff --git a/src/renderer/immediate.c b/src/renderer/immediate.c index e76d102..b3431fa 100644 --- a/src/renderer/immediate.c +++ b/src/renderer/immediate.c @@ -1,18 +1,50 @@ #include "immediate.h" +#include "glad/glad.h" #include "maths.h" #include "primitives.h" #include "ral_types.h" #include "render.h" +#include "render_types.h" -void imm_draw_sphere(vec3 pos, f32 radius, vec4 colour) { - // Create the vertices - geometry_data geometry = geo_create_uvsphere(radius, 16, 16); - geo_set_vertex_colours(&geometry, colour); +typedef struct immdraw_system { + // primitive meshes (get reused for each draw call) + mesh plane; + mesh cube; + mesh sphere; + // command lists + +} immdraw_system; - // Upload to GPU - mat4 model = mat4_translation(pos); +bool immdraw_system_init(immdraw_system* state) { + geometry_data plane_geometry = geo_create_plane(f32x2(1, 1)); + state->plane = mesh_create(&plane_geometry, true); - // Set pipeline + geometry_data cube_geometry = geo_create_cuboid(f32x3(1, 1, 1)); + state->cube = mesh_create(&cube_geometry, true); - // Draw -}
\ No newline at end of file + geometry_data sphere_geometry = geo_create_uvsphere(1.0, 48, 48); + state->sphere = mesh_create(&sphere_geometry, true); + + return true; +} + +void immdraw_plane(vec3 pos, quat rotation, f32 u_scale, f32 v_scale, vec4 colour) { + +} + +void immdraw_system_render(immdraw_system* state) { + +} + +// void imm_draw_sphere(vec3 pos, f32 radius, vec4 colour) { +// // Create the vertices +// geometry_data geometry = geo_create_uvsphere(radius, 16, 16); +// geo_set_vertex_colours(&geometry, colour); + +// // Upload to GPU +// mat4 model = mat4_translation(pos); + +// // Set pipeline + +// // Draw +// }
\ No newline at end of file diff --git a/src/renderer/immediate.h b/src/renderer/immediate.h index b9d7c61..f4b1729 100644 --- a/src/renderer/immediate.h +++ b/src/renderer/immediate.h @@ -3,18 +3,17 @@ #include "geometry.h" #include "maths_types.h" +typedef struct immdraw_system immdraw_system; + +bool immdraw_system_init(immdraw_system* state); +void immdraw_system_shutdown(immdraw_system* state); +void immdraw_system_render(immdraw_system* state); + // 3. SIMA (simplified immediate mode api) / render.h // - dont need to worry about uploading mesh data // - very useful for debugging -void imm_draw_cuboid(vec3 pos, quat rotation, f32x3 extents, vec4 colour); -void imm_draw_sphere(vec3 pos, f32 radius, vec4 colour); -void imm_draw_camera_frustum(); - -// static void imm_draw_model( -// const char* model_filepath); // tracks internally whether the model is loaded +void immdraw_plane(vec3 pos, quat rotation, f32 u_scale, f32 v_scale, vec4 colour); +void immdraw_cuboid(vec3 pos, quat rotation, f32x3 extents, vec4 colour); +void immdraw_sphere(vec3 pos, f32 radius, vec4 colour); -// static void imm_draw_model(const char* model_filepath) { -// check that model is loaded -// if not loaded, load model and upload to gpu - LRU cache for models -// else submit draw call -// }
\ No newline at end of file +void immdraw_camera_frustum(); diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 8588b87..b25fa14 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -35,11 +35,17 @@ typedef struct geometry_data { rgba colour; /** Optional: set vertex colours */ } geometry_data; +typedef struct u32_opt { + u32 value; + bool has_value; +} u32_opt; + // 'Upload' a geometry_data (to GPU) -> get back a mesh typedef struct mesh { buffer_handle vertex_buffer; buffer_handle index_buffer; geometry_data* geometry; // NULL means it has been freed + u32_opt material_index; bool is_uploaded; bool is_latent; } mesh; diff --git a/src/resources/gltf.c b/src/resources/gltf.c index 46ad4f3..f136595 100644 --- a/src/resources/gltf.c +++ b/src/resources/gltf.c @@ -192,6 +192,9 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel material_darray_push(out_model->materials, our_material); } + // TEMP + u32 mat_idx = 9999; + // --- Meshes size_t num_meshes = data->meshes_count; TRACE("Num meshes %d", num_meshes); @@ -288,14 +291,15 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel if (primitive.material != NULL) { ERROR("Primitive Material %s", primitive.material->name); - // for (int i = 0; i < material_darray_len(out_model->materials); i++) { - // printf("%s vs %s \n", primitive.material->name, out_model->materials->data[i].name); - // if (strcmp(primitive.material->name, out_model->materials->data[i].name) == 0) { - // TRACE("Found material"); - // mesh.material_index = i; - // break; - // } - // } + for (u32 i = 0; i < material_darray_len(out_model->materials); i++) { + printf("%s vs %s \n", primitive.material->name, out_model->materials->data[i].name); + if (strcmp(primitive.material->name, out_model->materials->data[i].name) == 0) { + INFO("Found material"); + mat_idx = i; + // mesh.material_index = i; + break; + } + } } // // FIXME @@ -317,17 +321,6 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel // // } // // } - /* - typedef struct mesh { - buffer_handle vertex_buffer; - buffer_handle index_buffer; - u32 index_count; - bool has_indices; - geometry_data* vertices; // NULL means it has been freed - bool is_uploaded; - bool is_latent; - } mesh; - */ bool has_indices = false; vertex_darray *geo_vertices = vertex_darray_new(3); u32_darray *geo_indices = u32_darray_new(0); @@ -384,7 +377,9 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel geometry->vertices = geo_vertices; geometry->indices = geo_indices; geometry->has_indices = has_indices; + mesh m = mesh_create(geometry, true); + m.material_index = (u32_opt){.has_value = mat_idx == 9999, .value = mat_idx }; mesh_darray_push(out_model->meshes, m); } diff --git a/src/transform_hierarchy.c b/src/transform_hierarchy.c index 2c427b2..b9795bc 100644 --- a/src/transform_hierarchy.c +++ b/src/transform_hierarchy.c @@ -11,7 +11,6 @@ #include "log.h" #include "maths.h" #include "maths_types.h" -// #include "render_types.h" struct transform_hierarchy { transform_node root; @@ -230,6 +230,13 @@ target("pbr_params") add_files("examples/pbr_params/ex_pbr_params.c") set_rundir("$(projectdir)") +target("pbr_textured") + set_kind("binary") + set_group("examples") + add_deps("core_static") + add_files("examples/pbr_textured/ex_pbr_textured.c") + set_rundir("$(projectdir)") + -- target("transforms") -- set_kind("binary") -- set_group("examples") |