Support lighting using a graphics buffer that is kep open!
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,14 @@
|
|||||||
#ifndef ROOT_CONSTANTS_HLSL
|
#ifndef ROOT_CONSTANTS_HLSL
|
||||||
#define ROOT_CONSTANTS_HLSL
|
#define ROOT_CONSTANTS_HLSL
|
||||||
|
|
||||||
|
struct PointLight
|
||||||
|
{
|
||||||
|
float3 Position;
|
||||||
|
float Radius;
|
||||||
|
float3 Color;
|
||||||
|
float Intensity;
|
||||||
|
};
|
||||||
|
|
||||||
cbuffer RootConstants : register(b0, space0)
|
cbuffer RootConstants : register(b0, space0)
|
||||||
{
|
{
|
||||||
row_major float4x4 ViewProjection;
|
row_major float4x4 ViewProjection;
|
||||||
@@ -16,6 +24,9 @@ cbuffer RootConstants : register(b0, space0)
|
|||||||
float LightPad;
|
float LightPad;
|
||||||
float3 LightColor;
|
float3 LightColor;
|
||||||
float AmbientIntensity;
|
float AmbientIntensity;
|
||||||
|
|
||||||
|
uint LightBufferIndex;
|
||||||
|
uint ActiveLightCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,46 @@
|
|||||||
#include "RootConstants.hlsl"
|
#include "RootConstants.hlsl"
|
||||||
|
|
||||||
float4 main(float4 Color : TEXCOORD0, float3 WorldNormal : TEXCOORD1) : SV_Target0
|
struct Input
|
||||||
{
|
{
|
||||||
float3 N = normalize(WorldNormal);
|
float4 Color : TEXCOORD0;
|
||||||
float NdotL = saturate(dot(N, -LightDirection));
|
float3 WorldNormal : TEXCOORD1;
|
||||||
float3 diffuse = Color.rgb * LightColor * NdotL;
|
float3 WorldPosition : TEXCOORD2;
|
||||||
float3 ambient = Color.rgb * AmbientIntensity;
|
};
|
||||||
return float4(diffuse + ambient, Color.a);
|
|
||||||
|
float4 main(Input input) : SV_Target0
|
||||||
|
{
|
||||||
|
float3 normal = normalize(input.WorldNormal);
|
||||||
|
|
||||||
|
// Initial ambient component
|
||||||
|
float3 result = input.Color.rgb * LightColor * AmbientIntensity;
|
||||||
|
|
||||||
|
// Directional light contribution
|
||||||
|
float ndotl = max(dot(normal, -LightDirection), 0.0);
|
||||||
|
result += input.Color.rgb * LightColor * ndotl;
|
||||||
|
|
||||||
|
// Point lights
|
||||||
|
if (ActiveLightCount > 0)
|
||||||
|
{
|
||||||
|
StructuredBuffer<PointLight> pointLights = ResourceDescriptorHeap[LightBufferIndex];
|
||||||
|
|
||||||
|
for (uint i = 0; i < ActiveLightCount; ++i)
|
||||||
|
{
|
||||||
|
PointLight light = pointLights[i];
|
||||||
|
|
||||||
|
float3 lightDir = light.Position - input.WorldPosition;
|
||||||
|
float dist = length(lightDir);
|
||||||
|
|
||||||
|
if (dist < light.Radius)
|
||||||
|
{
|
||||||
|
lightDir = normalize(lightDir);
|
||||||
|
float attenuation = 1.0 - (dist / light.Radius);
|
||||||
|
attenuation = max(attenuation, 0.0);
|
||||||
|
|
||||||
|
float pndotl = max(dot(normal, lightDir), 0.0);
|
||||||
|
result += light.Color * input.Color.rgb * pndotl * attenuation * light.Intensity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return float4(result, input.Color.a);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ struct Output
|
|||||||
{
|
{
|
||||||
float4 Color : TEXCOORD0;
|
float4 Color : TEXCOORD0;
|
||||||
float3 WorldNormal : TEXCOORD1;
|
float3 WorldNormal : TEXCOORD1;
|
||||||
|
float3 WorldPosition : TEXCOORD2;
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -20,8 +21,10 @@ Output main(uint vertexIndex : SV_VertexID)
|
|||||||
float3 normal = asfloat(buffer.Load3(offset + 12));
|
float3 normal = asfloat(buffer.Load3(offset + 12));
|
||||||
float4 col = asfloat(buffer.Load4(offset + 24));
|
float4 col = asfloat(buffer.Load4(offset + 24));
|
||||||
|
|
||||||
output.Position = mul(ViewProjection, mul(Model, float4(pos, 1.0f)));
|
float4 worldPos = mul(Model, float4(pos, 1.0f));
|
||||||
|
output.Position = mul(ViewProjection, worldPos);
|
||||||
output.Color = col;
|
output.Color = col;
|
||||||
|
output.WorldPosition = worldPos.xyz;
|
||||||
|
|
||||||
float3 worldNormal = mul((float3x3)Model, normal);
|
float3 worldNormal = mul((float3x3)Model, normal);
|
||||||
output.WorldNormal = worldNormal;
|
output.WorldNormal = worldNormal;
|
||||||
|
|||||||
@@ -193,11 +193,16 @@ namespace Juliet
|
|||||||
{
|
{
|
||||||
Assert(Arena);
|
Assert(Arena);
|
||||||
|
|
||||||
ArenaClear(Arena);
|
if (InternalArena)
|
||||||
|
{
|
||||||
|
ArenaClear(Arena);
|
||||||
|
Data = nullptr;
|
||||||
|
Capacity = 0;
|
||||||
|
Reserve(ReserveSize);
|
||||||
|
}
|
||||||
|
|
||||||
DataFirst = DataLast = nullptr;
|
DataFirst = DataLast = nullptr;
|
||||||
Data = nullptr;
|
|
||||||
Count = 0;
|
Count = 0;
|
||||||
Capacity = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEmpty() const { return Count == 0; }
|
bool IsEmpty() const { return Count == 0; }
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
|
|||||||
(void)hPrev;
|
(void)hPrev;
|
||||||
(void)szCmdLine;
|
(void)szCmdLine;
|
||||||
(void)sw;
|
(void)sw;
|
||||||
|
|
||||||
return Juliet::Bootstrap(JulietMain, __argc, __wargv);
|
return Juliet::Bootstrap(JulietMain, __argc, __wargv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,13 @@ namespace Juliet
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void MatrixTranslate(Matrix& m, const Vector3& v)
|
||||||
|
{
|
||||||
|
m.m[0][3] += v.x;
|
||||||
|
m.m[1][3] += v.y;
|
||||||
|
m.m[2][3] += v.z;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline Matrix MatrixRotation(float x, float y, float z)
|
[[nodiscard]] inline Matrix MatrixRotation(float x, float y, float z)
|
||||||
{
|
{
|
||||||
return MatrixRotationX(x) * MatrixRotationY(y) * MatrixRotationZ(z);
|
return MatrixRotationX(x) * MatrixRotationY(y) * MatrixRotationZ(z);
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ namespace Juliet
|
|||||||
extern JULIET_API GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo);
|
extern JULIET_API GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo);
|
||||||
extern JULIET_API GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device,
|
extern JULIET_API GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device,
|
||||||
const TransferBufferCreateInfo& createInfo);
|
const TransferBufferCreateInfo& createInfo);
|
||||||
|
extern JULIET_API void* MapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
extern JULIET_API void UnmapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
||||||
extern JULIET_API void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
extern JULIET_API void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||||
extern JULIET_API void UnmapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
extern JULIET_API void UnmapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||||
extern JULIET_API void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
extern JULIET_API void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ namespace Juliet
|
|||||||
IndexBuffer = 1 << 0,
|
IndexBuffer = 1 << 0,
|
||||||
ConstantBuffer = 1 << 1,
|
ConstantBuffer = 1 << 1,
|
||||||
StructuredBuffer = 1 << 2,
|
StructuredBuffer = 1 << 2,
|
||||||
VertexBuffer = 1 << 3,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TransferBufferUsage : uint8
|
enum class TransferBufferUsage : uint8
|
||||||
@@ -20,7 +19,9 @@ namespace Juliet
|
|||||||
struct BufferCreateInfo
|
struct BufferCreateInfo
|
||||||
{
|
{
|
||||||
size_t Size;
|
size_t Size;
|
||||||
|
size_t Stride;
|
||||||
BufferUsage Usage;
|
BufferUsage Usage;
|
||||||
|
bool IsDynamic;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransferBufferCreateInfo
|
struct TransferBufferCreateInfo
|
||||||
|
|||||||
15
Juliet/include/Graphics/Lighting.h
Normal file
15
Juliet/include/Graphics/Lighting.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Juliet.h>
|
||||||
|
#include <Core/Math/Vector.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
struct PointLight
|
||||||
|
{
|
||||||
|
Vector3 Position;
|
||||||
|
float Radius;
|
||||||
|
Vector3 Color;
|
||||||
|
float Intensity;
|
||||||
|
};
|
||||||
|
} // namespace Juliet
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <Core/Container/Vector.h>
|
#include <Core/Container/Vector.h>
|
||||||
#include <Core/Math/Matrix.h>
|
#include <Core/Math/Matrix.h>
|
||||||
|
#include <Graphics/Lighting.h>
|
||||||
#include <Graphics/PushConstants.h>
|
#include <Graphics/PushConstants.h>
|
||||||
#include <Graphics/VertexData.h>
|
#include <Graphics/VertexData.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
@@ -17,13 +18,15 @@ namespace Juliet
|
|||||||
struct GraphicsDevice;
|
struct GraphicsDevice;
|
||||||
struct Mesh;
|
struct Mesh;
|
||||||
|
|
||||||
using MeshID = index_t;
|
using MeshID = index_t;
|
||||||
|
using LightID = index_t;
|
||||||
|
|
||||||
constexpr size_t kGeometryPage = Megabytes(64);
|
constexpr size_t kGeometryPage = Megabytes(64);
|
||||||
constexpr size_t kIndexPage = Megabytes(32);
|
constexpr size_t kIndexPage = Megabytes(32);
|
||||||
constexpr size_t kDefaultMeshNumber = 500;
|
constexpr size_t kDefaultMeshNumber = 500;
|
||||||
constexpr size_t kDefaultVertexCount = 2'000'000; // Fit less than one geometry page
|
constexpr size_t kDefaultVertexCount = 2'000'000; // Fit less than one geometry page
|
||||||
constexpr size_t kDefaultIndexCount = 16'000'000; // Fit less than one index page
|
constexpr size_t kDefaultIndexCount = 16'000'000; // Fit less than one index page
|
||||||
|
constexpr size_t kDefaultLightCount = 1024;
|
||||||
|
|
||||||
struct MeshRenderer
|
struct MeshRenderer
|
||||||
{
|
{
|
||||||
@@ -31,12 +34,16 @@ namespace Juliet
|
|||||||
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
|
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
|
||||||
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
|
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
|
||||||
VectorArena<Index, kDefaultIndexCount, false> Indices;
|
VectorArena<Index, kDefaultIndexCount, false> Indices;
|
||||||
|
VectorArena<PointLight, kDefaultLightCount, false> PointLights;
|
||||||
|
|
||||||
GraphicsBuffer* VertexBuffer;
|
GraphicsBuffer* VertexBuffer;
|
||||||
GraphicsBuffer* IndexBuffer;
|
GraphicsBuffer* IndexBuffer;
|
||||||
GraphicsTransferBuffer* StreamCopyBuffer;
|
GraphicsTransferBuffer* StreamCopyBuffer;
|
||||||
GraphicsTransferBuffer* LoadCopyBuffer;
|
GraphicsTransferBuffer* LoadCopyBuffer;
|
||||||
|
|
||||||
|
GraphicsBuffer* LightsBuffer;
|
||||||
|
PointLight* MappedLights;
|
||||||
|
|
||||||
GraphicsDevice* Device;
|
GraphicsDevice* Device;
|
||||||
GraphicsPipeline* Pipeline;
|
GraphicsPipeline* Pipeline;
|
||||||
};
|
};
|
||||||
@@ -48,6 +55,12 @@ namespace Juliet
|
|||||||
JULIET_API void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList);
|
JULIET_API void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList);
|
||||||
JULIET_API void RenderMeshes(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, PushData& pushData);
|
JULIET_API void RenderMeshes(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, PushData& pushData);
|
||||||
|
|
||||||
|
// Lights
|
||||||
|
[[nodiscard]] JULIET_API LightID AddPointLight(const PointLight& light);
|
||||||
|
JULIET_API void SetPointLightPosition(LightID id, const Vector3& position);
|
||||||
|
JULIET_API void SetPointLightColor(LightID id, const Vector3& color);
|
||||||
|
JULIET_API void ClearPointLights();
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
[[nodiscard]] JULIET_API MeshID AddCube();
|
[[nodiscard]] JULIET_API MeshID AddCube();
|
||||||
[[nodiscard]] JULIET_API MeshID AddQuad();
|
[[nodiscard]] JULIET_API MeshID AddQuad();
|
||||||
|
|||||||
@@ -21,5 +21,8 @@ namespace Juliet
|
|||||||
float LightPad;
|
float LightPad;
|
||||||
Vector3 LightColor;
|
Vector3 LightColor;
|
||||||
float AmbientIntensity;
|
float AmbientIntensity;
|
||||||
|
|
||||||
|
uint32 LightBufferIndex;
|
||||||
|
uint32 ActiveLightCount;
|
||||||
};
|
};
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Juliet
|
|||||||
{
|
{
|
||||||
Byte* OS_Reserve(size_t size)
|
Byte* OS_Reserve(size_t size)
|
||||||
{
|
{
|
||||||
auto result = static_cast<Byte*>(VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE));
|
auto* result = static_cast<Byte*>(VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,8 +68,6 @@ namespace Juliet
|
|||||||
{
|
{
|
||||||
int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv)
|
int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
SetUnhandledExceptionFilter(&ExceptionFilter);
|
SetUnhandledExceptionFilter(&ExceptionFilter);
|
||||||
|
|
||||||
// Allow only one instance to be launched.
|
// Allow only one instance to be launched.
|
||||||
@@ -87,12 +85,8 @@ namespace Juliet
|
|||||||
GUID guid = WSAID_MULTIPLE_RIO;
|
GUID guid = WSAID_MULTIPLE_RIO;
|
||||||
DWORD rio_byte = 0;
|
DWORD rio_byte = 0;
|
||||||
SOCKET Sock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
SOCKET Sock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||||
int result = WSAIoctl(Sock, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
|
WSAIoctl(Sock, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
|
||||||
(void**)&w32_rio_functions, sizeof(w32_rio_functions), &rio_byte, nullptr, nullptr);
|
reinterpret_cast<void**>(&w32_rio_functions), sizeof(w32_rio_functions), &rio_byte, nullptr, nullptr);
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
LogError(LogCategory::Core, "Couldnt get w32 RIO Functions. Error code %d", result);
|
|
||||||
}
|
|
||||||
closesocket(Sock);
|
closesocket(Sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ namespace Juliet::D3D12
|
|||||||
case BufferUsage::ConstantBuffer: return "ConstantBuffer";
|
case BufferUsage::ConstantBuffer: return "ConstantBuffer";
|
||||||
case BufferUsage::StructuredBuffer: return "StructuredBuffer";
|
case BufferUsage::StructuredBuffer: return "StructuredBuffer";
|
||||||
case BufferUsage::IndexBuffer: return "IndexBuffer";
|
case BufferUsage::IndexBuffer: return "IndexBuffer";
|
||||||
case BufferUsage::VertexBuffer: return "VertexBuffer";
|
|
||||||
}
|
}
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
@@ -62,95 +61,62 @@ namespace Juliet::D3D12
|
|||||||
Free(buffer);
|
Free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12Buffer* CreateBuffer(NonNullPtr<D3D12Driver> d3d12Driver, size_t size, BufferUsage usage, D3D12BufferType type)
|
D3D12Buffer* CreateBuffer(NonNullPtr<D3D12Driver> d3d12Driver, size_t size, size_t stride, BufferUsage usage,
|
||||||
|
D3D12BufferType type, bool isDynamic)
|
||||||
{
|
{
|
||||||
auto buffer = static_cast<D3D12Buffer*>(Calloc(1, sizeof(D3D12Buffer)));
|
auto* buffer = static_cast<D3D12Buffer*>(Calloc(1, sizeof(D3D12Buffer)));
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == D3D12BufferType::Base && usage == BufferUsage::None)
|
||||||
|
{
|
||||||
|
Assert(false, "Creating Base buffer with BufferUsage::None is invalid");
|
||||||
|
DestroyBuffer(buffer);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Align size for Constant Buffers
|
// Align size for Constant Buffers
|
||||||
if (usage == BufferUsage::ConstantBuffer)
|
if (usage == BufferUsage::ConstantBuffer)
|
||||||
{
|
{
|
||||||
size = (size + 255U) & ~255U;
|
size = (size + 255U) & ~255U;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON;
|
|
||||||
D3D12_HEAP_PROPERTIES heapProperties = {};
|
D3D12_HEAP_PROPERTIES heapProperties = {};
|
||||||
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
|
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||||
|
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||||
|
|
||||||
switch (type)
|
D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON;
|
||||||
|
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
|
||||||
|
|
||||||
|
// Constant buffers or Dynamic buffers generally need to be uploaded every frame
|
||||||
|
const bool isUpload = isDynamic || (type == D3D12BufferType::TransferUpload) || (usage == BufferUsage::ConstantBuffer);
|
||||||
|
|
||||||
|
if (type == D3D12BufferType::TransferDownload)
|
||||||
{
|
{
|
||||||
case D3D12BufferType::Base:
|
heapProperties.Type = D3D12_HEAP_TYPE_READBACK;
|
||||||
|
initialState = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||||
|
}
|
||||||
|
else if (isUpload)
|
||||||
|
{
|
||||||
|
if (d3d12Driver->GPUUploadHeapSupported)
|
||||||
{
|
{
|
||||||
switch (usage)
|
heapProperties.Type = D3D12_HEAP_TYPE_GPU_UPLOAD;
|
||||||
{
|
initialState = D3D12_RESOURCE_STATE_COMMON;
|
||||||
case BufferUsage::None:
|
|
||||||
{
|
|
||||||
Assert(false, "Creating buffer with invalid usage");
|
|
||||||
DestroyBuffer(buffer);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
case BufferUsage::IndexBuffer:
|
|
||||||
case BufferUsage::StructuredBuffer:
|
|
||||||
case BufferUsage::VertexBuffer:
|
|
||||||
{
|
|
||||||
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
||||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
|
||||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
|
||||||
heapFlags = D3D12_HEAP_FLAG_NONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BufferUsage::ConstantBuffer:
|
|
||||||
{
|
|
||||||
if (d3d12Driver->GPUUploadHeapSupported)
|
|
||||||
{
|
|
||||||
heapProperties.Type = D3D12_HEAP_TYPE_GPU_UPLOAD;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
||||||
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
|
||||||
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
|
||||||
}
|
|
||||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
|
||||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case D3D12BufferType::TransferDownload:
|
else
|
||||||
{
|
{
|
||||||
heapProperties.Type = D3D12_HEAP_TYPE_READBACK;
|
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
|
||||||
heapFlags = D3D12_HEAP_FLAG_NONE;
|
|
||||||
initialState = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case D3D12BufferType::TransferUpload:
|
|
||||||
{
|
|
||||||
if (d3d12Driver->GPUUploadHeapSupported)
|
|
||||||
{
|
|
||||||
heapProperties.Type = D3D12_HEAP_TYPE_GPU_UPLOAD;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
||||||
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
|
||||||
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
|
||||||
}
|
|
||||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
|
||||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
|
{
|
||||||
|
// Must be a static buffer (Base type)
|
||||||
|
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||||
|
initialState = D3D12_RESOURCE_STATE_COMMON;
|
||||||
|
}
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC desc = {};
|
D3D12_RESOURCE_DESC desc = {};
|
||||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
@@ -167,20 +133,22 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Graphics, "CreateBuffer: Device=%p, Size=%zu, Type=%s Use=%s",
|
Log(LogLevel::Message, LogCategory::Graphics, "CreateBuffer: Device=%p, Size=%zu, Type=%s Use=%s",
|
||||||
(void*)d3d12Driver->D3D12Device, size, D3D12BufferTypeToString(type), BufferUsageToString(usage));
|
(void*)d3d12Driver->D3D12Device, size, D3D12BufferTypeToString(type), BufferUsageToString(usage));
|
||||||
|
|
||||||
ID3D12Resource* handle = nullptr;
|
ID3D12Resource* handle = nullptr;
|
||||||
HRESULT result = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProperties, heapFlags, &desc,
|
HRESULT result = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProperties, heapFlags, &desc,
|
||||||
initialState, nullptr, IID_ID3D12Resource,
|
initialState, nullptr, IID_ID3D12Resource,
|
||||||
reinterpret_cast<void**>(&handle));
|
reinterpret_cast<void**>(&handle));
|
||||||
|
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "Could not create buffer! HRESULT=0x%08X", (uint32)result);
|
Log(LogLevel::Error, LogCategory::Graphics, "Could not create buffer! HRESULT=0x%08X", static_cast<uint32>(result));
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "Failed Desc: Width=%llu Layout=%d HeapType=%d",
|
Log(LogLevel::Error, LogCategory::Graphics, "Failed Desc: Width=%llu Layout=%d HeapType=%d",
|
||||||
(unsigned long long)desc.Width, (int)desc.Layout, (int)heapProperties.Type);
|
(unsigned long long)desc.Width, (int)desc.Layout, (int)heapProperties.Type);
|
||||||
|
|
||||||
HRESULT removeReason = d3d12Driver->D3D12Device->GetDeviceRemovedReason();
|
HRESULT removeReason = d3d12Driver->D3D12Device->GetDeviceRemovedReason();
|
||||||
if (FAILED(removeReason))
|
if (FAILED(removeReason))
|
||||||
{
|
{
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "Device Removed Reason: 0x%08X", (uint32)removeReason);
|
Log(LogLevel::Error, LogCategory::Graphics, "Device Removed Reason: 0x%08X", static_cast<uint32>(removeReason));
|
||||||
}
|
}
|
||||||
|
|
||||||
DestroyBuffer(buffer);
|
DestroyBuffer(buffer);
|
||||||
@@ -205,20 +173,33 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
if (usage == BufferUsage::ConstantBuffer)
|
if (usage == BufferUsage::ConstantBuffer)
|
||||||
{
|
{
|
||||||
cbvDesc.BufferLocation = handle->GetGPUVirtualAddress();
|
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
|
||||||
cbvDesc.SizeInBytes = static_cast<uint32>(size);
|
cbvDesc.BufferLocation = handle->GetGPUVirtualAddress();
|
||||||
|
cbvDesc.SizeInBytes = static_cast<uint32>(size);
|
||||||
d3d12Driver->D3D12Device->CreateConstantBufferView(&cbvDesc, cpuHandle);
|
d3d12Driver->D3D12Device->CreateConstantBufferView(&cbvDesc, cpuHandle);
|
||||||
}
|
}
|
||||||
else if (usage == BufferUsage::StructuredBuffer)
|
else if (usage == BufferUsage::StructuredBuffer)
|
||||||
{
|
{
|
||||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||||
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
|
||||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
|
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
|
||||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||||
srvDesc.Buffer.FirstElement = 0;
|
srvDesc.Buffer.FirstElement = 0;
|
||||||
srvDesc.Buffer.NumElements = static_cast<uint32>(size / 4);
|
|
||||||
srvDesc.Buffer.StructureByteStride = 0;
|
if (stride > 0)
|
||||||
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
|
{
|
||||||
|
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
srvDesc.Buffer.NumElements = static_cast<uint32>(size / stride);
|
||||||
|
srvDesc.Buffer.StructureByteStride = static_cast<uint32>(stride);
|
||||||
|
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
||||||
|
srvDesc.Buffer.NumElements = static_cast<uint32>(size / 4);
|
||||||
|
srvDesc.Buffer.StructureByteStride = 0;
|
||||||
|
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
|
||||||
|
}
|
||||||
|
|
||||||
d3d12Driver->D3D12Device->CreateShaderResourceView(handle, &srvDesc, cpuHandle);
|
d3d12Driver->D3D12Device->CreateShaderResourceView(handle, &srvDesc, cpuHandle);
|
||||||
Log(LogLevel::Message, LogCategory::Graphics, " -> SRV DescriptorIndex=%u", descriptor.Index);
|
Log(LogLevel::Message, LogCategory::Graphics, " -> SRV DescriptorIndex=%u", descriptor.Index);
|
||||||
}
|
}
|
||||||
@@ -233,10 +214,10 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage)
|
GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, size_t stride, BufferUsage usage, bool isDynamic)
|
||||||
{
|
{
|
||||||
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
return reinterpret_cast<GraphicsBuffer*>(CreateBuffer(d3d12Driver, size, usage, D3D12BufferType::Base));
|
return reinterpret_cast<GraphicsBuffer*>(CreateBuffer(d3d12Driver, size, stride, usage, D3D12BufferType::Base, isDynamic));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer)
|
void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer)
|
||||||
@@ -248,8 +229,9 @@ namespace Juliet::D3D12
|
|||||||
{
|
{
|
||||||
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
return reinterpret_cast<GraphicsTransferBuffer*>(
|
return reinterpret_cast<GraphicsTransferBuffer*>(
|
||||||
CreateBuffer(d3d12Driver, size, BufferUsage::None,
|
CreateBuffer(d3d12Driver, size, 0, BufferUsage::None,
|
||||||
usage == TransferBufferUsage::Upload ? D3D12BufferType::TransferUpload : D3D12BufferType::TransferDownload));
|
usage == TransferBufferUsage::Upload ? D3D12BufferType::TransferUpload : D3D12BufferType::TransferDownload,
|
||||||
|
false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsTransferBuffer> buffer)
|
void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||||
@@ -276,6 +258,24 @@ namespace Juliet::D3D12
|
|||||||
d3d12Buffer->Handle->Unmap(0, nullptr);
|
d3d12Buffer->Handle->Unmap(0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* MapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
|
||||||
|
{
|
||||||
|
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
|
||||||
|
void* ptr = nullptr;
|
||||||
|
D3D12_RANGE readRange = { 0, 0 };
|
||||||
|
if (FAILED(d3d12Buffer->Handle->Map(0, &readRange, &ptr)))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnmapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
|
||||||
|
{
|
||||||
|
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
|
||||||
|
d3d12Buffer->Handle->Unmap(0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
|
uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
|
||||||
{
|
{
|
||||||
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
|
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Juliet::D3D12
|
|||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
|
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, size_t stride, BufferUsage usage, bool isDynamic);
|
||||||
extern void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer);
|
extern void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
|
||||||
extern GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
|
extern GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
|
||||||
|
|||||||
@@ -1032,8 +1032,10 @@ namespace Juliet::D3D12
|
|||||||
device->DestroyShader = DestroyShader;
|
device->DestroyShader = DestroyShader;
|
||||||
device->CreateGraphicsPipeline = CreateGraphicsPipeline;
|
device->CreateGraphicsPipeline = CreateGraphicsPipeline;
|
||||||
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
|
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
|
||||||
device->CreateGraphicsBuffer = CreateGraphicsBuffer;
|
device->CreateGraphicsBuffer = CreateGraphicsBuffer;
|
||||||
device->DestroyGraphicsBuffer = DestroyGraphicsBuffer;
|
device->DestroyGraphicsBuffer = DestroyGraphicsBuffer;
|
||||||
|
device->MapGraphicsBuffer = MapBuffer;
|
||||||
|
device->UnmapGraphicsBuffer = UnmapBuffer;
|
||||||
device->CreateGraphicsTransferBuffer = CreateGraphicsTransferBuffer;
|
device->CreateGraphicsTransferBuffer = CreateGraphicsTransferBuffer;
|
||||||
device->DestroyGraphicsTransferBuffer = DestroyGraphicsTransferBuffer;
|
device->DestroyGraphicsTransferBuffer = DestroyGraphicsTransferBuffer;
|
||||||
device->MapGraphicsTransferBuffer = MapBuffer;
|
device->MapGraphicsTransferBuffer = MapBuffer;
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ namespace Juliet
|
|||||||
|
|
||||||
GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo)
|
GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo)
|
||||||
{
|
{
|
||||||
return device->CreateGraphicsBuffer(device->Driver, createInfo.Size, createInfo.Usage);
|
return device->CreateGraphicsBuffer(device->Driver, createInfo.Size, createInfo.Stride, createInfo.Usage, createInfo.IsDynamic);
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, const TransferBufferCreateInfo& createInfo)
|
GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, const TransferBufferCreateInfo& createInfo)
|
||||||
@@ -379,6 +379,16 @@ namespace Juliet
|
|||||||
return device->CreateGraphicsTransferBuffer(device->Driver, createInfo.Size, createInfo.Usage);
|
return device->CreateGraphicsTransferBuffer(device->Driver, createInfo.Size, createInfo.Usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* MapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
|
||||||
|
{
|
||||||
|
return device->MapGraphicsBuffer(device->Driver, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnmapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
|
||||||
|
{
|
||||||
|
device->UnmapGraphicsBuffer(device->Driver, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer)
|
void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||||
{
|
{
|
||||||
return device->MapGraphicsTransferBuffer(device->Driver, buffer);
|
return device->MapGraphicsTransferBuffer(device->Driver, buffer);
|
||||||
|
|||||||
@@ -100,9 +100,12 @@ namespace Juliet
|
|||||||
void (*DestroyTexture)(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture);
|
void (*DestroyTexture)(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture);
|
||||||
|
|
||||||
// Buffers
|
// Buffers
|
||||||
GraphicsBuffer* (*CreateGraphicsBuffer)(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
|
GraphicsBuffer* (*CreateGraphicsBuffer)(NonNullPtr<GPUDriver> driver, size_t size, size_t stride, BufferUsage usage, bool isDynamic);
|
||||||
void (*DestroyGraphicsBuffer)(NonNullPtr<GraphicsBuffer> buffer);
|
void (*DestroyGraphicsBuffer)(NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
|
||||||
|
void* (*MapGraphicsBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
void (*UnmapGraphicsBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
|
||||||
GraphicsTransferBuffer* (*CreateGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
|
GraphicsTransferBuffer* (*CreateGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
|
||||||
void (*DestroyGraphicsTransferBuffer)(NonNullPtr<GraphicsTransferBuffer> buffer);
|
void (*DestroyGraphicsTransferBuffer)(NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||||
|
|
||||||
|
|||||||
@@ -150,8 +150,8 @@ namespace Juliet
|
|||||||
|
|
||||||
TextureCreateInfo texCI = {};
|
TextureCreateInfo texCI = {};
|
||||||
texCI.Type = TextureType::Texture_2D;
|
texCI.Type = TextureType::Texture_2D;
|
||||||
texCI.Width = (uint32)width;
|
texCI.Width = static_cast<uint32>(width);
|
||||||
texCI.Height = (uint32)height;
|
texCI.Height = static_cast<uint32>(height);
|
||||||
|
|
||||||
texCI.Format = TextureFormat::R8G8B8A8_UNORM;
|
texCI.Format = TextureFormat::R8G8B8A8_UNORM;
|
||||||
texCI.Flags = TextureUsageFlag::Sampler;
|
texCI.Flags = TextureUsageFlag::Sampler;
|
||||||
@@ -160,10 +160,10 @@ namespace Juliet
|
|||||||
texCI.SampleCount = TextureSampleCount::One;
|
texCI.SampleCount = TextureSampleCount::One;
|
||||||
|
|
||||||
g_ImGuiState.FontTexture = CreateTexture(device, texCI);
|
g_ImGuiState.FontTexture = CreateTexture(device, texCI);
|
||||||
io.Fonts->SetTexID((ImTextureID)g_ImGuiState.FontTexture);
|
io.Fonts->SetTexID(reinterpret_cast<ImTextureID>(g_ImGuiState.FontTexture));
|
||||||
|
|
||||||
// Upload data
|
// Upload data
|
||||||
uint32 rowPitch = (uint32)width * 4u;
|
uint32 rowPitch = static_cast<uint32>(width) * 4u;
|
||||||
uint32 alignedRowPitch = (rowPitch + 255u) & ~255u;
|
uint32 alignedRowPitch = (rowPitch + 255u) & ~255u;
|
||||||
uint32 textureSize = alignedRowPitch * static_cast<uint32>(height);
|
uint32 textureSize = alignedRowPitch * static_cast<uint32>(height);
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ namespace Juliet
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dst = (uint8*)MapGraphicsTransferBuffer(device, tb);
|
auto* dst = static_cast<uint8*>(MapGraphicsTransferBuffer(device, tb));
|
||||||
|
|
||||||
for (uint32 y = 0; y < static_cast<uint32>(height); ++y)
|
for (uint32 y = 0; y < static_cast<uint32>(height); ++y)
|
||||||
{
|
{
|
||||||
@@ -315,13 +315,13 @@ namespace Juliet
|
|||||||
FrameResources& currentFrame = g_ImGuiState.Frames[g_ImGuiState.FrameIndex];
|
FrameResources& currentFrame = g_ImGuiState.Frames[g_ImGuiState.FrameIndex];
|
||||||
|
|
||||||
// Upload Buffers
|
// Upload Buffers
|
||||||
uint32 totalVtx = (uint32)drawData->TotalVtxCount;
|
uint32 totalVtx = static_cast<uint32>(drawData->TotalVtxCount);
|
||||||
uint32 totalIdx = (uint32)drawData->TotalIdxCount;
|
uint32 totalIdx = static_cast<uint32>(drawData->TotalIdxCount);
|
||||||
|
|
||||||
EnsureBufferSize(currentFrame, totalVtx * sizeof(ImDrawVert), totalIdx * sizeof(ImDrawIdx));
|
EnsureBufferSize(currentFrame, totalVtx * sizeof(ImDrawVert), totalIdx * sizeof(ImDrawIdx));
|
||||||
|
|
||||||
auto vtxDst = (ImDrawVert*)MapGraphicsTransferBuffer(g_ImGuiState.Device, currentFrame.VertexUpload);
|
auto* vtxDst = static_cast<ImDrawVert*>(MapGraphicsTransferBuffer(g_ImGuiState.Device, currentFrame.VertexUpload));
|
||||||
auto idxDst = (ImDrawIdx*)MapGraphicsTransferBuffer(g_ImGuiState.Device, currentFrame.IndexUpload);
|
auto* idxDst = static_cast<ImDrawIdx*>(MapGraphicsTransferBuffer(g_ImGuiState.Device, currentFrame.IndexUpload));
|
||||||
|
|
||||||
for (int n = 0; n < drawData->CmdListsCount; n++)
|
for (int n = 0; n < drawData->CmdListsCount; n++)
|
||||||
{
|
{
|
||||||
@@ -403,28 +403,18 @@ namespace Juliet
|
|||||||
SetScissorRect(renderPass, scissorRect);
|
SetScissorRect(renderPass, scissorRect);
|
||||||
|
|
||||||
// Bind Texture
|
// Bind Texture
|
||||||
uint32 textureIndex = GetDescriptorIndex(g_ImGuiState.Device, (Texture*)pcmd->GetTexID());
|
uint32 textureIndex = GetDescriptorIndex(g_ImGuiState.Device, reinterpret_cast<Texture*>(pcmd->GetTexID()));
|
||||||
|
|
||||||
// Push Constants
|
// Push Constants
|
||||||
// Layout: ViewProjection(64) + BufferIndex(4) + TextureIndex(4) + VertexOffset(4) + Padding(4) + Scale(8) + Translate(8)
|
PushData pushData = {}; // Zero-initialize all fields
|
||||||
struct
|
|
||||||
{
|
|
||||||
float dummyVP[16]; // Occupy VP slot
|
|
||||||
uint32 bufferIndex;
|
|
||||||
uint32 textureIndex;
|
|
||||||
uint32 vertexOffset; // Base vertex for indexed bindless drawing
|
|
||||||
uint32 padding; // Alignment padding
|
|
||||||
float scale[2];
|
|
||||||
float translate[2];
|
|
||||||
} pushData = {}; // Zero-initialize all fields
|
|
||||||
|
|
||||||
pushData.bufferIndex = GetDescriptorIndex(g_ImGuiState.Device, currentFrame.VertexBuffer);
|
pushData.BufferIndex = GetDescriptorIndex(g_ImGuiState.Device, currentFrame.VertexBuffer);
|
||||||
pushData.textureIndex = textureIndex;
|
pushData.TextureIndex = textureIndex;
|
||||||
pushData.vertexOffset = pcmd->VtxOffset + globalVtxOffset; // Pass vertex offset for bindless
|
pushData.VertexOffset = pcmd->VtxOffset + globalVtxOffset; // Pass vertex offset for bindless
|
||||||
pushData.scale[0] = scale[0];
|
pushData.Scale[0] = scale[0];
|
||||||
pushData.scale[1] = scale[1];
|
pushData.Scale[1] = scale[1];
|
||||||
pushData.translate[0] = translate[0];
|
pushData.Translate[0] = translate[0];
|
||||||
pushData.translate[1] = translate[1];
|
pushData.Translate[1] = translate[1];
|
||||||
|
|
||||||
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
|
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace Juliet
|
|||||||
g_MeshRenderer.Meshes.Create(arena JULIET_DEBUG_PARAM("Meshes"));
|
g_MeshRenderer.Meshes.Create(arena JULIET_DEBUG_PARAM("Meshes"));
|
||||||
g_MeshRenderer.Vertices.Create(arena JULIET_DEBUG_PARAM("Vertices"));
|
g_MeshRenderer.Vertices.Create(arena JULIET_DEBUG_PARAM("Vertices"));
|
||||||
g_MeshRenderer.Indices.Create(arena JULIET_DEBUG_PARAM("Indices"));
|
g_MeshRenderer.Indices.Create(arena JULIET_DEBUG_PARAM("Indices"));
|
||||||
|
g_MeshRenderer.PointLights.Create(arena JULIET_DEBUG_PARAM("PointLights"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InitializeMeshRendererGraphics(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
bool InitializeMeshRendererGraphics(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
||||||
@@ -53,6 +54,8 @@ namespace Juliet
|
|||||||
.DepthStencilFormat = TextureFormat::D32_FLOAT,
|
.DepthStencilFormat = TextureFormat::D32_FLOAT,
|
||||||
.HasDepthStencilTarget = true };
|
.HasDepthStencilTarget = true };
|
||||||
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
|
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
|
||||||
|
pipelineCI.RasterizerState.CullMode = CullMode::None;
|
||||||
|
pipelineCI.RasterizerState.FrontFace = FrontFace::Clockwise;
|
||||||
pipelineCI.DepthStencilState.EnableDepthTest = true;
|
pipelineCI.DepthStencilState.EnableDepthTest = true;
|
||||||
pipelineCI.DepthStencilState.EnableDepthWrite = true;
|
pipelineCI.DepthStencilState.EnableDepthWrite = true;
|
||||||
pipelineCI.DepthStencilState.CompareOperation = CompareOperation::Less;
|
pipelineCI.DepthStencilState.CompareOperation = CompareOperation::Less;
|
||||||
@@ -67,13 +70,33 @@ namespace Juliet
|
|||||||
// Create the vertex and index buffers
|
// Create the vertex and index buffers
|
||||||
BufferCreateInfo vertexBufferCI = {};
|
BufferCreateInfo vertexBufferCI = {};
|
||||||
vertexBufferCI.Size = kGeometryPage;
|
vertexBufferCI.Size = kGeometryPage;
|
||||||
|
vertexBufferCI.Stride = 0;
|
||||||
vertexBufferCI.Usage = BufferUsage::StructuredBuffer;
|
vertexBufferCI.Usage = BufferUsage::StructuredBuffer;
|
||||||
g_MeshRenderer.VertexBuffer = CreateGraphicsBuffer(graphicsDevice, vertexBufferCI);
|
g_MeshRenderer.VertexBuffer = CreateGraphicsBuffer(graphicsDevice, vertexBufferCI);
|
||||||
|
Assert(g_MeshRenderer.VertexBuffer != nullptr);
|
||||||
|
|
||||||
BufferCreateInfo indexBufferCI = {};
|
BufferCreateInfo indexBufferCI = {};
|
||||||
indexBufferCI.Size = kIndexPage;
|
indexBufferCI.Size = kIndexPage;
|
||||||
indexBufferCI.Usage = BufferUsage::IndexBuffer;
|
indexBufferCI.Usage = BufferUsage::IndexBuffer;
|
||||||
g_MeshRenderer.IndexBuffer = CreateGraphicsBuffer(graphicsDevice, indexBufferCI);
|
g_MeshRenderer.IndexBuffer = CreateGraphicsBuffer(graphicsDevice, indexBufferCI);
|
||||||
|
Assert(g_MeshRenderer.IndexBuffer != nullptr);
|
||||||
|
|
||||||
|
// Lights Buffer
|
||||||
|
BufferCreateInfo lightsBufferCI = {};
|
||||||
|
lightsBufferCI.Size = 1024 * sizeof(PointLight); // Max 1024 lights for now
|
||||||
|
lightsBufferCI.Stride = sizeof(PointLight);
|
||||||
|
lightsBufferCI.Usage = BufferUsage::StructuredBuffer;
|
||||||
|
lightsBufferCI.IsDynamic = true;
|
||||||
|
g_MeshRenderer.LightsBuffer = CreateGraphicsBuffer(graphicsDevice, lightsBufferCI);
|
||||||
|
Assert(g_MeshRenderer.LightsBuffer != nullptr);
|
||||||
|
g_MeshRenderer.MappedLights = static_cast<PointLight*>(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.LightsBuffer));
|
||||||
|
Assert(g_MeshRenderer.MappedLights != nullptr);
|
||||||
|
|
||||||
|
// Sync existing lights that might have been added before graphics initialization
|
||||||
|
for (index_t i = 0; i < g_MeshRenderer.PointLights.Count; ++i)
|
||||||
|
{
|
||||||
|
g_MeshRenderer.MappedLights[i] = g_MeshRenderer.PointLights.Data[i];
|
||||||
|
}
|
||||||
|
|
||||||
if (vertexShader)
|
if (vertexShader)
|
||||||
{
|
{
|
||||||
@@ -88,7 +111,6 @@ namespace Juliet
|
|||||||
CommandList* loadCmd = AcquireCommandList(device);
|
CommandList* loadCmd = AcquireCommandList(device);
|
||||||
LoadMeshesOnGPU(loadCmd);
|
LoadMeshesOnGPU(loadCmd);
|
||||||
SubmitCommandLists(loadCmd);
|
SubmitCommandLists(loadCmd);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +125,12 @@ namespace Juliet
|
|||||||
|
|
||||||
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.IndexBuffer);
|
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.IndexBuffer);
|
||||||
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
|
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
|
||||||
|
|
||||||
|
if (g_MeshRenderer.LightsBuffer)
|
||||||
|
{
|
||||||
|
UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
|
||||||
|
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownMeshRenderer()
|
void ShutdownMeshRenderer()
|
||||||
@@ -110,6 +138,7 @@ namespace Juliet
|
|||||||
g_MeshRenderer.Indices.Destroy();
|
g_MeshRenderer.Indices.Destroy();
|
||||||
g_MeshRenderer.Vertices.Destroy();
|
g_MeshRenderer.Vertices.Destroy();
|
||||||
g_MeshRenderer.Meshes.Destroy();
|
g_MeshRenderer.Meshes.Destroy();
|
||||||
|
g_MeshRenderer.PointLights.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList)
|
void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList)
|
||||||
@@ -159,6 +188,8 @@ namespace Juliet
|
|||||||
|
|
||||||
MemCopy(ptrOneByte + indexOfByteOffset, g_MeshRenderer.Indices.Data, totalIndexBytes);
|
MemCopy(ptrOneByte + indexOfByteOffset, g_MeshRenderer.Indices.Data, totalIndexBytes);
|
||||||
|
|
||||||
|
UnmapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
|
||||||
|
|
||||||
CopyBuffer(cmdList, g_MeshRenderer.VertexBuffer, g_MeshRenderer.LoadCopyBuffer, totalVertexBytes, 0, 0);
|
CopyBuffer(cmdList, g_MeshRenderer.VertexBuffer, g_MeshRenderer.LoadCopyBuffer, totalVertexBytes, 0, 0);
|
||||||
CopyBuffer(cmdList, g_MeshRenderer.IndexBuffer, g_MeshRenderer.LoadCopyBuffer, totalIndexBytes, 0, indexOfByteOffset);
|
CopyBuffer(cmdList, g_MeshRenderer.IndexBuffer, g_MeshRenderer.LoadCopyBuffer, totalIndexBytes, 0, indexOfByteOffset);
|
||||||
|
|
||||||
@@ -181,8 +212,11 @@ namespace Juliet
|
|||||||
BindGraphicsPipeline(pass, g_MeshRenderer.Pipeline);
|
BindGraphicsPipeline(pass, g_MeshRenderer.Pipeline);
|
||||||
|
|
||||||
uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
|
uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
|
||||||
|
uint32 lightDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
|
||||||
|
|
||||||
pushData.BufferIndex = vertexDescriptorIndex;
|
pushData.BufferIndex = vertexDescriptorIndex;
|
||||||
|
pushData.LightBufferIndex = lightDescriptorIndex;
|
||||||
|
pushData.ActiveLightCount = static_cast<uint32>(g_MeshRenderer.PointLights.Count);
|
||||||
|
|
||||||
SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, g_MeshRenderer.Indices.Count, 0);
|
SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, g_MeshRenderer.Indices.Count, 0);
|
||||||
|
|
||||||
@@ -202,6 +236,43 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LightID AddPointLight(const PointLight& light)
|
||||||
|
{
|
||||||
|
Assert(g_MeshRenderer.PointLights.Count < kDefaultLightCount);
|
||||||
|
LightID id = g_MeshRenderer.PointLights.Count;
|
||||||
|
g_MeshRenderer.PointLights.PushBack(light);
|
||||||
|
if (g_MeshRenderer.MappedLights)
|
||||||
|
{
|
||||||
|
g_MeshRenderer.MappedLights[id] = light;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPointLightPosition(LightID id, const Vector3& position)
|
||||||
|
{
|
||||||
|
Assert(id < static_cast<LightID>(g_MeshRenderer.PointLights.Count));
|
||||||
|
g_MeshRenderer.PointLights.Data[id].Position = position;
|
||||||
|
if (g_MeshRenderer.MappedLights)
|
||||||
|
{
|
||||||
|
g_MeshRenderer.MappedLights[id].Position = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPointLightColor(LightID id, const Vector3& color)
|
||||||
|
{
|
||||||
|
Assert(id < static_cast<LightID>(g_MeshRenderer.PointLights.Count));
|
||||||
|
g_MeshRenderer.PointLights.Data[id].Color = color;
|
||||||
|
if (g_MeshRenderer.MappedLights)
|
||||||
|
{
|
||||||
|
g_MeshRenderer.MappedLights[id].Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearPointLights()
|
||||||
|
{
|
||||||
|
g_MeshRenderer.PointLights.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
MeshID AddCube()
|
MeshID AddCube()
|
||||||
{
|
{
|
||||||
Mesh result = {};
|
Mesh result = {};
|
||||||
@@ -300,6 +371,7 @@ namespace Juliet
|
|||||||
Assert(id < static_cast<MeshID>(g_MeshRenderer.Meshes.Count));
|
Assert(id < static_cast<MeshID>(g_MeshRenderer.Meshes.Count));
|
||||||
g_MeshRenderer.Meshes.Data[id].Transform = transform;
|
g_MeshRenderer.Meshes.Data[id].Transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ALLOW_SHADER_HOT_RELOAD
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
void ReloadMeshRendererShaders()
|
void ReloadMeshRendererShaders()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
#ifdef global
|
||||||
|
#undef global
|
||||||
|
#endif
|
||||||
|
#include <ios>
|
||||||
|
#include <iosfwd>
|
||||||
|
#define global static
|
||||||
|
|
||||||
#include <Core/Application/ApplicationManager.h>
|
#include <Core/Application/ApplicationManager.h>
|
||||||
#include <Core/Common/EnumUtils.h>
|
#include <Core/Common/EnumUtils.h>
|
||||||
#include <Core/Common/String.h>
|
#include <Core/Common/String.h>
|
||||||
@@ -44,13 +51,6 @@ static bool ShowMemoryDebugger = false;
|
|||||||
|
|
||||||
using namespace Juliet;
|
using namespace Juliet;
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
__declspec(dllexport) extern const unsigned int D3D12SDKVersion = 615;
|
|
||||||
}
|
|
||||||
extern "C" {
|
|
||||||
__declspec(dllexport) extern const char* D3D12SDKPath = ".\\";
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
using GameInit_t = void (*)(GameInitParams*);
|
using GameInit_t = void (*)(GameInitParams*);
|
||||||
@@ -64,6 +64,9 @@ namespace
|
|||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" };
|
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" };
|
||||||
|
|
||||||
|
LightID RedLightID = 0;
|
||||||
|
LightID BlueLightID = 0;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void JulietApplication::Init(NonNullPtr<Arena>)
|
void JulietApplication::Init(NonNullPtr<Arena>)
|
||||||
@@ -75,6 +78,7 @@ void JulietApplication::Init(NonNullPtr<Arena>)
|
|||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
config.EnableDebug = true;
|
config.EnableDebug = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GraphicsDevice = CreateGraphicsDevice(config);
|
GraphicsDevice = CreateGraphicsDevice(config);
|
||||||
|
|
||||||
MainWindow = CreatePlatformWindow("Juliet Editor", 1280, 720);
|
MainWindow = CreatePlatformWindow("Juliet Editor", 1280, 720);
|
||||||
@@ -119,6 +123,21 @@ void JulietApplication::Init(NonNullPtr<Arena>)
|
|||||||
SetMeshTransform(cube, MatrixTranslation(x, y, 0.0f) * rotation);
|
SetMeshTransform(cube, MatrixTranslation(x, y, 0.0f) * rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start with some default test lights
|
||||||
|
PointLight redLight = {};
|
||||||
|
redLight.Position = { 5.0f, 5.0f, 2.0f };
|
||||||
|
redLight.Radius = 10.0f;
|
||||||
|
redLight.Color = { 1.0f, 0.2f, 0.2f };
|
||||||
|
redLight.Intensity = 5.0f;
|
||||||
|
RedLightID = AddPointLight(redLight);
|
||||||
|
|
||||||
|
PointLight blueLight = {};
|
||||||
|
blueLight.Position = { -5.0f, 0.0f, 2.0f };
|
||||||
|
blueLight.Radius = 15.0f;
|
||||||
|
blueLight.Color = { 0.2f, 0.2f, 1.0f };
|
||||||
|
blueLight.Intensity = 8.0f;
|
||||||
|
BlueLightID = AddPointLight(blueLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameCode.Functions = reinterpret_cast<void**>(&Game);
|
GameCode.Functions = reinterpret_cast<void**>(&Game);
|
||||||
@@ -232,14 +251,23 @@ void JulietApplication::Update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArenaClear(GameScratchArena);
|
||||||
|
|
||||||
|
Vector3 redLightPos{ cosf(CameraTime * 2.0f) * 5.0f, sinf(CameraTime * 2.0f) * 5.0f, 2.0f };
|
||||||
|
SetPointLightPosition(RedLightID, redLightPos);
|
||||||
|
Vector3 blueLightPos{ -5.0f, cosf(CameraTime) * 3.0f, 2.0f };
|
||||||
|
SetPointLightPosition(BlueLightID, blueLightPos);
|
||||||
|
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
// ImGui::ShowDemoWindow();
|
ImGui::ShowDemoWindow();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false);
|
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false);
|
||||||
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true);
|
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true);
|
||||||
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, true);
|
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, true);
|
||||||
DebugDisplay_DrawSphere({ 0.0f, 0.0f, 0.0f }, 0.5f, { 1.0f, 1.0f, 0.0f, 1.0f }, true);
|
DebugDisplay_DrawSphere({ 0.0f, 0.0f, 0.0f }, 0.5f, { 1.0f, 1.0f, 0.0f, 1.0f }, true);
|
||||||
|
DebugDisplay_DrawSphere(blueLightPos, 0.5f, { 0.0f, 0.0f, 1.0f, 1.0f }, true);
|
||||||
|
DebugDisplay_DrawSphere(redLightPos, 0.5f, { 1.0f, 0.0f, 0.0f, 1.0f }, true);
|
||||||
|
|
||||||
Game.Update(0.0f);
|
Game.Update(0.0f);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user