Skip to content

Commit

Permalink
instancable (per object) vertex ao
Browse files Browse the repository at this point in the history
  • Loading branch information
turanszkij committed Jan 27, 2024
1 parent ecd6994 commit c316cea
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 90 deletions.
13 changes: 0 additions & 13 deletions Editor/MeshWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,16 +441,6 @@ void MeshWindow::Create(EditorComponent* _editor)
merged_mesh.vertex_colors.push_back(mesh->vertex_colors[i]);
}

if (mesh->vertex_ao.empty())
{
merged_mesh.vertex_ao.push_back(0xFF);
}
else
{
valid_ao = true;
merged_mesh.vertex_ao.push_back(mesh->vertex_ao[i]);
}

if (mesh->vertex_windweights.empty())
{
merged_mesh.vertex_windweights.emplace_back();
Expand Down Expand Up @@ -499,8 +489,6 @@ void MeshWindow::Create(EditorComponent* _editor)
merged_mesh.vertex_boneweights.clear();
if (!valid_colors)
merged_mesh.vertex_colors.clear();
if (!valid_ao)
merged_mesh.vertex_ao.clear();
if (!valid_windweights)
merged_mesh.vertex_windweights.clear();

Expand Down Expand Up @@ -906,7 +894,6 @@ void MeshWindow::SetEntity(Entity entity, int subset)
if (mesh->vb_uvs.IsValid()) ss += "\tuvsets;\n";
if (mesh->vb_atl.IsValid()) ss += "\tatlas;\n";
if (mesh->vb_col.IsValid()) ss += "\tcolor;\n";
if (mesh->vb_ao.IsValid()) ss += "\tao;\n";
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";
Expand Down
37 changes: 18 additions & 19 deletions Editor/ObjectWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,34 +678,34 @@ void ObjectWindow::Create(EditorComponent* _editor)
}
}
}
wi::backlog::post("Building BVHs for vertex AO took " + wi::helper::GetTimerDurationText(timer.elapsed_seconds()));
wi::backlog::post("Building BVHs for vertex AO took " + wi::helper::GetTimerDurationText((float)timer.elapsed_seconds()));
}

