From 51167365d5e16c26da12310dd5e66bba6ec941e7 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Thu, 30 Apr 2026 20:35:11 -0500 Subject: [PATCH] minecraft: hacky diffuse lighting --- include/minecraft/vulkan.h | 1 + shader/minecraft.hlsl | 23 ++++++++++++++++------ src/main.cpp | 5 +++-- src/minecraft/vulkan.cpp | 40 +++++++++++++++++++++----------------- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/include/minecraft/vulkan.h b/include/minecraft/vulkan.h index 772221a..46b2625 100644 --- a/include/minecraft/vulkan.h +++ b/include/minecraft/vulkan.h @@ -101,6 +101,7 @@ namespace minecraft::vulkan { void write_descriptor_sets(); void transfer_transforms(XMMATRIX const & projection, XMMATRIX const & view, + XMVECTOR const & lightPosition, uint32_t frameIndex); void load_image(char const * filename, Image & image); diff --git a/shader/minecraft.hlsl b/shader/minecraft.hlsl index 24e6ff5..4c4929e 100644 --- a/shader/minecraft.hlsl +++ b/shader/minecraft.hlsl @@ -14,6 +14,8 @@ struct VSInput struct VSOutput { float4 Position : SV_POSITION; + float4 WorldPosition : WorldPosition; + float3 Normal : NORMAL0; float4 Texture : TEXCOORD0; }; @@ -23,14 +25,14 @@ struct Scene column_major float4x4 View; column_major float4x4 ShadowProjection; column_major float4x4 ShadowView; - float4 LightPosition; // view space + float4 LightPosition; // world space }; // set 0: per-frame [[vk::binding(0, 0)]] ConstantBuffer Scene; // set 1: constant -[[vk::binding(0, 1)]] SamplerState LinearSampler; +[[vk::binding(0, 1)]] SamplerState ClosestSampler; [[vk::binding(1, 1)]] Texture2DArray ShadowTexture; [[vk::binding(2, 1)]] Texture2D TerrainTexture; @@ -43,8 +45,10 @@ float2 yf(float2 v, float scale) VSOutput VSMain(VSInput input) { VSOutput output = (VSOutput)0; - float4 Position = float4(input.Position.xyz + input.BlockPosition, 1.0); - output.Position = mul(Scene.Projection, mul(Scene.View, Position.xzyw)); + float4 Position = float4(input.Position.xyz + input.BlockPosition, 1.0).xzyw; + output.WorldPosition = Position; + output.Position = mul(Scene.Projection, mul(Scene.View, Position)); + output.Normal = input.Normal; float2 textureOffset = float2(input.TextureID % 8, input.TextureID / 8) * 16; output.Texture = float4(yf(input.Texture.xy, 16), textureOffset); @@ -55,7 +59,14 @@ VSOutput VSMain(VSInput input) float4 PSMain(VSOutput input) : SV_TARGET { float2 texture = input.Texture.xy + input.Texture.zw; - float4 color = TerrainTexture.Load(int3(texture, 0)).xyzw; + //float4 color = TerrainTexture.Load(int3(texture, 0)); + float4 color = TerrainTexture.Sample(ClosestSampler, texture * 0.0078125); - return float4(color.xyz, 1); + if (color.w < 0.5) + discard; + + float3 light_direction = normalize(Scene.LightPosition.xzy + float3(0, 100, 0) - input.WorldPosition.xyz); + float diffuse = max(dot(input.Normal, light_direction), 0.0); + + return float4(color.xyz * max(0.1, diffuse), 1.0); } diff --git a/src/main.cpp b/src/main.cpp index fd319a6..2c72290 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -635,9 +635,9 @@ int main() .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - .anisotropyEnable = VK_TRUE, + .anisotropyEnable = VK_FALSE, .maxAnisotropy = 16.0f, - .maxLod = VK_LOD_CLAMP_NONE, // (float)ddsFile->header.dwMipMapCount, + .maxLod = 3.0, // (float)ddsFile->header.dwMipMapCount, }; VK_CHECK(vkCreateSampler(device, &samplerCreateInfo2, nullptr, &textureSamplers[2])); @@ -824,6 +824,7 @@ int main() minecraft_state.transfer_transforms(projection, view, + lightPositionWorld, frameIndex); } diff --git a/src/minecraft/vulkan.cpp b/src/minecraft/vulkan.cpp index cc97b0b..db390a7 100644 --- a/src/minecraft/vulkan.cpp +++ b/src/minecraft/vulkan.cpp @@ -635,10 +635,13 @@ namespace minecraft::vulkan { void vulkan::transfer_transforms(XMMATRIX const & projection, XMMATRIX const & view, + XMVECTOR const & lightPosition, uint32_t frameIndex) { - XMStoreFloat4x4(&shaderDataDevice.frame[frameIndex].sceneMapped->projection, projection); - XMStoreFloat4x4(&shaderDataDevice.frame[frameIndex].sceneMapped->view, view); + Scene * scene = shaderDataDevice.frame[frameIndex].sceneMapped; + XMStoreFloat4x4(&scene->projection, projection); + XMStoreFloat4x4(&scene->view, view); + XMStoreFloat4(&scene->lightPosition, lightPosition); // flush constexpr int mappedMemoryRangesCount = 1; @@ -675,25 +678,26 @@ namespace minecraft::vulkan { 0, nullptr); vkCmdBindIndexBuffer(commandBuffer, vertexIndex.buffer, vertexIndex.indexOffset, VK_INDEX_TYPE_UINT16); - VkBuffer vertexBuffers[2]{ - vertexIndex.buffer, - worlds[0].regions[0].vertexBuffer, - }; - VkDeviceSize vertexOffsets[2]{ 0, 0 }; - - vkCmdBindVertexBuffers(commandBuffer, 0, 2, vertexBuffers, vertexOffsets); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - for (int configuration = 1; configuration < 64; configuration++) { - int index_count = 6 * popcount(configuration); - int first_index = index_buffer_configuration_offsets[configuration]; - int instance_count = worlds[0].regions[0].instanceCFG[configuration].count; - int first_instance = worlds[0].regions[0].instanceCFG[configuration].offset / perInstanceSize; + VkDeviceSize vertexOffset{ 0 }; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndex.buffer, &vertexOffset); - if (instance_count == 0) - continue; + minecraft::vulkan::per_world const & world = worlds[0]; - vkCmdDrawIndexed(commandBuffer, index_count, instance_count, first_index, 0, first_instance); - }; + for (int region = 0; region < world.descriptor->region_count; region++) { + vkCmdBindVertexBuffers(commandBuffer, 1, 1, &world.regions[region].vertexBuffer, &vertexOffset); + for (int configuration = 1; configuration < 64; configuration++) { + int index_count = 6 * popcount(configuration); + int first_index = index_buffer_configuration_offsets[configuration]; + int instance_count = world.regions[region].instanceCFG[configuration].count; + int first_instance = world.regions[region].instanceCFG[configuration].offset / perInstanceSize; + + if (instance_count == 0) + continue; + + vkCmdDrawIndexed(commandBuffer, index_count, instance_count, first_index, 0, first_instance); + }; + } } }