Explorar el Código

add shadow rays on objects that are not simple blocks

Kolja Strohm hace 1 semana
padre
commit
40071d8a11

+ 22 - 14
FactoryCraft/Block.cpp

@@ -51,15 +51,14 @@ Block::~Block()
     }
 }
 
-void Block::beforeRender(
-    GraphicsApi* api, Shader* zVertexShader, Shader* zPixelShader)
+bool Block::tick(double time)
 {
     if (needRequestModelInfo)
     {
         needRequestModelInfo = 0;
         World::INSTANCE->zClient()->blockAPIRequest(location, "\0", 1);
     }
-    FactoryCraftModel::beforeRender(api, zVertexShader, zPixelShader);
+    return FactoryCraftModel::tick(time);
 }
 
 void Block::setFlow(char flowOptions, char distanceToSource)
@@ -105,6 +104,7 @@ void Block::api(char* message)
             flowOptions = message[1];
             distanceToSource = message[2];
             // TODO: update fluid gpu data
+            break;
         }
     case 3: // update passable and speed modifier
         {
@@ -132,20 +132,28 @@ void Block::setLightData(Direction dir, unsigned char* data, Chunk* zC)
     {
         zC->setLightChanged(1);
     }
-    int sum1 = 0;
-    int sum2 = 0;
-    int sum3 = 0;
+    int sum[6];
+    memset(sum, 0, 6 * sizeof(int));
+    int count = 0;
+    for (int i = 0; i < 6; i++)
+    {
+        bool notZero = 0;
+        for (int j = 0; j < 6; j++)
+        {
+            sum[j] += *(lightData + i * 6 + j);
+            notZero |= *(lightData + i * 6 + j) > 0;
+        }
+        if (notZero)
+        {
+            ++count;
+        }
+    }
+    unsigned char average[6];
     for (int i = 0; i < 6; i++)
     {
-        sum1 += *(lightData + i * 6 + 3);
-        sum2 += *(lightData + i * 6 + 4);
-        sum3 += *(lightData + i * 6 + 5);
+        sum[i] = count > 0 ? sum[i] / count : 0;
     }
-    unsigned char average[3];
-    average[0] = (unsigned char)(sum1 / 6);
-    average[1] = (unsigned char)(sum2 / 6);
-    average[2] = (unsigned char)(sum3 / 6);
-    setAverageLight(average);
+    setLightBuffer(average);
 }
 
 const unsigned char* Block::getLightData(Direction dir) const

+ 2 - 3
FactoryCraft/Block.h

@@ -29,9 +29,6 @@ protected:
     Direction frontDirection;
     ModelInfo* currentModelInfo;
 
-    void beforeRender(
-        GraphicsApi* api, Shader* zVertexShader, Shader* zPixelShader) override;
-
 public:
     Block(const BlockType* zType,
         Vec3<int> position,
@@ -46,6 +43,8 @@ public:
         Direction frontDirection);
     virtual ~Block();
 
+    bool tick(double time) override;
+
     void setFlow(char flowOptions, char distanceToSource);
     void api(char* message);
     void copyLightTo(Block* zB);

+ 7 - 7
FactoryCraft/ChunkAnyHit.hlsl

@@ -3,13 +3,6 @@
 [shader("anyhit")]
 void ChunkAnyHit(inout RayHits rayPayload, ChunkHitAttributes attrib)
 {
-    if (rayPayload.hitCount < 0)
-    { // shadow ray
-        rayPayload.hitCount = 0;
-        // TODO: transparent objects should lead to half shadows
-        AcceptHitAndEndSearch();
-        return;
-    }
     Texture2D<float4> texture = textures[attrib.textureId];
     float4 color = texture.SampleLevel(gSampler, attrib.texCoord, 0);
     if (color.w == 0.f)
@@ -17,6 +10,13 @@ void ChunkAnyHit(inout RayHits rayPayload, ChunkHitAttributes attrib)
         IgnoreHit();
         return;
     }
+    if (rayPayload.hitCount < 0)
+    { // shadow ray
+        rayPayload.hitCount = 0;
+        // TODO: transparent objects should lead to half shadows
+        AcceptHitAndEndSearch();
+        return;
+    }
     SingleHit hit;
     hit.color = color;
     hit.normal = attrib.normal;

+ 1 - 1
FactoryCraft/ChunkClosestHit.hlsl

@@ -28,7 +28,7 @@ void ChunkClosestHit(inout RayHits currentPayload, ChunkHitAttributes attrib)
         }
         else
         {
-            color = color * (0.5 + normalFactor / 2);
+            color = dayLightFactor * (0.5 + normalFactor / 2);
         }
         currentPayload.hits[i].dayLight = packLight(color);
     }

+ 48 - 69
FactoryCraft/ChunkIntersection.hlsl

@@ -19,27 +19,6 @@ ByteAddressBuffer lightBuffer : register(t1, space4);
 
 #define between(v1, vmin, vmax) (v1.x >= vmin.x && v1.x <= vmax.x && v1.y >= vmin.y && v1.y <= vmax.y && v1.z >= vmin.z && v1.z <= vmax.z)
 
