vertex buffer quantization (#777)
This commit is contained in:
@@ -105,6 +105,7 @@
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64;../$(Platform)/$(Configuration)</AdditionalLibraryDirectories>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<FxCompile>
|
||||
<ShaderModel>5.0</ShaderModel>
|
||||
|
||||
@@ -278,6 +278,7 @@ void HairParticleWindow::UpdateData()
|
||||
|
||||
std::string ss;
|
||||
ss += "To use hair particle system, first you must select a surface mesh to spawn particles on.\n\n";
|
||||
ss += "Position format: " + std::string(wi::graphics::GetFormatString(hair->position_format)) + "\n";
|
||||
ss += "Memory usage: " + wi::helper::GetMemorySizeText(hair->GetMemorySizeInBytes()) + "\n";
|
||||
infoLabel.SetText(ss);
|
||||
|
||||
|
||||
+24
-2
@@ -12,7 +12,7 @@ void MeshWindow::Create(EditorComponent* _editor)
|
||||
{
|
||||
editor = _editor;
|
||||
wi::gui::Window::Create(ICON_MESH " Mesh", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE);
|
||||
SetSize(XMFLOAT2(580, 780));
|
||||
SetSize(XMFLOAT2(580, 800));
|
||||
|
||||
closeButton.SetTooltip("Delete MeshComponent");
|
||||
OnClose([=](wi::gui::EventArgs args) {
|
||||
@@ -157,6 +157,24 @@ void MeshWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&bvhCheckBox);
|
||||
|
||||
quantizeCheckBox.Create("Quantization Disabled: ");
|
||||
quantizeCheckBox.SetTooltip("Disable quantization of vertex positions if you notice inaccuracy errors with UNORM position formats.");
|
||||
quantizeCheckBox.SetSize(XMFLOAT2(hei, hei));
|
||||
quantizeCheckBox.SetPos(XMFLOAT2(x, y += step));
|
||||
quantizeCheckBox.OnClick([&](wi::gui::EventArgs args) {
|
||||
MeshComponent* mesh = editor->GetCurrentScene().meshes.GetComponent(entity);
|
||||
if (mesh != nullptr)
|
||||
{
|
||||
mesh->SetQuantizedPositionsDisabled(args.bValue);
|
||||
mesh->CreateRenderData();
|
||||
if (!mesh->BLASes.empty())
|
||||
{
|
||||
mesh->CreateRaytracingRenderData();
|
||||
}
|
||||
}
|
||||
});
|
||||
AddWidget(&quantizeCheckBox);
|
||||
|
||||
impostorCreateButton.Create("Create Impostor");
|
||||
impostorCreateButton.SetTooltip("Create an impostor image of the mesh. The mesh will be replaced by this image when far away, to render faster.");
|
||||
impostorCreateButton.SetSize(XMFLOAT2(wid, hei));
|
||||
@@ -848,6 +866,7 @@ void MeshWindow::SetEntity(Entity entity, int subset)
|
||||
ss += "Vertex count: " + std::to_string(mesh->vertex_positions.size()) + "\n";
|
||||
ss += "Index count: " + std::to_string(mesh->indices.size()) + "\n";
|
||||
ss += "Index format: " + std::string(wi::graphics::GetIndexBufferFormatString(mesh->GetIndexFormat())) + "\n";
|
||||
ss += "Position format: " + std::string(wi::graphics::GetFormatString(mesh->position_format)) + "\n";
|
||||
ss += "Subset count: " + std::to_string(mesh->subsets.size()) + " (" + std::to_string(mesh->GetLODCount()) + " LODs)\n";
|
||||
if (!mesh->morph_targets.empty())
|
||||
{
|
||||
@@ -878,7 +897,8 @@ void MeshWindow::SetEntity(Entity entity, int subset)
|
||||
if (mesh->so_pre.IsValid()) ss += "\tprevious_position;\n";
|
||||
if (mesh->vb_bon.IsValid()) ss += "\tbone;\n";
|
||||
if (mesh->vb_tan.IsValid()) ss += "\ttangent;\n";
|
||||
if (mesh->so_pos_nor_wind.IsValid()) ss += "\tstreamout_position_normal_wind;\n";
|
||||
if (mesh->so_pos.IsValid()) ss += "\tstreamout_position;\n";
|
||||
if (mesh->so_nor.IsValid()) ss += "\tstreamout_normals;\n";
|
||||
if (mesh->so_tan.IsValid()) ss += "\tstreamout_tangents;\n";
|
||||
meshInfoLabel.SetText(ss);
|
||||
|
||||
@@ -923,6 +943,7 @@ void MeshWindow::SetEntity(Entity entity, int subset)
|
||||
doubleSidedCheckBox.SetCheck(mesh->IsDoubleSided());
|
||||
doubleSidedShadowCheckBox.SetCheck(mesh->IsDoubleSidedShadow());
|
||||
bvhCheckBox.SetCheck(mesh->bvh.IsValid());
|
||||
quantizeCheckBox.SetCheck(mesh->IsQuantizedPositionsDisabled());
|
||||
|
||||
const ImpostorComponent* impostor = scene.impostors.GetComponent(entity);
|
||||
if (impostor != nullptr)
|
||||
@@ -1013,6 +1034,7 @@ void MeshWindow::ResizeLayout()
|
||||
add_right(doubleSidedCheckBox);
|
||||
add_right(doubleSidedShadowCheckBox);
|
||||
add_right(bvhCheckBox);
|
||||
add_right(quantizeCheckBox);
|
||||
add_fullwidth(impostorCreateButton);
|
||||
add(impostorDistanceSlider);
|
||||
add(tessellationFactorSlider);
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
wi::gui::CheckBox doubleSidedCheckBox;
|
||||
wi::gui::CheckBox doubleSidedShadowCheckBox;
|
||||
wi::gui::CheckBox bvhCheckBox;
|
||||
wi::gui::CheckBox quantizeCheckBox;
|
||||
wi::gui::Button impostorCreateButton;
|
||||
wi::gui::Slider impostorDistanceSlider;
|
||||
wi::gui::Slider tessellationFactorSlider;
|
||||
|
||||
@@ -927,7 +927,7 @@ void PaintToolWindow::Update(float dt)
|
||||
break;
|
||||
|
||||
SoftBodyPhysicsComponent* softbody = scene.softbodies.GetComponent(object->meshID);
|
||||
if (softbody == nullptr || softbody->vertex_positions_simulation.empty())
|
||||
if (softbody == nullptr || !softbody->HasVertices())
|
||||
break;
|
||||
|
||||
// Painting:
|
||||
@@ -971,18 +971,18 @@ void PaintToolWindow::Update(float dt)
|
||||
const float weight1 = softbody->weights[physicsIndex1];
|
||||
const float weight2 = softbody->weights[physicsIndex2];
|
||||
wi::renderer::RenderableTriangle tri;
|
||||
if (softbody->vertex_positions_simulation.empty())
|
||||
if (softbody->HasVertices())
|
||||
{
|
||||
tri.positionA = softbody->vertex_positions_simulation[graphicsIndex0].GetPOS();
|
||||
tri.positionB = softbody->vertex_positions_simulation[graphicsIndex1].GetPOS();
|
||||
tri.positionC = softbody->vertex_positions_simulation[graphicsIndex2].GetPOS();
|
||||
}
|
||||
else
|
||||
{
|
||||
XMStoreFloat3(&tri.positionA, XMVector3Transform(XMLoadFloat3(&mesh->vertex_positions[graphicsIndex0]), W));
|
||||
XMStoreFloat3(&tri.positionB, XMVector3Transform(XMLoadFloat3(&mesh->vertex_positions[graphicsIndex1]), W));
|
||||
XMStoreFloat3(&tri.positionC, XMVector3Transform(XMLoadFloat3(&mesh->vertex_positions[graphicsIndex2]), W));
|
||||
}
|
||||
else
|
||||
{
|
||||
tri.positionA = softbody->vertex_positions_simulation[graphicsIndex0].pos;
|
||||
tri.positionB = softbody->vertex_positions_simulation[graphicsIndex1].pos;
|
||||
tri.positionC = softbody->vertex_positions_simulation[graphicsIndex2].pos;
|
||||
}
|
||||
if (weight0 == 0)
|
||||
tri.colorA = XMFLOAT4(1, 1, 0, 1);
|
||||
else
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64;../$(Platform)/$(Configuration)</AdditionalLibraryDirectories>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
|
||||
@@ -3146,7 +3146,7 @@ namespace jpgd {
|
||||
|
||||
for (int y = 0; y < image_height; y++)
|
||||
{
|
||||
const uint8* pScan_line;
|
||||
const uint8* pScan_line = nullptr;
|
||||
uint scan_line_len;
|
||||
if (decoder.decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS)
|
||||
{
|
||||
|
||||
@@ -42,6 +42,7 @@ static const uint EMITTER_OPTION_BIT_USE_RAIN_BLOCKER = 1 << 4;
|
||||
CBUFFER(EmittedParticleCB, CBSLOT_OTHER_EMITTEDPARTICLE)
|
||||
{
|
||||
ShaderTransform xEmitterTransform;
|
||||
ShaderTransform xEmitterBaseMeshUnormRemap;
|
||||
|
||||
uint xEmitCount;
|
||||
uint xEmitterMeshIndexCount;
|
||||
|
||||
@@ -17,6 +17,7 @@ struct PatchSimulationData
|
||||
CBUFFER(HairParticleCB, CBSLOT_OTHER_HAIRPARTICLE)
|
||||
{
|
||||
ShaderTransform xHairTransform;
|
||||
ShaderTransform xHairBaseMeshUnormRemap;
|
||||
|
||||
uint xHairRegenerate;
|
||||
float xLength;
|
||||
@@ -30,8 +31,8 @@ CBUFFER(HairParticleCB, CBSLOT_OTHER_HAIRPARTICLE)
|
||||
|
||||
float xHairViewDistance;
|
||||
uint xHairBaseMeshIndexCount;
|
||||
uint xHairBaseMeshVertexPositionStride;
|
||||
uint xHairInstanceIndex;
|
||||
uint padding0_xHair;
|
||||
|
||||
uint2 xHairFramesXY;
|
||||
uint xHairFrameCount;
|
||||
|
||||
@@ -444,47 +444,60 @@ static const uint SHADERMESH_FLAG_EMITTEDPARTICLE = 1 << 2;
|
||||
// But because these are always loaded toghether by shaders, they are unrolled into one to reduce individual buffer loads
|
||||
struct ShaderGeometry
|
||||
{
|
||||
int vb_pos_nor_wind;
|
||||
int vb_pos_wind;
|
||||
int vb_uvs;
|
||||
int ib;
|
||||
uint indexOffset;
|
||||
|
||||
int vb_nor;
|
||||
int vb_tan;
|
||||
int vb_col;
|
||||
int vb_atl;
|
||||
int vb_pre;
|
||||
|
||||
int vb_pre;
|
||||
uint materialIndex;
|
||||
uint meshletOffset; // offset of this subset in meshlets (locally within the mesh)
|
||||
uint meshletCount;
|
||||
int impostorSliceOffset;
|
||||
|
||||
float3 aabb_min;
|
||||
uint flags;
|
||||
float3 aabb_max;
|
||||
float tessellation_factor;
|
||||
|
||||
float2 uv_range_min;
|
||||
float2 uv_range_max;
|
||||
|
||||
int impostorSliceOffset;
|
||||
int padding0;
|
||||
int padding1;
|
||||
int padding2;
|
||||
|
||||
void init()
|
||||
{
|
||||
ib = -1;
|
||||
indexOffset = 0;
|
||||
vb_pos_nor_wind = -1;
|
||||
vb_pos_wind = -1;
|
||||
vb_uvs = -1;
|
||||
|
||||
vb_nor = -1;
|
||||
vb_tan = -1;
|
||||
vb_col = -1;
|
||||
vb_atl = -1;
|
||||
vb_pre = -1;
|
||||
|
||||
vb_pre = -1;
|
||||
materialIndex = 0;
|
||||
meshletOffset = 0;
|
||||
meshletCount = 0;
|
||||
impostorSliceOffset = -1;
|
||||
|
||||
aabb_min = float3(0, 0, 0);
|
||||
flags = 0;
|
||||
aabb_max = float3(0, 0, 0);
|
||||
tessellation_factor = 0;
|
||||
|
||||
uv_range_min = float2(0, 0);
|
||||
uv_range_max = float2(1, 1);
|
||||
|
||||
impostorSliceOffset = -1;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1263,20 +1276,39 @@ CBUFFER(PaintRadiusCB, CBSLOT_RENDERER_MISC)
|
||||
|
||||
struct SkinningPushConstants
|
||||
{
|
||||
uint vertexCount;
|
||||
int vb_pos_nor_wind;
|
||||
int vb_pos_wind;
|
||||
int vb_nor;
|
||||
int vb_tan;
|
||||
int so_pos_nor_wind;
|
||||
int so_pos;
|
||||
|
||||
int so_nor;
|
||||
int so_tan;
|
||||
int vb_bon;
|
||||
int morphvb_index;
|
||||
|
||||
int skinningbuffer_index;
|
||||
uint bone_offset;
|
||||
|
||||
uint morph_offset;
|
||||
uint morph_count;
|
||||
int morphvb_index;
|
||||
int padding;
|
||||
|
||||
float3 aabb_min;
|
||||
uint vertexCount;
|
||||
|
||||
float3 aabb_max;
|
||||
float padding;
|
||||
};
|
||||
|
||||
struct DebugObjectPushConstants
|
||||
{
|
||||
int vb_pos_wind;
|
||||
};
|
||||
|
||||
struct LightmapPushConstants
|
||||
{
|
||||
int vb_pos_wind;
|
||||
int vb_nor;
|
||||
int vb_atl;
|
||||
uint instanceIndex;
|
||||
};
|
||||
|
||||
struct MorphTargetGPU
|
||||
|
||||
@@ -32,9 +32,9 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
|
||||
uint i1 = bindless_buffers_uint[geometry.ib][startIndex + 1];
|
||||
uint i2 = bindless_buffers_uint[geometry.ib][startIndex + 2];
|
||||
|
||||
float3 p0 = bindless_buffers_float4[geometry.vb_pos_nor_wind][i0].xyz;
|
||||
float3 p1 = bindless_buffers_float4[geometry.vb_pos_nor_wind][i1].xyz;
|
||||
float3 p2 = bindless_buffers_float4[geometry.vb_pos_nor_wind][i2].xyz;
|
||||
float3 p0 = bindless_buffers_float4[geometry.vb_pos_wind][i0].xyz;
|
||||
float3 p1 = bindless_buffers_float4[geometry.vb_pos_wind][i1].xyz;
|
||||
float3 p2 = bindless_buffers_float4[geometry.vb_pos_wind][i2].xyz;
|
||||
float3 P0 = mul(inst.transform.GetMatrix(), float4(p0, 1)).xyz;
|
||||
float3 P1 = mul(inst.transform.GetMatrix(), float4(p1, 1)).xyz;
|
||||
float3 P2 = mul(inst.transform.GetMatrix(), float4(p2, 1)).xyz;
|
||||
|
||||
@@ -75,9 +75,9 @@ void main(
|
||||
{
|
||||
uint vertexID = particleIndex * 4 + i;
|
||||
|
||||
float4 pos_nor_wind = bindless_buffers_float4[geometry.vb_pos_nor_wind][vertexID];
|
||||
float3 position = pos_nor_wind.xyz;
|
||||
float3 normal = normalize(unpack_unitvector(asuint(pos_nor_wind.w)));
|
||||
float4 pos_wind = bindless_buffers_float4[geometry.vb_pos_wind][vertexID];
|
||||
float3 position = pos_wind.xyz;
|
||||
float3 normal = normalize(bindless_buffers_float4[geometry.vb_nor][vertexID].xyz);
|
||||
float4 uvsets = bindless_buffers_float4[geometry.vb_uvs][vertexID];
|
||||
|
||||
VertextoPixel_MS Out;
|
||||
|
||||
@@ -20,9 +20,9 @@ VertextoPixel main(uint vid : SV_VertexID, uint instanceID : SV_InstanceID)
|
||||
uint particleIndex = culledIndirectionBuffer2[culledIndirectionBuffer[instanceID]];
|
||||
uint vertexID = particleIndex * 4 + vid;
|
||||
|
||||
float4 pos_nor_wind = bindless_buffers_float4[geometry.vb_pos_nor_wind][vertexID];
|
||||
float3 position = pos_nor_wind.xyz;
|
||||
float3 normal = normalize(unpack_unitvector(asuint(pos_nor_wind.w)));
|
||||
float4 pos_wind = bindless_buffers_float4[geometry.vb_pos_wind][vertexID];
|
||||
float3 position = pos_wind.xyz;
|
||||
float3 normal = normalize(bindless_buffers_float4[geometry.vb_nor][vertexID].xyz);
|
||||
float4 uvsets = bindless_buffers_float4[geometry.vb_uvs][vertexID];
|
||||
float4 color = bindless_buffers_float4[geometry.vb_col][vertexID];
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ RWByteAddressBuffer counterBuffer : register(u4);
|
||||
#ifdef EMIT_FROM_MESH
|
||||
Buffer<uint> meshIndexBuffer : register(t0);
|
||||
Buffer<float4> meshVertexBuffer_POS : register(t1);
|
||||
Buffer<float4> meshVertexBuffer_NOR : register(t2);
|
||||
#endif // EMIT_FROM_MESH
|
||||
|
||||
|
||||
@@ -39,13 +40,13 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
uint i2 = meshIndexBuffer[tri * 3 + 2];
|
||||
|
||||
// load vertices of triangle from vertex buffer:
|
||||
float4 pos_nor0 = meshVertexBuffer_POS[i0];
|
||||
float4 pos_nor1 = meshVertexBuffer_POS[i1];
|
||||
float4 pos_nor2 = meshVertexBuffer_POS[i2];
|
||||
float3 pos0 = meshVertexBuffer_POS[i0].xyz;
|
||||
float3 pos1 = meshVertexBuffer_POS[i1].xyz;
|
||||
float3 pos2 = meshVertexBuffer_POS[i2].xyz;
|
||||
|
||||
float3 nor0 = unpack_unitvector(asuint(pos_nor0.w));
|
||||
float3 nor1 = unpack_unitvector(asuint(pos_nor1.w));
|
||||
float3 nor2 = unpack_unitvector(asuint(pos_nor2.w));
|
||||
float3 nor0 = meshVertexBuffer_NOR[i0].xyz;
|
||||
float3 nor1 = meshVertexBuffer_NOR[i1].xyz;
|
||||
float3 nor2 = meshVertexBuffer_NOR[i2].xyz;
|
||||
|
||||
// random barycentric coords:
|
||||
float f = rng.next_float();
|
||||
@@ -59,7 +60,8 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
float2 bary = float2(f, g);
|
||||
|
||||
// compute final surface position on triangle from barycentric coords:
|
||||
emitPos = attribute_at_bary(pos_nor0.xyz, pos_nor1.xyz, pos_nor2.xyz, bary);
|
||||
emitPos = attribute_at_bary(pos0.xyz, pos1.xyz, pos2.xyz, bary);
|
||||
emitPos = mul(xEmitterBaseMeshUnormRemap.GetMatrix(), float4(emitPos, 1)).xyz;
|
||||
float3 nor = normalize(attribute_at_bary(nor0, nor1, nor2, bary));
|
||||
nor = normalize(mul((float3x3)worldMatrix, nor));
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@ RWStructuredBuffer<uint> aliveBuffer_NEW : register(u2);
|
||||
RWStructuredBuffer<uint> deadBuffer : register(u3);
|
||||
RWByteAddressBuffer counterBuffer : register(u4);
|
||||
RWStructuredBuffer<float> distanceBuffer : register(u6);
|
||||
RWBuffer<float4> vertexBuffer_POS : register(u7);
|
||||
RWBuffer<float4> vertexBuffer_UVS : register(u8);
|
||||
RWBuffer<float4> vertexBuffer_COL : register(u9);
|
||||
RWStructuredBuffer<uint> culledIndirectionBuffer : register(u10);
|
||||
RWStructuredBuffer<uint> culledIndirectionBuffer2 : register(u11);
|
||||
RWByteAddressBuffer vertexBuffer_POS : register(u7);
|
||||
RWBuffer<float4> vertexBuffer_NOR : register(u8);
|
||||
RWBuffer<float4> vertexBuffer_UVS : register(u9);
|
||||
RWBuffer<float4> vertexBuffer_COL : register(u10);
|
||||
RWStructuredBuffer<uint> culledIndirectionBuffer : register(u11);
|
||||
RWStructuredBuffer<uint> culledIndirectionBuffer2 : register(u12);
|
||||
|
||||
//#define SPH_FLOOR_COLLISION
|
||||
//#define SPH_BOX_COLLISION
|
||||
@@ -319,7 +320,8 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex)
|
||||
quadPos = mul(quadPos, (float3x3)GetCamera().view); // reversed mul for inverse camera rotation!
|
||||
|
||||
// write out vertex:
|
||||
vertexBuffer_POS[v0 + vertexID] = float4(particle.position + quadPos, asfloat(pack_unitvector(normalize(-GetCamera().forward))));
|
||||
vertexBuffer_POS.Store<float3>((v0 + vertexID) * sizeof(float3), particle.position + quadPos);
|
||||
vertexBuffer_NOR[v0 + vertexID] = float4(normalize(-GetCamera().forward), 0);
|
||||
vertexBuffer_UVS[v0 + vertexID] = float4(uv, uv2);
|
||||
vertexBuffer_COL[v0 + vertexID] = unpack_rgba(particleColorPacked);
|
||||
}
|
||||
@@ -353,10 +355,10 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex)
|
||||
counterBuffer.InterlockedAdd(PARTICLECOUNTER_OFFSET_DEADCOUNT, 1, deadIndex);
|
||||
deadBuffer[deadIndex] = particleIndex;
|
||||
|
||||
vertexBuffer_POS[v0 + 0] = 0;
|
||||
vertexBuffer_POS[v0 + 1] = 0;
|
||||
vertexBuffer_POS[v0 + 2] = 0;
|
||||
vertexBuffer_POS[v0 + 3] = 0;
|
||||
vertexBuffer_POS.Store<float3>((v0 + 0) * sizeof(float3), 0);
|
||||
vertexBuffer_POS.Store<float3>((v0 + 1) * sizeof(float3), 0);
|
||||
vertexBuffer_POS.Store<float3>((v0 + 2) * sizeof(float3), 0);
|
||||
vertexBuffer_POS.Store<float3>((v0 + 3) * sizeof(float3), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -435,6 +435,12 @@ inline float3 clipspace_to_uv(in float3 clipspace)
|
||||
return clipspace * float3(0.5, -0.5, 0.5) + 0.5;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T inverse_lerp(T value1, T value2, T pos)
|
||||
{
|
||||
return all(value2 == value1) ? 0 : ((pos - value1) / (value2 - value1));
|
||||
}
|
||||
|
||||
inline float3 GetSunColor() { return GetWeather().sun_color; } // sun color with intensity applied
|
||||
inline float3 GetSunDirection() { return GetWeather().sun_direction; }
|
||||
inline float3 GetHorizonColor() { return GetWeather().horizon.rgb; }
|
||||
|
||||
@@ -6,15 +6,16 @@ Buffer<uint> primitiveBuffer : register(t0);
|
||||
|
||||
VertexToPixel main(uint vid : SV_VERTEXID)
|
||||
{
|
||||
ShaderMeshInstance inst = HairGetInstance();
|
||||
ShaderGeometry geometry = HairGetGeometry();
|
||||
|
||||
VertexToPixel Out;
|
||||
Out.primitiveID = vid / 3;
|
||||
|
||||
uint vertexID = primitiveBuffer[vid];
|
||||
float4 pos_nor_wind = bindless_buffers_float4[geometry.vb_pos_nor_wind][vertexID];
|
||||
float3 position = pos_nor_wind.xyz;
|
||||
float3 normal = normalize(unpack_unitvector(asuint(pos_nor_wind.w)));
|
||||
float4 pos_wind = bindless_buffers_float4[geometry.vb_pos_wind][vertexID];
|
||||
float3 position = mul(inst.transform.GetMatrix(), float4(pos_wind.xyz, 1)).xyz;
|
||||
float3 normal = normalize(bindless_buffers_float4[geometry.vb_nor][vertexID].xyz);
|
||||
float4 uvsets = bindless_buffers_float4[geometry.vb_uvs][vertexID];
|
||||
|
||||
Out.fade = saturate(distance(position.xyz, GetCamera().position.xyz) / xHairViewDistance);
|
||||
|
||||
@@ -11,20 +11,24 @@ static const float3 HAIRPATCH[] = {
|
||||
|
||||
Buffer<uint> meshIndexBuffer : register(t0);
|
||||
Buffer<float4> meshVertexBuffer_POS : register(t1);
|
||||
Buffer<float> meshVertexBuffer_length : register(t2);
|
||||
Buffer<float4> meshVertexBuffer_NOR : register(t2);
|
||||
Buffer<float> meshVertexBuffer_length : register(t3);
|
||||
|
||||
RWStructuredBuffer<PatchSimulationData> simulationBuffer : register(u0);
|
||||
RWBuffer<float4> vertexBuffer_POS : register(u1);
|
||||
RWBuffer<float4> vertexBuffer_UVS : register(u2);
|
||||
RWBuffer<uint> culledIndexBuffer : register(u3);
|
||||
RWStructuredBuffer<IndirectDrawArgsIndexedInstanced> indirectBuffer : register(u4);
|
||||
RWByteAddressBuffer vertexBuffer_POS_RT : register(u5);
|
||||
RWBuffer<float4> vertexBuffer_POS_RT : register(u5);
|
||||
RWBuffer<float4> vertexBuffer_NOR : register(u6);
|
||||
|
||||
[numthreads(THREADCOUNT_SIMULATEHAIR, 1, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex)
|
||||
{
|
||||
if (DTid.x >= xHairParticleCount)
|
||||
return;
|
||||
|
||||
ShaderGeometry geometry = HairGetGeometry();
|
||||
|
||||
RNG rng;
|
||||
rng.init(uint2(xHairRandomSeed, DTid.x), 0);
|
||||
@@ -39,12 +43,12 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn
|
||||
uint i2 = meshIndexBuffer[tri * 3 + 2];
|
||||
|
||||
// load vertices of triangle from vertex buffer:
|
||||
float4 pos_nor0 = meshVertexBuffer_POS[i0];
|
||||
float4 pos_nor1 = meshVertexBuffer_POS[i1];
|
||||
float4 pos_nor2 = meshVertexBuffer_POS[i2];
|
||||
float3 nor0 = unpack_unitvector(asuint(pos_nor0.w));
|
||||
float3 nor1 = unpack_unitvector(asuint(pos_nor1.w));
|
||||
float3 nor2 = unpack_unitvector(asuint(pos_nor2.w));
|
||||
float3 pos0 = meshVertexBuffer_POS[i0].xyz;
|
||||
float3 pos1 = meshVertexBuffer_POS[i1].xyz;
|
||||
float3 pos2 = meshVertexBuffer_POS[i2].xyz;
|
||||
float3 nor0 = meshVertexBuffer_NOR[i0].xyz;
|
||||
float3 nor1 = meshVertexBuffer_NOR[i1].xyz;
|
||||
float3 nor2 = meshVertexBuffer_NOR[i2].xyz;
|
||||
float length0 = meshVertexBuffer_length[i0];
|
||||
float length1 = meshVertexBuffer_length[i1];
|
||||
float length2 = meshVertexBuffer_length[i2];
|
||||
@@ -61,7 +65,8 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn
|
||||
float2 bary = float2(f, g);
|
||||
|
||||
// compute final surface position on triangle from barycentric coords:
|
||||
float3 position = attribute_at_bary(pos_nor0.xyz, pos_nor1.xyz, pos_nor2.xyz, bary);
|
||||
float3 position = attribute_at_bary(pos0, pos1, pos2, bary);
|
||||
position = mul(xHairBaseMeshUnormRemap.GetMatrix(), float4(position, 1)).xyz;
|
||||
float3 target = normalize(attribute_at_bary(nor0, nor1, nor2, bary));
|
||||
float3 tangent = normalize(mul(float3(hemispherepoint_cos(rng.next_float(), rng.next_float()).xy, 0), get_tangentspace(target)));
|
||||
float3 binormal = cross(target, tangent);
|
||||
@@ -269,15 +274,17 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn
|
||||
const float3 wind = sample_wind(rootposition, segmentID + patchPos.y);
|
||||
|
||||
float3 position = rootposition + patchPos + wind;
|
||||
position = inverse_lerp(geometry.aabb_min, geometry.aabb_max, position); // remap to UNORM
|
||||
|
||||
vertexBuffer_POS[v0 + vertexID] = float4(position, asfloat(pack_unitvector(normalize(normal + wind))));
|
||||
vertexBuffer_POS[v0 + vertexID] = float4(position, 0);
|
||||
vertexBuffer_NOR[v0 + vertexID] = float4(normalize(normal + wind), 0);
|
||||
vertexBuffer_UVS[v0 + vertexID] = uv.xyxy; // a second uv set could be used here
|
||||
|
||||
if (distance_culled)
|
||||
{
|
||||
position = 0; // We can only zero out for raytracing geometry to keep correct prevpos swapping motion vectors!
|
||||
}
|
||||
vertexBuffer_POS_RT.Store<float3>((v0 + vertexID) * sizeof(float3), position);
|
||||
vertexBuffer_POS_RT[v0 + vertexID] = float4(position, 0);
|
||||
}
|
||||
|
||||
// Frustum culling:
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
struct VSOut
|
||||
{
|
||||
precise float4 pos : SV_Position;
|
||||
float clip : SV_ClipDistance0;
|
||||
float2 uv : TEXCOORD;
|
||||
uint slice : SLICE;
|
||||
nointerpolation float dither : DITHER;
|
||||
|
||||
@@ -8,7 +8,7 @@ static const float2 BILLBOARD[] = {
|
||||
float2(1, 1),
|
||||
};
|
||||
|
||||
Buffer<float4> vb_pos_nor : register(t0);
|
||||
Buffer<float4> vb_pos : register(t0);
|
||||
ByteAddressBuffer impostor_data : register(t2);
|
||||
|
||||
VSOut main(uint vertexID : SV_VertexID)
|
||||
@@ -16,7 +16,8 @@ VSOut main(uint vertexID : SV_VertexID)
|
||||
uint2 data = impostor_data.Load2((vertexID / 4u) * sizeof(uint2));
|
||||
|
||||
VSOut Out;
|
||||
Out.pos3D = vb_pos_nor[vertexID].xyz;
|
||||
Out.pos3D = vb_pos[vertexID].xyz;
|
||||
Out.clip = dot(float4(Out.pos3D, 1), GetCamera().clip_plane);
|
||||
Out.pos = mul(GetCamera().view_projection, float4(Out.pos3D, 1));
|
||||
Out.uv = float2(BILLBOARD[vertexID % 4u] * float2(0.5f, -0.5f) + 0.5f);
|
||||
Out.slice = data.x & 0xFFFFFF;
|
||||
|
||||
@@ -11,9 +11,10 @@ static const float3 BILLBOARD[] =
|
||||
};
|
||||
|
||||
RWBuffer<uint> output_indices : register(u0);
|
||||
RWBuffer<float4> output_vertices_pos_nor : register(u1);
|
||||
RWByteAddressBuffer output_impostor_data : register(u2);
|
||||
RWStructuredBuffer<IndirectDrawArgsIndexedInstanced> output_indirect : register(u3);
|
||||
RWByteAddressBuffer output_vertices_pos : register(u1);
|
||||
RWBuffer<float4> output_vertices_nor : register(u2);
|
||||
RWByteAddressBuffer output_impostor_data : register(u3);
|
||||
RWStructuredBuffer<IndirectDrawArgsIndexedInstanced> output_indirect : register(u4);
|
||||
|
||||
struct ObjectCount
|
||||
{
|
||||
@@ -103,7 +104,8 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
pos = mul(pos, float3x3(right, up, face));
|
||||
pos *= instance.radius;
|
||||
pos += instance.center;
|
||||
output_vertices_pos_nor[vertexOffset + vertexID] = float4(pos, asfloat(pack_unitvector(face)));
|
||||
output_vertices_pos.Store<float3>((vertexOffset + vertexID) * sizeof(float3), pos);
|
||||
output_vertices_nor[vertexOffset + vertexID] = float4(face, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,17 +121,17 @@ struct VertexInput
|
||||
uint vertexID : SV_VertexID;
|
||||
uint instanceID : SV_InstanceID;
|
||||
|
||||
float4 GetPositionNormalWind()
|
||||
float4 GetPositionWind()
|
||||
{
|
||||
return bindless_buffers_float4[GetMesh().vb_pos_nor_wind][vertexID];
|
||||
return bindless_buffers_float4[GetMesh().vb_pos_wind][vertexID];
|
||||
}
|
||||
|
||||
min16float4 GetUVSets()
|
||||
float4 GetUVSets()
|
||||
{
|
||||
[branch]
|
||||
if (GetMesh().vb_uvs < 0)
|
||||
return 0;
|
||||
return (min16float4)bindless_buffers_float4[GetMesh().vb_uvs][vertexID];
|
||||
return lerp(GetMesh().uv_range_min.xyxy, GetMesh().uv_range_max.xyxy, bindless_buffers_float4[GetMesh().vb_uvs][vertexID]);
|
||||
}
|
||||
|
||||
ShaderMeshInstancePointer GetInstancePointer()
|
||||
@@ -159,6 +159,14 @@ struct VertexInput
|
||||
return 1;
|
||||
return (min16float4)bindless_buffers_float4[GetMesh().vb_col][vertexID];
|
||||
}
|
||||
|
||||
min16float3 GetNormal()
|
||||
{
|
||||
[branch]
|
||||
if (GetMesh().vb_nor < 0)
|
||||
return 0;
|
||||
return (min16float3)bindless_buffers_float4[GetMesh().vb_nor][vertexID].xyz;
|
||||
}
|
||||
|
||||
min16float4 GetTangent()
|
||||
{
|
||||
@@ -191,10 +199,9 @@ struct VertexSurface
|
||||
|
||||
inline void create(in ShaderMaterial material, in VertexInput input)
|
||||
{
|
||||
float4 pos_nor_wind = input.GetPositionNormalWind();
|
||||
uint normal_wind = asuint(pos_nor_wind.w);
|
||||
position = float4(pos_nor_wind.xyz, 1);
|
||||
normal = min16float3(unpack_unitvector(normal_wind));
|
||||
float4 pos_wind = input.GetPositionWind();
|
||||
position = float4(pos_wind.xyz, 1);
|
||||
normal = input.GetNormal();
|
||||
color = min16float4(GetMaterial().baseColor * unpack_rgba(input.GetInstance().color));
|
||||
color.a *= min16float(1 - input.GetInstancePointer().GetDither());
|
||||
|
||||
@@ -223,7 +230,7 @@ struct VertexSurface
|
||||
[branch]
|
||||
if (material.IsUsingWind())
|
||||
{
|
||||
position.xyz += sample_wind(position.xyz, ((normal_wind >> 24u) & 0xFF) / 255.0);
|
||||
position.xyz += sample_wind(position.xyz, pos_wind.w);
|
||||
}
|
||||
#endif // DISABLE_WIND
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "globals.hlsli"
|
||||
|
||||
float4 main(float4 inPos : POSITION_NORMAL_WIND) : SV_POSITION
|
||||
{
|
||||
float4 pos = mul(g_xTransform, float4(inPos.xyz, 1));
|
||||
PUSHCONSTANT(push, DebugObjectPushConstants);
|
||||
|
||||
return pos;
|
||||
float4 main(uint vertexID : SV_VertexID) : SV_POSITION
|
||||
{
|
||||
return mul(g_xTransform, float4(bindless_buffers_float4[push.vb_pos_wind][vertexID].xyz, 1));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
#include "globals.hlsli"
|
||||
#include "ShaderInterop_Raytracing.h"
|
||||
|
||||
struct Input
|
||||
{
|
||||
float4 pos : POSITION_NORMAL_WIND;
|
||||
float2 atl : ATLAS;
|
||||
};
|
||||
PUSHCONSTANT(push, LightmapPushConstants);
|
||||
|
||||
struct Output
|
||||
{
|
||||
@@ -15,24 +11,25 @@ struct Output
|
||||
float3 normal : NORMAL;
|
||||
};
|
||||
|
||||
Output main(Input input)
|
||||
Output main(uint vertexID : SV_VertexID)
|
||||
{
|
||||
ShaderMeshInstance inst = load_instance(push.instanceIndex);
|
||||
float3 pos = bindless_buffers_float4[push.vb_pos_wind][vertexID].xyz;
|
||||
float3 nor = bindless_buffers_float4[push.vb_nor][vertexID].xyz;
|
||||
float2 atl = bindless_buffers_float2[push.vb_atl][vertexID];
|
||||
|
||||
Output output;
|
||||
|
||||
output.pos = float4(input.atl, 0, 1);
|
||||
output.pos = float4(atl, 0, 1);
|
||||
output.pos.xy = output.pos.xy * 2 - 1;
|
||||
output.pos.y *= -1;
|
||||
output.pos.xy += xTracePixelOffset;
|
||||
|
||||
output.uv = input.atl;
|
||||
output.uv = atl;
|
||||
|
||||
output.pos3D = mul(g_xTransform, float4(input.pos.xyz, 1)).xyz;
|
||||
output.pos3D = mul(inst.transform.GetMatrix(), float4(pos, 1)).xyz;
|
||||
|
||||
uint normal_wind = asuint(input.pos.w);
|
||||
output.normal.x = (float)((normal_wind >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f;
|
||||
output.normal.y = (float)((normal_wind >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f;
|
||||
output.normal.z = (float)((normal_wind >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f;
|
||||
output.normal = mul((float3x3)g_xTransform, output.normal);
|
||||
output.normal = mul((float3x3)inst.transformInverseTranspose.GetMatrix(), nor);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -2,24 +2,72 @@
|
||||
|
||||
PUSHCONSTANT(push, SkinningPushConstants);
|
||||
|
||||
#ifndef __PSSL__
|
||||
#undef WICKED_ENGINE_DEFAULT_ROOTSIGNATURE // don't use auto root signature!
|
||||
[RootSignature(
|
||||
"RootConstants(num32BitConstants=20, b999),"
|
||||
"DescriptorTable( "
|
||||
"SRV(t0, space = 2, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 3, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 4, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 5, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 6, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 7, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 8, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 9, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 10, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 11, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 12, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 13, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 14, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 15, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 16, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 17, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 18, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 19, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 20, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 21, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 22, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 23, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 24, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 25, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 26, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 27, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 28, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 29, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 30, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 31, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 32, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"UAV(u0, space = 33, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 34, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 35, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 36, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 37, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 38, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 39, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)," \
|
||||
"SRV(t0, space = 40, offset = 0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE | DATA_VOLATILE)" \
|
||||
")"
|
||||
)]
|
||||
#endif // __PSSL__
|
||||
|
||||
[numthreads(64, 1, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID)
|
||||
{
|
||||
const uint vertexID = DTid.x;
|
||||
|
||||
[branch]
|
||||
if (push.vb_pos_nor_wind < 0 || vertexID >= push.vertexCount)
|
||||
if (push.vb_pos_wind < 0 || vertexID >= push.vertexCount)
|
||||
return;
|
||||
|
||||
float4 pos_nor_wind = bindless_buffers_float4[push.vb_pos_nor_wind][vertexID];
|
||||
uint nor_wind = asuint(pos_nor_wind.w);
|
||||
float4 pos_wind = bindless_buffers_float4[push.vb_pos_wind][vertexID];
|
||||
float3 nor = bindless_buffers_float4[push.vb_nor][vertexID].xyz;
|
||||
|
||||
float3 pos = pos_nor_wind.xyz;
|
||||
float4 nor = 0;
|
||||
nor.x = (float)((nor_wind >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f;
|
||||
nor.y = (float)((nor_wind >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f;
|
||||
nor.z = (float)((nor_wind >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f;
|
||||
nor.w = (float)((nor_wind >> 24) & 0x000000FF) / 255.0f; // wind
|
||||
float3 pos = pos_wind.xyz;
|
||||
if(any(push.aabb_min) || any(push.aabb_max))
|
||||
{
|
||||
// UNORM vertex position remap:
|
||||
pos = lerp(push.aabb_min, push.aabb_max, pos);
|
||||
}
|
||||
|
||||
float4 tan = bindless_buffers_float4[push.vb_tan][vertexID];
|
||||
|
||||
@@ -92,15 +140,15 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID)
|
||||
|
||||
// Store data:
|
||||
[branch]
|
||||
if (push.so_pos_nor_wind >= 0)
|
||||
if (push.so_pos >= 0)
|
||||
{
|
||||
uint nor_wind = 0;
|
||||
nor_wind |= uint((nor.x * 0.5f + 0.5f) * 255.0f) << 0;
|
||||
nor_wind |= uint((nor.y * 0.5f + 0.5f) * 255.0f) << 8;
|
||||
nor_wind |= uint((nor.z * 0.5f + 0.5f) * 255.0f) << 16;
|
||||
nor_wind |= uint(nor.w * 255.0f) << 24; // wind
|
||||
pos_nor_wind = float4(pos.xyz, asfloat(nor_wind));
|
||||
bindless_rwbuffers_float4[push.so_pos_nor_wind][vertexID] = pos_nor_wind;
|
||||
bindless_rwbuffers[push.so_pos].Store<float3>(vertexID * sizeof(float3), pos);
|
||||
}
|
||||
|
||||
[branch]
|
||||
if (push.so_nor >= 0)
|
||||
{
|
||||
bindless_rwbuffers_float4[push.so_nor][vertexID] = float4(nor, 0);
|
||||
}
|
||||
|
||||
[branch]
|
||||
|
||||
@@ -331,7 +331,7 @@ struct Surface
|
||||
return false;
|
||||
|
||||
geometry = load_geometry(inst.geometryOffset + prim.subsetIndex);
|
||||
if (geometry.vb_pos_nor_wind < 0)
|
||||
if (geometry.vb_pos_wind < 0)
|
||||
return false;
|
||||
|
||||
material = load_material(geometry.materialIndex);
|
||||
@@ -345,7 +345,7 @@ struct Surface
|
||||
i1 = indexBuffer[startIndex + 1];
|
||||
i2 = indexBuffer[startIndex + 2];
|
||||
|
||||
Buffer<float4> buf = bindless_buffers_float4[NonUniformResourceIndex(geometry.vb_pos_nor_wind)];
|
||||
Buffer<float4> buf = bindless_buffers_float4[NonUniformResourceIndex(geometry.vb_pos_wind)];
|
||||
data0 = buf[i0];
|
||||
data1 = buf[i1];
|
||||
data2 = buf[i2];
|
||||
@@ -360,13 +360,19 @@ struct Surface
|
||||
const bool is_emittedparticle = geometry.flags & SHADERMESH_FLAG_EMITTEDPARTICLE;
|
||||
const bool simple_lighting = is_hairparticle || is_emittedparticle;
|
||||
const bool is_backface = flags & SURFACE_FLAG_BACKFACE;
|
||||
|
||||
float3 n0 = unpack_unitvector(asuint(data0.w));
|
||||
float3 n1 = unpack_unitvector(asuint(data1.w));
|
||||
float3 n2 = unpack_unitvector(asuint(data2.w));
|
||||
N = attribute_at_bary(n0, n1, n2, bary);
|
||||
N = mul((float3x3)inst.transformInverseTranspose.GetMatrix(), N);
|
||||
N = normalize(N);
|
||||
|
||||
[branch]
|
||||
if (geometry.vb_nor >= 0)
|
||||
{
|
||||
Buffer<float4> buf = bindless_buffers_float4[NonUniformResourceIndex(geometry.vb_nor)];
|
||||
float3 n0 = buf[i0].xyz;
|
||||
float3 n1 = buf[i1].xyz;
|
||||
float3 n2 = buf[i2].xyz;
|
||||
N = attribute_at_bary(n0, n1, n2, bary);
|
||||
N = mul((float3x3)inst.transformInverseTranspose.GetMatrix(), N);
|
||||
N = normalize(N);
|
||||
}
|
||||
|
||||
if (is_backface && !is_hairparticle && !is_emittedparticle)
|
||||
{
|
||||
N = -N;
|
||||
@@ -396,9 +402,9 @@ struct Surface
|
||||
if (geometry.vb_uvs >= 0)
|
||||
{
|
||||
Buffer<float4> buf = bindless_buffers_float4[NonUniformResourceIndex(geometry.vb_uvs)];
|
||||
float4 uv0 = buf[i0];
|
||||
float4 uv1 = buf[i1];
|
||||
float4 uv2 = buf[i2];
|
||||
float4 uv0 = lerp(geometry.uv_range_min.xyxy, geometry.uv_range_max.xyxy, buf[i0]);
|
||||
float4 uv1 = lerp(geometry.uv_range_min.xyxy, geometry.uv_range_max.xyxy, buf[i1]);
|
||||
float4 uv2 = lerp(geometry.uv_range_min.xyxy, geometry.uv_range_max.xyxy, buf[i2]);
|
||||
// all three must be transformed, to have correct derivatives (not enough to only transform final uvsets):
|
||||
uv0.xy = mad(uv0.xy, material.texMulAdd.xy, material.texMulAdd.zw);
|
||||
uv1.xy = mad(uv1.xy, material.texMulAdd.xy, material.texMulAdd.zw);
|
||||
@@ -882,12 +888,9 @@ struct Surface
|
||||
[branch]
|
||||
if (material.IsUsingWind())
|
||||
{
|
||||
float wind0 = ((asuint(data0.w) >> 24u) & 0xFF) / 255.0;
|
||||
float wind1 = ((asuint(data1.w) >> 24u) & 0xFF) / 255.0;
|
||||
float wind2 = ((asuint(data2.w) >> 24u) & 0xFF) / 255.0;
|
||||
pre0 += sample_wind_prev(pre0, wind0);
|
||||
pre1 += sample_wind_prev(pre1, wind1);
|
||||
pre2 += sample_wind_prev(pre2, wind2);
|
||||
pre0 += sample_wind_prev(pre0, data0.w);
|
||||
pre1 += sample_wind_prev(pre1, data1.w);
|
||||
pre2 += sample_wind_prev(pre2, data2.w);
|
||||
}
|
||||
pre = attribute_at_bary(pre0, pre1, pre2, bary);
|
||||
#else
|
||||
@@ -959,12 +962,9 @@ struct Surface
|
||||
[branch]
|
||||
if (material.IsUsingWind())
|
||||
{
|
||||
float wind0 = ((asuint(data0.w) >> 24u) & 0xFF) / 255.0;
|
||||
float wind1 = ((asuint(data1.w) >> 24u) & 0xFF) / 255.0;
|
||||
float wind2 = ((asuint(data2.w) >> 24u) & 0xFF) / 255.0;
|
||||
P0 += sample_wind(P0, wind0);
|
||||
P1 += sample_wind(P1, wind1);
|
||||
P2 += sample_wind(P2, wind2);
|
||||
P0 += sample_wind(P0, data0.w);
|
||||
P1 += sample_wind(P1, data1.w);
|
||||
P2 += sample_wind(P2, data2.w);
|
||||
}
|
||||
#endif // SURFACE_LOAD_ENABLE_WIND
|
||||
|
||||
@@ -1003,14 +1003,9 @@ struct Surface
|
||||
[branch]
|
||||
if (material.IsUsingWind())
|
||||
{
|
||||
float wind0 = ((asuint(data0.w) >> 24u) & 0xFF) / 255.0;
|
||||
float wind1 = ((asuint(data1.w) >> 24u) & 0xFF) / 255.0;
|
||||
float wind2 = ((asuint(data2.w) >> 24u) & 0xFF) / 255.0;
|
||||
|
||||
// this is hella slow to do per pixel:
|
||||
P0 += sample_wind(P0, wind0);
|
||||
P1 += sample_wind(P1, wind1);
|
||||
P2 += sample_wind(P2, wind2);
|
||||
P0 += sample_wind(P0, data0.w);
|
||||
P1 += sample_wind(P1, data1.w);
|
||||
P2 += sample_wind(P2, data2.w);
|
||||
}
|
||||
#endif // SURFACE_LOAD_ENABLE_WIND
|
||||
|
||||
|
||||
@@ -104,12 +104,14 @@ namespace wi
|
||||
}
|
||||
const uint64_t alignment = device->GetMinOffsetAlignment(&bd);
|
||||
|
||||
vb_pos.size = sizeof(MeshComponent::Vertex_POS) * 4 * MAX_PARTICLES;
|
||||
vb_pos.size = sizeof(MeshComponent::Vertex_POS32) * 4 * MAX_PARTICLES;
|
||||
vb_nor.size = sizeof(MeshComponent::Vertex_NOR) * 4 * MAX_PARTICLES;
|
||||
vb_uvs.size = sizeof(MeshComponent::Vertex_UVS) * 4 * MAX_PARTICLES;
|
||||
vb_col.size = sizeof(MeshComponent::Vertex_COL) * 4 * MAX_PARTICLES;
|
||||
|
||||
bd.size =
|
||||
AlignTo(vb_pos.size, alignment) +
|
||||
AlignTo(vb_nor.size, alignment) +
|
||||
AlignTo(vb_uvs.size, alignment) +
|
||||
AlignTo(vb_col.size, alignment)
|
||||
;
|
||||
@@ -121,11 +123,18 @@ namespace wi
|
||||
|
||||
vb_pos.offset = buffer_offset;
|
||||
buffer_offset += AlignTo(vb_pos.size, alignment);
|
||||
vb_pos.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos.offset, vb_pos.size, &MeshComponent::Vertex_POS::FORMAT);
|
||||
vb_pos.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos.offset, vb_pos.size, &MeshComponent::Vertex_POS::FORMAT);
|
||||
vb_pos.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos.offset, vb_pos.size, &MeshComponent::Vertex_POS32::FORMAT);
|
||||
vb_pos.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos.offset, vb_pos.size); // UAV can't have RGB32_F format!
|
||||
vb_pos.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_pos.subresource_srv);
|
||||
vb_pos.descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_pos.subresource_uav);
|
||||
|
||||
vb_nor.offset = buffer_offset;
|
||||
buffer_offset += AlignTo(vb_nor.size, alignment);
|
||||
vb_nor.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_nor.offset, vb_nor.size, &MeshComponent::Vertex_NOR::FORMAT);
|
||||
vb_nor.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_nor.offset, vb_nor.size, &MeshComponent::Vertex_NOR::FORMAT);
|
||||
vb_nor.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_nor.subresource_srv);
|
||||
vb_nor.descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_nor.subresource_uav);
|
||||
|
||||
vb_uvs.offset = buffer_offset;
|
||||
buffer_offset += AlignTo(vb_uvs.size, alignment);
|
||||
vb_uvs.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_uvs.offset, vb_uvs.size, &MeshComponent::Vertex_UVS::FORMAT);
|
||||
@@ -278,9 +287,9 @@ namespace wi
|
||||
geometry.triangles.index_format = GetIndexBufferFormat(primitiveBuffer.desc.format);
|
||||
geometry.triangles.index_count = MAX_PARTICLES * 6;
|
||||
geometry.triangles.index_offset = 0;
|
||||
geometry.triangles.vertex_count = (uint32_t)(vb_pos.size / sizeof(MeshComponent::Vertex_POS));
|
||||
geometry.triangles.vertex_format = Format::R32G32B32_FLOAT;
|
||||
geometry.triangles.vertex_stride = sizeof(MeshComponent::Vertex_POS);
|
||||
geometry.triangles.vertex_count = (uint32_t)(vb_pos.size / sizeof(MeshComponent::Vertex_POS32));
|
||||
geometry.triangles.vertex_format = MeshComponent::Vertex_POS32::FORMAT;
|
||||
geometry.triangles.vertex_stride = sizeof(MeshComponent::Vertex_POS32);
|
||||
|
||||
bool success = device->CreateRaytracingAccelerationStructure(&desc, &BLAS);
|
||||
assert(success);
|
||||
@@ -365,6 +374,16 @@ namespace wi
|
||||
{
|
||||
EmittedParticleCB cb;
|
||||
cb.xEmitterTransform.Create(worldMatrix);
|
||||
if (mesh == nullptr || !IsFormatUnorm(mesh->position_format) || mesh->so_pos.IsValid())
|
||||
{
|
||||
cb.xEmitterBaseMeshUnormRemap.init();
|
||||
}
|
||||
else
|
||||
{
|
||||
XMFLOAT4X4 unormRemap;
|
||||
XMStoreFloat4x4(&unormRemap, mesh->aabb.getUnormRemapMatrix());
|
||||
cb.xEmitterBaseMeshUnormRemap.Create(unormRemap);
|
||||
}
|
||||
cb.xEmitCount = (uint32_t)emit;
|
||||
cb.xEmitterMeshIndexCount = mesh == nullptr ? 0 : (uint32_t)mesh->indices.size();
|
||||
cb.xEmitterRandomness = wi::random::GetRandom(0.0f, 1.0f);
|
||||
@@ -446,21 +465,24 @@ namespace wi
|
||||
device->BindUAV(&indirectBuffers, 5, cmd);
|
||||
device->BindUAV(&distanceBuffer, 6, cmd);
|
||||
device->BindUAV(&generalBuffer, 7, cmd, vb_pos.subresource_uav);
|
||||
device->BindUAV(&generalBuffer, 8, cmd, vb_uvs.subresource_uav);
|
||||
device->BindUAV(&generalBuffer, 9, cmd, vb_col.subresource_uav);
|
||||
device->BindUAV(&culledIndirectionBuffer, 10, cmd);
|
||||
device->BindUAV(&culledIndirectionBuffer2, 11, cmd);
|
||||
device->BindUAV(&generalBuffer, 8, cmd, vb_nor.subresource_uav);
|
||||
device->BindUAV(&generalBuffer, 9, cmd, vb_uvs.subresource_uav);
|
||||
device->BindUAV(&generalBuffer, 10, cmd, vb_col.subresource_uav);
|
||||
device->BindUAV(&culledIndirectionBuffer, 11, cmd);
|
||||
device->BindUAV(&culledIndirectionBuffer2, 12, cmd);
|
||||
|
||||
if (mesh != nullptr)
|
||||
{
|
||||
device->BindResource(&mesh->generalBuffer, 0, cmd, mesh->ib.subresource_srv);
|
||||
if (mesh->streamoutBuffer.IsValid())
|
||||
{
|
||||
device->BindResource(&mesh->streamoutBuffer, 1, cmd, mesh->so_pos_nor_wind.subresource_srv);
|
||||
device->BindResource(&mesh->streamoutBuffer, 1, cmd, mesh->so_pos.subresource_srv);
|
||||
device->BindResource(&mesh->streamoutBuffer, 2, cmd, mesh->so_nor.subresource_srv);
|
||||
}
|
||||
else
|
||||
{
|
||||
device->BindResource(&mesh->generalBuffer, 1, cmd, mesh->vb_pos_nor_wind.subresource_srv);
|
||||
device->BindResource(&mesh->generalBuffer, 1, cmd, mesh->vb_pos_wind.subresource_srv);
|
||||
device->BindResource(&mesh->generalBuffer, 2, cmd, mesh->vb_nor.subresource_srv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,10 +646,11 @@ namespace wi
|
||||
device->BindUAV(&indirectBuffers, 5, cmd);
|
||||
device->BindUAV(&distanceBuffer, 6, cmd);
|
||||
device->BindUAV(&generalBuffer, 7, cmd, vb_pos.subresource_uav);
|
||||
device->BindUAV(&generalBuffer, 8, cmd, vb_uvs.subresource_uav);
|
||||
device->BindUAV(&generalBuffer, 9, cmd, vb_col.subresource_uav);
|
||||
device->BindUAV(&culledIndirectionBuffer, 10, cmd);
|
||||
device->BindUAV(&culledIndirectionBuffer2, 11, cmd);
|
||||
device->BindUAV(&generalBuffer, 8, cmd, vb_nor.subresource_uav);
|
||||
device->BindUAV(&generalBuffer, 9, cmd, vb_uvs.subresource_uav);
|
||||
device->BindUAV(&generalBuffer, 10, cmd, vb_col.subresource_uav);
|
||||
device->BindUAV(&culledIndirectionBuffer, 11, cmd);
|
||||
device->BindUAV(&culledIndirectionBuffer2, 12, cmd);
|
||||
|
||||
// update CURRENT alive list, write NEW alive list
|
||||
if (IsSorted())
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace wi
|
||||
wi::graphics::GPUBuffer constantBuffer;
|
||||
wi::graphics::GPUBuffer generalBuffer;
|
||||
wi::scene::MeshComponent::BufferView vb_pos;
|
||||
wi::scene::MeshComponent::BufferView vb_nor;
|
||||
wi::scene::MeshComponent::BufferView vb_uvs;
|
||||
wi::scene::MeshComponent::BufferView vb_col;
|
||||
wi::graphics::GPUBuffer primitiveBuffer; // raytracing
|
||||
|
||||
@@ -408,8 +408,6 @@ namespace wi::enums
|
||||
// input layouts
|
||||
enum ILTYPES
|
||||
{
|
||||
ILTYPE_OBJECT_DEBUG,
|
||||
ILTYPE_RENDERLIGHTMAP,
|
||||
ILTYPE_VERTEXCOLOR,
|
||||
ILTYPE_POSITION,
|
||||
ILTYPE_COUNT
|
||||
|
||||
@@ -48,6 +48,15 @@ namespace wi
|
||||
|
||||
void HairParticleSystem::CreateFromMesh(const wi::scene::MeshComponent& mesh)
|
||||
{
|
||||
if (mesh.so_pos.IsValid())
|
||||
{
|
||||
position_format = MeshComponent::Vertex_POS32::FORMAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
position_format = MeshComponent::Vertex_POS16::FORMAT;
|
||||
}
|
||||
|
||||
if (vertex_lengths.size() != mesh.vertex_positions.size())
|
||||
{
|
||||
vertex_lengths.resize(mesh.vertex_positions.size());
|
||||
@@ -96,22 +105,25 @@ namespace wi
|
||||
bd.misc_flags |= ResourceMiscFlag::RAY_TRACING;
|
||||
}
|
||||
|
||||
const size_t position_stride = GetFormatStride(position_format);
|
||||
const Format ib_format = GetIndexBufferFormatRaw(particleCount * 4);
|
||||
const uint64_t alignment = device->GetMinOffsetAlignment(&bd);
|
||||
|
||||
simulation_view.size = sizeof(PatchSimulationData) * particleCount;
|
||||
vb_pos[0].size = sizeof(MeshComponent::Vertex_POS) * 4 * particleCount;
|
||||
vb_pos[1].size = sizeof(MeshComponent::Vertex_POS) * 4 * particleCount;
|
||||
vb_pos[0].size = position_stride * 4 * particleCount;
|
||||
vb_pos[1].size = position_stride * 4 * particleCount;
|
||||
vb_nor.size = sizeof(MeshComponent::Vertex_NOR) * 4 * particleCount;
|
||||
vb_uvs.size = sizeof(MeshComponent::Vertex_UVS) * 4 * particleCount;
|
||||
ib_culled.size = GetFormatStride(ib_format) * 6 * particleCount;
|
||||
indirect_view.size = sizeof(IndirectDrawArgsIndexedInstanced);
|
||||
vb_pos_raytracing.size = sizeof(float3) * 4 * particleCount;
|
||||
vb_pos_raytracing.size = position_stride * 4 * particleCount;
|
||||
|
||||
bd.size =
|
||||
AlignTo(AlignTo(indirect_view.size, alignment), sizeof(IndirectDrawArgsIndexedInstanced)) + // additional structured buffer alignment
|
||||
AlignTo(AlignTo(simulation_view.size, alignment), sizeof(PatchSimulationData)) + // additional structured buffer alignment
|
||||
AlignTo(vb_pos[0].size, alignment) +
|
||||
AlignTo(vb_pos[1].size, alignment) +
|
||||
AlignTo(vb_nor.size, alignment) +
|
||||
AlignTo(vb_uvs.size, alignment) +
|
||||
AlignTo(ib_culled.size, alignment) +
|
||||
AlignTo(vb_pos_raytracing.size, alignment)
|
||||
@@ -144,20 +156,28 @@ namespace wi
|
||||
|
||||
buffer_offset = AlignTo(buffer_offset, alignment);
|
||||
vb_pos[0].offset = buffer_offset;
|
||||
vb_pos[0].subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos[0].offset, vb_pos[0].size, &MeshComponent::Vertex_POS::FORMAT);
|
||||
vb_pos[0].subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos[0].offset, vb_pos[0].size, &MeshComponent::Vertex_POS::FORMAT);
|
||||
vb_pos[0].subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos[0].offset, vb_pos[0].size, &position_format);
|
||||
vb_pos[0].subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos[0].offset, vb_pos[0].size, &position_format);
|
||||
vb_pos[0].descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_pos[0].subresource_srv);
|
||||
vb_pos[0].descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_pos[0].subresource_uav);
|
||||
buffer_offset += vb_pos[0].size;
|
||||
|
||||
buffer_offset = AlignTo(buffer_offset, alignment);
|
||||
vb_pos[1].offset = buffer_offset;
|
||||
vb_pos[1].subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos[1].offset, vb_pos[1].size, &MeshComponent::Vertex_POS::FORMAT);
|
||||
vb_pos[1].subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos[1].offset, vb_pos[1].size, &MeshComponent::Vertex_POS::FORMAT);
|
||||
vb_pos[1].subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos[1].offset, vb_pos[1].size, &position_format);
|
||||
vb_pos[1].subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos[1].offset, vb_pos[1].size, &position_format);
|
||||
vb_pos[1].descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_pos[1].subresource_srv);
|
||||
vb_pos[1].descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_pos[1].subresource_uav);
|
||||
buffer_offset += vb_pos[1].size;
|
||||
|
||||
buffer_offset = AlignTo(buffer_offset, alignment);
|
||||
vb_nor.offset = buffer_offset;
|
||||
vb_nor.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_nor.offset, vb_nor.size, &MeshComponent::Vertex_NOR::FORMAT);
|
||||
vb_nor.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_nor.offset, vb_nor.size, &MeshComponent::Vertex_NOR::FORMAT);
|
||||
vb_nor.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_nor.subresource_srv);
|
||||
vb_nor.descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_nor.subresource_uav);
|
||||
buffer_offset += vb_nor.size;
|
||||
|
||||
buffer_offset = AlignTo(buffer_offset, alignment);
|
||||
vb_uvs.offset = buffer_offset;
|
||||
vb_uvs.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_uvs.offset, vb_uvs.size, &MeshComponent::Vertex_UVS::FORMAT);
|
||||
@@ -176,7 +196,7 @@ namespace wi
|
||||
|
||||
buffer_offset = AlignTo(buffer_offset, alignment);
|
||||
vb_pos_raytracing.offset = buffer_offset;
|
||||
vb_pos_raytracing.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos_raytracing.offset, vb_pos_raytracing.size);
|
||||
vb_pos_raytracing.subresource_uav = device->CreateSubresource(&generalBuffer, SubresourceType::UAV, vb_pos_raytracing.offset, vb_pos_raytracing.size, &position_format);
|
||||
vb_pos_raytracing.descriptor_uav = device->GetDescriptorIndex(&generalBuffer, SubresourceType::UAV, vb_pos_raytracing.subresource_uav);
|
||||
buffer_offset += vb_pos_raytracing.size;
|
||||
|
||||
@@ -240,9 +260,9 @@ namespace wi
|
||||
geometry.triangles.index_format = GetIndexBufferFormat(primitiveBuffer.desc.format);
|
||||
geometry.triangles.index_count = GetParticleCount() * 6;
|
||||
geometry.triangles.index_offset = 0;
|
||||
geometry.triangles.vertex_count = (uint32_t)(vb_pos_raytracing.size / sizeof(float3));
|
||||
geometry.triangles.vertex_format = Format::R32G32B32_FLOAT;
|
||||
geometry.triangles.vertex_stride = sizeof(float3);
|
||||
geometry.triangles.vertex_count = (uint32_t)(vb_pos_raytracing.size / GetFormatStride(position_format));
|
||||
geometry.triangles.vertex_format = position_format == Format::R32G32B32A32_FLOAT ? Format::R32G32B32_FLOAT : position_format;
|
||||
geometry.triangles.vertex_stride = GetFormatStride(position_format);
|
||||
geometry.triangles.vertex_byte_offset = vb_pos_raytracing.offset;
|
||||
|
||||
bool success = device->CreateRaytracingAccelerationStructure(&desc, &BLAS);
|
||||
@@ -317,6 +337,16 @@ namespace wi
|
||||
}
|
||||
HairParticleCB hcb;
|
||||
hcb.xHairTransform.Create(hair.world);
|
||||
if (!IsFormatUnorm(mesh.position_format) || mesh.so_pos.IsValid())
|
||||
{
|
||||
hcb.xHairBaseMeshUnormRemap.init();
|
||||
}
|
||||
else
|
||||
{
|
||||
XMFLOAT4X4 unormRemap;
|
||||
XMStoreFloat4x4(&unormRemap, mesh.aabb.getUnormRemapMatrix());
|
||||
hcb.xHairBaseMeshUnormRemap.Create(unormRemap);
|
||||
}
|
||||
hcb.xHairRegenerate = hair.regenerate_frame ? 1 : 0;
|
||||
hcb.xLength = hair.length;
|
||||
hcb.xStiffness = hair.stiffness;
|
||||
@@ -327,7 +357,6 @@ namespace wi
|
||||
hcb.xHairRandomSeed = hair.randomSeed;
|
||||
hcb.xHairViewDistance = hair.viewDistance;
|
||||
hcb.xHairBaseMeshIndexCount = (uint)hair.indices.size();
|
||||
hcb.xHairBaseMeshVertexPositionStride = sizeof(MeshComponent::Vertex_POS);
|
||||
hcb.xHairFramesXY = uint2(std::max(1u, hair.framesX), std::max(1u, hair.framesY));
|
||||
hcb.xHairFrameCount = std::max(1u, hair.frameCount);
|
||||
hcb.xHairFrameStart = hair.frameStart;
|
||||
@@ -375,6 +404,7 @@ namespace wi
|
||||
device->BindUAV(&hair.generalBuffer, 3, cmd, hair.ib_culled.subresource_uav);
|
||||
device->BindUAV(&hair.generalBuffer, 4, cmd, hair.indirect_view.subresource_uav);
|
||||
device->BindUAV(&hair.generalBuffer, 5, cmd, hair.vb_pos_raytracing.subresource_uav);
|
||||
device->BindUAV(&hair.generalBuffer, 6, cmd, hair.vb_nor.subresource_uav);
|
||||
|
||||
if (hair.indexBuffer.IsValid())
|
||||
{
|
||||
@@ -386,13 +416,15 @@ namespace wi
|
||||
}
|
||||
if (mesh.streamoutBuffer.IsValid())
|
||||
{
|
||||
device->BindResource(&mesh.streamoutBuffer, 1, cmd, mesh.so_pos_nor_wind.subresource_srv);
|
||||
device->BindResource(&mesh.streamoutBuffer, 1, cmd, mesh.so_pos.subresource_srv);
|
||||
device->BindResource(&mesh.streamoutBuffer, 2, cmd, mesh.so_nor.subresource_srv);
|
||||
}
|
||||
else
|
||||
{
|
||||
device->BindResource(&mesh.generalBuffer, 1, cmd, mesh.vb_pos_nor_wind.subresource_srv);
|
||||
device->BindResource(&mesh.generalBuffer, 1, cmd, mesh.vb_pos_wind.subresource_srv);
|
||||
device->BindResource(&mesh.generalBuffer, 2, cmd, mesh.vb_nor.subresource_srv);
|
||||
}
|
||||
device->BindResource(&hair.vertexBuffer_length, 2, cmd);
|
||||
device->BindResource(&hair.vertexBuffer_length, 3, cmd);
|
||||
|
||||
device->Dispatch((hair.strandCount + THREADCOUNT_SIMULATEHAIR - 1) / THREADCOUNT_SIMULATEHAIR, 1, 1, cmd);
|
||||
|
||||
@@ -406,6 +438,8 @@ namespace wi
|
||||
|
||||
void HairParticleSystem::InitializeGPUDataIfNeeded(wi::graphics::CommandList cmd)
|
||||
{
|
||||
if (strandCount == 0 || !generalBuffer.IsValid())
|
||||
return;
|
||||
if (gpu_initialized)
|
||||
return;
|
||||
GraphicsDevice* device = wi::graphics::GetDevice();
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace wi
|
||||
wi::graphics::GPUBuffer generalBuffer;
|
||||
wi::scene::MeshComponent::BufferView simulation_view;
|
||||
wi::scene::MeshComponent::BufferView vb_pos[2];
|
||||
wi::scene::MeshComponent::BufferView vb_nor;
|
||||
wi::scene::MeshComponent::BufferView vb_pos_raytracing;
|
||||
wi::scene::MeshComponent::BufferView vb_uvs;
|
||||
wi::scene::MeshComponent::BufferView ib_culled;
|
||||
@@ -98,6 +99,7 @@ namespace wi
|
||||
wi::vector<uint32_t> indices; // it is dependent on vertex_lengths and contains triangles with non-zero lengths
|
||||
uint32_t layerMask = ~0u;
|
||||
mutable bool regenerate_frame = true;
|
||||
wi::graphics::Format position_format = wi::graphics::Format::R16G16B16A16_UNORM;
|
||||
|
||||
void Serialize(wi::Archive& archive, wi::ecs::EntitySerializer& seri);
|
||||
|
||||
|
||||
@@ -115,6 +115,10 @@ namespace wi::math
|
||||
{
|
||||
return XMFLOAT3((a.x + b.x)*0.5f, (a.y + b.y)*0.5f, (a.z + b.z)*0.5f);
|
||||
}
|
||||
inline XMVECTOR InverseLerp(XMVECTOR value1, XMVECTOR value2, XMVECTOR pos)
|
||||
{
|
||||
return (pos - value1) / (value2 - value1);
|
||||
}
|
||||
constexpr float InverseLerp(float value1, float value2, float pos)
|
||||
{
|
||||
return value2 == value1 ? 0 : ((pos - value1) / (value2 - value1));
|
||||
@@ -131,6 +135,10 @@ namespace wi::math
|
||||
{
|
||||
return XMFLOAT4(InverseLerp(value1.x, value2.x, pos.x), InverseLerp(value1.y, value2.y, pos.y), InverseLerp(value1.z, value2.z, pos.z), InverseLerp(value1.w, value2.w, pos.w));
|
||||
}
|
||||
inline XMVECTOR Lerp(XMVECTOR value1, XMVECTOR value2, XMVECTOR amount)
|
||||
{
|
||||
return value1 + (value2 - value1) * amount;
|
||||
}
|
||||
constexpr float Lerp(float value1, float value2, float amount)
|
||||
{
|
||||
return value1 + (value2 - value1) * amount;
|
||||
@@ -147,6 +155,18 @@ namespace wi::math
|
||||
{
|
||||
return XMFLOAT4(Lerp(a.x, b.x, i), Lerp(a.y, b.y, i), Lerp(a.z, b.z, i), Lerp(a.w, b.w, i));
|
||||
}
|
||||
constexpr XMFLOAT2 Lerp(const XMFLOAT2& a, const XMFLOAT2& b, const XMFLOAT2& i)
|
||||
{
|
||||
return XMFLOAT2(Lerp(a.x, b.x, i.x), Lerp(a.y, b.y, i.y));
|
||||
}
|
||||
constexpr XMFLOAT3 Lerp(const XMFLOAT3& a, const XMFLOAT3& b, const XMFLOAT3& i)
|
||||
{
|
||||
return XMFLOAT3(Lerp(a.x, b.x, i.x), Lerp(a.y, b.y, i.y), Lerp(a.z, b.z, i.z));
|
||||
}
|
||||
constexpr XMFLOAT4 Lerp(const XMFLOAT4& a, const XMFLOAT4& b, const XMFLOAT4& i)
|
||||
{
|
||||
return XMFLOAT4(Lerp(a.x, b.x, i.x), Lerp(a.y, b.y, i.y), Lerp(a.z, b.z, i.z), Lerp(a.w, b.w, i.w));
|
||||
}
|
||||
inline XMFLOAT4 Slerp(const XMFLOAT4& a, const XMFLOAT4& b, float i)
|
||||
{
|
||||
XMVECTOR _a = XMLoadFloat4(&a);
|
||||
@@ -156,12 +176,33 @@ namespace wi::math
|
||||
XMStoreFloat4(&retVal, result);
|
||||
return retVal;
|
||||
}
|
||||
constexpr XMFLOAT2 Max(const XMFLOAT2& a, const XMFLOAT2& b) {
|
||||
return XMFLOAT2(std::max(a.x, b.x), std::max(a.y, b.y));
|
||||
}
|
||||
constexpr XMFLOAT3 Max(const XMFLOAT3& a, const XMFLOAT3& b) {
|
||||
return XMFLOAT3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
|
||||
}
|
||||
constexpr XMFLOAT4 Max(const XMFLOAT4& a, const XMFLOAT4& b) {
|
||||
return XMFLOAT4(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z), std::max(a.w, b.w));
|
||||
}
|
||||
constexpr XMFLOAT2 Min(const XMFLOAT2& a, const XMFLOAT2& b) {
|
||||
return XMFLOAT2(std::min(a.x, b.x), std::min(a.y, b.y));
|
||||
}
|
||||
constexpr XMFLOAT3 Min(const XMFLOAT3& a, const XMFLOAT3& b) {
|
||||
return XMFLOAT3(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z));
|
||||
}
|
||||
constexpr XMFLOAT4 Min(const XMFLOAT4& a, const XMFLOAT4& b) {
|
||||
return XMFLOAT4(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z), std::min(a.w, b.w));
|
||||
}
|
||||
constexpr XMFLOAT2 Abs(const XMFLOAT2& a) {
|
||||
return XMFLOAT2(std::abs(a.x), std::abs(a.y));
|
||||
}
|
||||
constexpr XMFLOAT3 Abs(const XMFLOAT3& a) {
|
||||
return XMFLOAT3(std::abs(a.x), std::abs(a.y), std::abs(a.z));
|
||||
}
|
||||
constexpr XMFLOAT4 Abs(const XMFLOAT4& a) {
|
||||
return XMFLOAT4(std::abs(a.x), std::abs(a.y), std::abs(a.z), std::abs(a.w));
|
||||
}
|
||||
constexpr float Clamp(float val, float min, float max)
|
||||
{
|
||||
return std::min(max, std::max(min, val));
|
||||
|
||||
@@ -1403,24 +1403,17 @@ namespace wi::physics
|
||||
btVector3 aabb_max;
|
||||
softbody->getAabb(aabb_min, aabb_max);
|
||||
physicscomponent->aabb = wi::primitive::AABB(XMFLOAT3(aabb_min.x(), aabb_min.y(), aabb_min.z()), XMFLOAT3(aabb_max.x(), aabb_max.y(), aabb_max.z()));
|
||||
mesh.aabb = physicscomponent->aabb;
|
||||
|
||||
// Soft body simulation nodes will update graphics mesh:
|
||||
for (size_t ind = 0; ind < physicscomponent->vertex_positions_simulation.size(); ++ind)
|
||||
for (size_t ind = 0; ind < mesh.vertex_positions.size(); ++ind)
|
||||
{
|
||||
uint32_t physicsInd = physicscomponent->graphicsToPhysicsVertexMapping[ind];
|
||||
|
||||
btSoftBody::Node& node = softbody->m_nodes[physicsInd];
|
||||
|
||||
MeshComponent::Vertex_POS& vertex = physicscomponent->vertex_positions_simulation[ind];
|
||||
vertex.pos.x = node.m_x.getX();
|
||||
vertex.pos.y = node.m_x.getY();
|
||||
vertex.pos.z = node.m_x.getZ();
|
||||
|
||||
XMFLOAT3 normal;
|
||||
normal.x = -node.m_n.getX();
|
||||
normal.y = -node.m_n.getY();
|
||||
normal.z = -node.m_n.getZ();
|
||||
vertex.MakeFromParams(normal);
|
||||
physicscomponent->vertex_positions_simulation[ind].FromFULL(XMFLOAT3(node.m_x.getX(), node.m_x.getY(), node.m_x.getZ()));
|
||||
physicscomponent->vertex_normals_simulation[ind].FromFULL(XMFLOAT3(-node.m_n.getX(), -node.m_n.getY(), -node.m_n.getZ()));
|
||||
}
|
||||
|
||||
// Update tangent vectors:
|
||||
@@ -1438,17 +1431,17 @@ namespace wi::physics
|
||||
const uint32_t i1 = mesh.indices[i + 1];
|
||||
const uint32_t i2 = mesh.indices[i + 2];
|
||||
|
||||
const XMFLOAT3 v0 = physicscomponent->vertex_positions_simulation[i0].pos;
|
||||
const XMFLOAT3 v1 = physicscomponent->vertex_positions_simulation[i1].pos;
|
||||
const XMFLOAT3 v2 = physicscomponent->vertex_positions_simulation[i2].pos;
|
||||
const XMFLOAT3 v0 = physicscomponent->vertex_positions_simulation[i0].GetPOS();
|
||||
const XMFLOAT3 v1 = physicscomponent->vertex_positions_simulation[i1].GetPOS();
|
||||
const XMFLOAT3 v2 = physicscomponent->vertex_positions_simulation[i2].GetPOS();
|
||||
|
||||
const XMFLOAT2 u0 = mesh.vertex_uvset_0[i0];
|
||||
const XMFLOAT2 u1 = mesh.vertex_uvset_0[i1];
|
||||
const XMFLOAT2 u2 = mesh.vertex_uvset_0[i2];
|
||||
|
||||
const XMVECTOR nor0 = physicscomponent->vertex_positions_simulation[i0].LoadNOR();
|
||||
const XMVECTOR nor1 = physicscomponent->vertex_positions_simulation[i1].LoadNOR();
|
||||
const XMVECTOR nor2 = physicscomponent->vertex_positions_simulation[i2].LoadNOR();
|
||||
const XMVECTOR nor0 = physicscomponent->vertex_normals_simulation[i0].LoadNOR();
|
||||
const XMVECTOR nor1 = physicscomponent->vertex_normals_simulation[i1].LoadNOR();
|
||||
const XMVECTOR nor2 = physicscomponent->vertex_normals_simulation[i2].LoadNOR();
|
||||
|
||||
const XMVECTOR facenormal = XMVector3Normalize(XMVectorAdd(XMVectorAdd(nor0, nor1), nor2));
|
||||
|
||||
|
||||
@@ -64,6 +64,13 @@ namespace wi::primitive
|
||||
|
||||
return sca * tra;
|
||||
}
|
||||
XMMATRIX AABB::AABB::getUnormRemapMatrix() const
|
||||
{
|
||||
return
|
||||
XMMatrixScaling(_max.x - _min.x, _max.y - _min.y, _max.z - _min.z) *
|
||||
XMMatrixTranslation(_min.x, _min.y, _min.z)
|
||||
;
|
||||
}
|
||||
float AABB::getArea() const
|
||||
{
|
||||
XMFLOAT3 _min = getMin();
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace wi::primitive
|
||||
XMFLOAT3 getCenter() const;
|
||||
XMFLOAT3 getHalfWidth() const;
|
||||
XMMATRIX getAsBoxMatrix() const;
|
||||
XMMATRIX getUnormRemapMatrix() const;
|
||||
float getArea() const;
|
||||
float getRadius() const;
|
||||
INTERSECTION_TYPE intersects2D(const AABB& b) const;
|
||||
|
||||
+59
-55
@@ -741,10 +741,6 @@ void LoadShaders()
|
||||
wi::jobsystem::context ctx;
|
||||
|
||||
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) {
|
||||
inputLayouts[ILTYPE_OBJECT_DEBUG].elements =
|
||||
{
|
||||
{ "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayout::APPEND_ALIGNED_ELEMENT, InputClassification::PER_VERTEX_DATA },
|
||||
};
|
||||
LoadShader(ShaderStage::VS, shaders[VSTYPE_OBJECT_DEBUG], "objectVS_debug.cso");
|
||||
});
|
||||
|
||||
@@ -774,11 +770,6 @@ void LoadShaders()
|
||||
});
|
||||
|
||||
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) {
|
||||
inputLayouts[ILTYPE_RENDERLIGHTMAP].elements =
|
||||
{
|
||||
{ "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayout::APPEND_ALIGNED_ELEMENT, InputClassification::PER_VERTEX_DATA },
|
||||
{ "ATLAS", 0, MeshComponent::Vertex_TEX::FORMAT, 1, InputLayout::APPEND_ALIGNED_ELEMENT, InputClassification::PER_VERTEX_DATA },
|
||||
};
|
||||
LoadShader(ShaderStage::VS, shaders[VSTYPE_RENDERLIGHTMAP], "renderlightmapVS.cso");
|
||||
});
|
||||
|
||||
@@ -1347,7 +1338,6 @@ void LoadShaders()
|
||||
});
|
||||
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) {
|
||||
PipelineStateDesc desc;
|
||||
desc.il = &inputLayouts[ILTYPE_RENDERLIGHTMAP];
|
||||
desc.vs = &shaders[VSTYPE_RENDERLIGHTMAP];
|
||||
desc.ps = &shaders[PSTYPE_RENDERLIGHTMAP];
|
||||
desc.rs = &rasterizers[RSTYPE_DOUBLESIDED];
|
||||
@@ -1541,7 +1531,6 @@ void LoadShaders()
|
||||
case DEBUGRENDERING_EMITTER:
|
||||
desc.vs = &shaders[VSTYPE_OBJECT_DEBUG];
|
||||
desc.ps = &shaders[PSTYPE_OBJECT_DEBUG];
|
||||
desc.il = &inputLayouts[ILTYPE_OBJECT_DEBUG];
|
||||
desc.dss = &depthStencils[DSSTYPE_DEPTHREAD];
|
||||
desc.rs = &rasterizers[RSTYPE_WIRE_DOUBLESIDED_SMOOTH];
|
||||
desc.bs = &blendStates[BSTYPE_OPAQUE];
|
||||
@@ -2959,7 +2948,7 @@ void RenderImpostors(
|
||||
vis.scene->impostor_ib_format == Format::R32_UINT ? vis.scene->impostor_ib32.offset : vis.scene->impostor_ib16.offset,
|
||||
cmd
|
||||
);
|
||||
device->BindResource(&vis.scene->impostorBuffer, 0, cmd, vis.scene->impostor_vb.subresource_srv);
|
||||
device->BindResource(&vis.scene->impostorBuffer, 0, cmd, vis.scene->impostor_vb_pos.subresource_srv);
|
||||
device->BindResource(&vis.scene->impostorBuffer, 2, cmd, vis.scene->impostor_data.subresource_srv);
|
||||
device->BindResource(&vis.scene->impostorArray, 1, cmd);
|
||||
|
||||
@@ -4235,15 +4224,28 @@ void UpdateRenderData(
|
||||
const SoftBodyPhysicsComponent& softbody = vis.scene->softbodies[i];
|
||||
|
||||
const MeshComponent* mesh = vis.scene->meshes.GetComponent(entity);
|
||||
if (mesh != nullptr && mesh->streamoutBuffer.IsValid() && !softbody.vertex_positions_simulation.empty())
|
||||
if (mesh != nullptr && mesh->streamoutBuffer.IsValid() && softbody.HasVertices())
|
||||
{
|
||||
GraphicsDevice::GPUAllocation allocation = device->AllocateGPU(mesh->so_pos_nor_wind.size + mesh->so_tan.size, cmd);
|
||||
std::memcpy(allocation.data, softbody.vertex_positions_simulation.data(), mesh->so_pos_nor_wind.size);
|
||||
device->CopyBuffer(&mesh->streamoutBuffer, mesh->so_pos_nor_wind.offset, &allocation.buffer, allocation.offset, mesh->so_pos_nor_wind.size, cmd);
|
||||
GraphicsDevice::GPUAllocation allocation = device->AllocateGPU(mesh->so_pos.size + mesh->so_nor.size + mesh->so_tan.size, cmd);
|
||||
uint8_t* dst = (uint8_t*)allocation.data;
|
||||
uint64_t offset = allocation.offset;
|
||||
std::memcpy(dst, softbody.vertex_positions_simulation.data(), mesh->so_pos.size);
|
||||
device->CopyBuffer(&mesh->streamoutBuffer, mesh->so_pos.offset, &allocation.buffer, offset, mesh->so_pos.size, cmd);
|
||||
dst += mesh->so_pos.size;
|
||||
offset += mesh->so_pos.size;
|
||||
if (!softbody.vertex_normals_simulation.empty())
|
||||
{
|
||||
std::memcpy(dst, softbody.vertex_normals_simulation.data(), mesh->so_nor.size);
|
||||
device->CopyBuffer(&mesh->streamoutBuffer, mesh->so_nor.offset, &allocation.buffer, offset, mesh->so_nor.size, cmd);
|
||||
dst += mesh->so_nor.size;
|
||||
offset += mesh->so_nor.size;
|
||||
}
|
||||
if (!softbody.vertex_tangents_simulation.empty())
|
||||
{
|
||||
std::memcpy((uint8_t*)allocation.data + mesh->so_pos_nor_wind.size, softbody.vertex_tangents_simulation.data(), mesh->so_tan.size);
|
||||
device->CopyBuffer(&mesh->streamoutBuffer, mesh->so_tan.offset, &allocation.buffer, allocation.offset + mesh->so_pos_nor_wind.size, mesh->so_tan.size, cmd);
|
||||
std::memcpy(dst, softbody.vertex_tangents_simulation.data(), mesh->so_tan.size);
|
||||
device->CopyBuffer(&mesh->streamoutBuffer, mesh->so_tan.offset, &allocation.buffer, offset, mesh->so_tan.size, cmd);
|
||||
dst += mesh->so_tan.size;
|
||||
offset += mesh->so_tan.size;
|
||||
}
|
||||
barrier_stack.push_back(GPUBarrier::Buffer(&mesh->streamoutBuffer, ResourceState::COPY_DST, ResourceState::SHADER_RESOURCE));
|
||||
}
|
||||
@@ -4306,10 +4308,11 @@ void UpdateRenderData(
|
||||
}
|
||||
|
||||
SkinningPushConstants push;
|
||||
push.vertexCount = (uint)mesh.vertex_positions.size();
|
||||
push.vb_pos_nor_wind = mesh.vb_pos_nor_wind.descriptor_srv;
|
||||
push.vb_pos_wind = mesh.vb_pos_wind.descriptor_srv;
|
||||
push.vb_nor = mesh.vb_nor.descriptor_srv;
|
||||
push.vb_tan = mesh.vb_tan.descriptor_srv;
|
||||
push.so_pos_nor_wind = mesh.so_pos_nor_wind.descriptor_uav;
|
||||
push.so_pos = mesh.so_pos.descriptor_uav;
|
||||
push.so_nor = mesh.so_nor.descriptor_uav;
|
||||
push.so_tan = mesh.so_tan.descriptor_uav;
|
||||
push.skinningbuffer_index = descriptor_skinningbuffer;
|
||||
const ArmatureComponent* armature = vis.scene->armatures.GetComponent(mesh.armatureID);
|
||||
@@ -4334,6 +4337,17 @@ void UpdateRenderData(
|
||||
push.morph_offset = ~0u;
|
||||
push.morphvb_index = -1;
|
||||
}
|
||||
if (IsFormatUnorm(mesh.position_format))
|
||||
{
|
||||
push.aabb_min = mesh.aabb._min;
|
||||
push.aabb_max = mesh.aabb._max;
|
||||
}
|
||||
else
|
||||
{
|
||||
push.aabb_min = {};
|
||||
push.aabb_max = {};
|
||||
}
|
||||
push.vertexCount = (uint)mesh.vertex_positions.size();
|
||||
device->PushConstants(&push, sizeof(push), cmd);
|
||||
|
||||
device->Dispatch(((uint32_t)mesh.vertex_positions.size() + 63) / 64, 1, 1, cmd);
|
||||
@@ -4404,9 +4418,10 @@ void UpdateRenderData(
|
||||
|
||||
device->BindComputeShader(&shaders[CSTYPE_IMPOSTOR_PREPARE], cmd);
|
||||
device->BindUAV(&vis.scene->impostorBuffer, 0, cmd, vis.scene->impostor_ib_format == Format::R32_UINT ? vis.scene->impostor_ib32.subresource_uav : vis.scene->impostor_ib16.subresource_uav);
|
||||
device->BindUAV(&vis.scene->impostorBuffer, 1, cmd, vis.scene->impostor_vb.subresource_uav);
|
||||
device->BindUAV(&vis.scene->impostorBuffer, 2, cmd, vis.scene->impostor_data.subresource_uav);
|
||||
device->BindUAV(&vis.scene->impostorBuffer, 3, cmd, vis.scene->impostor_indirect.subresource_uav);
|
||||
device->BindUAV(&vis.scene->impostorBuffer, 1, cmd, vis.scene->impostor_vb_pos.subresource_uav);
|
||||
device->BindUAV(&vis.scene->impostorBuffer, 2, cmd, vis.scene->impostor_vb_nor.subresource_uav);
|
||||
device->BindUAV(&vis.scene->impostorBuffer, 3, cmd, vis.scene->impostor_data.subresource_uav);
|
||||
device->BindUAV(&vis.scene->impostorBuffer, 4, cmd, vis.scene->impostor_indirect.subresource_uav);
|
||||
|
||||
uint object_count = (uint)vis.scene->objects.GetCount();
|
||||
device->PushConstants(&object_count, sizeof(object_count), cmd);
|
||||
@@ -7134,16 +7149,9 @@ void DrawDebugWorld(
|
||||
{
|
||||
// Draw mesh wireframe:
|
||||
device->BindPipelineState(&PSO_debug[DEBUGRENDERING_EMITTER], cmd);
|
||||
const GPUBuffer* vbs[] = {
|
||||
mesh->streamoutBuffer.IsValid() ? &mesh->streamoutBuffer : &mesh->generalBuffer,
|
||||
};
|
||||
const uint32_t strides[] = {
|
||||
sizeof(MeshComponent::Vertex_POS),
|
||||
};
|
||||
const uint64_t offsets[] = {
|
||||
mesh->so_pos_nor_wind.IsValid() ? mesh->so_pos_nor_wind.offset : mesh->vb_pos_nor_wind.offset,
|
||||
};
|
||||
device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd);
|
||||
DebugObjectPushConstants push;
|
||||
push.vb_pos_wind = mesh->so_pos.IsValid() ? mesh->so_pos.descriptor_srv : mesh->vb_pos_wind.descriptor_srv;
|
||||
device->PushConstants(&push, sizeof(push), cmd);
|
||||
device->BindIndexBuffer(&mesh->generalBuffer, mesh->GetIndexFormat(), mesh->ib.offset, cmd);
|
||||
|
||||
device->DrawIndexed((uint32_t)mesh->indices.size(), 0, 0, cmd);
|
||||
@@ -8321,9 +8329,16 @@ void RefreshImpostors(const Scene& scene, CommandList cmd)
|
||||
impostorcamera.TransformCamera(camera_transform);
|
||||
impostorcamera.UpdateCamera();
|
||||
|
||||
if (IsFormatUnorm(mesh.position_format))
|
||||
{
|
||||
XMMATRIX VP = impostorcamera.GetViewProjection();
|
||||
VP = mesh.aabb.getUnormRemapMatrix() * VP;
|
||||
XMStoreFloat4x4(&impostorcamera.VP, VP);
|
||||
}
|
||||
|
||||
BindCameraCB(impostorcamera, impostorcamera, impostorcamera, cmd);
|
||||
|
||||
int slice = (int)(impostor.textureIndex * impostorCaptureAngles * 3 + i * 3);
|
||||
int slice = int(impostor.textureIndex * impostorCaptureAngles * 3 + i * 3);
|
||||
|
||||
const RenderPassImage rp[] = {
|
||||
RenderPassImage::RenderTarget(
|
||||
@@ -9665,26 +9680,17 @@ void RefreshLightmaps(const Scene& scene, CommandList cmd)
|
||||
vp.height = (float)desc.height;
|
||||
device->BindViewports(1, &vp, cmd);
|
||||
|
||||
MiscCB misccb;
|
||||
misccb.g_xTransform = scene.matrix_objects[objectIndex];
|
||||
device->BindPipelineState(&PSO_renderlightmap, cmd);
|
||||
|
||||
device->BindDynamicConstantBuffer(misccb, CB_GETBINDSLOT(MiscCB), cmd);
|
||||
|
||||
const GPUBuffer* vbs[] = {
|
||||
&mesh.generalBuffer,
|
||||
&mesh.generalBuffer,
|
||||
};
|
||||
uint32_t strides[] = {
|
||||
sizeof(MeshComponent::Vertex_POS),
|
||||
sizeof(MeshComponent::Vertex_TEX),
|
||||
};
|
||||
uint64_t offsets[] = {
|
||||
mesh.vb_pos_nor_wind.offset,
|
||||
mesh.vb_atl.offset,
|
||||
};
|
||||
device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd);
|
||||
device->BindIndexBuffer(&mesh.generalBuffer, mesh.GetIndexFormat(), mesh.ib.offset, cmd);
|
||||
|
||||
LightmapPushConstants push;
|
||||
push.vb_pos_wind = mesh.vb_pos_wind.descriptor_srv;
|
||||
push.vb_nor = mesh.vb_nor.descriptor_srv;
|
||||
push.vb_atl = mesh.vb_atl.descriptor_srv;
|
||||
push.instanceIndex = objectIndex;
|
||||
device->PushConstants(&push, sizeof(push), cmd);
|
||||
|
||||
RaytracingCB cb;
|
||||
cb.xTraceResolution.x = desc.width;
|
||||
cb.xTraceResolution.y = desc.height;
|
||||
@@ -9702,9 +9708,7 @@ void RefreshLightmaps(const Scene& scene, CommandList cmd)
|
||||
cb.xTraceSampleIndex = object.lightmapIterationCount;
|
||||
device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(RaytracingCB), cmd);
|
||||
|
||||
device->BindPipelineState(&PSO_renderlightmap, cmd);
|
||||
|
||||
device->DrawIndexedInstanced((uint32_t)mesh.indices.size(), 1, 0, 0, 0, cmd);
|
||||
device->DrawIndexed((uint32_t)mesh.indices.size(), 0, 0, cmd);
|
||||
object.lightmapIterationCount++;
|
||||
|
||||
device->RenderPassEnd(cmd);
|
||||
|
||||
+84
-34
@@ -693,12 +693,17 @@ namespace wi::scene
|
||||
desc.bind_flags = BindFlag::INDEX_BUFFER | BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS;
|
||||
desc.misc_flags = ResourceMiscFlag::BUFFER_RAW | ResourceMiscFlag::TYPED_FORMAT_CASTING | ResourceMiscFlag::INDIRECT_ARGS | ResourceMiscFlag::NO_DEFAULT_DESCRIPTORS;
|
||||
|
||||
const uint64_t alignment = device->GetMinOffsetAlignment(&desc);
|
||||
const uint64_t alignment =
|
||||
device->GetMinOffsetAlignment(&desc) *
|
||||
sizeof(IndirectDrawArgsIndexedInstanced) * // additional alignment
|
||||
sizeof(MeshComponent::Vertex_POS32) // additional alignment
|
||||
;
|
||||
|
||||
desc.size =
|
||||
AlignTo(AlignTo(sizeof(IndirectDrawArgsIndexedInstanced), alignment), sizeof(IndirectDrawArgsIndexedInstanced)) + // indirect args, additional structured buffer alignment
|
||||
AlignTo(sizeof(IndirectDrawArgsIndexedInstanced), alignment) + // indirect args
|
||||
AlignTo(allocated_impostor_capacity * sizeof(uint) * 6, alignment) + // indices (must overestimate here for 32-bit indices, because we create 16 bit and 32 bit descriptors)
|
||||
AlignTo(allocated_impostor_capacity * sizeof(MeshComponent::Vertex_POS) * 4, alignment) + // vertices
|
||||
AlignTo(allocated_impostor_capacity * sizeof(MeshComponent::Vertex_POS32) * 4, alignment) + // vertices
|
||||
AlignTo(allocated_impostor_capacity * sizeof(MeshComponent::Vertex_NOR) * 4, alignment) + // vertices
|
||||
AlignTo(allocated_impostor_capacity * sizeof(uint2), alignment) // impostordata
|
||||
;
|
||||
device->CreateBuffer(&desc, nullptr, &impostorBuffer);
|
||||
@@ -733,13 +738,22 @@ namespace wi::scene
|
||||
impostor_ib16.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_ib16.subresource_uav);
|
||||
|
||||
buffer_offset = AlignTo(buffer_offset, alignment);
|
||||
impostor_vb.offset = buffer_offset;
|
||||
impostor_vb.size = allocated_impostor_capacity * sizeof(MeshComponent::Vertex_POS) * 4;
|
||||
impostor_vb.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_vb.offset, impostor_vb.size, &MeshComponent::Vertex_POS::FORMAT);
|
||||
impostor_vb.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_vb.offset, impostor_vb.size, &MeshComponent::Vertex_POS::FORMAT);
|
||||
impostor_vb.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_vb.subresource_srv);
|
||||
impostor_vb.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_vb.subresource_uav);
|
||||
buffer_offset += impostor_vb.size;
|
||||
impostor_vb_pos.offset = buffer_offset;
|
||||
impostor_vb_pos.size = allocated_impostor_capacity * sizeof(MeshComponent::Vertex_POS32) * 4;
|
||||
impostor_vb_pos.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_vb_pos.offset, impostor_vb_pos.size, &MeshComponent::Vertex_POS32::FORMAT);
|
||||
impostor_vb_pos.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_vb_pos.offset, impostor_vb_pos.size); // can't have RGB32F format for UAV!
|
||||
impostor_vb_pos.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_vb_pos.subresource_srv);
|
||||
impostor_vb_pos.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_vb_pos.subresource_uav);
|
||||
buffer_offset += impostor_vb_pos.size;
|
||||
|
||||
buffer_offset = AlignTo(buffer_offset, alignment);
|
||||
impostor_vb_nor.offset = buffer_offset;
|
||||
impostor_vb_nor.size = allocated_impostor_capacity * sizeof(MeshComponent::Vertex_NOR) * 4;
|
||||
impostor_vb_nor.subresource_srv = device->CreateSubresource(&impostorBuffer, SubresourceType::SRV, impostor_vb_nor.offset, impostor_vb_nor.size, &MeshComponent::Vertex_NOR::FORMAT);
|
||||
impostor_vb_nor.subresource_uav = device->CreateSubresource(&impostorBuffer, SubresourceType::UAV, impostor_vb_nor.offset, impostor_vb_nor.size, &MeshComponent::Vertex_NOR::FORMAT);
|
||||
impostor_vb_nor.descriptor_srv = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::SRV, impostor_vb_nor.subresource_srv);
|
||||
impostor_vb_nor.descriptor_uav = device->GetDescriptorIndex(&impostorBuffer, SubresourceType::UAV, impostor_vb_nor.subresource_uav);
|
||||
buffer_offset += impostor_vb_nor.size;
|
||||
|
||||
buffer_offset = AlignTo(buffer_offset, alignment);
|
||||
impostor_data.offset = buffer_offset;
|
||||
@@ -3376,9 +3390,9 @@ namespace wi::scene
|
||||
}
|
||||
}
|
||||
|
||||
if (mesh.so_pos_nor_wind.IsValid() && mesh.so_pre.IsValid())
|
||||
if (mesh.so_pos.IsValid() && mesh.so_pre.IsValid())
|
||||
{
|
||||
std::swap(mesh.so_pos_nor_wind, mesh.so_pre);
|
||||
std::swap(mesh.so_pos, mesh.so_pre);
|
||||
}
|
||||
|
||||
mesh._flags &= ~MeshComponent::TLAS_FORCE_DOUBLE_SIDED;
|
||||
@@ -3408,13 +3422,21 @@ namespace wi::scene
|
||||
ShaderGeometry geometry;
|
||||
geometry.init();
|
||||
geometry.ib = mesh.ib.descriptor_srv;
|
||||
if (mesh.so_pos_nor_wind.IsValid())
|
||||
if (mesh.so_pos.IsValid())
|
||||
{
|
||||
geometry.vb_pos_nor_wind = mesh.so_pos_nor_wind.descriptor_srv;
|
||||
geometry.vb_pos_wind = mesh.so_pos.descriptor_srv;
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry.vb_pos_nor_wind = mesh.vb_pos_nor_wind.descriptor_srv;
|
||||
geometry.vb_pos_wind = mesh.vb_pos_wind.descriptor_srv;
|
||||
}
|
||||
if (mesh.so_nor.IsValid())
|
||||
{
|
||||
geometry.vb_nor = mesh.so_nor.descriptor_srv;
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry.vb_nor = mesh.vb_nor.descriptor_srv;
|
||||
}
|
||||
if (mesh.so_tan.IsValid())
|
||||
{
|
||||
@@ -3431,6 +3453,8 @@ namespace wi::scene
|
||||
geometry.aabb_min = mesh.aabb._min;
|
||||
geometry.aabb_max = mesh.aabb._max;
|
||||
geometry.tessellation_factor = mesh.tessellationFactor;
|
||||
geometry.uv_range_min = mesh.uv_range_min;
|
||||
geometry.uv_range_max = mesh.uv_range_max;
|
||||
|
||||
const ImpostorComponent* impostor = impostors.GetComponent(entity);
|
||||
if (impostor != nullptr && impostor->textureIndex >= 0)
|
||||
@@ -3508,7 +3532,7 @@ namespace wi::scene
|
||||
{
|
||||
mesh.BLAS_state = MeshComponent::BLAS_STATE_NEEDS_REBUILD;
|
||||
geometry.triangles.vertex_buffer = mesh.streamoutBuffer;
|
||||
geometry.triangles.vertex_byte_offset = mesh.so_pos_nor_wind.offset;
|
||||
geometry.triangles.vertex_byte_offset = mesh.so_pos.offset;
|
||||
}
|
||||
if (material.IsDoubleSided())
|
||||
{
|
||||
@@ -3714,7 +3738,8 @@ namespace wi::scene
|
||||
geometry.meshletCount = triangle_count_to_meshlet_count(uint32_t(objects.GetCount()) * 2);
|
||||
geometry.meshletOffset = 0; // local meshlet offset
|
||||
geometry.ib = impostor_ib_format == Format::R32_UINT ? impostor_ib32.descriptor_srv : impostor_ib16.descriptor_srv;
|
||||
geometry.vb_pos_nor_wind = impostor_vb.descriptor_srv;
|
||||
geometry.vb_pos_wind = impostor_vb_pos.descriptor_srv;
|
||||
geometry.vb_nor = impostor_vb_nor.descriptor_srv;
|
||||
geometry.materialIndex = impostorMaterialOffset;
|
||||
std::memcpy(geometryArrayMapped + impostorGeometryOffset, &geometry, sizeof(geometry));
|
||||
|
||||
@@ -3910,21 +3935,30 @@ namespace wi::scene
|
||||
|
||||
object.sort_bits = sort_bits.value;
|
||||
|
||||
// Create GPU instance data:
|
||||
GraphicsDevice* device = wi::graphics::GetDevice();
|
||||
ShaderMeshInstance inst;
|
||||
inst.init();
|
||||
XMFLOAT4X4& worldMatrix = matrix_objects[args.jobIndex];
|
||||
matrix_objects_prev[args.jobIndex] = worldMatrix;
|
||||
inst.transformPrev.Create(worldMatrix);
|
||||
XMStoreFloat4x4(&worldMatrix, W);
|
||||
inst.transform.Create(worldMatrix);
|
||||
|
||||
// Correction matrix for mesh normals with non-uniform object scaling:
|
||||
XMMATRIX worldMatrixInverseTranspose = XMMatrixTranspose(XMMatrixInverse(nullptr, W));
|
||||
XMFLOAT4X4 transformIT;
|
||||
XMStoreFloat4x4(&transformIT, worldMatrixInverseTranspose);
|
||||
|
||||
// Create GPU instance data:
|
||||
GraphicsDevice* device = wi::graphics::GetDevice();
|
||||
ShaderMeshInstance inst;
|
||||
inst.init();
|
||||
XMFLOAT4X4 worldMatrixPrev = matrix_objects[args.jobIndex];
|
||||
matrix_objects_prev[args.jobIndex] = worldMatrixPrev;
|
||||
XMStoreFloat4x4(matrix_objects.data() + args.jobIndex, W);
|
||||
XMFLOAT4X4 worldMatrix = matrix_objects[args.jobIndex];
|
||||
|
||||
if (IsFormatUnorm(mesh.position_format) && !mesh.so_pos.IsValid())
|
||||
{
|
||||
// The UNORM correction is only done for the GPU data!
|
||||
XMMATRIX R = mesh.aabb.getUnormRemapMatrix();
|
||||
XMStoreFloat4x4(&worldMatrix, R * W);
|
||||
XMStoreFloat4x4(&worldMatrixPrev, R * XMLoadFloat4x4(&worldMatrixPrev));
|
||||
}
|
||||
inst.transform.Create(worldMatrix);
|
||||
inst.transformPrev.Create(worldMatrixPrev);
|
||||
|
||||
inst.transformInverseTranspose.Create(transformIT);
|
||||
if (object.lightmap.IsValid())
|
||||
{
|
||||
@@ -4301,12 +4335,15 @@ namespace wi::scene
|
||||
geometry.indexOffset = 0;
|
||||
geometry.materialIndex = (uint)materials.GetIndex(entity);
|
||||
geometry.ib = device->GetDescriptorIndex(&hair.primitiveBuffer, SubresourceType::SRV);
|
||||
geometry.vb_pos_nor_wind = hair.vb_pos[0].descriptor_srv;
|
||||
geometry.vb_pos_wind = hair.vb_pos[0].descriptor_srv;
|
||||
geometry.vb_nor = hair.vb_nor.descriptor_srv;
|
||||
geometry.vb_pre = hair.vb_pos[1].descriptor_srv;
|
||||
geometry.vb_uvs = hair.vb_uvs.descriptor_srv;
|
||||
geometry.flags = SHADERMESH_FLAG_DOUBLE_SIDED | SHADERMESH_FLAG_HAIRPARTICLE;
|
||||
geometry.meshletOffset = 0;
|
||||
geometry.meshletCount = meshletCount;
|
||||
geometry.aabb_min = hair.aabb._min;
|
||||
geometry.aabb_max = hair.aabb._max;
|
||||
|
||||
size_t geometryAllocation = geometryAllocator.fetch_add(1);
|
||||
std::memcpy(geometryArrayMapped + geometryAllocation, &geometry, sizeof(geometry));
|
||||
@@ -4325,6 +4362,11 @@ namespace wi::scene
|
||||
inst.baseGeometryCount = inst.geometryCount;
|
||||
inst.meshletOffset = meshletOffset;
|
||||
|
||||
XMFLOAT4X4 remapMatrix;
|
||||
XMStoreFloat4x4(&remapMatrix, hair.aabb.getUnormRemapMatrix());
|
||||
inst.transform.Create(remapMatrix);
|
||||
inst.transformPrev = inst.transform;
|
||||
|
||||
const size_t instanceIndex = objects.GetCount() + args.jobIndex;
|
||||
std::memcpy(instanceArrayMapped + instanceIndex, &inst, sizeof(inst));
|
||||
|
||||
@@ -4342,7 +4384,7 @@ namespace wi::scene
|
||||
{
|
||||
for (int j = 0; j < arraysize(instance.transform[i]); ++j)
|
||||
{
|
||||
instance.transform[i][j] = wi::math::IDENTITY_MATRIX.m[j][i];
|
||||
instance.transform[i][j] = remapMatrix.m[j][i];
|
||||
}
|
||||
}
|
||||
instance.instance_id = (uint32_t)instanceIndex;
|
||||
@@ -4398,7 +4440,8 @@ namespace wi::scene
|
||||
geometry.indexOffset = 0;
|
||||
geometry.materialIndex = (uint)materials.GetIndex(entity);
|
||||
geometry.ib = device->GetDescriptorIndex(&emitter.primitiveBuffer, SubresourceType::SRV);
|
||||
geometry.vb_pos_nor_wind = emitter.vb_pos.descriptor_srv;
|
||||
geometry.vb_pos_wind = emitter.vb_pos.descriptor_srv;
|
||||
geometry.vb_nor = emitter.vb_nor.descriptor_srv;
|
||||
geometry.vb_uvs = emitter.vb_uvs.descriptor_srv;
|
||||
geometry.vb_col = emitter.vb_col.descriptor_srv;
|
||||
geometry.flags = SHADERMESH_FLAG_DOUBLE_SIDED | SHADERMESH_FLAG_EMITTEDPARTICLE;
|
||||
@@ -4547,7 +4590,8 @@ namespace wi::scene
|
||||
geometry.indexOffset = 0;
|
||||
geometry.materialIndex = rainMaterialOffset;
|
||||
geometry.ib = device->GetDescriptorIndex(&rainEmitter.primitiveBuffer, SubresourceType::SRV);
|
||||
geometry.vb_pos_nor_wind = rainEmitter.vb_pos.descriptor_srv;
|
||||
geometry.vb_pos_wind = rainEmitter.vb_pos.descriptor_srv;
|
||||
geometry.vb_nor = rainEmitter.vb_nor.descriptor_srv;
|
||||
geometry.vb_uvs = rainEmitter.vb_uvs.descriptor_srv;
|
||||
geometry.vb_col = rainEmitter.vb_col.descriptor_srv;
|
||||
geometry.flags = SHADERMESH_FLAG_DOUBLE_SIDED | SHADERMESH_FLAG_EMITTEDPARTICLE;
|
||||
@@ -4806,6 +4850,8 @@ namespace wi::scene
|
||||
const XMVECTOR rayOrigin_local = XMVector3Transform(rayOrigin, objectMat_Inverse);
|
||||
const XMVECTOR rayDirection_local = XMVector3Normalize(XMVector3TransformNormal(rayDirection, objectMat_Inverse));
|
||||
const ArmatureComponent* armature = mesh->IsSkinned() ? armatures.GetComponent(mesh->armatureID) : nullptr;
|
||||
const XMVECTOR aabb_min = XMLoadFloat3(&mesh->aabb._min);
|
||||
const XMVECTOR aabb_max = XMLoadFloat3(&mesh->aabb._max);
|
||||
|
||||
auto intersect_triangle = [&](uint32_t subsetIndex, uint32_t indexOffset, uint32_t triangleIndex)
|
||||
{
|
||||
@@ -4817,7 +4863,7 @@ namespace wi::scene
|
||||
XMVECTOR p1;
|
||||
XMVECTOR p2;
|
||||
|
||||
const bool softbody_active = softbody != nullptr && !softbody->vertex_positions_simulation.empty();
|
||||
const bool softbody_active = softbody != nullptr && softbody->HasVertices();
|
||||
if (softbody_active)
|
||||
{
|
||||
p0 = softbody->vertex_positions_simulation[i0].LoadPOS();
|
||||
@@ -5000,6 +5046,8 @@ namespace wi::scene
|
||||
const XMMATRIX objectMatPrev = XMLoadFloat4x4(&matrix_objects_prev[objectIndex]);
|
||||
const XMMATRIX objectMatInverse = XMMatrixInverse(nullptr, objectMat);
|
||||
const ArmatureComponent* armature = mesh->IsSkinned() ? armatures.GetComponent(mesh->armatureID) : nullptr;
|
||||
const XMVECTOR aabb_min = XMLoadFloat3(&mesh->aabb._min);
|
||||
const XMVECTOR aabb_max = XMLoadFloat3(&mesh->aabb._max);
|
||||
|
||||
auto intersect_triangle = [&](uint32_t subsetIndex, uint32_t indexOffset, uint32_t triangleIndex)
|
||||
{
|
||||
@@ -5011,7 +5059,7 @@ namespace wi::scene
|
||||
XMVECTOR p1;
|
||||
XMVECTOR p2;
|
||||
|
||||
const bool softbody_active = softbody != nullptr && !softbody->vertex_positions_simulation.empty();
|
||||
const bool softbody_active = softbody != nullptr && softbody->HasVertices();
|
||||
if (softbody_active)
|
||||
{
|
||||
p0 = softbody->vertex_positions_simulation[i0].LoadPOS();
|
||||
@@ -5282,6 +5330,8 @@ namespace wi::scene
|
||||
const XMMATRIX objectMatPrev = XMLoadFloat4x4(&matrix_objects_prev[objectIndex]);
|
||||
const ArmatureComponent* armature = mesh->IsSkinned() ? armatures.GetComponent(mesh->armatureID) : nullptr;
|
||||
const XMMATRIX objectMat_Inverse = XMMatrixInverse(nullptr, objectMat);
|
||||
const XMVECTOR aabb_min = XMLoadFloat3(&mesh->aabb._min);
|
||||
const XMVECTOR aabb_max = XMLoadFloat3(&mesh->aabb._max);
|
||||
|
||||
auto intersect_triangle = [&](uint32_t subsetIndex, uint32_t indexOffset, uint32_t triangleIndex)
|
||||
{
|
||||
@@ -5293,7 +5343,7 @@ namespace wi::scene
|
||||
XMVECTOR p1;
|
||||
XMVECTOR p2;
|
||||
|
||||
const bool softbody_active = softbody != nullptr && !softbody->vertex_positions_simulation.empty();
|
||||
const bool softbody_active = softbody != nullptr && softbody->HasVertices();
|
||||
if (softbody_active)
|
||||
{
|
||||
p0 = softbody->vertex_positions_simulation[i0].LoadPOS();
|
||||
|
||||
@@ -228,7 +228,8 @@ namespace wi::scene
|
||||
uint32_t allocated_impostor_capacity = 0;
|
||||
MeshComponent::BufferView impostor_ib32;
|
||||
MeshComponent::BufferView impostor_ib16;
|
||||
MeshComponent::BufferView impostor_vb;
|
||||
MeshComponent::BufferView impostor_vb_pos;
|
||||
MeshComponent::BufferView impostor_vb_nor;
|
||||
MeshComponent::BufferView impostor_data;
|
||||
MeshComponent::BufferView impostor_indirect;
|
||||
wi::graphics::Format impostor_ib_format = wi::graphics::Format::R32_UINT;
|
||||
|
||||
@@ -460,13 +460,15 @@ namespace wi::scene
|
||||
generalBuffer = {};
|
||||
streamoutBuffer = {};
|
||||
ib = {};
|
||||
vb_pos_nor_wind = {};
|
||||
vb_pos_wind = {};
|
||||
vb_nor = {};
|
||||
vb_tan = {};
|
||||
vb_uvs = {};
|
||||
vb_atl = {};
|
||||
vb_col = {};
|
||||
vb_bon = {};
|
||||
so_pos_nor_wind = {};
|
||||
so_pos = {};
|
||||
so_nor = {};
|
||||
so_tan = {};
|
||||
so_pre = {};
|
||||
BLASes.clear();
|
||||
@@ -562,6 +564,108 @@ namespace wi::scene
|
||||
|
||||
const size_t uv_count = std::max(vertex_uvset_0.size(), vertex_uvset_1.size());
|
||||
|
||||
// Bounds computation:
|
||||
XMFLOAT3 _min = XMFLOAT3(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
|
||||
XMFLOAT3 _max = XMFLOAT3(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest());
|
||||
for (size_t i = 0; i < vertex_positions.size(); ++i)
|
||||
{
|
||||
const XMFLOAT3& pos = vertex_positions[i];
|
||||
_min = wi::math::Min(_min, pos);
|
||||
_max = wi::math::Max(_max, pos);
|
||||
}
|
||||
aabb = AABB(_min, _max);
|
||||
|
||||
if (IsQuantizedPositionsDisabled())
|
||||
{
|
||||
position_format = vertex_windweights.empty() ? Vertex_POS32::FORMAT : Vertex_POS32W::FORMAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine minimum precision for positions:
|
||||
const float target_precision = 1.0f / 1000.0f; // millimeter
|
||||
position_format = Vertex_POS10::FORMAT;
|
||||
for (size_t i = 0; i < vertex_positions.size(); ++i)
|
||||
{
|
||||
const XMFLOAT3& pos = vertex_positions[i];
|
||||
const uint8_t wind = vertex_windweights.empty() ? 0xFF : vertex_windweights[i];
|
||||
if (position_format == Vertex_POS10::FORMAT)
|
||||
{
|
||||
Vertex_POS10 v;
|
||||
v.FromFULL(aabb, pos, wind);
|
||||
XMFLOAT3 p = v.GetPOS(aabb);
|
||||
if (
|
||||
std::abs(p.x - pos.x) <= target_precision &&
|
||||
std::abs(p.y - pos.y) <= target_precision &&
|
||||
std::abs(p.z - pos.z) <= target_precision &&
|
||||
wind == v.GetWind()
|
||||
)
|
||||
{
|
||||
// success, continue to next vertex with 8 bits
|
||||
continue;
|
||||
}
|
||||
position_format = Vertex_POS16::FORMAT; // failed, increase to 16 bits
|
||||
}
|
||||
if (position_format == Vertex_POS16::FORMAT)
|
||||
{
|
||||
Vertex_POS16 v;
|
||||
v.FromFULL(aabb, pos, wind);
|
||||
XMFLOAT3 p = v.GetPOS(aabb);
|
||||
if (
|
||||
std::abs(p.x - pos.x) <= target_precision &&
|
||||
std::abs(p.y - pos.y) <= target_precision &&
|
||||
std::abs(p.z - pos.z) <= target_precision &&
|
||||
wind == v.GetWind()
|
||||
)
|
||||
{
|
||||
// success, continue to next vertex with 16 bits
|
||||
continue;
|
||||
}
|
||||
position_format = vertex_windweights.empty() ? Vertex_POS32::FORMAT : Vertex_POS32W::FORMAT; // failed, increase to 32 bits
|
||||
break; // since 32 bit is the max, we can bail out
|
||||
}
|
||||
}
|
||||
|
||||
if (IsFormatUnorm(position_format))
|
||||
{
|
||||
// This is done to avoid 0 scaling on any axis of the UNORM remap matrix of the AABB
|
||||
// It specifically solves a problem with hardware raytracing which treats AABB with zero axis as invisible
|
||||
if (aabb._max.x - aabb._min.x < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
aabb._max.x += std::numeric_limits<float>::epsilon();
|
||||
aabb._min.x -= std::numeric_limits<float>::epsilon();
|
||||
}
|
||||
if (aabb._max.y - aabb._min.y < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
aabb._max.y += std::numeric_limits<float>::epsilon();
|
||||
aabb._min.y -= std::numeric_limits<float>::epsilon();
|
||||
}
|
||||
if (aabb._max.z - aabb._min.z < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
aabb._max.z += std::numeric_limits<float>::epsilon();
|
||||
aabb._min.z -= std::numeric_limits<float>::epsilon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine UV range for normalization:
|
||||
if (!vertex_uvset_0.empty() || !vertex_uvset_1.empty())
|
||||
{
|
||||
const XMFLOAT2* uv0_stream = vertex_uvset_0.empty() ? vertex_uvset_1.data() : vertex_uvset_0.data();
|
||||
const XMFLOAT2* uv1_stream = vertex_uvset_1.empty() ? vertex_uvset_0.data() : vertex_uvset_1.data();
|
||||
|
||||
uv_range_min = XMFLOAT2(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
|
||||
uv_range_max = XMFLOAT2(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest());
|
||||
for (size_t i = 0; i < uv_count; ++i)
|
||||
{
|
||||
uv_range_max = wi::math::Max(uv_range_max, uv0_stream[i]);
|
||||
uv_range_max = wi::math::Max(uv_range_max, uv1_stream[i]);
|
||||
uv_range_min = wi::math::Min(uv_range_min, uv0_stream[i]);
|
||||
uv_range_min = wi::math::Min(uv_range_min, uv1_stream[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const size_t position_stride = GetFormatStride(position_format);
|
||||
|
||||
GPUBufferDesc bd;
|
||||
if (device->CheckCapability(GraphicsDeviceCapability::CACHE_COHERENT_UMA))
|
||||
{
|
||||
@@ -580,8 +684,9 @@ namespace wi::scene
|
||||
}
|
||||
const uint64_t alignment = device->GetMinOffsetAlignment(&bd);
|
||||
bd.size =
|
||||
AlignTo(vertex_positions.size() * position_stride, alignment) + // position will be first to have 0 offset for flexible alignment!
|
||||
AlignTo(indices.size() * GetIndexStride(), alignment) +
|
||||
AlignTo(vertex_positions.size() * sizeof(Vertex_POS), alignment) +
|
||||
AlignTo(vertex_normals.size() * sizeof(Vertex_NOR), alignment) +
|
||||
AlignTo(vertex_tangents.size() * sizeof(Vertex_TAN), alignment) +
|
||||
AlignTo(uv_count * sizeof(Vertex_UVS), alignment) +
|
||||
AlignTo(vertex_atlas.size() * sizeof(Vertex_TEX), alignment) +
|
||||
@@ -607,6 +712,78 @@ namespace wi::scene
|
||||
uint8_t* buffer_data = (uint8_t*)dest;
|
||||
uint64_t buffer_offset = 0ull;
|
||||
|
||||
// vertexBuffer - POSITION + WIND:
|
||||
switch (position_format)
|
||||
{
|
||||
case Vertex_POS10::FORMAT:
|
||||
{
|
||||
vb_pos_wind.offset = buffer_offset;
|
||||
vb_pos_wind.size = vertex_positions.size() * sizeof(Vertex_POS10);
|
||||
Vertex_POS10* vertices = (Vertex_POS10*)(buffer_data + buffer_offset);
|
||||
buffer_offset += AlignTo(vb_pos_wind.size, alignment);
|
||||
for (size_t i = 0; i < vertex_positions.size(); ++i)
|
||||
{
|
||||
XMFLOAT3 pos = vertex_positions[i];
|
||||
const uint8_t wind = vertex_windweights.empty() ? 0xFF : vertex_windweights[i];
|
||||
Vertex_POS10 vert;
|
||||
vert.FromFULL(aabb, pos, wind);
|
||||
std::memcpy(vertices + i, &vert, sizeof(vert));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Vertex_POS16::FORMAT:
|
||||
{
|
||||
vb_pos_wind.offset = buffer_offset;
|
||||
vb_pos_wind.size = vertex_positions.size() * sizeof(Vertex_POS16);
|
||||
Vertex_POS16* vertices = (Vertex_POS16*)(buffer_data + buffer_offset);
|
||||
buffer_offset += AlignTo(vb_pos_wind.size, alignment);
|
||||
for (size_t i = 0; i < vertex_positions.size(); ++i)
|
||||
{
|
||||
XMFLOAT3 pos = vertex_positions[i];
|
||||
const uint8_t wind = vertex_windweights.empty() ? 0xFF : vertex_windweights[i];
|
||||
Vertex_POS16 vert;
|
||||
vert.FromFULL(aabb, pos, wind);
|
||||
std::memcpy(vertices + i, &vert, sizeof(vert));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Vertex_POS32::FORMAT:
|
||||
{
|
||||
vb_pos_wind.offset = buffer_offset;
|
||||
vb_pos_wind.size = vertex_positions.size() * sizeof(Vertex_POS32);
|
||||
Vertex_POS32* vertices = (Vertex_POS32*)(buffer_data + buffer_offset);
|
||||
buffer_offset += AlignTo(vb_pos_wind.size, alignment);
|
||||
for (size_t i = 0; i < vertex_positions.size(); ++i)
|
||||
{
|
||||
const XMFLOAT3& pos = vertex_positions[i];
|
||||
const uint8_t wind = vertex_windweights.empty() ? 0xFF : vertex_windweights[i];
|
||||
Vertex_POS32 vert;
|
||||
vert.FromFULL(pos);
|
||||
std::memcpy(vertices + i, &vert, sizeof(vert));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Vertex_POS32W::FORMAT:
|
||||
{
|
||||
vb_pos_wind.offset = buffer_offset;
|
||||
vb_pos_wind.size = vertex_positions.size() * sizeof(Vertex_POS32W);
|
||||
Vertex_POS32W* vertices = (Vertex_POS32W*)(buffer_data + buffer_offset);
|
||||
buffer_offset += AlignTo(vb_pos_wind.size, alignment);
|
||||
for (size_t i = 0; i < vertex_positions.size(); ++i)
|
||||
{
|
||||
const XMFLOAT3& pos = vertex_positions[i];
|
||||
const uint8_t wind = vertex_windweights.empty() ? 0xFF : vertex_windweights[i];
|
||||
Vertex_POS32W vert;
|
||||
vert.FromFULL(pos, wind);
|
||||
std::memcpy(vertices + i, &vert, sizeof(vert));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Create index buffer GPU data:
|
||||
if (GetIndexFormat() == IndexBufferFormat::UINT32)
|
||||
{
|
||||
@@ -628,32 +805,23 @@ namespace wi::scene
|
||||
}
|
||||
}
|
||||
|
||||
XMFLOAT3 _min = XMFLOAT3(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
|
||||
XMFLOAT3 _max = XMFLOAT3(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest());
|
||||
|
||||
// vertexBuffer - POSITION + NORMAL + WIND:
|
||||
// vertexBuffer - NORMALS:
|
||||
if (!vertex_normals.empty())
|
||||
{
|
||||
vb_pos_nor_wind.offset = buffer_offset;
|
||||
vb_pos_nor_wind.size = vertex_positions.size() * sizeof(Vertex_POS);
|
||||
Vertex_POS* vertices = (Vertex_POS*)(buffer_data + buffer_offset);
|
||||
buffer_offset += AlignTo(vb_pos_nor_wind.size, alignment);
|
||||
for (size_t i = 0; i < vertex_positions.size(); ++i)
|
||||
vb_nor.offset = buffer_offset;
|
||||
vb_nor.size = vertex_normals.size() * sizeof(Vertex_NOR);
|
||||
Vertex_NOR* vertices = (Vertex_NOR*)(buffer_data + buffer_offset);
|
||||
buffer_offset += AlignTo(vb_nor.size, alignment);
|
||||
for (size_t i = 0; i < vertex_normals.size(); ++i)
|
||||
{
|
||||
const XMFLOAT3& pos = vertex_positions[i];
|
||||
XMFLOAT3 nor = vertex_normals.empty() ? XMFLOAT3(1, 1, 1) : vertex_normals[i];
|
||||
XMStoreFloat3(&nor, XMVector3Normalize(XMLoadFloat3(&nor)));
|
||||
const uint8_t wind = vertex_windweights.empty() ? 0xFF : vertex_windweights[i];
|
||||
Vertex_POS vert;
|
||||
vert.FromFULL(pos, nor, wind);
|
||||
Vertex_NOR vert;
|
||||
vert.FromFULL(nor);
|
||||
std::memcpy(vertices + i, &vert, sizeof(vert));
|
||||
|
||||
_min = wi::math::Min(_min, pos);
|
||||
_max = wi::math::Max(_max, pos);
|
||||
}
|
||||
}
|
||||
|
||||
aabb = AABB(_min, _max);
|
||||
|
||||
// vertexBuffer - TANGENTS
|
||||
if (!vertex_tangents.empty())
|
||||
{
|
||||
@@ -682,8 +850,8 @@ namespace wi::scene
|
||||
for (size_t i = 0; i < uv_count; ++i)
|
||||
{
|
||||
Vertex_UVS vert;
|
||||
vert.uv0.FromFULL(uv0_stream[i]);
|
||||
vert.uv1.FromFULL(uv1_stream[i]);
|
||||
vert.uv0.FromFULL(uv0_stream[i], uv_range_min, uv_range_max);
|
||||
vert.uv1.FromFULL(uv1_stream[i], uv_range_min, uv_range_max);
|
||||
std::memcpy(vertices + i, &vert, sizeof(vert));
|
||||
}
|
||||
}
|
||||
@@ -812,10 +980,15 @@ namespace wi::scene
|
||||
ib.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, ib.offset, ib.size, &ib_format);
|
||||
ib.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, ib.subresource_srv);
|
||||
|
||||
assert(vb_pos_nor_wind.IsValid());
|
||||
vb_pos_nor_wind.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos_nor_wind.offset, vb_pos_nor_wind.size, &Vertex_POS::FORMAT);
|
||||
vb_pos_nor_wind.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_pos_nor_wind.subresource_srv);
|
||||
assert(vb_pos_wind.IsValid());
|
||||
vb_pos_wind.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_pos_wind.offset, vb_pos_wind.size, &position_format);
|
||||
vb_pos_wind.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_pos_wind.subresource_srv);
|
||||
|
||||
if (vb_nor.IsValid())
|
||||
{
|
||||
vb_nor.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_nor.offset, vb_nor.size, &Vertex_NOR::FORMAT);
|
||||
vb_nor.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_nor.subresource_srv);
|
||||
}
|
||||
if (vb_tan.IsValid())
|
||||
{
|
||||
vb_tan.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_tan.offset, vb_tan.size, &Vertex_TAN::FORMAT);
|
||||
@@ -864,9 +1037,12 @@ namespace wi::scene
|
||||
{
|
||||
desc.misc_flags |= ResourceMiscFlag::RAY_TRACING;
|
||||
}
|
||||
const uint64_t alignment = device->GetMinOffsetAlignment(&desc);
|
||||
|
||||
const uint64_t alignment = device->GetMinOffsetAlignment(&desc) * sizeof(Vertex_POS32); // additional alignment for RGB32F
|
||||
desc.size =
|
||||
AlignTo(vertex_positions.size() * sizeof(Vertex_POS) * 2, alignment) + // *2 because prevpos also goes into this!
|
||||
AlignTo(vertex_positions.size() * sizeof(Vertex_POS32), alignment) + // pos
|
||||
AlignTo(vertex_positions.size() * sizeof(Vertex_POS32), alignment) + // prevpos
|
||||
AlignTo(vertex_normals.size() * sizeof(Vertex_NOR), alignment) +
|
||||
AlignTo(vertex_tangents.size() * sizeof(Vertex_TAN), alignment)
|
||||
;
|
||||
|
||||
@@ -876,13 +1052,32 @@ namespace wi::scene
|
||||
|
||||
uint64_t buffer_offset = 0ull;
|
||||
|
||||
so_pos_nor_wind.offset = buffer_offset;
|
||||
so_pos_nor_wind.size = vb_pos_nor_wind.size;
|
||||
buffer_offset += AlignTo(so_pos_nor_wind.size, alignment);
|
||||
so_pos_nor_wind.subresource_srv = device->CreateSubresource(&streamoutBuffer, SubresourceType::SRV, so_pos_nor_wind.offset, so_pos_nor_wind.size, &Vertex_POS::FORMAT);
|
||||
so_pos_nor_wind.subresource_uav = device->CreateSubresource(&streamoutBuffer, SubresourceType::UAV, so_pos_nor_wind.offset, so_pos_nor_wind.size, &Vertex_POS::FORMAT);
|
||||
so_pos_nor_wind.descriptor_srv = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::SRV, so_pos_nor_wind.subresource_srv);
|
||||
so_pos_nor_wind.descriptor_uav = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::UAV, so_pos_nor_wind.subresource_uav);
|
||||
so_pos.offset = buffer_offset;
|
||||
so_pos.size = vertex_positions.size() * sizeof(Vertex_POS32);
|
||||
buffer_offset += AlignTo(so_pos.size, alignment);
|
||||
so_pos.subresource_srv = device->CreateSubresource(&streamoutBuffer, SubresourceType::SRV, so_pos.offset, so_pos.size, &Vertex_POS32::FORMAT);
|
||||
so_pos.subresource_uav = device->CreateSubresource(&streamoutBuffer, SubresourceType::UAV, so_pos.offset, so_pos.size); // UAV can't have RGB32_F format!
|
||||
so_pos.descriptor_srv = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::SRV, so_pos.subresource_srv);
|
||||
so_pos.descriptor_uav = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::UAV, so_pos.subresource_uav);
|
||||
|
||||
so_pre.offset = buffer_offset;
|
||||
so_pre.size = so_pos.size;
|
||||
buffer_offset += AlignTo(so_pre.size, alignment);
|
||||
so_pre.subresource_srv = device->CreateSubresource(&streamoutBuffer, SubresourceType::SRV, so_pre.offset, so_pre.size, &Vertex_POS32::FORMAT);
|
||||
so_pre.subresource_uav = device->CreateSubresource(&streamoutBuffer, SubresourceType::UAV, so_pre.offset, so_pre.size); // UAV can't have RGB32_F format!
|
||||
so_pre.descriptor_srv = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::SRV, so_pre.subresource_srv);
|
||||
so_pre.descriptor_uav = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::UAV, so_pre.subresource_uav);
|
||||
|
||||
if (vb_nor.IsValid())
|
||||
{
|
||||
so_nor.offset = buffer_offset;
|
||||
so_nor.size = vb_nor.size;
|
||||
buffer_offset += AlignTo(so_nor.size, alignment);
|
||||
so_nor.subresource_srv = device->CreateSubresource(&streamoutBuffer, SubresourceType::SRV, so_nor.offset, so_nor.size, &Vertex_NOR::FORMAT);
|
||||
so_nor.subresource_uav = device->CreateSubresource(&streamoutBuffer, SubresourceType::UAV, so_nor.offset, so_nor.size, &Vertex_NOR::FORMAT);
|
||||
so_nor.descriptor_srv = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::SRV, so_nor.subresource_srv);
|
||||
so_nor.descriptor_uav = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::UAV, so_nor.subresource_uav);
|
||||
}
|
||||
|
||||
if (vb_tan.IsValid())
|
||||
{
|
||||
@@ -894,14 +1089,6 @@ namespace wi::scene
|
||||
so_tan.descriptor_srv = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::SRV, so_tan.subresource_srv);
|
||||
so_tan.descriptor_uav = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::UAV, so_tan.subresource_uav);
|
||||
}
|
||||
|
||||
so_pre.offset = buffer_offset;
|
||||
so_pre.size = vb_pos_nor_wind.size;
|
||||
buffer_offset += AlignTo(so_pre.size, alignment);
|
||||
so_pre.subresource_srv = device->CreateSubresource(&streamoutBuffer, SubresourceType::SRV, so_pre.offset, so_pre.size, &Vertex_POS::FORMAT);
|
||||
so_pre.subresource_uav = device->CreateSubresource(&streamoutBuffer, SubresourceType::UAV, so_pre.offset, so_pre.size, &Vertex_POS::FORMAT);
|
||||
so_pre.descriptor_srv = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::SRV, so_pre.subresource_srv);
|
||||
so_pre.descriptor_uav = device->GetDescriptorIndex(&streamoutBuffer, SubresourceType::UAV, so_pre.subresource_uav);
|
||||
}
|
||||
void MeshComponent::CreateRaytracingRenderData()
|
||||
{
|
||||
@@ -939,14 +1126,22 @@ namespace wi::scene
|
||||
auto& geometry = desc.bottom_level.geometries.back();
|
||||
geometry.type = RaytracingAccelerationStructureDesc::BottomLevel::Geometry::Type::TRIANGLES;
|
||||
geometry.triangles.vertex_buffer = generalBuffer;
|
||||
geometry.triangles.vertex_byte_offset = vb_pos_nor_wind.offset;
|
||||
geometry.triangles.vertex_byte_offset = vb_pos_wind.offset;
|
||||
geometry.triangles.index_buffer = generalBuffer;
|
||||
geometry.triangles.index_format = GetIndexFormat();
|
||||
geometry.triangles.index_count = subset.indexCount;
|
||||
geometry.triangles.index_offset = ib.offset / GetIndexStride() + subset.indexOffset;
|
||||
geometry.triangles.vertex_count = (uint32_t)vertex_positions.size();
|
||||
geometry.triangles.vertex_format = Format::R32G32B32_FLOAT;
|
||||
geometry.triangles.vertex_stride = sizeof(MeshComponent::Vertex_POS);
|
||||
if (so_pos.IsValid())
|
||||
{
|
||||
geometry.triangles.vertex_format = Vertex_POS32::FORMAT;
|
||||
geometry.triangles.vertex_stride = sizeof(Vertex_POS32);
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry.triangles.vertex_format = position_format == Format::R32G32B32A32_FLOAT ? Format::R32G32B32_FLOAT : position_format;
|
||||
geometry.triangles.vertex_stride = GetFormatStride(position_format);
|
||||
}
|
||||
}
|
||||
|
||||
bool success = device->CreateRaytracingAccelerationStructure(&desc, &BLASes[lod]);
|
||||
@@ -1616,20 +1811,18 @@ namespace wi::scene
|
||||
void SoftBodyPhysicsComponent::CreateFromMesh(const MeshComponent& mesh)
|
||||
{
|
||||
vertex_positions_simulation.resize(mesh.vertex_positions.size());
|
||||
vertex_normals_simulation.resize(mesh.vertex_normals.size());
|
||||
vertex_tangents_tmp.resize(mesh.vertex_tangents.size());
|
||||
vertex_tangents_simulation.resize(mesh.vertex_tangents.size());
|
||||
|
||||
XMMATRIX W = XMLoadFloat4x4(&worldMatrix);
|
||||
XMFLOAT3 _min = XMFLOAT3(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
|
||||
XMFLOAT3 _max = XMFLOAT3(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest());
|
||||
for (size_t i = 0; i < vertex_positions_simulation.size(); ++i)
|
||||
XMMATRIX W = XMLoadFloat4x4(&worldMatrix);
|
||||
for (size_t i = 0; i < mesh.vertex_positions.size(); ++i)
|
||||
{
|
||||
XMFLOAT3 pos = mesh.vertex_positions[i];
|
||||
XMStoreFloat3(&pos, XMVector3Transform(XMLoadFloat3(&pos), W));
|
||||
XMFLOAT3 nor = mesh.vertex_normals.empty() ? XMFLOAT3(1, 1, 1) : mesh.vertex_normals[i];
|
||||
XMStoreFloat3(&nor, XMVector3Normalize(XMVector3TransformNormal(XMLoadFloat3(&nor), W)));
|
||||
const uint8_t wind = mesh.vertex_windweights.empty() ? 0xFF : mesh.vertex_windweights[i];
|
||||
vertex_positions_simulation[i].FromFULL(pos, nor, wind);
|
||||
vertex_positions_simulation[i].FromFULL(pos);
|
||||
_min = wi::math::Min(_min, pos);
|
||||
_max = wi::math::Max(_max, pos);
|
||||
}
|
||||
|
||||
@@ -339,6 +339,7 @@ namespace wi::scene
|
||||
TLAS_FORCE_DOUBLE_SIDED = 1 << 6,
|
||||
DOUBLE_SIDED_SHADOW = 1 << 7,
|
||||
BVH_ENABLED = 1 << 8,
|
||||
QUANTIZED_POSITIONS_DISABLED = 1 << 9,
|
||||
};
|
||||
uint32_t _flags = RENDERABLE;
|
||||
|
||||
@@ -403,20 +404,24 @@ namespace wi::scene
|
||||
}
|
||||
};
|
||||
BufferView ib;
|
||||
BufferView vb_pos_nor_wind;
|
||||
BufferView vb_pos_wind;
|
||||
BufferView vb_nor;
|
||||
BufferView vb_tan;
|
||||
BufferView vb_uvs;
|
||||
BufferView vb_atl;
|
||||
BufferView vb_col;
|
||||
BufferView vb_bon;
|
||||
BufferView vb_mor;
|
||||
BufferView so_pos_nor_wind;
|
||||
BufferView so_pos;
|
||||
BufferView so_nor;
|
||||
BufferView so_tan;
|
||||
BufferView so_pre;
|
||||
uint32_t geometryOffset = 0;
|
||||
uint32_t meshletCount = 0;
|
||||
uint32_t active_morph_count = 0;
|
||||
uint32_t morphGPUOffset = 0;
|
||||
XMFLOAT2 uv_range_min = XMFLOAT2(0, 0);
|
||||
XMFLOAT2 uv_range_max = XMFLOAT2(1, 1);
|
||||
|
||||
wi::vector<wi::graphics::RaytracingAccelerationStructure> BLASes; // one BLAS per LOD
|
||||
enum BLAS_STATE
|
||||
@@ -440,11 +445,16 @@ namespace wi::scene
|
||||
// false: BVH will be deleted immediately if it exists
|
||||
inline void SetBVHEnabled(bool value) { if (value) { _flags |= BVH_ENABLED; if (!bvh.IsValid()) { BuildBVH(); } } else { _flags &= ~BVH_ENABLED; bvh = {}; bvh_leaf_aabbs.clear(); } }
|
||||
|
||||
// Disable quantization of position GPU data. You can use this if you notice inaccuracy in positions.
|
||||
// This should be enabled for connecting meshes like terrain chunks if their AABB is not consistent with each other
|
||||
inline void SetQuantizedPositionsDisabled(bool value) { if (value) { _flags |= QUANTIZED_POSITIONS_DISABLED; } else { _flags &= ~QUANTIZED_POSITIONS_DISABLED; } }
|
||||
|
||||
inline bool IsRenderable() const { return _flags & RENDERABLE; }
|
||||
inline bool IsDoubleSided() const { return _flags & DOUBLE_SIDED; }
|
||||
inline bool IsDoubleSidedShadow() const { return _flags & DOUBLE_SIDED_SHADOW; }
|
||||
inline bool IsDynamic() const { return _flags & DYNAMIC; }
|
||||
inline bool IsBVHEnabled() const { return _flags & BVH_ENABLED; }
|
||||
inline bool IsQuantizedPositionsDisabled() const { return _flags & QUANTIZED_POSITIONS_DISABLED; }
|
||||
|
||||
inline float GetTessellationFactor() const { return tessellationFactor; }
|
||||
inline wi::graphics::IndexBufferFormat GetIndexFormat() const { return wi::graphics::GetIndexBufferFormat((uint32_t)vertex_positions.size()); }
|
||||
@@ -493,75 +503,145 @@ namespace wi::scene
|
||||
|
||||
void Serialize(wi::Archive& archive, wi::ecs::EntitySerializer& seri);
|
||||
|
||||
|
||||
struct Vertex_POS
|
||||
struct Vertex_POS10
|
||||
{
|
||||
XMFLOAT3 pos = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
uint8_t n_x = 0;
|
||||
uint8_t n_y = 0;
|
||||
uint8_t n_z = 0;
|
||||
uint8_t w = 0;
|
||||
uint32_t x : 10;
|
||||
uint32_t y : 10;
|
||||
uint32_t z : 10;
|
||||
uint32_t w : 2;
|
||||
|
||||
constexpr void FromFULL(const XMFLOAT3& _pos, const XMFLOAT3& _nor, uint8_t wind)
|
||||
constexpr void FromFULL(const wi::primitive::AABB& aabb, XMFLOAT3 pos, uint8_t wind)
|
||||
{
|
||||
pos.x = _pos.x;
|
||||
pos.y = _pos.y;
|
||||
pos.z = _pos.z;
|
||||
MakeFromParams(_nor, wind);
|
||||
pos = wi::math::InverseLerp(aabb._min, aabb._max, pos); // UNORM remap
|
||||
x = uint32_t(wi::math::saturate(pos.x) * 1023.0f);
|
||||
y = uint32_t(wi::math::saturate(pos.y) * 1023.0f);
|
||||
z = uint32_t(wi::math::saturate(pos.z) * 1023.0f);
|
||||
w = uint32_t((float(wind) / 255.0f) * 3);
|
||||
}
|
||||
inline XMVECTOR LoadPOS() const
|
||||
inline XMVECTOR LoadPOS(const wi::primitive::AABB& aabb) const
|
||||
{
|
||||
return XMLoadFloat3(&pos);
|
||||
XMFLOAT3 v = GetPOS(aabb);
|
||||
return XMLoadFloat3(&v);
|
||||
}
|
||||
inline XMVECTOR LoadNOR() const
|
||||
constexpr XMFLOAT3 GetPOS(const wi::primitive::AABB& aabb) const
|
||||
{
|
||||
XMFLOAT3 N = GetNor_FULL();
|
||||
return XMLoadFloat3(&N);
|
||||
}
|
||||
constexpr void MakeFromParams(const XMFLOAT3& normal)
|
||||
{
|
||||
n_x = uint8_t((normal.x * 0.5f + 0.5f) * 255.0f);
|
||||
n_y = uint8_t((normal.y * 0.5f + 0.5f) * 255.0f);
|
||||
n_z = uint8_t((normal.z * 0.5f + 0.5f) * 255.0f);
|
||||
}
|
||||
constexpr void MakeFromParams(const XMFLOAT3& normal, uint8_t wind)
|
||||
{
|
||||
n_x = uint8_t((normal.x * 0.5f + 0.5f) * 255.0f);
|
||||
n_y = uint8_t((normal.y * 0.5f + 0.5f) * 255.0f);
|
||||
n_z = uint8_t((normal.z * 0.5f + 0.5f) * 255.0f);
|
||||
w = wind;
|
||||
}
|
||||
constexpr XMFLOAT3 GetNor_FULL() const
|
||||
{
|
||||
XMFLOAT3 nor_FULL(0, 0, 0);
|
||||
nor_FULL.x = (float(n_x) / 255.0f) * 2.0f - 1.0f;
|
||||
nor_FULL.y = (float(n_y) / 255.0f) * 2.0f - 1.0f;
|
||||
nor_FULL.z = (float(n_z) / 255.0f) * 2.0f - 1.0f;
|
||||
return nor_FULL;
|
||||
XMFLOAT3 v = XMFLOAT3(
|
||||
float(x) / 1023.0f,
|
||||
float(y) / 1023.0f,
|
||||
float(z) / 1023.0f
|
||||
);
|
||||
return wi::math::Lerp(aabb._min, aabb._max, v);
|
||||
}
|
||||
constexpr uint8_t GetWind() const
|
||||
{
|
||||
return w;
|
||||
return uint8_t((float(w) / 3.0f) * 255);
|
||||
}
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R10G10B10A2_UNORM;
|
||||
};
|
||||
struct Vertex_POS16
|
||||
{
|
||||
uint16_t x = 0;
|
||||
uint16_t y = 0;
|
||||
uint16_t z = 0;
|
||||
uint16_t w = 0;
|
||||
|
||||
constexpr void FromFULL(const wi::primitive::AABB& aabb, XMFLOAT3 pos, uint8_t wind)
|
||||
{
|
||||
pos = wi::math::InverseLerp(aabb._min, aabb._max, pos); // UNORM remap
|
||||
x = uint16_t(pos.x * 65535.0f);
|
||||
y = uint16_t(pos.y * 65535.0f);
|
||||
z = uint16_t(pos.z * 65535.0f);
|
||||
w = uint16_t((float(wind) / 255.0f) * 65535.0f);
|
||||
}
|
||||
inline XMVECTOR LoadPOS(const wi::primitive::AABB& aabb) const
|
||||
{
|
||||
XMFLOAT3 v = GetPOS(aabb);
|
||||
return XMLoadFloat3(&v);
|
||||
}
|
||||
constexpr XMFLOAT3 GetPOS(const wi::primitive::AABB& aabb) const
|
||||
{
|
||||
XMFLOAT3 v = XMFLOAT3(
|
||||
float(x) / 65535.0f,
|
||||
float(y) / 65535.0f,
|
||||
float(z) / 65535.0f
|
||||
);
|
||||
return wi::math::Lerp(aabb._min, aabb._max, v);
|
||||
}
|
||||
constexpr uint8_t GetWind() const
|
||||
{
|
||||
return uint8_t((float(w) / 65535.0f) * 255);
|
||||
}
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R16G16B16A16_UNORM;
|
||||
};
|
||||
struct Vertex_POS32
|
||||
{
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
|
||||
constexpr void FromFULL(const XMFLOAT3& pos)
|
||||
{
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
z = pos.z;
|
||||
}
|
||||
inline XMVECTOR LoadPOS() const
|
||||
{
|
||||
return XMVectorSet(x, y, z, 1);
|
||||
}
|
||||
constexpr XMFLOAT3 GetPOS() const
|
||||
{
|
||||
return XMFLOAT3(x, y, z);
|
||||
}
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R32G32B32_FLOAT;
|
||||
};
|
||||
struct Vertex_POS32W
|
||||
{
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
float w = 0;
|
||||
|
||||
constexpr void FromFULL(const XMFLOAT3& pos, uint8_t wind)
|
||||
{
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
z = pos.z;
|
||||
w = float(wind) / 255.0f;
|
||||
}
|
||||
inline XMVECTOR LoadPOS() const
|
||||
{
|
||||
return XMVectorSet(x, y, z, 1);
|
||||
}
|
||||
constexpr XMFLOAT3 GetPOS() const
|
||||
{
|
||||
return XMFLOAT3(x, y, z);
|
||||
}
|
||||
constexpr uint8_t GetWind() const
|
||||
{
|
||||
return uint8_t(w * 255);
|
||||
}
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R32G32B32A32_FLOAT;
|
||||
};
|
||||
wi::graphics::Format position_format = Vertex_POS16::FORMAT; // CreateRenderData() will choose the appropriate format
|
||||
|
||||
struct Vertex_TEX
|
||||
{
|
||||
XMHALF2 tex = XMHALF2(0.0f, 0.0f);
|
||||
uint16_t x = 0;
|
||||
uint16_t y = 0;
|
||||
|
||||
void FromFULL(const XMFLOAT2& texcoords)
|
||||
constexpr void FromFULL(const XMFLOAT2& uv, const XMFLOAT2& uv_range_min = XMFLOAT2(0, 0), const XMFLOAT2& uv_range_max = XMFLOAT2(1, 1))
|
||||
{
|
||||
tex = XMHALF2(texcoords.x, texcoords.y);
|
||||
x = uint16_t(wi::math::InverseLerp(uv_range_min.x, uv_range_max.x, uv.x) * 65535.0f);
|
||||
y = uint16_t(wi::math::InverseLerp(uv_range_min.y, uv_range_max.y, uv.y) * 65535.0f);
|
||||
}
|
||||
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R16G16_FLOAT;
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R16G16_UNORM;
|
||||
};
|
||||
struct Vertex_UVS
|
||||
{
|
||||
Vertex_TEX uv0;
|
||||
Vertex_TEX uv1;
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R16G16B16A16_FLOAT;
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R16G16B16A16_UNORM;
|
||||
};
|
||||
struct Vertex_BON
|
||||
{
|
||||
@@ -606,6 +686,44 @@ namespace wi::scene
|
||||
uint32_t color = 0;
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R8G8B8A8_UNORM;
|
||||
};
|
||||
struct Vertex_NOR
|
||||
{
|
||||
int8_t x = 0;
|
||||
int8_t y = 0;
|
||||
int8_t z = 0;
|
||||
int8_t w = 0;
|
||||
|
||||
void FromFULL(const XMFLOAT3& nor)
|
||||
{
|
||||
XMVECTOR N = XMLoadFloat3(&nor);
|
||||
N = XMVector3Normalize(N);
|
||||
XMFLOAT3 n;
|
||||
XMStoreFloat3(&n, N);
|
||||
|
||||
x = int8_t(n.x * 127.5f);
|
||||
y = int8_t(n.y * 127.5f);
|
||||
z = int8_t(n.z * 127.5f);
|
||||
w = 0;
|
||||
}
|
||||
inline XMFLOAT3 GetNOR() const
|
||||
{
|
||||
return XMFLOAT3(
|
||||
float(x) / 127.5f,
|
||||
float(y) / 127.5f,
|
||||
float(z) / 127.5f
|
||||
);
|
||||
}
|
||||
inline XMVECTOR LoadNOR() const
|
||||
{
|
||||
return XMVectorSet(
|
||||
float(x) / 127.5f,
|
||||
float(y) / 127.5f,
|
||||
float(z) / 127.5f,
|
||||
0
|
||||
);
|
||||
}
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R8G8B8A8_SNORM;
|
||||
};
|
||||
struct Vertex_TAN
|
||||
{
|
||||
int8_t x = 0;
|
||||
@@ -626,7 +744,15 @@ namespace wi::scene
|
||||
z = int8_t(t.z * 127.5f);
|
||||
w = int8_t(t.w * 127.5f);
|
||||
}
|
||||
|
||||
inline XMFLOAT4 GetTAN() const
|
||||
{
|
||||
return XMFLOAT4(
|
||||
float(x) / 127.5f,
|
||||
float(y) / 127.5f,
|
||||
float(z) / 127.5f,
|
||||
float(w) / 127.5f
|
||||
);
|
||||
}
|
||||
static constexpr wi::graphics::Format FORMAT = wi::graphics::Format::R8G8B8A8_SNORM;
|
||||
};
|
||||
|
||||
@@ -819,7 +945,8 @@ namespace wi::scene
|
||||
// Non-serialized attributes:
|
||||
std::shared_ptr<void> physicsobject = nullptr; // You can set to null to recreate the physics object the next time phsyics system will be running.
|
||||
XMFLOAT4X4 worldMatrix = wi::math::IDENTITY_MATRIX;
|
||||
wi::vector<MeshComponent::Vertex_POS> vertex_positions_simulation; // graphics vertices after simulation (world space)
|
||||
wi::vector<MeshComponent::Vertex_POS32> vertex_positions_simulation; // graphics vertices after simulation (world space)
|
||||
wi::vector<MeshComponent::Vertex_NOR> vertex_normals_simulation;
|
||||
wi::vector<XMFLOAT4>vertex_tangents_tmp;
|
||||
wi::vector<MeshComponent::Vertex_TAN> vertex_tangents_simulation;
|
||||
wi::primitive::AABB aabb;
|
||||
@@ -828,6 +955,11 @@ namespace wi::scene
|
||||
|
||||
inline bool IsDisableDeactivation() const { return _flags & DISABLE_DEACTIVATION; }
|
||||
|
||||
inline bool HasVertices() const
|
||||
{
|
||||
return !vertex_positions_simulation.empty();
|
||||
}
|
||||
|
||||
// Create physics represenation of graphics mesh
|
||||
void CreateFromMesh(const MeshComponent& mesh);
|
||||
|
||||
|
||||
@@ -750,6 +750,7 @@ namespace wi::terrain
|
||||
material.SetReflectance(1);
|
||||
|
||||
MeshComponent& mesh = generator->scene.meshes.Create(chunk_data.entity);
|
||||
mesh.SetQuantizedPositionsDisabled(true); // connecting meshes quantization is not correct because mismatching AABBs
|
||||
object.meshID = chunk_data.entity;
|
||||
mesh.indices = chunk_indices().indices;
|
||||
for (auto& lod : chunk_indices().lods)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wi::version
|
||||
// minor features, major updates, breaking compatibility changes
|
||||
const int minor = 71;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 344;
|
||||
const int revision = 345;
|
||||
|
||||
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user