for (auto& x : this->editor->translator.selected)
{
ObjectComponent* objectcomponent = scene.objects.GetComponent(x.entity);
if (objectcomponent != nullptr)
{
const size_t objectcomponentIndex = scene.objects.GetIndex(x.entity);
MeshComponent* meshcomponent = scene.meshes.GetComponent(objectcomponent->meshID);
if (meshcomponent == nullptr)
continue;
if (deleteAOMode)
{
meshcomponent->vertex_ao.clear();
objectcomponent->vertex_ao.clear();
}
else
{
const MeshComponent* meshcomponent = scene.meshes.GetComponent(objectcomponent->meshID);
if (meshcomponent == nullptr)
continue;
if (meshcomponent->vertex_normals.size() != meshcomponent->vertex_positions.size())
continue;
wi::Timer timer;
using namespace wi::primitive;
meshcomponent->vertex_ao.resize(meshcomponent->vertex_positions.size());
objectcomponent->vertex_ao.resize(meshcomponent->vertex_positions.size());
const size_t objectcomponentIndex = scene.objects.GetIndex(x.entity);

uint32_t groupSizePerCore = wi::jobsystem::DispatchGroupCount((uint32_t)meshcomponent->vertex_ao.size(), wi::jobsystem::GetThreadCount());
uint32_t groupSizePerCore = wi::jobsystem::DispatchGroupCount((uint32_t)objectcomponent->vertex_ao.size(), wi::jobsystem::GetThreadCount());

wi::jobsystem::context ctx;
wi::jobsystem::Dispatch(ctx, (uint32_t)meshcomponent->vertex_ao.size(), groupSizePerCore, [&](wi::jobsystem::JobArgs args) {
wi::jobsystem::Dispatch(ctx, (uint32_t)objectcomponent->vertex_ao.size(), groupSizePerCore, [&](wi::jobsystem::JobArgs args) {
XMFLOAT3 position = meshcomponent->vertex_positions[args.jobIndex];
XMFLOAT3 normal = meshcomponent->vertex_normals[args.jobIndex];
const XMMATRIX W = XMLoadFloat4x4(&scene.matrix_objects[objectcomponentIndex]);
Expand All @@ -718,7 +718,8 @@ void ObjectWindow::Create(EditorComponent* _editor)
const XMVECTOR rayOrigin = XMLoadFloat3(&position);
for (uint32_t sam = 0; sam < samplecount; ++sam)
{
XMFLOAT3 hemi = wi::math::HemispherePoint_Cos(wi::random::GetRandom(1.0f), wi::random::GetRandom(1.0f));
XMFLOAT2 hamm = wi::math::Hammersley2D(sam, samplecount);
XMFLOAT3 hemi = wi::math::HemispherePoint_Cos(hamm.x, hamm.y);
XMVECTOR rayDirection = XMLoadFloat3(&hemi);
rayDirection = XMVector3TransformNormal(rayDirection, TBN);
rayDirection = XMVector3Normalize(rayDirection);
Expand All @@ -742,13 +743,11 @@ void ObjectWindow::Create(EditorComponent* _editor)
continue;

const Entity entity = scene.objects.GetEntity(objectIndex);
const SoftBodyPhysicsComponent* softbody = scene.softbodies.GetComponent(object.meshID);
const XMMATRIX objectMat = XMLoadFloat4x4(&scene.matrix_objects[objectIndex]);
const XMMATRIX objectMatPrev = XMLoadFloat4x4(&scene.matrix_objects_prev[objectIndex]);
const XMMATRIX objectMat_Inverse = XMMatrixInverse(nullptr, objectMat);
const XMVECTOR rayOrigin_local = XMVector3Transform(rayOrigin, objectMat_Inverse);
const XMVECTOR rayDirection_local = XMVector3Normalize(XMVector3TransformNormal(rayDirection, objectMat_Inverse));
const ArmatureComponent* armature = mesh->IsSkinned() ? scene.armatures.GetComponent(mesh->armatureID) : nullptr;

auto intersect_triangle = [&](uint32_t subsetIndex, uint32_t indexOffset, uint32_t triangleIndex)
{
Expand Down Expand Up @@ -785,7 +784,7 @@ void ObjectWindow::Create(EditorComponent* _editor)
if (intersect_triangle(subsetIndex, indexOffset, triangleIndex))
return true;
return false;
});
});
}
else
{
Expand Down Expand Up @@ -816,12 +815,12 @@ void ObjectWindow::Create(EditorComponent* _editor)
accum += 1.0f;
}
accum /= float(samplecount);
meshcomponent->vertex_ao[args.jobIndex] = uint8_t(accum * 255);
});
objectcomponent->vertex_ao[args.jobIndex] = uint8_t(accum * 255);
});
wi::jobsystem::Wait(ctx);
wi::backlog::post("Vertex AO baking took " + wi::helper::GetTimerDurationText(timer.elapsed_seconds()));
wi::backlog::post("Vertex AO baking took " + wi::helper::GetTimerDurationText((float)timer.elapsed_seconds()));
}
meshcomponent->CreateRenderData();
objectcomponent->CreateRenderData();
}
}

Expand All @@ -843,6 +842,7 @@ void ObjectWindow::Create(EditorComponent* _editor)
}
}

SetEntity(entity);
});
AddWidget(&vertexAOButton);

Expand Down Expand Up @@ -910,8 +910,7 @@ void ObjectWindow::SetEntity(Entity entity)

if (object != nullptr)
{
const MeshComponent* mesh = scene.meshes.GetComponent(object->meshID);
if (mesh != nullptr && mesh->vertex_ao.empty())
if (object->vertex_ao.empty())
{
vertexAOButton.SetText("Compute Vertex AO");
deleteAOMode = false;
Expand Down
13 changes: 9 additions & 4 deletions WickedEngine/shaders/ShaderInterop_Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,9 @@ struct ShaderGeometry
int vb_tan;
int vb_col;
int vb_atl;
int vb_ao;

int vb_pre;

int impostorSliceOffset;
uint materialIndex;
uint meshletOffset; // offset of this subset in meshlets (locally within the mesh)
uint meshletCount;
Expand All @@ -471,8 +471,8 @@ struct ShaderGeometry

uint indexOffset;
uint indexCount;
int impostorSliceOffset;
int padding0;
int padding1;

void init()
{
Expand All @@ -483,7 +483,6 @@ struct ShaderGeometry
vb_tan = -1;
vb_col = -1;
vb_atl = -1;
vb_ao = -1;
vb_pre = -1;
materialIndex = 0;
meshletOffset = 0;
Expand Down Expand Up @@ -569,6 +568,11 @@ struct ShaderMeshInstance
float3 center;
float radius;

int vb_ao;
int padding0;
int padding1;
int padding2;

ShaderTransform transform;
ShaderTransform transformInverseTranspose; // This correctly handles non uniform scaling for normals
ShaderTransform transformPrev;
Expand All @@ -589,6 +593,7 @@ struct ShaderMeshInstance
fadeDistance = 0;
center = float3(0, 0, 0);
radius = 0;
vb_ao = -1;
transform.init();
transformInverseTranspose.init();
transformPrev.init();
Expand Down
16 changes: 8 additions & 8 deletions WickedEngine/shaders/objectHF.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,6 @@ struct VertexInput
return 1;
return (min16float4)bindless_buffers_float4[GetMesh().vb_col][vertexID];
}

min16float GetVertexAO()
{
[branch]
if (GetMesh().vb_ao < 0)
return 1;
return (min16float)bindless_buffers_float[GetMesh().vb_ao][vertexID];
}

min16float3 GetNormal()
{
Expand All @@ -195,6 +187,14 @@ struct VertexInput
inst.init();
return inst;
}

min16float GetVertexAO()
{
[branch]
if (GetInstance().vb_ao < 0)
return 1;
return (min16float)bindless_buffers_float[GetInstance().vb_ao][vertexID];
}
};


Expand Down
4 changes: 2 additions & 2 deletions WickedEngine/shaders/surfaceHF.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,9 @@ struct Surface
}