-float3 getLight(int index)
-{
-    uint raw = lightBuffer.Load((index / 4) * 4);
-    uint shift = (index % 4) * 8;
-    float r = ((raw >> shift) & 0xFF) / 255.0;
-    shift += 8;
-    if (shift == 32)
-    {
-        raw = lightBuffer.Load((index / 4) * 4 + 4);
-        shift = 0;
-    }
-    float g = ((raw >> shift) & 0xFF) / 255.0;
-    shift += 8;
-    if (shift == 32)
-    {
-        raw = lightBuffer.Load((index / 4) * 4 + 4);
-        shift = 0;
-    }
-    float b = ((raw >> shift) & 0xFF) / 255.0;
-    return float3(r, g, b);
-}
 
 float3 interpolateLight(float3 topLeft, float3 topRight, float3 bottomLeft, float3 bottomRight, float2 coords)
 {
@@ -149,74 +128,74 @@ void ChunkIntersection()
                 case 0: // front | NORTH
                     intersectionAttributes.normal = float3(0, -1, 0);
                     intersectionAttributes.texCoord = float2(1 - (currentPos.x - floor(currentPos.x)), 1 - (currentPos.z - floor(currentPos.z)));
-                    topLeftDayLight = getLight(lightOffset + 0);
-                    topLeftDynamicLight = getLight(lightOffset + 3);
-                    topRightDayLight = getLight(lightOffset + 18);
-                    topRightDynamicLight = getLight(lightOffset + 21);
-                    bottomLeftDayLight = getLight(lightOffset + 24);
-                    bottomLeftDynamicLight = getLight(lightOffset + 27);
-                    bottomRightDayLight = getLight(lightOffset + 42);
-                    bottomRightDynamicLight = getLight(lightOffset + 45);
+                    topLeftDayLight = getLight(lightBuffer, lightOffset + 0);
+                    topLeftDynamicLight = getLight(lightBuffer, lightOffset + 3);
+                    topRightDayLight = getLight(lightBuffer, lightOffset + 18);
+                    topRightDynamicLight = getLight(lightBuffer, lightOffset + 21);
+                    bottomLeftDayLight = getLight(lightBuffer, lightOffset + 24);
+                    bottomLeftDynamicLight = getLight(lightBuffer, lightOffset + 27);
+                    bottomRightDayLight = getLight(lightBuffer, lightOffset + 42);
+                    bottomRightDynamicLight = getLight(lightBuffer, lightOffset + 45);
                     break;
                 case 1: // back | SOUTH
                     intersectionAttributes.normal = float3(0, 1, 0);
                     intersectionAttributes.texCoord = float2(currentPos.x - floor(currentPos.x), 1 - (currentPos.z - floor(currentPos.z)));
-                    topLeftDayLight = getLight(lightOffset + 12);
-                    topLeftDynamicLight = getLight(lightOffset + 15);
-                    topRightDayLight = getLight(lightOffset + 6);
-                    topRightDynamicLight = getLight(lightOffset + 9);
-                    bottomLeftDayLight = getLight(lightOffset + 36);
-                    bottomLeftDynamicLight = getLight(lightOffset + 39);
-                    bottomRightDayLight = getLight(lightOffset + 30);
-                    bottomRightDynamicLight = getLight(lightOffset + 33);
+                    topLeftDayLight = getLight(lightBuffer, lightOffset + 12);
+                    topLeftDynamicLight = getLight(lightBuffer, lightOffset + 15);
+                    topRightDayLight = getLight(lightBuffer, lightOffset + 6);
+                    topRightDynamicLight = getLight(lightBuffer, lightOffset + 9);
+                    bottomLeftDayLight = getLight(lightBuffer, lightOffset + 36);
+                    bottomLeftDynamicLight = getLight(lightBuffer, lightOffset + 39);
+                    bottomRightDayLight = getLight(lightBuffer, lightOffset + 30);
+                    bottomRightDynamicLight = getLight(lightBuffer, lightOffset + 33);
                     break;
                 case 2: // left | EAST
                     intersectionAttributes.normal = float3(1, 0, 0);
                     intersectionAttributes.texCoord = float2(1 - (currentPos.y - floor(currentPos.y)), 1 - (currentPos.z - floor(currentPos.z)));
-                    topLeftDayLight = getLight(lightOffset + 6);
-                    topLeftDynamicLight = getLight(lightOffset + 9);
-                    topRightDayLight = getLight(lightOffset + 0);
-                    topRightDynamicLight = getLight(lightOffset + 3);
-                    bottomLeftDayLight = getLight(lightOffset + 30);
-                    bottomLeftDynamicLight = getLight(lightOffset + 33);
-                    bottomRightDayLight = getLight(lightOffset + 24);
-                    bottomRightDynamicLight = getLight(lightOffset + 27);
+                    topLeftDayLight = getLight(lightBuffer, lightOffset + 6);
+                    topLeftDynamicLight = getLight(lightBuffer, lightOffset + 9);
+                    topRightDayLight = getLight(lightBuffer, lightOffset + 0);
+                    topRightDynamicLight = getLight(lightBuffer, lightOffset + 3);
+                    bottomLeftDayLight = getLight(lightBuffer, lightOffset + 30);
+                    bottomLeftDynamicLight = getLight(lightBuffer, lightOffset + 33);
+                    bottomRightDayLight = getLight(lightBuffer, lightOffset + 24);
+                    bottomRightDynamicLight = getLight(lightBuffer, lightOffset + 27);
                     break;
                 case 3: // right | WEST
                     intersectionAttributes.normal = float3(-1, 0, 0);
                     intersectionAttributes.texCoord = float2(currentPos.y - floor(currentPos.y), 1 - (currentPos.z - floor(currentPos.z)));
-                    topLeftDayLight = getLight(lightOffset + 18);
-                    topLeftDynamicLight = getLight(lightOffset + 21);
-                    topRightDayLight = getLight(lightOffset + 12);
-                    topRightDynamicLight = getLight(lightOffset + 15);
-                    bottomLeftDayLight = getLight(lightOffset + 42);
-                    bottomLeftDynamicLight = getLight(lightOffset + 45);
-                    bottomRightDayLight = getLight(lightOffset + 36);
-                    bottomRightDynamicLight = getLight(lightOffset + 39);
+                    topLeftDayLight = getLight(lightBuffer, lightOffset + 18);
+                    topLeftDynamicLight = getLight(lightBuffer, lightOffset + 21);
+                    topRightDayLight = getLight(lightBuffer, lightOffset + 12);
+                    topRightDynamicLight = getLight(lightBuffer, lightOffset + 15);
+                    bottomLeftDayLight = getLight(lightBuffer, lightOffset + 42);
+                    bottomLeftDynamicLight = getLight(lightBuffer, lightOffset + 45);
+                    bottomRightDayLight = getLight(lightBuffer, lightOffset + 36);
+                    bottomRightDynamicLight = getLight(lightBuffer, lightOffset + 39);
                     break;
                 case 4: // top
                     intersectionAttributes.normal = float3(0, 0, 1);
                     intersectionAttributes.texCoord = float2(1 - (currentPos.x - floor(currentPos.x)), 1 - (currentPos.y - floor(currentPos.y)));
-                    topLeftDayLight = getLight(lightOffset + 6);
-                    topLeftDynamicLight = getLight(lightOffset + 9);
-                    topRightDayLight = getLight(lightOffset + 12);
-                    topRightDynamicLight = getLight(lightOffset + 15);
-                    bottomLeftDayLight = getLight(lightOffset + 0);
-                    bottomLeftDynamicLight = getLight(lightOffset + 3);
-                    bottomRightDayLight = getLight(lightOffset + 18);
-                    bottomRightDynamicLight = getLight(lightOffset + 21);
+                    topLeftDayLight = getLight(lightBuffer, lightOffset + 6);
+                    topLeftDynamicLight = getLight(lightBuffer, lightOffset + 9);
+                    topRightDayLight = getLight(lightBuffer, lightOffset + 12);
+                    topRightDynamicLight = getLight(lightBuffer, lightOffset + 15);
+                    bottomLeftDayLight = getLight(lightBuffer, lightOffset + 0);
+                    bottomLeftDynamicLight = getLight(lightBuffer, lightOffset + 3);
+                    bottomRightDayLight = getLight(lightBuffer, lightOffset + 18);
+                    bottomRightDynamicLight = getLight(lightBuffer, lightOffset + 21);
                     break;
                 case 5: // bottom
                     intersectionAttributes.normal = float3(0, 0, -1);
                     intersectionAttributes.texCoord = float2(1 - (currentPos.x - floor(currentPos.x)), currentPos.y - floor(currentPos.y));
-                    topLeftDayLight = getLight(lightOffset + 24);
-                    topLeftDynamicLight = getLight(lightOffset + 27);
-                    topRightDayLight = getLight(lightOffset + 42);
-                    topRightDynamicLight = getLight(lightOffset + 45);
-                    bottomLeftDayLight = getLight(lightOffset + 30);
-                    bottomLeftDynamicLight = getLight(lightOffset + 33);
-                    bottomRightDayLight = getLight(lightOffset + 36);
-                    bottomRightDynamicLight = getLight(lightOffset + 39);
+                    topLeftDayLight = getLight(lightBuffer, lightOffset + 24);
+                    topLeftDynamicLight = getLight(lightBuffer, lightOffset + 27);
+                    topRightDayLight = getLight(lightBuffer, lightOffset + 42);
+                    topRightDynamicLight = getLight(lightBuffer, lightOffset + 45);
+                    bottomLeftDayLight = getLight(lightBuffer, lightOffset + 30);
+                    bottomLeftDynamicLight = getLight(lightBuffer, lightOffset + 33);
+                    bottomRightDayLight = getLight(lightBuffer, lightOffset + 36);
+                    bottomRightDynamicLight = getLight(lightBuffer, lightOffset + 39);
                     break;
             }
             intersectionAttributes.dayLight = packLight(interpolateLight(topLeftDayLight, topRightDayLight, bottomLeftDayLight, bottomRightDayLight, intersectionAttributes.texCoord));

