vertex buffer quantization (#777)

This commit is contained in:
Turánszki János
2023-11-16 18:23:23 +01:00
committed by GitHub
parent ed15992c1b
commit 1479fe9084
45 changed files with 1001 additions and 388 deletions
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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
View File
@@ -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);
+1
View File
@@ -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;
+8 -8
View File
@@ -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
+1
View File
@@ -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>
+1
View File
@@ -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;
+44 -12
View File
@@ -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
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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;
+3 -3
View File
@@ -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);
}
}
+6
View File
@@ -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; }
+4 -3
View File
@@ -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:
+1
View File
@@ -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;
+3 -2
View File
@@ -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;
+6 -4
View File
@@ -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);
}
}
}
+16 -9
View File
@@ -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
}
+4 -4
View File
@@ -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));
}
+11 -14
View File
@@ -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;
}
+65 -17
View File
@@ -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]
+27 -32
View File
@@ -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
+39 -16
View File
@@ -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())
+1
View File
@@ -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
-2
View File
@@ -408,8 +408,6 @@ namespace wi::enums
// input layouts
enum ILTYPES
{
ILTYPE_OBJECT_DEBUG,
ILTYPE_RENDERLIGHTMAP,
ILTYPE_VERTEXCOLOR,
ILTYPE_POSITION,
ILTYPE_COUNT
+49 -15
View File
@@ -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();
+2
View File
@@ -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);
+41
View File
@@ -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));
+10 -17
View File
@@ -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));
+7
View File
@@ -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();
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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();
+2 -1
View File
@@ -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;
+245 -52
View File
@@ -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);
}
+181 -49
View File
@@ -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);
+1
View File
@@ -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)
+1 -1
View File
@@ -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);