minecraft: hacky diffuse lighting

This commit is contained in:
Zack Buhman 2026-04-30 20:35:11 -05:00
parent e1db1bc978
commit 51167365d5
4 changed files with 43 additions and 26 deletions

View File

@ -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);

View File

@ -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> 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);
}

View File

@ -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);
}

View File

@ -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,20 +678,20 @@ 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);
VkDeviceSize vertexOffset{ 0 };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndex.buffer, &vertexOffset);
minecraft::vulkan::per_world const & world = worlds[0];
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 = worlds[0].regions[0].instanceCFG[configuration].count;
int first_instance = worlds[0].regions[0].instanceCFG[configuration].offset / perInstanceSize;
int instance_count = world.regions[region].instanceCFG[configuration].count;
int first_instance = world.regions[region].instanceCFG[configuration].offset / perInstanceSize;
if (instance_count == 0)
continue;
@ -696,4 +699,5 @@ namespace minecraft::vulkan {
vkCmdDrawIndexed(commandBuffer, index_count, instance_count, first_index, 0, first_instance);
};
}
}
}