+ 23 - 1
FactoryCraft/Common.hlsl

@@ -120,4 +120,26 @@ cbuffer RayGenerationSettings : register(b0, space0)
     float maxDistance;
     float4x4 inverseView;
     float4x4 inverseProjection;
-};
+};
+
+float3 getLight(ByteAddressBuffer lightBuffer, int index)
+{
+    uint raw = lightBuffer.Load((index / 4) * 4);
+    uint shift = (index % 4) * 8;
+    float r = ((raw >> shift) & 0xFF) / 255.0;
+    shift += 8;
+    if (shift == 32)
+    {
+        raw = lightBuffer.Load((index / 4) * 4 + 4);
+        shift = 0;
+    }
+    float g = ((raw >> shift) & 0xFF) / 255.0;
+    shift += 8;
+    if (shift == 32)
+    {
+        raw = lightBuffer.Load((index / 4) * 4 + 4);
+        shift = 0;
+    }
+    float b = ((raw >> shift) & 0xFF) / 255.0;
+    return float3(r, g, b);
+}

+ 58 - 1
FactoryCraft/CustomDX12API.cpp

@@ -23,7 +23,21 @@ using namespace Framework;
 
 CustomDX12API::CustomDX12API()
     : DirectX12(),
-      lightInfoBuffer(0)
+      sbtChunkTextureIdBufferOffset(0),
+      sbtChunkIndexBufferOffset(0),
+      sbtChunkDataBufferOffset(0),
+      sbtChunkLightBufferOffset(0),
+      sbtSimpleBlocksTextureIdBufferOffset(0),
+      sbtSimpleBlocksIndexBufferOffset(0),
+      sbtSimpleBlocksVertexDataBufferOffset(0),
+      sbtSimpleBlocksIndexOffsetBufferOffset(0),
+      sbtSimpleBlocksLightBufferOffset(0),
+      sbtDefaultLightBufferOffset(0),
+      globalLightBufferOffset(0),
+      chunkHitGroup(0),
+      simpleBlocksHitGroup(0),
+      lightInfoBuffer(0),
+      defaultLightBuffer(0)
 {}
 
 CustomDX12API::~CustomDX12API()
@@ -32,6 +46,10 @@ CustomDX12API::~CustomDX12API()
     {
         lightInfoBuffer->release();
     }
+    if (defaultLightBuffer)
+    {
+        defaultLightBuffer->release();
+    }
 }
 
 void CustomDX12API::initializePipeline()
