diff --git a/Editor/Editor_UWP.vcxproj b/Editor/Editor_UWP.vcxproj
index 0fcb5835f..1ea96c25b 100644
--- a/Editor/Editor_UWP.vcxproj
+++ b/Editor/Editor_UWP.vcxproj
@@ -105,6 +105,7 @@
%(AdditionalDependencies)
$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64;../$(Platform)/$(Configuration)
false
+ UseLinkTimeCodeGeneration
stdafx.h
diff --git a/Editor/Editor_Windows.vcxproj b/Editor/Editor_Windows.vcxproj
index bc8f798a0..33ab7da19 100644
--- a/Editor/Editor_Windows.vcxproj
+++ b/Editor/Editor_Windows.vcxproj
@@ -110,6 +110,7 @@
true
true
$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
+ UseLinkTimeCodeGeneration
5.0
diff --git a/Editor/HairParticleWindow.cpp b/Editor/HairParticleWindow.cpp
index 3d87f2ab6..dfbc96502 100644
--- a/Editor/HairParticleWindow.cpp
+++ b/Editor/HairParticleWindow.cpp
@@ -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);
diff --git a/Editor/MeshWindow.cpp b/Editor/MeshWindow.cpp
index b29797dc6..1a75307fc 100644
--- a/Editor/MeshWindow.cpp
+++ b/Editor/MeshWindow.cpp
@@ -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);
diff --git a/Editor/MeshWindow.h b/Editor/MeshWindow.h
index e354252f5..490717814 100644
--- a/Editor/MeshWindow.h
+++ b/Editor/MeshWindow.h
@@ -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;
diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp
index 3db611cfb..ed74a1de9 100644
--- a/Editor/PaintToolWindow.cpp
+++ b/Editor/PaintToolWindow.cpp
@@ -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
diff --git a/Template_UWP/Template_UWP.vcxproj b/Template_UWP/Template_UWP.vcxproj
index 686c449e6..392996991 100644
--- a/Template_UWP/Template_UWP.vcxproj
+++ b/Template_UWP/Template_UWP.vcxproj
@@ -105,6 +105,7 @@
%(AdditionalDependencies)
$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64;../$(Platform)/$(Configuration)
false
+ UseLinkTimeCodeGeneration
pch.h
diff --git a/Template_Windows/Template_Windows.vcxproj b/Template_Windows/Template_Windows.vcxproj
index 0d1a9a1ce..256726128 100644
--- a/Template_Windows/Template_Windows.vcxproj
+++ b/Template_Windows/Template_Windows.vcxproj
@@ -73,6 +73,7 @@
true
true
$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
+ UseLinkTimeCodeGeneration
diff --git a/Tests/Tests.vcxproj b/Tests/Tests.vcxproj
index 69062a077..22b6960de 100644
--- a/Tests/Tests.vcxproj
+++ b/Tests/Tests.vcxproj
@@ -76,6 +76,7 @@
true
true
$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
+ UseLinkTimeCodeGeneration
diff --git a/WickedEngine/Utility/basis_universal/encoder/jpgd.cpp b/WickedEngine/Utility/basis_universal/encoder/jpgd.cpp
index fec8b7143..8ee3d06cf 100644
--- a/WickedEngine/Utility/basis_universal/encoder/jpgd.cpp
+++ b/WickedEngine/Utility/basis_universal/encoder/jpgd.cpp
@@ -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)
{
diff --git a/WickedEngine/shaders/ShaderInterop_EmittedParticle.h b/WickedEngine/shaders/ShaderInterop_EmittedParticle.h
index a3169e20f..39f909eab 100644
--- a/WickedEngine/shaders/ShaderInterop_EmittedParticle.h
+++ b/WickedEngine/shaders/ShaderInterop_EmittedParticle.h
@@ -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;
diff --git a/WickedEngine/shaders/ShaderInterop_HairParticle.h b/WickedEngine/shaders/ShaderInterop_HairParticle.h
index 4401d99bf..2f6c45c09 100644
--- a/WickedEngine/shaders/ShaderInterop_HairParticle.h
+++ b/WickedEngine/shaders/ShaderInterop_HairParticle.h
@@ -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;
diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h
index bc17dd76d..623fc71ab 100644
--- a/WickedEngine/shaders/ShaderInterop_Renderer.h
+++ b/WickedEngine/shaders/ShaderInterop_Renderer.h
@@ -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
diff --git a/WickedEngine/shaders/bvh_primitivesCS.hlsl b/WickedEngine/shaders/bvh_primitivesCS.hlsl
index 112edf669..2bb075105 100644
--- a/WickedEngine/shaders/bvh_primitivesCS.hlsl
+++ b/WickedEngine/shaders/bvh_primitivesCS.hlsl
@@ -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;
diff --git a/WickedEngine/shaders/emittedparticleMS.hlsl b/WickedEngine/shaders/emittedparticleMS.hlsl
index 168e1b674..86b957035 100644
--- a/WickedEngine/shaders/emittedparticleMS.hlsl
+++ b/WickedEngine/shaders/emittedparticleMS.hlsl
@@ -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;
diff --git a/WickedEngine/shaders/emittedparticleVS.hlsl b/WickedEngine/shaders/emittedparticleVS.hlsl
index 09d57f09d..a73985555 100644
--- a/WickedEngine/shaders/emittedparticleVS.hlsl
+++ b/WickedEngine/shaders/emittedparticleVS.hlsl
@@ -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];
diff --git a/WickedEngine/shaders/emittedparticle_emitCS.hlsl b/WickedEngine/shaders/emittedparticle_emitCS.hlsl
index 28d397a16..adbe40bf2 100644
--- a/WickedEngine/shaders/emittedparticle_emitCS.hlsl
+++ b/WickedEngine/shaders/emittedparticle_emitCS.hlsl
@@ -12,6 +12,7 @@ RWByteAddressBuffer counterBuffer : register(u4);
#ifdef EMIT_FROM_MESH
Buffer meshIndexBuffer : register(t0);
Buffer meshVertexBuffer_POS : register(t1);
+Buffer 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));
diff --git a/WickedEngine/shaders/emittedparticle_simulateCS.hlsl b/WickedEngine/shaders/emittedparticle_simulateCS.hlsl
index 001bcd2b6..89e18846c 100644
--- a/WickedEngine/shaders/emittedparticle_simulateCS.hlsl
+++ b/WickedEngine/shaders/emittedparticle_simulateCS.hlsl
@@ -16,11 +16,12 @@ RWStructuredBuffer aliveBuffer_NEW : register(u2);
RWStructuredBuffer deadBuffer : register(u3);
RWByteAddressBuffer counterBuffer : register(u4);
RWStructuredBuffer distanceBuffer : register(u6);
-RWBuffer vertexBuffer_POS : register(u7);
-RWBuffer vertexBuffer_UVS : register(u8);
-RWBuffer vertexBuffer_COL : register(u9);
-RWStructuredBuffer culledIndirectionBuffer : register(u10);
-RWStructuredBuffer culledIndirectionBuffer2 : register(u11);
+RWByteAddressBuffer vertexBuffer_POS : register(u7);
+RWBuffer vertexBuffer_NOR : register(u8);
+RWBuffer vertexBuffer_UVS : register(u9);
+RWBuffer vertexBuffer_COL : register(u10);
+RWStructuredBuffer culledIndirectionBuffer : register(u11);
+RWStructuredBuffer 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((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((v0 + 0) * sizeof(float3), 0);
+ vertexBuffer_POS.Store((v0 + 1) * sizeof(float3), 0);
+ vertexBuffer_POS.Store((v0 + 2) * sizeof(float3), 0);
+ vertexBuffer_POS.Store((v0 + 3) * sizeof(float3), 0);
}
}
diff --git a/WickedEngine/shaders/globals.hlsli b/WickedEngine/shaders/globals.hlsli
index e0632895a..7a972513d 100644
--- a/WickedEngine/shaders/globals.hlsli
+++ b/WickedEngine/shaders/globals.hlsli
@@ -435,6 +435,12 @@ inline float3 clipspace_to_uv(in float3 clipspace)
return clipspace * float3(0.5, -0.5, 0.5) + 0.5;
}
+template
+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; }
diff --git a/WickedEngine/shaders/hairparticleVS.hlsl b/WickedEngine/shaders/hairparticleVS.hlsl
index c43747006..d028daf87 100644
--- a/WickedEngine/shaders/hairparticleVS.hlsl
+++ b/WickedEngine/shaders/hairparticleVS.hlsl
@@ -6,15 +6,16 @@ Buffer 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);
diff --git a/WickedEngine/shaders/hairparticle_simulateCS.hlsl b/WickedEngine/shaders/hairparticle_simulateCS.hlsl
index c81c79f37..57a4ad0b2 100644
--- a/WickedEngine/shaders/hairparticle_simulateCS.hlsl
+++ b/WickedEngine/shaders/hairparticle_simulateCS.hlsl
@@ -11,20 +11,24 @@ static const float3 HAIRPATCH[] = {
Buffer meshIndexBuffer : register(t0);
Buffer meshVertexBuffer_POS : register(t1);
-Buffer meshVertexBuffer_length : register(t2);
+Buffer meshVertexBuffer_NOR : register(t2);
+Buffer meshVertexBuffer_length : register(t3);
RWStructuredBuffer simulationBuffer : register(u0);
RWBuffer vertexBuffer_POS : register(u1);
RWBuffer vertexBuffer_UVS : register(u2);
RWBuffer culledIndexBuffer : register(u3);
RWStructuredBuffer indirectBuffer : register(u4);
-RWByteAddressBuffer vertexBuffer_POS_RT : register(u5);
+RWBuffer vertexBuffer_POS_RT : register(u5);
+RWBuffer 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((v0 + vertexID) * sizeof(float3), position);
+ vertexBuffer_POS_RT[v0 + vertexID] = float4(position, 0);
}
// Frustum culling:
diff --git a/WickedEngine/shaders/impostorHF.hlsli b/WickedEngine/shaders/impostorHF.hlsli
index 555531374..d44163f6a 100644
--- a/WickedEngine/shaders/impostorHF.hlsli
+++ b/WickedEngine/shaders/impostorHF.hlsli
@@ -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;
diff --git a/WickedEngine/shaders/impostorVS.hlsl b/WickedEngine/shaders/impostorVS.hlsl
index 97aba0e30..c3c463c72 100644
--- a/WickedEngine/shaders/impostorVS.hlsl
+++ b/WickedEngine/shaders/impostorVS.hlsl
@@ -8,7 +8,7 @@ static const float2 BILLBOARD[] = {
float2(1, 1),
};
-Buffer vb_pos_nor : register(t0);
+Buffer 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;
diff --git a/WickedEngine/shaders/impostor_prepareCS.hlsl b/WickedEngine/shaders/impostor_prepareCS.hlsl
index 467659995..97ee48f86 100644
--- a/WickedEngine/shaders/impostor_prepareCS.hlsl
+++ b/WickedEngine/shaders/impostor_prepareCS.hlsl
@@ -11,9 +11,10 @@ static const float3 BILLBOARD[] =
};
RWBuffer output_indices : register(u0);
-RWBuffer output_vertices_pos_nor : register(u1);
-RWByteAddressBuffer output_impostor_data : register(u2);
-RWStructuredBuffer output_indirect : register(u3);
+RWByteAddressBuffer output_vertices_pos : register(u1);
+RWBuffer output_vertices_nor : register(u2);
+RWByteAddressBuffer output_impostor_data : register(u3);
+RWStructuredBuffer 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((vertexOffset + vertexID) * sizeof(float3), pos);
+ output_vertices_nor[vertexOffset + vertexID] = float4(face, 0);
}
}
}
diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli
index da7c611c0..115a42195 100644
--- a/WickedEngine/shaders/objectHF.hlsli
+++ b/WickedEngine/shaders/objectHF.hlsli
@@ -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
}
diff --git a/WickedEngine/shaders/objectVS_debug.hlsl b/WickedEngine/shaders/objectVS_debug.hlsl
index ec41aee91..db527cbe0 100644
--- a/WickedEngine/shaders/objectVS_debug.hlsl
+++ b/WickedEngine/shaders/objectVS_debug.hlsl
@@ -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));
}
diff --git a/WickedEngine/shaders/renderlightmapVS.hlsl b/WickedEngine/shaders/renderlightmapVS.hlsl
index f74a02e05..e76ba7ff1 100644
--- a/WickedEngine/shaders/renderlightmapVS.hlsl
+++ b/WickedEngine/shaders/renderlightmapVS.hlsl
@@ -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;
}
diff --git a/WickedEngine/shaders/skinningCS.hlsl b/WickedEngine/shaders/skinningCS.hlsl
index de396323b..19d141716 100644
--- a/WickedEngine/shaders/skinningCS.hlsl
+++ b/WickedEngine/shaders/skinningCS.hlsl
@@ -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(vertexID * sizeof(float3), pos);
+ }
+
+ [branch]
+ if (push.so_nor >= 0)
+ {
+ bindless_rwbuffers_float4[push.so_nor][vertexID] = float4(nor, 0);
}
[branch]
diff --git a/WickedEngine/shaders/surfaceHF.hlsli b/WickedEngine/shaders/surfaceHF.hlsli
index f070311f5..69d90a0a3 100644
--- a/WickedEngine/shaders/surfaceHF.hlsli
+++ b/WickedEngine/shaders/surfaceHF.hlsli
@@ -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 buf = bindless_buffers_float4[NonUniformResourceIndex(geometry.vb_pos_nor_wind)];
+ Buffer 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 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 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
diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp
index 54ec9f768..660751b17 100644
--- a/WickedEngine/wiEmittedParticle.cpp
+++ b/WickedEngine/wiEmittedParticle.cpp
@@ -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())
diff --git a/WickedEngine/wiEmittedParticle.h b/WickedEngine/wiEmittedParticle.h
index 0b61b9cdd..810a3181e 100644
--- a/WickedEngine/wiEmittedParticle.h
+++ b/WickedEngine/wiEmittedParticle.h
@@ -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
diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h
index ad0bff20b..41779641a 100644
--- a/WickedEngine/wiEnums.h
+++ b/WickedEngine/wiEnums.h
@@ -408,8 +408,6 @@ namespace wi::enums
// input layouts
enum ILTYPES
{
- ILTYPE_OBJECT_DEBUG,
- ILTYPE_RENDERLIGHTMAP,
ILTYPE_VERTEXCOLOR,
ILTYPE_POSITION,
ILTYPE_COUNT
diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp
index 096eff1f1..ae9d48793 100644
--- a/WickedEngine/wiHairParticle.cpp
+++ b/WickedEngine/wiHairParticle.cpp
@@ -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();
diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h
index 4321a1eac..6f6317007 100644
--- a/WickedEngine/wiHairParticle.h
+++ b/WickedEngine/wiHairParticle.h
@@ -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 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);
diff --git a/WickedEngine/wiMath.h b/WickedEngine/wiMath.h
index e0d4a7a6d..32b1013d4 100644
--- a/WickedEngine/wiMath.h
+++ b/WickedEngine/wiMath.h
@@ -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));
diff --git a/WickedEngine/wiPhysics_Bullet.cpp b/WickedEngine/wiPhysics_Bullet.cpp
index bab00273e..b1ed2a436 100644
--- a/WickedEngine/wiPhysics_Bullet.cpp
+++ b/WickedEngine/wiPhysics_Bullet.cpp
@@ -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));
diff --git a/WickedEngine/wiPrimitive.cpp b/WickedEngine/wiPrimitive.cpp
index 9f014e677..a55cc57bf 100644
--- a/WickedEngine/wiPrimitive.cpp
+++ b/WickedEngine/wiPrimitive.cpp
@@ -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();
diff --git a/WickedEngine/wiPrimitive.h b/WickedEngine/wiPrimitive.h
index 6837100e8..38a9fd2bf 100644
--- a/WickedEngine/wiPrimitive.h
+++ b/WickedEngine/wiPrimitive.h
@@ -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;
diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp
index 90865d7b8..e321f0cb7 100644
--- a/WickedEngine/wiRenderer.cpp
+++ b/WickedEngine/wiRenderer.cpp
@@ -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);
diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp
index bab2236b7..c434f1c36 100644
--- a/WickedEngine/wiScene.cpp
+++ b/WickedEngine/wiScene.cpp
@@ -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();
diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h
index 20b5c44ff..ca40a3446 100644
--- a/WickedEngine/wiScene.h
+++ b/WickedEngine/wiScene.h
@@ -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;
diff --git a/WickedEngine/wiScene_Components.cpp b/WickedEngine/wiScene_Components.cpp
index c2e6fce37..3c1902c26 100644
--- a/WickedEngine/wiScene_Components.cpp
+++ b/WickedEngine/wiScene_Components.cpp
@@ -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::max(), std::numeric_limits::max(), std::numeric_limits::max());
+ XMFLOAT3 _max = XMFLOAT3(std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::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::epsilon())
+ {
+ aabb._max.x += std::numeric_limits::epsilon();
+ aabb._min.x -= std::numeric_limits::epsilon();
+ }
+ if (aabb._max.y - aabb._min.y < std::numeric_limits::epsilon())
+ {
+ aabb._max.y += std::numeric_limits::epsilon();
+ aabb._min.y -= std::numeric_limits::epsilon();
+ }
+ if (aabb._max.z - aabb._min.z < std::numeric_limits::epsilon())
+ {
+ aabb._max.z += std::numeric_limits::epsilon();
+ aabb._min.z -= std::numeric_limits::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::max(), std::numeric_limits::max());
+ uv_range_max = XMFLOAT2(std::numeric_limits::lowest(), std::numeric_limits::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::max(), std::numeric_limits::max(), std::numeric_limits::max());
- XMFLOAT3 _max = XMFLOAT3(std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::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::max(), std::numeric_limits::max(), std::numeric_limits::max());
XMFLOAT3 _max = XMFLOAT3(std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::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);
}
diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h
index c4e2e042d..ec889beec 100644
--- a/WickedEngine/wiScene_Components.h
+++ b/WickedEngine/wiScene_Components.h
@@ -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 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 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 vertex_positions_simulation; // graphics vertices after simulation (world space)
+ wi::vector vertex_positions_simulation; // graphics vertices after simulation (world space)
+ wi::vector vertex_normals_simulation;
wi::vectorvertex_tangents_tmp;
wi::vector 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);
diff --git a/WickedEngine/wiTerrain.cpp b/WickedEngine/wiTerrain.cpp
index e8616af06..36f0e4249 100644
--- a/WickedEngine/wiTerrain.cpp
+++ b/WickedEngine/wiTerrain.cpp
@@ -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)
diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp
index 548a74778..a9d4de404 100644
--- a/WickedEngine/wiVersion.cpp
+++ b/WickedEngine/wiVersion.cpp
@@ -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);