[branch]
if (geometry.vb_ao >= 0 && material.IsUsingVertexAO())
if (inst.vb_ao >= 0 && material.IsUsingVertexAO())
{
Buffer<float> buf = bindless_buffers_float[NonUniformResourceIndex(geometry.vb_ao)];
Buffer<float> buf = bindless_buffers_float[NonUniformResourceIndex(inst.vb_ao)];
const float ao0 = buf[i0];
const float ao1 = buf[i1];
const float ao2 = buf[i2];
Expand Down
14 changes: 14 additions & 0 deletions WickedEngine/wiMath.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,20 @@ namespace wi::math
return ++x;
}

// A uniform 2D random generator for hemisphere sampling: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
// idx : iteration index
// num : number of iterations in total
constexpr XMFLOAT2 Hammersley2D(uint32_t idx, uint32_t num) {
uint32_t bits = idx;
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
const float radicalInverse_VdC = float(bits) * 2.3283064365386963e-10f; // / 0x100000000

return XMFLOAT2(float(idx) / float(num), radicalInverse_VdC);
}
inline XMMATRIX GetTangentSpace(const XMFLOAT3& N)
{
// Choose a helper vector for the cross product
Expand Down
2 changes: 1 addition & 1 deletion WickedEngine/wiScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3447,7 +3447,6 @@ namespace wi::scene
geometry.vb_tan = mesh.vb_tan.descriptor_srv;
}
geometry.vb_col = mesh.vb_col.descriptor_srv;
geometry.vb_ao = mesh.vb_ao.descriptor_srv;
geometry.vb_uvs = mesh.vb_uvs.descriptor_srv;
geometry.vb_atl = mesh.vb_atl.descriptor_srv;
geometry.vb_pre = mesh.so_pre.descriptor_srv;
Expand Down Expand Up @@ -3978,6 +3977,7 @@ namespace wi::scene
inst.fadeDistance = object.fadeDistance;
inst.center = object.center;
inst.radius = object.radius;
inst.vb_ao = object.vb_ao_srv;
inst.SetUserStencilRef(object.userStencilRef);

std::memcpy(instanceArrayMapped + args.jobIndex, &inst, sizeof(inst)); // memcpy whole structure into mapped pointer to avoid read from uncached memory
Expand Down
4 changes: 2 additions & 2 deletions WickedEngine/wiScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ namespace wi::scene
wi::ecs::ComponentManager<TransformComponent>& transforms = componentLibrary.Register<TransformComponent>("wi::scene::Scene::transforms");
wi::ecs::ComponentManager<HierarchyComponent>& hierarchy = componentLibrary.Register<HierarchyComponent>("wi::scene::Scene::hierarchy");
wi::ecs::ComponentManager<MaterialComponent>& materials = componentLibrary.Register<MaterialComponent>("wi::scene::Scene::materials", 2); // version = 2
wi::ecs::ComponentManager<MeshComponent>& meshes = componentLibrary.Register<MeshComponent>("wi::scene::Scene::meshes", 3); // version = 2
wi::ecs::ComponentManager<MeshComponent>& meshes = componentLibrary.Register<MeshComponent>("wi::scene::Scene::meshes", 2); // version = 2
wi::ecs::ComponentManager<ImpostorComponent>& impostors = componentLibrary.Register<ImpostorComponent>("wi::scene::Scene::impostors");
wi::ecs::ComponentManager<ObjectComponent>& objects = componentLibrary.Register<ObjectComponent>("wi::scene::Scene::objects", 2); // version = 2
wi::ecs::ComponentManager<ObjectComponent>& objects = componentLibrary.Register<ObjectComponent>("wi::scene::Scene::objects", 3); // version = 3
wi::ecs::ComponentManager<RigidBodyPhysicsComponent>& rigidbodies = componentLibrary.Register<RigidBodyPhysicsComponent>("wi::scene::Scene::rigidbodies", 1); // version = 1
wi::ecs::ComponentManager<SoftBodyPhysicsComponent>& softbodies = componentLibrary.Register<SoftBodyPhysicsComponent>("wi::scene::Scene::softbodies");
wi::ecs::ComponentManager<ArmatureComponent>& armatures = componentLibrary.Register<ArmatureComponent>("wi::scene::Scene::armatures");
Expand Down
53 changes: 29 additions & 24 deletions WickedEngine/wiScene_Components.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,6 @@ namespace wi::scene
vb_uvs = {};
vb_atl = {};
vb_col = {};
vb_ao = {};
vb_bon = {};
so_pos = {};
so_nor = {};
Expand Down Expand Up @@ -696,7 +695,6 @@ namespace wi::scene
AlignTo(uv_count * sizeof(Vertex_UVS), alignment) +
AlignTo(vertex_atlas.size() * sizeof(Vertex_TEX), alignment) +
AlignTo(vertex_colors.size() * sizeof(Vertex_COL), alignment) +
AlignTo(vertex_ao.size() * sizeof(Vertex_AO), alignment) +
AlignTo(vertex_boneindices.size() * sizeof(Vertex_BON), alignment)
;

