diff --git a/core/entity.jai b/core/entity.jai index dcfa014..d3c7da1 100644 --- a/core/entity.jai +++ b/core/entity.jai @@ -41,6 +41,8 @@ Renderable :: struct { visible: bool = true; type : Renderable_Type; @DontSerialize + use_default_pipeline: bool = true; + model: Model_Handle; @DontSerialize nodes: [MAX_NODES] Node_Render_Data; @DontSerialize num_nodes: s64; @DontSerialize @@ -55,7 +57,8 @@ MAX_CHILDREN :: 16; SPHERE; BOX; CAPSULE; - MESH; + TRIANGLE_MESH; + CONVEX_MESH; } Physics_Lock :: enum_flags u8 { diff --git a/physics/physx.jai b/physics/physx.jai index 386a47e..6c1cf8a 100644 --- a/physics/physx.jai +++ b/physics/physx.jai @@ -81,6 +81,19 @@ tick_physx :: (scene: *PhysX_Scene, dt: float) { PhysX.PxScene_fetchResults(scene.scene, true, null); } +//custom_filter_shader :: (attributes0: u32, filterData0: PhysX.PxFilterData, attributes1: u32, filterData1: PhysX.PxFilterData, pairFlags: *PhysX.PxPairFlags, constantBlock: *void, constantBlockSize: u32) -> PhysX.PxFilterFlags #c_call { +// pairFlags.* = PhysX.PxPairFlags.ContactDefault; +// return PhysX.PxFilterFlags.Default; +//} + +custom_filter_shader :: (attributes0: *u32, filterData0: *PhysX.PxFilterData, attributes1: *u32, filterData1: *PhysX.PxFilterData, pairFlags: *PhysX.PxPairFlags) -> u16 #c_call { + pairFlags.* = PhysX.PxPairFlags.ContactDefault; + push_context { + print("DUDE!\n"); + } + return xx PhysX.PxFilterFlags.Default; +} + init_physx_scene :: (game_scene: *Scene) { tolerance_scale : PhysX.PxTolerancesScale; tolerance_scale.length = 1; @@ -91,7 +104,10 @@ init_physx_scene :: (game_scene: *Scene) { scene_desc.cpuDispatcher = xx dispatcher; scene_desc.simulationEventCallback = event_callback; - PhysX.set_default_filter_shader(*scene_desc); + PhysX.set_custom_filter_shader(*scene_desc, PhysX.create_custom_filter_shader(custom_filter_shader)); + //scene_desc.filterShader = custom_filter_shader;// + //scene_desc.filterShaderData = null; + //scene_desc.filterShaderDataSize = 0; scene := PhysX.PxPhysics_createScene(physics, *scene_desc); @@ -203,7 +219,7 @@ create_physx_actor :: (e: *Entity) { case .CAPSULE; { geo = PhysX.PxCapsuleGeometry_new(e.physics.capsule.radius, e.physics.capsule.half_height-e.physics.capsule.radius); } - case .MESH; { + case .CONVEX_MESH; { if e.flags & .RENDERABLE { points : [..] Vector3; points.allocator = temp; @@ -213,7 +229,6 @@ create_physx_actor :: (e: *Entity) { model := get_model_by_handle(e.renderable.model); for node, node_index: model.nodes { - index_start : u32 = xx indices.count; render_data := e.renderable.nodes[node_index]; success, inv_matrix := inverse(e.transform.model_matrix); @@ -222,9 +237,63 @@ create_physx_actor :: (e: *Entity) { if node.meshes.count > 0 { for m, mi: node.meshes { + index_start : u32 = xx indices.count; mesh := parray_get(*engine.renderer.meshes, m); for v: mesh.positions { - array_add(*points, transform_position(v, matrix)); + array_add(*points, v);//transform_position(v, matrix)); + } + + for i: mesh.indices { + array_add(*indices, index_start + i); + } + } + } + } + mesh_desc := PhysX.PxConvexMeshDesc_new(); + mesh_desc.points.count = xx points.count; + mesh_desc.points.stride = size_of(Vector3); + mesh_desc.points.data = points.data; + + mesh_desc.polygons.count = cast(u32)(indices.count / 3); + mesh_desc.polygons.stride = 3 * size_of(u32); + mesh_desc.polygons.data = indices.data; + + if !PhysX.PxValidateConvexMesh(*cooking_params, *mesh_desc) { + assert(false); + } + + stream : PhysX.PxOutputStream; + callback := PhysX.PxGetStandaloneInsertionCallback(); + //read_buffer : PhysX.PxDefaultMemoryInputData_new(; + cond : s32; + mesh := PhysX.PxCreateConvexMesh(*cooking_params, *mesh_desc, callback, null); + scale := PhysX.PxMeshScale_new(*e.transform.scale); + geo = PhysX.PxConvexMeshGeometry_new(mesh, *scale, 0); + } + } + case .TRIANGLE_MESH; { + if e.flags & .RENDERABLE { + points : [..] Vector3; + points.allocator = temp; + indices : [..] u32; + indices.allocator = temp; + + model := get_model_by_handle(e.renderable.model); + + for node, node_index: model.nodes { + render_data := e.renderable.nodes[node_index]; + + success, inv_matrix := inverse(e.transform.model_matrix); + // We need to undo the local to world part of every world matrix + matrix := inv_matrix * render_data.transform.world_matrix; + + if node.meshes.count > 0 { + print("NUM MESHES %\n", node.meshes.count); + for m, mi: node.meshes { + index_start : u32 = xx indices.count; + mesh := parray_get(*engine.renderer.meshes, m); + for v: mesh.positions { + array_add(*points, v);//transform_position(v, matrix)); } for i: mesh.indices { @@ -242,7 +311,7 @@ create_physx_actor :: (e: *Entity) { mesh_desc.triangles.stride = 3 * size_of(u32); mesh_desc.triangles.data = indices.data; - if PhysX.PxValidateTriangleMesh(*cooking_params, *mesh_desc) { + if !PhysX.PxValidateTriangleMesh(*cooking_params, *mesh_desc) { assert(false); } @@ -259,6 +328,16 @@ create_physx_actor :: (e: *Entity) { shape := PhysX.PxPhysics_createShape(physics, geo, material, false, ifx e.physics.trigger then PHYSX_DEFAULT_TRIGGER_SHAPE_FLAGS else PHYSX_DEFAULT_SIMULATION_SHAPE_FLAGS); + // Setup layers + filter_data := PhysX.PxFilterData_new(); + filter_data.word0 = 1; + filter_data.word1 = 1; + filter_data.word2 = 1; + filter_data.word3 = 1; + + //PhysX.PxShape_setSimulationFilterData(shape, *filter_data); + //PhysX.PxShape_setQueryFilterData(shape, *filter_data); + PhysX.PxRigidActor_attachShape(actor, shape); if e.physics.dynamic { diff --git a/renderer/renderer.jai b/renderer/renderer.jai index 18c1fba..cc6e5ed 100644 --- a/renderer/renderer.jai +++ b/renderer/renderer.jai @@ -624,6 +624,7 @@ Renderer :: struct { default_pipelines : struct { message_text : Pipeline_State_Handle; + entity_pipeline : Pipeline_State_Handle; } default_samplers : struct { @@ -684,6 +685,7 @@ create_renderer :: (window: *Window) -> *Renderer { init_freetype(); init_default_meshes(); init_trigger_line_rendering(); + init_default_pipelines(); array_reserve(*engine.renderer.command_buffer.commands, 4096); @@ -698,35 +700,42 @@ create_renderer :: (window: *Window) -> *Renderer { } init_default_pipelines :: () { - { - vs := create_vertex_shader(renderer, "../modules/Coven/shaders/font.hlsl", "VS"); - ps := create_pixel_shader(renderer, "../modules/Coven/shaders/font.hlsl", "PS"); + //{ + // vs := create_vertex_shader(renderer, "../modules/Coven/shaders/font.hlsl", "VS"); + // ps := create_pixel_shader(renderer, "../modules/Coven/shaders/font.hlsl", "PS"); - layout : [3] Vertex_Data_Info; - layout[0] = .{0,.POSITION2D, 0}; - layout[1] = .{0,.TEXCOORD0, 0}; - layout[2] = .{0,.COLOR_WITH_ALPHA, 0}; + // layout : [3] Vertex_Data_Info; + // layout[0] = .{0,.POSITION2D, 0}; + // layout[1] = .{0,.TEXCOORD0, 0}; + // layout[2] = .{0,.COLOR_WITH_ALPHA, 0}; - params : [2] Shader_Parameter; - params[0].shader = .PIXEL; - params[0].type = .SAMPLER; - params[0].name = "ss"; - params[0].slot = 0; - params[0].mapping = .CLAMP_SAMPLER; + // params : [2] Shader_Parameter; + // params[0].shader = .PIXEL; + // params[0].type = .SAMPLER; + // params[0].name = "ss"; + // params[0].slot = 0; + // params[0].mapping = .CLAMP_SAMPLER; - params[1].shader = .PIXEL; - params[1].type = .TEXTURE; - params[1].name = "tex"; - params[1].slot = 1; + // params[1].shader = .PIXEL; + // params[1].type = .TEXTURE; + // params[1].name = "tex"; + // params[1].slot = 1; - engine.renderer.default_pipelines.message_text = create_pipeline_state(renderer, vs, ps, layout, params, blend_type=.TRANSPARENT); - } + // engine.renderer.default_pipelines.message_text = create_pipeline_state(renderer, vs, ps, layout, params, blend_type=.TRANSPARENT); + //} + + //{ + // vs := create_vertex_shader_from_source(engine.renderer, "fallback", FALLBACK_SHADER, "VS", mesh_data_types = .[.POSITION]); + // ps := create_pixel_shader_from_source(engine.renderer, "fallback", FALLBACK_SHADER, "PS"); + + // projectile_pipeline = create_pipeline_state2(engine.renderer, vs, ps, blend_type=.OPAQUE); + //} { - vs := create_vertex_shader_from_source(engine.renderer, FALLBACK_SHADER, "VS", mesh_data_types = .[.POSITION]); - ps := create_pixel_shader_from_source(engine.renderer, FALLBACK_SHADER, "PS"); + vs := create_vertex_shader_from_source(engine.renderer, "default_entity", DEFAULT_ENTITY_SHADER, "VS", mesh_data_types = .[.POSITION, .NORMAL, .TEXCOORD]); + ps := create_pixel_shader_from_source(engine.renderer, "default_entity", DEFAULT_ENTITY_SHADER, "PS"); - projectile_pipeline = create_pipeline_state2(engine.renderer, vs, ps, blend_type=.OPAQUE); + engine.renderer.default_pipelines.entity_pipeline = create_pipeline_state(engine.renderer, vs, ps, blend_type=.OPAQUE); } } @@ -1689,6 +1698,55 @@ render :: () { // #load "ui.jai"; //} +render_default_renderable_entities :: () { + for e: engine.current_scene.entities { + if e.flags & .RENDERABLE && e.renderable.use_default_pipeline { + render_entity(e, engine.renderer.default_pipelines.entity_pipeline); + } + } +} + +render_entity :: (e: *Entity, pipeline: Pipeline_State_Handle) { + if e.renderable.type == { + case .MODEL; { + model := get_model_by_handle(e.renderable.model); + if model == null return; + + for node, node_index: model.nodes { + render_data := e.renderable.nodes[node_index]; + if !render_data.enabled continue; + + if node.meshes.count > 0 { + for m, mi: node.meshes { + push_cmd_set_pipeline_state(engine.renderer, pipeline); + push_cmd_set_constant_buffer(engine.renderer, 1, engine.directional_light_buffer, .VERTEX); + push_cmd_set_constant_buffer(engine.renderer, 1, engine.directional_light_buffer, .PIXEL); + + push_cmd_set_constant_buffer(engine.renderer, 2, render_data.transform_buffer, .VERTEX); + push_cmd_set_constant_buffer(engine.renderer, 3, render_data.material_buffer, .PIXEL); + + if node.num_bones > 0 { + push_cmd_set_constant_buffer(engine.renderer, 4, render_data.bone_buffers[mi], .VERTEX); + } + + mesh := parray_get(*engine.renderer.meshes, m); + + vb := get_mesh_vb(mesh); + push_cmd_set_vertex_buffer(engine.renderer, vb); + + if mesh.ib != 0 { + push_cmd_set_index_buffer(engine.renderer, mesh.ib); + push_cmd_draw_indexed(engine.renderer, mesh.indices.count); + } else { + push_cmd_draw(engine.renderer, mesh.positions.count); + } + } + } + } + } + } +} + #scope_module #load "dx11_renderer.jai"; @@ -1724,3 +1782,146 @@ float4 PS(PSInput input) : SV_Target { return float4(1,0,1,1); } DONE + +DEFAULT_ENTITY_SHADER :: #string DONE +cbuffer CameraData : register(b0) +{ + float4x4 projection; + float4x4 view; + float4 camera_position; +}; + +cbuffer Directional_Light_Data : register(b1) +{ + float4 color_and_intensity; + float4 direction; + float4x4 light_matrix; +}; + +cbuffer Transform : register(b2) +{ + float4x4 model; +}; + +cbuffer Material : register(b3) +{ + float4 base_color; +}; + +#ifdef SKINNING + +#define MAX_BONES 128 + +cbuffer Bone_Matrices : register(b4) +{ + float4x4 bone_matrices[MAX_BONES]; +}; +#endif + +struct VSInput { + float3 position : POSITION; + float3 normal : NORMAL; + float2 texcoord : TEXCOORD0; + +#ifdef SKINNING + float4 bone_indices : TEXCOORD1; + float4 bone_weights : TEXCOORD2; +#endif +}; + +struct PSInput { + float4 position : SV_POSITION; + float2 texcoord : TEXCOORD1; + float3 normal : NORMAL; + float2 screen_pos : TEXCOORD0; + float4 light_view_position : TEXCOORD3; +}; + +struct PSOutput { + float4 color : SV_Target0; +}; + +sampler samp : register(s0); +Texture2D shadow_map: register(t0); + +PSInput VS(VSInput input) { + PSInput output; + + float3 position = input.position; +#ifdef SKINNING + float4x4 m = float4x4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + for(int i = 0; i < 4; i++) { + m += bone_matrices[int(input.bone_indices[i])] * input.bone_weights[i]; + } + + output.position = mul(float4(position, 1.0), m); +#else + output.position = mul(float4(position, 1.0), model); +#endif + + output.light_view_position = mul(output.position, light_matrix); + + output.position = mul(output.position, view); + output.position = mul(output.position, projection); + output.screen_pos = output.position.xy / output.position.w; + output.screen_pos = output.screen_pos * 0.5 + 0.5; + output.normal = normalize(mul(input.normal, model)); + output.texcoord = input.texcoord; + + return output; +} + +float calculate_shadow(float2 shadow_coord, float bias, float current_depth) { + if(current_depth > 1.0) + return 0.0; + + float2 texture_size; + shadow_map.GetDimensions(texture_size.x, texture_size.y); + float2 texel_size = 1.0 / texture_size; + float shadow = 0.0; + + for(int x = -1; x <= 1; ++x) + { + for(int y = -1; y <= 1; ++y) + { + float pcf_depth = shadow_map.Sample(samp, shadow_coord + float2(x, y) * texel_size).r; + shadow += current_depth - bias > pcf_depth ? 1.0 : 0.0; + } + } + shadow /= 9.0; + + + return 1.0 - shadow; +} + +PSOutput PS(PSInput input) { + PSOutput output; + float ao = 1.0;//ssao.Sample(samp, float2(input.screen_pos.x, 1.0 - input.screen_pos.y)); + //output.color = float4(ao, ao, ao, 1.0); + //return output; + float3 ambient = 0.1; + + // Diffuse + float3 light_dir = normalize(-direction); + float diffuse_factor = max(0, dot(input.normal, light_dir)); + float3 diffuse = 0.5 * diffuse_factor; + + // Specular + float3 view_dir = normalize(-input.position.xyz); + float3 reflect_dir = reflect(-light_dir, input.normal); + float specular_factor = pow(max(dot(view_dir, reflect_dir), 0), 32.0); + float3 specular = 0.3 * specular_factor; + + float2 shadow_coord; + shadow_coord.x = input.light_view_position.x / input.light_view_position.w * 0.5 + 0.5; + shadow_coord.y = -input.light_view_position.y / input.light_view_position.w * 0.5 + 0.5; + float current_depth = input.light_view_position.z / input.light_view_position.w; + + float shadow_amount = calculate_shadow(shadow_coord, 0.01, current_depth); + + output.color = base_color * color_and_intensity.w * float4(ao*(ambient + diffuse + specular), base_color.a); + output.color *= max(0.2, shadow_amount); + + return output; +} +DONE