@@ -45,6 +63,17 @@ void CustomDX12API::initializePipeline()
         lightInfoBuffer->setData(&lightInfo, 1);
         lightInfoBuffer->setLength(sizeof(DX12ShaderLightInfo));
     }
+    if (!defaultLightBuffer)
+    {
+        defaultLightBuffer = new DX12Buffer(sizeof(unsigned char),
+            device,
+            dynamic_cast<DX12CommandQueue*>(directCommandQueue->getThis()),
+            D3D12_RESOURCE_FLAG_NONE);
+        defaultLightBuffer->setLength(6);
+        unsigned char defaultLight[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+        defaultLightBuffer->setData(defaultLight, 1);
+        defaultLightBuffer->copyToGPU();
+    }
     if (pipeline->getShaders().getEntryCount() == 0)
     { // add default shaders
         pipeline->zGlobalSignature()->addRegisterUsageLinkedToDescriptorHeap(
@@ -101,6 +130,9 @@ void CustomDX12API::initializePipeline()
         sbtPolygonSizeBufferOffset
             = hitSignature->addRegisterUsageLinkedToShaderBindingTable(
                 DX12_SHADER_REGISTER_T_SHADER_RESOURCE, 1, 5);
+        sbtDefaultLightBufferOffset
+            = hitSignature->addRegisterUsageLinkedToShaderBindingTable(
+                DX12_SHADER_REGISTER_T_SHADER_RESOURCE, 1, 6);
         DX12Shader* anyHitShader = new DX12Shader(
             CustomDefaultAnyHitShader, sizeof(CustomDefaultAnyHitShader));
         DX12ShaderFunction* anyHitFunction = new DX12ShaderFunction(
@@ -196,6 +228,10 @@ void CustomDX12API::initializePipeline()
             = simpleBlocksHitSignature
                   ->addRegisterUsageLinkedToShaderBindingTable(
                       DX12_SHADER_REGISTER_T_SHADER_RESOURCE, 1, 5);
+        sbtSimpleBlocksLightBufferOffset
+            = simpleBlocksHitSignature
+                  ->addRegisterUsageLinkedToShaderBindingTable(
+                      DX12_SHADER_REGISTER_T_SHADER_RESOURCE, 1, 6);
 
         DX12Shader* simpleBlocksAnyHitShader
             = new DX12Shader(CustomSimpleBlocksAnyHitShader,
@@ -243,6 +279,22 @@ void CustomDX12API::fillShaderBindingTable(
 {
     DirectX12::fillShaderBindingTable(
         zShaderBindingTable, zModel, objectIndex, zBLAS, lastHitGroupIndex);
+    FactoryCraftModel* fcmdl = dynamic_cast<FactoryCraftModel*>(zModel);
+    if (fcmdl)
+    {
+        fcmdl->zLightBuffer()->copyToGPU();
+        zShaderBindingTable->setHitGroupShaderInput(lastHitGroupIndex,
+            sbtDefaultLightBufferOffset,
+            dynamic_cast<DX12Buffer*>(fcmdl->zLightBuffer())
+                ->zBuffer()
+                ->GetGPUVirtualAddress());
+    }
+    else
+    {
+        zShaderBindingTable->setHitGroupShaderInput(lastHitGroupIndex,
+            sbtDefaultLightBufferOffset,
+            defaultLightBuffer->zBuffer()->GetGPUVirtualAddress());
+    }
 }
 
 int CustomDX12API::fillGlobalShaderParams(
@@ -339,6 +391,11 @@ void CustomDX12API::renderWorld(Framework::World3D* zWorld,
                             chunkData->zCustomBlocksIndexOffsetBuffer()
                                 ->zBuffer()
                                 ->GetGPUVirtualAddress());
+                        zSBT->setHitGroupShaderInput(hitGroupOffset,
+                            sbtDefaultLightBufferOffset,
+                            chunkData->zCustomBlocksLightBuffer()
+                                ->zBuffer()
+                                ->GetGPUVirtualAddress());
                     }
                     chunkData->setCustomBufferChanged(0);
                     ++objectIndex;

+ 5 - 2
FactoryCraft/CustomDX12API.h

@@ -8,9 +8,9 @@
 struct DX12ShaderLightInfo
 {
     Framework::Vec3<float> dayLightFactor;
-    unsigned int padding; // Padding to align to 16 bytes
+    unsigned int padding = 0; // Padding to align to 16 bytes
     Framework::Vec3<float> dayLightDirection;
-    unsigned int padding2; // Padding to align to 16 bytes
+    unsigned int padding2 = 0; // Padding to align to 16 bytes
 };
 
 class CustomDX12API : public Framework::DirectX12
@@ -24,11 +24,14 @@ private:
     int* sbtSimpleBlocksIndexBufferOffset;
     int* sbtSimpleBlocksVertexDataBufferOffset;
     int* sbtSimpleBlocksIndexOffsetBufferOffset;
+    int* sbtSimpleBlocksLightBufferOffset;
+    int* sbtDefaultLightBufferOffset;
     int* globalLightBufferOffset;
     Framework::DX12ShaderHitGroup* chunkHitGroup;
     Framework::DX12ShaderHitGroup* simpleBlocksHitGroup;
     Framework::DX12Buffer* lightInfoBuffer;
     DX12ShaderLightInfo lightInfo;
+    Framework::DX12Buffer* defaultLightBuffer;
 
 public:
     CustomDX12API();

+ 89 - 11
FactoryCraft/DX12ChunkData.cpp

@@ -22,7 +22,10 @@ DX12ChunkData::DX12ChunkData(Framework::Point center)
       customBlocksCombinedIndexBuffer(0),
       customBlocksVertexDataBuffer(0),
       customBlocksIndexOffsetBuffer(0),
-      customBlockMatrixBuffer(0),
+      customBlocksMatrixBuffer(0),
+      customLightBuffer(0),
+      customLightBufferSize(0),
+      customBlocksLightBuffer(0),
       lastObjectIndex(-1),
       lastCustomObjectIndex(-1),
       lastHitGroupIndex(-1),
@@ -99,15 +102,20 @@ DX12ChunkData::~DX12ChunkData()
     {
         customBlocksIndexOffsetBuffer->release();
     }
-    if (customBlockMatrixBuffer)
+    if (customBlocksMatrixBuffer)
     {
-        customBlockMatrixBuffer->release();
+        customBlocksMatrixBuffer->release();
+    }
+    if (customBlocksLightBuffer)
+    {
+        customBlocksLightBuffer->release();
     }
     if (dxLightBuffer)
     {
         dxLightBuffer->release();
     }
     delete[] lightBuffer;
+    delete[] customLightBuffer;
     delete[] blockIndices;
 }
 
@@ -161,6 +169,11 @@ Framework::DX12Buffer* DX12ChunkData::zCustomBlocksIndexOffsetBuffer() const
     return customBlocksIndexOffsetBuffer;
 }
 
+Framework::DX12Buffer* DX12ChunkData::zCustomBlocksLightBuffer() const
+{
+    return customBlocksLightBuffer;
+}
+
 void DX12ChunkData::setBlock(int index, Block* zBlock)
 {
     cs.lock();
@@ -289,6 +302,7 @@ void DX12ChunkData::setBlock(int index, Block* zBlock)
 
 void DX12ChunkData::updateLightning(Chunk* zChunk)
 {
+    // simple blocks
     int neededSize = textureIds.getEntryCount() * 8;
     if (neededSize > lightBufferSize)
     {
@@ -412,6 +426,53 @@ void DX12ChunkData::updateLightning(Chunk* zChunk)
         dxLightBuffer->setChanged();
         dxLightBuffer->copyToGPU();
     }
+    // custom blocks
+    neededSize = customBlocks.getEntryCount() * 6;
+    if (neededSize >= customLightBufferSize)
+    {
+        delete[] customLightBuffer;
+        customLightBuffer = new unsigned char[neededSize];
+        customLightBufferSize = neededSize;
+        if (customBlocksLightBuffer)
+        {
+            customBlocksLightBuffer->setData(customLightBuffer, 1);
+            customBlocksLightBuffer->setLength(neededSize);
+        }
+    }
+    int index = 0;
+    for (const Block* zBlock : customBlocks)
+    {
+        int offset = index * 6;
+        int lightData[6];
+        memset(lightData, 0, sizeof(int) * 6);
+        int count = 0;
+        for (int d = 0; d < 6; ++d)
+        {
+            const unsigned char* currentLight
+                = zBlock->getLightData(getDirectionFromIndex(d));
+            bool notZero = 0;
+            for (int i = 0; i < 6; ++i)
+            {
+                lightData[i] += (int)currentLight[i];
+                notZero |= currentLight[i] > 0;
+            }
+            if (notZero)
+            {
+                ++count;
+            }
+        }
+        for (int k = 0; k < 6; ++k)
+        {
+            customLightBuffer[offset + k]
+                = count > 0 ? (unsigned char)(lightData[k] / count) : 0;
+        }
+        ++index;
+    }
+    if (customBlocksLightBuffer)
+    {
+        customBlocksLightBuffer->setChanged();
+        customBlocksLightBuffer->copyToGPU();
+    }
 }
 
 struct ModelIdMapping
@@ -616,20 +677,20 @@ void DX12ChunkData::updateBuffers(
                 12 * sizeof(float));
             ++blockIndex;
         }
-        if (!customBlockMatrixBuffer)
+        if (!customBlocksMatrixBuffer)
         {
-            customBlockMatrixBuffer = new DX12Buffer(sizeof(float) * 12,
+            customBlocksMatrixBuffer = new DX12Buffer(sizeof(float) * 12,
                 zDevice,
                 dynamic_cast<DX12CommandQueue*>(zQueue->getThis()),
                 D3D12_RESOURCE_FLAG_NONE);
         }
-        customBlockMatrixBuffer->setLength(
+        customBlocksMatrixBuffer->setLength(
             sizeof(float) * 12 * customBlocks.getEntryCount());
-        customBlockMatrixBuffer->setData(matrixDataBuffer, 1);
-        customBlockMatrixBuffer->copyToGPU();
+        customBlocksMatrixBuffer->setData(matrixDataBuffer, 1);
+        customBlocksMatrixBuffer->copyToGPU();
         CD3DX12_RESOURCE_BARRIER transition
             = CD3DX12_RESOURCE_BARRIER::Transition(
-                customBlockMatrixBuffer->zBuffer(),
+                customBlocksMatrixBuffer->zBuffer(),
                 D3D12_RESOURCE_STATE_COMMON,
                 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
         zQueue->zCommandList()->ResourceBarrier(1, &transition);
@@ -718,7 +779,7 @@ void DX12ChunkData::updateBuffers(
                 = (unsigned)iBuffer->getElementCount();
 
             simpleBlockDescs[index].Triangles.Transform3x4
-                = customBlockMatrixBuffer->zBuffer()->GetGPUVirtualAddress()
+                = customBlocksMatrixBuffer->zBuffer()->GetGPUVirtualAddress()
                 + 12 * index * sizeof(float);
             cbts[index] = block->zTexture()->zPolygonTexture(0)->getId();
             indexOffsets[index] = mapping.indexBufferOffset;
@@ -871,12 +932,29 @@ void DX12ChunkData::updateBuffers(
                 = max(textureIds.getEntryCount() * 8, 6 * 8 * 16 * 16 * 2);
             lightBuffer = new unsigned char[neededSize];
             lightBufferSize = neededSize;
-            memset(lightBuffer, -1, lightBufferSize);
+            memset(lightBuffer, 0, lightBufferSize);
         }
         dxLightBuffer->setData(lightBuffer, 1);
         dxLightBuffer->setLength(lightBufferSize);
         dxLightBuffer->copyToGPU();
     }
+    if (!customBlocksLightBuffer)
+    {
+        customBlocksLightBuffer = new DX12Buffer(sizeof(unsigned char),
+            zDevice,
+            dynamic_cast<DX12CommandQueue*>(zQueue->getThis()),
+            D3D12_RESOURCE_FLAG_NONE);
+        if (!customLightBuffer)
+        {
+            int neededSize = max(customBlocks.getEntryCount() * 6, 6);
+            customLightBuffer = new unsigned char[neededSize];
+            customLightBufferSize = neededSize;
+            memset(customLightBuffer, 0, customLightBufferSize);
+        }
+        customBlocksLightBuffer->setData(customLightBuffer, 1);
+        customBlocksLightBuffer->setLength(customLightBufferSize);
+        customBlocksLightBuffer->copyToGPU();
+    }
     cs.unlock();
 }
 

+ 5 - 1
FactoryCraft/DX12ChunkData.h

@@ -34,7 +34,10 @@ private:
     Framework::DX12Buffer* customBlocksCombinedIndexBuffer;
     Framework::DX12Buffer* customBlocksVertexDataBuffer;
     Framework::DX12Buffer* customBlocksIndexOffsetBuffer;
-    Framework::DX12Buffer* customBlockMatrixBuffer;
+    Framework::DX12Buffer* customBlocksMatrixBuffer;
+    unsigned char* customLightBuffer;
+    int customLightBufferSize;
+    Framework::DX12Buffer* customBlocksLightBuffer;
     RCArray<Block> customBlocks;
     Framework::Point chunkCenter;
     int* blockIndices;
@@ -65,6 +68,7 @@ public:
     Framework::DX12Buffer* zCustomBlocksVertexDataBuffer() const;
     Framework::DX12Buffer* zCustomBlocksCombinedIndexBuffer() const;
     Framework::DX12Buffer* zCustomBlocksIndexOffsetBuffer() const;
+    Framework::DX12Buffer* zCustomBlocksLightBuffer() const;
     void setBlock(int index, Block* zBlock);
     void updateLightning(Chunk* zChunk);
     void updateBuffers(

+ 10 - 9
FactoryCraft/DefaultAnyHit.hlsl

@@ -4,17 +4,11 @@ StructuredBuffer<int> textureIdBuffer : register(t1, space2);
 StructuredBuffer<int> indexBuffer : register(t1, space3);
 StructuredBuffer<VertexData> vertexData : register(t1, space4);
 StructuredBuffer<int> polygonSizeBuffer : register(t1, space5);
+ByteAddressBuffer lightBuffer : register(t1, space6);
 
 [shader("anyhit")]
 void AnyHit(inout RayHits rayPayload, SimpleBlocksAttributes attrib)
 {
-    if (rayPayload.hitCount < 0)
-    { // shadow ray
-        rayPayload.hitCount = 0;
-        // TODO: transparent objects should lead to half shadows
-        AcceptHitAndEndSearch();
-        return;
-    }
     int instanceId = InstanceID();
     int currentTriangle = PrimitiveIndex();
     int textureId = 0;
@@ -51,12 +45,19 @@ void AnyHit(inout RayHits rayPayload, SimpleBlocksAttributes attrib)
         IgnoreHit();
         return;
     }
+    if (rayPayload.hitCount < 0)
+    { // shadow ray
+        rayPayload.hitCount = 0;
+        // TODO: transparent objects should lead to half shadows
+        AcceptHitAndEndSearch();
+        return;
+    }
     SingleHit hit;
     hit.color = color;
     hit.normal = normal;
     hit.distance = RayTCurrent();
-    hit.dayLight = 0xFFFFFF;
-    hit.dynamicLight = 0xFFFFFF;
+    hit.dayLight = getLight(lightBuffer, 0);
+    hit.dynamicLight = getLight(lightBuffer, 3);
     applyHit(rayPayload, hit);
     if (color.w < 1.f)
     {

+ 31 - 2
FactoryCraft/DefaultClosestHit.hlsl

@@ -6,7 +6,36 @@ StructuredBuffer<VertexData> vertexData : register(t1, space4);
 StructuredBuffer<int> polygonSizeBuffer : register(t1, space5);
 
 [shader("closesthit")]
-void ClosestHit(inout RayHits rayPayload, SimpleBlocksAttributes attrib)
+void ClosestHit(inout RayHits currentPayload, SimpleBlocksAttributes attrib)
 {
-    // TODO: reflection rays and shadow rays ...
+    if (currentPayload.hitCount == 0)
+    {
+        return; // already inside of shadow ray
+    }
+    RayHits tmpPayload;
+    // shadow rays
+    for (int i = 0; i < currentPayload.hitCount; i++)
+    {
+        tmpPayload.hitCount = -1; // shadow ray
+        RayDesc ray;
+        ray.Origin = WorldRayOrigin() + (currentPayload.hits[i].distance - 0.001) * WorldRayDirection();
+        ray.Direction = dayLightDirection;
+        ray.TMin = 0.00001;
+        ray.TMax = 1000;
+        TraceRay(TLAS,
+            0, 0xFF, 0,
+           0, 0, ray, tmpPayload);
+        float normalFactor = saturate(dot(normalize(currentPayload.hits[i].normal), normalize(dayLightDirection)));
+        float3 color = unpackLight(currentPayload.hits[i].dayLight) * dayLightFactor;
+        if (tmpPayload.hitCount == 0)
+        {
+            color = color / 2;
+        }
+        else
+        {
+            color = dayLightFactor * (0.5 + normalFactor / 2);
+        }
+        currentPayload.hits[i].dayLight = packLight(color);
+    }
+    // TODO: reflection rays
 }

+ 10 - 100
FactoryCraft/FactoryCraftModel.cpp

@@ -9,28 +9,17 @@
 FactoryCraftModel::FactoryCraftModel()
     : Model3D()
 {
-    vertexLightBuffer = 0;
-    lightBuffer = 0;
-    vertexLightBufferCount = 0;
-    visible = 1;
+    memset(lightBufferData, -1, 6);
+    lightBuffer = uiFactory.initParam.bildschirm->zGraphicsApi()
+                      ->createStructuredBuffer(1);
+    lightBuffer->setLength(6);
+    lightBuffer->setData(lightBufferData, 1);
     destroyedState = 0;
-    breakTextur
-        = uiFactory.initParam.bildschirm->zGraphicsApi()->createOrGetTexture(
-            "blocks.ltdb/crack.png", 0);
-    effectAlpha = 0;
-    memset(averageLight, 0, 8);
-    *(int*)averageLight = 0xFFFFFF00;
-    fallbackVertexLightBuffer = uiFactory.initParam.bildschirm->zGraphicsApi()
-                                    ->createStructuredBuffer(16);
-    fallbackVertexLightBuffer->setData(averageLight, 1);
 }
 
 FactoryCraftModel::~FactoryCraftModel()
 {
-    breakTextur->release();
-    if (vertexLightBuffer) vertexLightBuffer->release();
-    fallbackVertexLightBuffer->release();
-    delete[] lightBuffer;
+    if (lightBuffer) lightBuffer->release();
 }
 
 struct TexturEffect
@@ -39,102 +28,23 @@ struct TexturEffect
     float percentage;
 };
 
-void FactoryCraftModel::beforeRender(Framework::GraphicsApi* api,
-    Framework::Shader* zVertexShader,
-    Framework::Shader* zPixelShader)
+void FactoryCraftModel::setLightBuffer(unsigned char light[6])
 {
-    if (!World::INSTANCE) return;
-    CustomDX12API* cApi = dynamic_cast<CustomDX12API*>(api);
-    if (cApi)
-    {
-        /*
-        * TODO: set vertex and index and light buffer in shader binding table
-        char buffer[8];
-        *(int*)buffer
-            = vertexLightBufferCount == 0 ? 1 : vertexLightBufferCount;
-        *(float*)(buffer + 4) = World::INSTANCE->getDayLightFactor();
-        zVertexShader->fillConstBuffer(
-            buffer, cApi->getVertexShaderLightBufferIndex(), 8);
-        if (vertexLightBuffer)
-        {
-            vertexLightBuffer->copyToGPU();
-            cApi->setVertexLightBuffer(vertexLightBuffer);
-        }
-        else
-        {
-            fallbackVertexLightBuffer->copyToGPU(8);
-            cApi->setVertexLightBuffer(fallbackVertexLightBuffer);
-        }
-        if (destroyedState > 0 && effectAlpha)
-        {
-            TexturEffect e = {1, 1.f + destroyedState};
-            zPixelShader->fillConstBuffer((char*)&e, 3, sizeof(TexturEffect));
-        }*/
-    }
+    memcpy(lightBufferData, light, 6);
+    lightBuffer->setChanged();
 }
 
-void FactoryCraftModel::setVertexLightBuffer(__int64* data, int vertexCount)
-{
-    if (!vertexLightBuffer)
-    {
-        vertexLightBuffer = uiFactory.initParam.bildschirm->zGraphicsApi()
-                                ->createStructuredBuffer(16);
-    }
-    if (lightBuffer)
-    {
-        delete[] lightBuffer;
-    }
-    lightBuffer = data;
-    vertexLightBufferCount = vertexCount;
-    vertexLightBuffer->setData(data, 1);
-    vertexLightBuffer->setLength(vertexCount * 8);
-    vertexLightBuffer->setChanged();
-}
-
-__int64* FactoryCraftModel::zLightBuffer()
+Framework::DXBuffer* FactoryCraftModel::zLightBuffer() const
 {
     return lightBuffer;
 }
 
-void FactoryCraftModel::copyLightToGPU()
-{
-    vertexLightBuffer->setChanged();
-}
-
-void FactoryCraftModel::setVisible(bool visible)
-{
-    this->visible = visible;
-}
-
 void FactoryCraftModel::setDestroyedState(float percentage)
 {
     destroyedState = percentage;
 }
 
-void FactoryCraftModel::setUseEffectAlpha(bool useAlpha)
-{
-    effectAlpha = useAlpha;
-}
-
-bool FactoryCraftModel::needRenderPolygon(int index)
-{
-    return visible;
-}
-
-Texture* FactoryCraftModel::zEffectTexture()
-{
-    return destroyedState > 0 ? breakTextur : 0;
-}
-
 float FactoryCraftModel::getEffectPercentage()
 {
     return destroyedState;
 }
-
-void FactoryCraftModel::setAverageLight(unsigned char light[3])
-{
-    *(averageLight + 5) = light[2];
-    *(averageLight + 6) = light[1];
-    *(averageLight + 7) = light[0];
-    fallbackVertexLightBuffer->setChanged();
-}

+ 4 - 21
FactoryCraft/FactoryCraftModel.h

@@ -8,32 +8,15 @@
 class FactoryCraftModel : public Framework::Model3D
 {
 private:
-    Framework::DXBuffer* vertexLightBuffer;
-    Framework::DXBuffer* fallbackVertexLightBuffer;
-    __int64* lightBuffer;
-    int vertexLightBufferCount;
-    bool visible;
+    Framework::DXBuffer* lightBuffer;
+    unsigned char lightBufferData[6];
     float destroyedState;
-    Framework::Texture* breakTextur;
-    bool effectAlpha;
-    unsigned char averageLight[8];
-
-protected:
-    void beforeRender(Framework::GraphicsApi* api,
-        Framework::Shader* zVertexShader,
-        Framework::Shader* zPixelShader) override;
 
 public:
     FactoryCraftModel();
     ~FactoryCraftModel();
-    void setVertexLightBuffer(__int64* data, int vertexCount);
-    __int64* zLightBuffer();
-    void copyLightToGPU();
-    void setVisible(bool visible);
+    void setLightBuffer(unsigned char light[6]);
+    Framework::DXBuffer* zLightBuffer() const;
     void setDestroyedState(float percentage);
-    void setUseEffectAlpha(bool useAlpha);
-    bool needRenderPolygon(int index) override;
-    Framework::Texture* zEffectTexture() override;
     float getEffectPercentage() override;
-    void setAverageLight(unsigned char light[3]);
 };

+ 10 - 10
FactoryCraft/SimpleBlocksAnyHit.hlsl

@@ -4,19 +4,12 @@ StructuredBuffer<int> textureIdBuffer : register(t1, space2);
 StructuredBuffer<int> indexBuffer : register(t1, space3);
 StructuredBuffer<VertexData> vertexData : register(t1, space4);
 StructuredBuffer<int> indexOffsetBuffer : register(t1, space5);
+ByteAddressBuffer lightBuffer : register(t1, space6);
 
 
 [shader("anyhit")]
 void SimpleBlocksAnyHit(inout RayHits rayPayload, SimpleBlocksAttributes attrib)
 {
-    if (rayPayload.hitCount < 0)
-    { // shadow ray
-        rayPayload.hitCount = 0;
-        // TODO: transparent objects should lead to half shadows
-        AcceptHitAndEndSearch();
-        return;
-    }
-    int instanceId = InstanceID();
     int currentTriangle = PrimitiveIndex();
     int geometryIndex = GeometryIndex();
 
@@ -51,12 +44,19 @@ void SimpleBlocksAnyHit(inout RayHits rayPayload, SimpleBlocksAttributes attrib)
         IgnoreHit();
         return;
     }
+    if (rayPayload.hitCount < 0)
+    { // shadow ray
+        rayPayload.hitCount = 0;
+        // TODO: transparent objects should lead to half shadows
+        AcceptHitAndEndSearch();
+        return;
+    }
     SingleHit hit;
     hit.color = color;
     hit.normal = normal;
     hit.distance = RayTCurrent();
-    hit.dayLight = 0xFFFFFF;
-    hit.dynamicLight = 0xFFFFFF;
+    hit.dayLight = getLight(lightBuffer, geometryIndex * 6);
+    hit.dynamicLight = getLight(lightBuffer, geometryIndex * 6 + 3);
     applyHit(rayPayload, hit);
     if (color.w < 1.f)
     {

+ 31 - 2
FactoryCraft/SimpleBlocksClosestHit.hlsl

@@ -6,7 +6,36 @@ StructuredBuffer<VertexData> vertexData : register(t1, space4);
 StructuredBuffer<int> indexOffsetBuffer : register(t1, space5);
 
 [shader("closesthit")]
-void SimpleBlocksClosestHit(inout RayHits rayPayload, SimpleBlocksAttributes attrib)
+void SimpleBlocksClosestHit(inout RayHits currentPayload, SimpleBlocksAttributes attrib)
 {
-    // TODO: reflection rays and shadow rays ...
+    if (currentPayload.hitCount == 0)
+    {
+        return; // already inside of shadow ray
+    }
+    RayHits tmpPayload;
+    // shadow rays
+    for (int i = 0; i < currentPayload.hitCount; i++)
+    {
+        tmpPayload.hitCount = -1; // shadow ray
+        RayDesc ray;
+        ray.Origin = WorldRayOrigin() + (currentPayload.hits[i].distance - 0.001) * WorldRayDirection();
+        ray.Direction = dayLightDirection;
+        ray.TMin = 0.00001;
+        ray.TMax = 1000;
+        TraceRay(TLAS,
+            0, 0xFF, 0,
+           0, 0, ray, tmpPayload);
+        float normalFactor = saturate(dot(normalize(currentPayload.hits[i].normal), normalize(dayLightDirection)));
+        float3 color = unpackLight(currentPayload.hits[i].dayLight) * dayLightFactor;
+        if (tmpPayload.hitCount == 0)
+        {
+            color = color / 2;
+        }
+        else
+        {
+            color = dayLightFactor * (0.5 + normalFactor / 2);
+        }
+        currentPayload.hits[i].dayLight = packLight(color);
+    }
+    // TODO: reflection rays
 }

+ 3 - 7
FactoryCraft/World.cpp

@@ -44,10 +44,7 @@ World::World(Screen3D* zScreen, FactoryClient* client)
     nightLength = 0;
     selectionModel = new FactoryCraftModel();
     selectionModel->setModelData(zScreen->zGraphicsApi()->getModel("cube"));
-    selectionModel->setSize(1.005f);
-    selectionModel->setVisible(0);
-    unsigned char light[3] = {0xff, 0xff, 0xff};
-    selectionModel->setAverageLight(light);
+    selectionModel->setSize(0);
     selectionModel->setModelTextur(new Model3DTexture());
     for (int i = 0; i < 6; i++)
     {
@@ -56,7 +53,6 @@ World::World(Screen3D* zScreen, FactoryClient* client)
                 "data/textures/blocks.ltdb/selectedblock.p"));
     }
     selectionModel->setAlpha(1);
-    selectionModel->setUseEffectAlpha(1);
     renderedWorld->addDrawable(selectionModel);
     start();
 }
@@ -491,7 +487,7 @@ void World::setTarget(Framework::Model3D* zTarget)
         targetLock.lock();
         if (!zTarget)
         {
-            selectionModel->setVisible(0);
+            selectionModel->setSize(0);
         }
         else
         {
@@ -506,7 +502,7 @@ void World::setTarget(Framework::Model3D* zTarget)
             {
                 selectionModel->setDestroyedState(0);
             }
-            selectionModel->setVisible(1);
+            selectionModel->setSize(1.005f);
         }
         if (currentTarget)
         {