diff --git a/Crafter.Graphics-Camera.cpp b/Crafter.Graphics-Camera.cpp index 86710fc..929b0a0 100644 --- a/Crafter.Graphics-Camera.cpp +++ b/Crafter.Graphics-Camera.cpp @@ -39,4 +39,31 @@ Camera::Camera(float fov, float aspectRatio, float near, float far) { void Camera::Update() { projectionView = projection*view; onUpdate.Invoke(); -} \ No newline at end of file +} + +Vector Camera::ToRay(uint32_t x, uint32_t y) { + // // Normalize the screen coordinates + // float mx = (2.0f * x) / sizeX - 1.0f; + // float my = 1.0f - (2.0f * y) / sizeY; + // + // // Construct Ray in Homogeneous Clip Space + // Vector rayOrigin = Vector(mx, my, 0.0f); + // Vector rayEnd = Vector(mx, my, 1.0f); + // + // // Transform Ray to View Space + // MatrixRowMajor invProjection = DirectX::XMMatrixInverse(NULL, projectionMatrix); + // Vector rayOriginView = DirectX::XMVector3TransformCoord(rayOrigin, invProjection); + // Vector rayEndView = DirectX::XMVector3TransformCoord(rayEnd, invProjection); + // + // // Transform Ray to World Space + // DirectX::XMMATRIX viewMatrix = GetViewMatrix(); // Assuming this returns the view matrix + // DirectX::XMMATRIX invView = DirectX::XMMatrixInverse(NULL, viewMatrix); + // Vector rayOriginWorld = DirectX::XMVector3TransformCoord(rayOriginView, invView); + // Vector rayEndWorld = DirectX::XMVector3TransformCoord(rayEndView, invView); + // + // // Compute Ray Direction + // DirectX::XMVECTOR rayDirWorld = DirectX::XMVector3Normalize(DirectX::XMVectorSubtract(rayEndWorld, rayOriginWorld)); + // + // return rayDirWorld; + return Vector(0,0,0); +} diff --git a/Crafter.Graphics-Camera.cppm b/Crafter.Graphics-Camera.cppm index 00aefe3..66e3b53 100644 --- a/Crafter.Graphics-Camera.cppm +++ b/Crafter.Graphics-Camera.cppm @@ -36,5 +36,7 @@ namespace Crafter { Event onUpdate; Camera(float fov, float aspectRatio, float near, float far); void Update(); + Vector ToRay(uint32_t x, uint32_t y); + }; } diff --git a/Crafter.Graphics-VoxelShader.cppm b/Crafter.Graphics-VoxelShader.cppm new file mode 100644 index 0000000..cacb21b --- /dev/null +++ b/Crafter.Graphics-VoxelShader.cppm @@ -0,0 +1,75 @@ +/* +Crafter®.Graphics +Copyright (C) 2025 Catcrafts® +Catcrafts.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +module; + +#include +#include +#include +#include +#include +#include "VulkanInitializers.hpp" + +export module Crafter.Graphics:VoxelShader; +import :Mesh; +import :Camera; +import :VulkanPipeline; +import :DescriptorSet; +import Crafter.Math; + +namespace Crafter { + export struct VoxelShaderData { + MatrixRowMajor mvp; + uint32_t sizeX; + uint32_t sizeY; + uint32_t sizeZ; + }; + + export template + class VoxelShader { + public: + MatrixRowMajor transform; + Camera* camera; + Buffer grid; + Buffer data; + std::uint32_t threadCount; + EventListener cameraUpdate; + VoxelShader(uint32_t sizeX, uint32_t sizeY, uint sizeZ, Camera* camera) : threadCount((sizeX*sizeY*sizeZ)/16), data(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), grid(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, sizeX*sizeY*sizeZ) ,camera(camera), cameraUpdate( + &camera->onUpdate, [this](){ + Update(); + } + ) { + transform = MatrixRowMajor::Identity(); + data.value->sizeX = sizeX; + data.value->sizeY = sizeY; + data.value->sizeZ = sizeZ; + } + void WriteDescriptors(VkDescriptorSet set) { + VkWriteDescriptorSet write[2] = { + vks::initializers::writeDescriptorSet(set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &data.descriptor), + vks::initializers::writeDescriptorSet(set, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, &grid.descriptor), + }; + vkUpdateDescriptorSets(VulkanDevice::device, 2, &write[0], 0, nullptr); + } + void Update() { + data.value->mvp = camera->projectionView*transform; + } + }; +} diff --git a/Crafter.Graphics.cppm b/Crafter.Graphics.cppm index 7106672..819228c 100644 --- a/Crafter.Graphics.cppm +++ b/Crafter.Graphics.cppm @@ -31,6 +31,7 @@ export import :VulkanPipeline; export import :VulkanShader; export import :Camera; export import :VulkanBuffer; +export import :VoxelShader; export import :Mesh; export import :MeshShader; export import :VulkanTexture; diff --git a/MeshShaderMixedVoxelGrid.glsl b/MeshShaderMixedVoxelGrid.glsl new file mode 100644 index 0000000..1a50be0 --- /dev/null +++ b/MeshShaderMixedVoxelGrid.glsl @@ -0,0 +1,144 @@ +/* + * Crafter®.Graphics + * Copyright (C) 2025 Catcrafts® + * Catcrafts.net + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#version 450 +#extension GL_EXT_mesh_shader : require + +layout (binding = 0) uniform UBO +{ + mat4 modelProjectionView; + uint sizeX; + uint sizeY; + uint sizeZ; +} ubo; + +struct VoxelType +{ + uint type; +}; + +layout (binding = 1) buffer VOXELS +{ + VoxelType voxel[]; +} voxels; + +/* +layout (location = 0) out PerVertexData +{ + vec4 color; +} outVert[]; +*/ + +shared uint writeCounter; + +layout(local_size_x = 16, local_size_y = 1, local_size_z = 1) in; +layout(triangles, max_vertices = 128, max_primitives = 192) out; +void main() +{ + //if (gl_LocalInvocationIndex == 0) { + //writeCounter = 0; + //} + + //barrier(); + + //uint type = voxels.voxel[gl_GlobalInvocationID.x].type; + + //if(type != 0) { + uint old = atomicAdd(writeCounter, 1); + uint z = gl_GlobalInvocationID.x / (ubo.sizeX * ubo.sizeY); + uint y = (gl_GlobalInvocationID.x % (ubo.sizeX * ubo.sizeY)) / ubo.sizeX; + uint x = gl_GlobalInvocationID.x % ubo.sizeX; + + float zF = float(z); + float yF = float(y); + float xF = float(x); + + uint oldVertexOffset = old*8; + + gl_MeshVerticesEXT[oldVertexOffset + 0].gl_Position = vec4(xF - 0.5, yF - 0.5, zF - 0.5, 1.0); // Vertex 0 + gl_MeshVerticesEXT[oldVertexOffset + 1].gl_Position = vec4(xF + 0.5, yF - 0.5, zF - 0.5, 1.0); // Vertex 1 + gl_MeshVerticesEXT[oldVertexOffset + 2].gl_Position = vec4(xF + 0.5, yF + 0.5, zF - 0.5, 1.0); // Vertex 2 + gl_MeshVerticesEXT[oldVertexOffset + 3].gl_Position = vec4(xF - 0.5, yF + 0.5, zF - 0.5, 1.0); // Vertex 3 + gl_MeshVerticesEXT[oldVertexOffset + 4].gl_Position = vec4(xF - 0.5, yF - 0.5, zF + 0.5, 1.0); // Vertex 4 + gl_MeshVerticesEXT[oldVertexOffset + 5].gl_Position = vec4(xF + 0.5, yF - 0.5, zF + 0.5, 1.0); // Vertex 5 + gl_MeshVerticesEXT[oldVertexOffset + 6].gl_Position = vec4(xF + 0.5, yF + 0.5, zF + 0.5, 1.0); // Vertex 6 + gl_MeshVerticesEXT[oldVertexOffset + 7].gl_Position = vec4(xF - 0.5, yF + 0.5, zF + 0.5, 1.0); // Vertex 7 + + + uint oldPrimOffset = old*12; + + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 0] = uvec3(oldVertexOffset + 0, oldVertexOffset + 1, oldVertexOffset + 2); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 1] = uvec3(oldVertexOffset + 2, oldVertexOffset + 3, oldVertexOffset + 0); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 2] = uvec3(oldVertexOffset + 4, oldVertexOffset + 6, oldVertexOffset + 5); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 3] = uvec3(oldVertexOffset + 6, oldVertexOffset + 4, oldVertexOffset + 7); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 4] = uvec3(oldVertexOffset + 0, oldVertexOffset + 5, oldVertexOffset + 1); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 5] = uvec3(oldVertexOffset + 0, oldVertexOffset + 4, oldVertexOffset + 5); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 6] = uvec3(oldVertexOffset + 3, oldVertexOffset + 2, oldVertexOffset + 6); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 7] = uvec3(oldVertexOffset + 6, oldVertexOffset + 7, oldVertexOffset + 3); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 8] = uvec3(oldVertexOffset + 0, oldVertexOffset + 3, oldVertexOffset + 7); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 9] = uvec3(oldVertexOffset + 7, oldVertexOffset + 4, oldVertexOffset + 0); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 10] = uvec3(oldVertexOffset + 1, oldVertexOffset + 2, oldVertexOffset + 6); + gl_PrimitiveTriangleIndicesEXT[oldPrimOffset + 11] = uvec3(oldVertexOffset + 6, oldVertexOffset + 5, oldVertexOffset + 1); + //} + + //barrier(); + + //SetMeshOutputsEXT(writeCounter*8, writeCounter*12); + + SetMeshOutputsEXT(128, 192); +} + + +/** + + int z = gl_GlobalInvocationID.x / (ubo.sizeX * ubo.sizeY); + int y = (gl_GlobalInvocationID.x % (ubo.sizeX * ubo.sizeY)) / ubo.sizeX; + int x = gl_GlobalInvocationID.x % ubo.sizeX; + + // Top (y+1) if within bounds + if (y < ubo.sizeY - 1 && vertex.pos[gl_GlobalInvocationID.x + ubo.sizeX]) { + + } + + // Bottom (y-1) if within bounds + if (y > 0 && vertex.pos[gl_GlobalInvocationID.x - ubo.sizeX]) { + + } + + // Left (x-1) if within bounds + if (x > 0 && vertex.pos[gl_GlobalInvocationID.x - 1]) { + + } + + // Right (x+1) if within bounds + if (x < ubo.sizeX - 1 && vertex.pos[gl_GlobalInvocationID.x + 1]) { + + } + + // Front (z+1) if within bounds + if (z < ubo.sizeZ - 1 && vertex.pos[gl_GlobalInvocationID.x + ubo.sizeX * ubo.sizeY]) { + + } + + // Back (z-1) if within bounds + if (z > 0 && vertex.pos[gl_GlobalInvocationID.x - ubo.sizeX * ubo.sizeY]) { + + } + **/ \ No newline at end of file diff --git a/main.cpp b/main.cpp index 11b17ea..131bfd8 100644 --- a/main.cpp +++ b/main.cpp @@ -31,8 +31,8 @@ import Crafter.Event; import Crafter.Math; using namespace Crafter; -typedef VulkanShader<"MeshShaderHeightmapRGBA.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT, 2, {{{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}}}> MeshVulkanShader; -typedef VulkanShader<"FragmentShaderVertexColor.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT, 0, {}> FragmentShader; +typedef VulkanShader<"MeshShaderMixedVoxelGrid.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT, 2, {{{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}}}> MeshVulkanShader; +typedef VulkanShader<"FragmentShaderSolidWhite.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT, 0, {}> FragmentShader; typedef VulkanPipeline Pipeline; int main() { @@ -44,21 +44,16 @@ int main() { WindowWaylandVulkan window("Crafter.Graphics", 1280, 720); Camera camera(1.57079633, 1280.0f / 720.0f, 0.01, 512); - camera.view = MatrixRowMajor::Translation(0, 2, -10); + camera.view = MatrixRowMajor::Translation(0, 0, 10); camera.Update(); VkCommandBuffer cmd = window.StartInit(); DescriptorSet descriptors; - HeightmapShader meshShader(4, 2, 1, &camera); - for(uint32_t i = 0; i < 1*1*4*64; i++) { - meshShader.heights.value[i].height = -0.5; - meshShader.heights.value[i].r = 255; - meshShader.heights.value[i].g = 255; - meshShader.heights.value[i].b = 255; - meshShader.heights.value[i].a = 255; + VoxelShader meshShader(1, 4, 4, &camera); + for(uint32_t i = 0; i < 16; i++) { + meshShader.grid.value[i] = 1; } - meshShader.WriteDescriptors(descriptors.set[0]); meshShader.Update(); diff --git a/project.json b/project.json index d7c55ab..0ed779a 100644 --- a/project.json +++ b/project.json @@ -6,7 +6,7 @@ "standard": "c++26", "source_files": ["Crafter.Graphics-Window","Crafter.Graphics-WindowWayland","Crafter.Graphics-WindowWaylandWayland", "Crafter.Graphics-UiElement", "Crafter.Graphics-VulkanDevice", "Crafter.Graphics-WindowWaylandVulkan", "VulkanBuffer", "VulkanTools", "Crafter.Graphics-Camera"], "c_files": ["wayland-xdg-decoration-unstable-v1-client-protocol", "xdg-shell-protocol", "shm"], - "module_files": ["Crafter.Graphics-Window","Crafter.Graphics-WindowWayland","Crafter.Graphics-WindowWaylandWayland", "Crafter.Graphics", "Crafter.Graphics-UiElement", "Crafter.Graphics-Types", "Crafter.Graphics-VulkanDevice", "Crafter.Graphics-VulkanPipeline", "Crafter.Graphics-VulkanShader", "Crafter.Graphics-WindowWaylandVulkan", "Crafter.Graphics-Camera", "Crafter.Graphics-VulkanBuffer", "Crafter.Graphics-Mesh", "Crafter.Graphics-MeshShader", "Crafter.Graphics-HeightmapShader", "Crafter.Graphics-VulkanTexture", "Crafter.Graphics-TextureShader", "Crafter.Graphics-DescriptorSet"], + "module_files": ["Crafter.Graphics-Window","Crafter.Graphics-WindowWayland","Crafter.Graphics-WindowWaylandWayland", "Crafter.Graphics", "Crafter.Graphics-UiElement", "Crafter.Graphics-Types", "Crafter.Graphics-VulkanDevice", "Crafter.Graphics-VulkanPipeline", "Crafter.Graphics-VulkanShader", "Crafter.Graphics-WindowWaylandVulkan", "Crafter.Graphics-Camera", "Crafter.Graphics-VulkanBuffer", "Crafter.Graphics-Mesh", "Crafter.Graphics-MeshShader", "Crafter.Graphics-HeightmapShader","Crafter.Graphics-VoxelShader", "Crafter.Graphics-VulkanTexture", "Crafter.Graphics-TextureShader", "Crafter.Graphics-DescriptorSet"], "build_dir": "build", "output_dir": "bin", "type":"library", @@ -33,6 +33,11 @@ "type":13, "entrypoint":"main" }, + { + "path":"MeshShaderMixedVoxelGrid.glsl", + "type":13, + "entrypoint":"main" + }, { "path":"FragmentShaderSolidWhite.glsl", "type":4,