Expand Down Expand Up @@ -892,21 +890,6 @@ namespace wi::scene
}
}

// vertexBuffer - AO (ambient occlusion)
if (!vertex_ao.empty())
{
vb_ao.offset = buffer_offset;
vb_ao.size = vertex_ao.size() * sizeof(Vertex_AO);
Vertex_AO* vertices = (Vertex_AO*)(buffer_data + buffer_offset);
buffer_offset += AlignTo(vb_ao.size, alignment);
for (size_t i = 0; i < vertex_ao.size(); ++i)
{
Vertex_AO vert;
vert.value = vertex_ao[i];
std::memcpy(vertices + i, &vert, sizeof(vert));
}
}

// skinning buffers:
if (!vertex_boneindices.empty())
{
Expand Down Expand Up @@ -1030,11 +1013,6 @@ namespace wi::scene
vb_col.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_col.offset, vb_col.size, &Vertex_COL::FORMAT);
vb_col.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_col.subresource_srv);
}
if (vb_ao.IsValid())
{
vb_ao.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_ao.offset, vb_ao.size, &Vertex_AO::FORMAT);
vb_ao.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_ao.subresource_srv);
}
if (vb_bon.IsValid())
{
vb_bon.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_bon.offset, vb_bon.size);
Expand Down Expand Up @@ -1589,7 +1567,6 @@ namespace wi::scene
vertex_boneweights.size() * sizeof(XMFLOAT4) +
vertex_atlas.size() * sizeof(XMFLOAT2) +
vertex_colors.size() * sizeof(uint32_t) +
vertex_ao.size() * sizeof(uint8_t) +
vertex_windweights.size() * sizeof(uint8_t) +
indices.size() * sizeof(uint32_t);

Expand Down Expand Up @@ -1626,7 +1603,6 @@ namespace wi::scene
lightmapTextureData.clear();
SetLightmapRenderRequest(false);
}

void ObjectComponent::SaveLightmap()
{
if (lightmap.IsValid() && has_flag(lightmap.desc.bind_flags, BindFlag::RENDER_TARGET))
Expand Down Expand Up @@ -1729,6 +1705,35 @@ namespace wi::scene
lightmap.desc = desc;
}
}
void ObjectComponent::DeleteRenderData()
{
vb_ao = {};
vb_ao_srv = -1;
}
void ObjectComponent::CreateRenderData()
{
DeleteRenderData();

GraphicsDevice* device = wi::graphics::GetDevice();

if (!vertex_ao.empty())
{
GPUBufferDesc desc;
desc.bind_flags = BindFlag::SHADER_RESOURCE;
desc.size = sizeof(Vertex_AO) * vertex_ao.size();
desc.format = Vertex_AO::FORMAT;

auto fill_ao = [&](void* data) {
std::memcpy(data, vertex_ao.data(), vertex_ao.size());
};

bool success = device->CreateBuffer2(&desc, fill_ao, &vb_ao);
assert(success);
device->SetName(&vb_ao, "ObjectComponent::vb_ao");

vb_ao_srv = device->GetDescriptorIndex(&vb_ao, SubresourceType::SRV);
}
}

void EnvironmentProbeComponent::CreateRenderData()
{
Expand Down
Loading

0 comments on commit c316cea

Please sign in to comment.