From 71d03f917f360d6ad0678a5ca66c4c7a409ab362 Mon Sep 17 00:00:00 2001 From: turanszkij Date: Wed, 20 Jun 2018 17:17:20 +0100 Subject: [PATCH] traced scene texture atlas --- WickedEngine/ShaderInterop_TracedRendering.h | 18 +++ WickedEngine/bvh_classificationCS.hlsl | 2 +- WickedEngine/raytrace_lightsamplingCS.hlsl | 21 ++- WickedEngine/raytrace_primaryCS.hlsl | 27 ++-- WickedEngine/tracedRenderingHF.hlsli | 14 -- WickedEngine/wiRenderer.cpp | 147 ++++++++++++++++++- WickedEngine/wiTextureHelper.cpp | 6 +- 7 files changed, 192 insertions(+), 43 deletions(-) diff --git a/WickedEngine/ShaderInterop_TracedRendering.h b/WickedEngine/ShaderInterop_TracedRendering.h index a05a7243e..8af325266 100644 --- a/WickedEngine/ShaderInterop_TracedRendering.h +++ b/WickedEngine/ShaderInterop_TracedRendering.h @@ -24,5 +24,23 @@ struct TracedRenderingStoredRay float2 bary; }; +struct TracedRenderingMaterial +{ + float4 baseColor; + float4 texMulAdd; + float roughness; + float reflectance; + float metalness; + float emissive; + float refractionIndex; + float subsurfaceScattering; + float normalMapStrength; + float parallaxOcclusionMapping; + + float4 baseColorAtlasMulAdd; + float4 surfaceMapAtlasMulAdd; + float4 normalMapAtlasMulAdd; +}; + #endif // _SHADERINTEROP_TRACEDRENDERING_H_ diff --git a/WickedEngine/bvh_classificationCS.hlsl b/WickedEngine/bvh_classificationCS.hlsl index ad33cf247..9fe65db1c 100644 --- a/WickedEngine/bvh_classificationCS.hlsl +++ b/WickedEngine/bvh_classificationCS.hlsl @@ -21,7 +21,7 @@ RWSTRUCTUREDBUFFER(clusterOffsetBuffer, uint2, 4); // offset, count RWSTRUCTUREDBUFFER(clusterAABBBuffer, BVHAABB, 5); // if defined, triangles will be grouped into clusters, else every triangle will be its own cluster: -//#define CLUSTER_GROUP +#define CLUSTER_GROUP #ifdef CLUSTER_GROUP static const uint clusterTriangleCapacity = 4; diff --git a/WickedEngine/raytrace_lightsamplingCS.hlsl b/WickedEngine/raytrace_lightsamplingCS.hlsl index 25f449c8a..fe356a761 100644 --- a/WickedEngine/raytrace_lightsamplingCS.hlsl +++ b/WickedEngine/raytrace_lightsamplingCS.hlsl @@ -5,7 +5,7 @@ RWTEXTURE2D(resultTexture, float4, 0); -STRUCTUREDBUFFER(materialBuffer, Material, TEXSLOT_ONDEMAND0); +STRUCTUREDBUFFER(materialBuffer, TracedRenderingMaterial, TEXSLOT_ONDEMAND0); STRUCTUREDBUFFER(triangleBuffer, BVHMeshTriangle, TEXSLOT_ONDEMAND1); RAWBUFFER(clusterCounterBuffer, TEXSLOT_ONDEMAND2); STRUCTUREDBUFFER(clusterIndexBuffer, uint, TEXSLOT_ONDEMAND3); @@ -14,6 +14,8 @@ STRUCTUREDBUFFER(clusterConeBuffer, ClusterCone, TEXSLOT_ONDEMAND5); STRUCTUREDBUFFER(bvhNodeBuffer, BVHNode, TEXSLOT_ONDEMAND6); STRUCTUREDBUFFER(bvhAABBBuffer, BVHAABB, TEXSLOT_ONDEMAND7); +TEXTURE2D(materialTextureAtlas, float4, TEXSLOT_ONDEMAND8); + RAWBUFFER(counterBuffer_READ, TEXSLOT_UNIQUE0); STRUCTUREDBUFFER(rayBuffer_READ, TracedRenderingStoredRay, TEXSLOT_UNIQUE1); @@ -138,18 +140,23 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) float3 P = ray.origin; float3 N = normalize(tri.n0 * w + tri.n1 * u + tri.n2 * v); + float2 UV = tri.t0 * w + tri.t1 * u + tri.t2 * v; float3 V = normalize(g_xFrame_MainCamera_CamPos - P); uint materialIndex = tri.materialIndex; - Material mat = materialBuffer[materialIndex]; + TracedRenderingMaterial mat = materialBuffer[materialIndex]; - float4 baseColor = DEGAMMA(mat.baseColor /** baseColorMap*/); - float reflectance = mat.reflectance/* * surfaceMap.r*/; - float metalness = mat.metalness/* * surfaceMap.g*/; - float emissive = mat.emissive /** surfaceMap.b*/; - float roughness = mat.roughness/* * normalMap.a*/; + float4 baseColorMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.baseColorAtlasMulAdd.xy + mat.baseColorAtlasMulAdd.zw, 0); + float4 surfaceMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.surfaceMapAtlasMulAdd.xy + mat.surfaceMapAtlasMulAdd.zw, 0); + float4 normalMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.normalMapAtlasMulAdd.xy + mat.normalMapAtlasMulAdd.zw, 0); + + float4 baseColor = DEGAMMA(mat.baseColor * baseColorMap); + float reflectance = mat.reflectance * surfaceMap.r; + float metalness = mat.metalness * surfaceMap.g; + float emissive = mat.emissive * surfaceMap.b; + float roughness = mat.roughness /** normalMap.a*/; float sss = mat.subsurfaceScattering; Surface surface = CreateSurface(P, N, V, baseColor, roughness, reflectance, metalness, emissive, sss); diff --git a/WickedEngine/raytrace_primaryCS.hlsl b/WickedEngine/raytrace_primaryCS.hlsl index e005d25ea..193c93bfb 100644 --- a/WickedEngine/raytrace_primaryCS.hlsl +++ b/WickedEngine/raytrace_primaryCS.hlsl @@ -18,7 +18,7 @@ groupshared uint GroupRayCount; groupshared uint GroupRayWriteOffset; #endif // ADVANCED_ALLOCATION -STRUCTUREDBUFFER(materialBuffer, Material, TEXSLOT_ONDEMAND0); +STRUCTUREDBUFFER(materialBuffer, TracedRenderingMaterial, TEXSLOT_ONDEMAND0); STRUCTUREDBUFFER(triangleBuffer, BVHMeshTriangle, TEXSLOT_ONDEMAND1); RAWBUFFER(clusterCounterBuffer, TEXSLOT_ONDEMAND2); STRUCTUREDBUFFER(clusterIndexBuffer, uint, TEXSLOT_ONDEMAND3); @@ -27,9 +27,7 @@ STRUCTUREDBUFFER(clusterConeBuffer, ClusterCone, TEXSLOT_ONDEMAND5); STRUCTUREDBUFFER(bvhNodeBuffer, BVHNode, TEXSLOT_ONDEMAND6); STRUCTUREDBUFFER(bvhAABBBuffer, BVHAABB, TEXSLOT_ONDEMAND7); -//TEXTURE2D(texture_baseColor, float4, TEXSLOT_ONDEMAND4); -//TEXTURE2D(texture_normalMap, float4, TEXSLOT_ONDEMAND5); -//TEXTURE2D(texture_surfaceMap, float4, TEXSLOT_ONDEMAND6); +TEXTURE2D(materialTextureAtlas, float4, TEXSLOT_ONDEMAND8); RAWBUFFER(counterBuffer_READ, TEXSLOT_UNIQUE0); STRUCTUREDBUFFER(rayBuffer_READ, TracedRenderingStoredRay, TEXSLOT_UNIQUE1); @@ -133,19 +131,20 @@ inline float3 Shade(inout Ray ray, RayHit hit, inout float seed, in float2 pixel float3 N = normalize(tri.n0 * w + tri.n1 * u + tri.n2 * v); float2 UV = tri.t0 * w + tri.t1 * u + tri.t2 * v; - //float4 baseColorMap = texture_baseColor.SampleLevel(sampler_linear_wrap, UV, 0); - //float4 normalMap = texture_normalMap.SampleLevel(sampler_linear_wrap, UV, 0); - //float4 surfaceMap = texture_surfaceMap.SampleLevel(sampler_linear_wrap, UV, 0); - uint materialIndex = tri.materialIndex; - Material mat = materialBuffer[materialIndex]; + TracedRenderingMaterial mat = materialBuffer[materialIndex]; + + float4 baseColorMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.baseColorAtlasMulAdd.xy + mat.baseColorAtlasMulAdd.zw, 0); + float4 surfaceMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.surfaceMapAtlasMulAdd.xy + mat.surfaceMapAtlasMulAdd.zw, 0); + float4 normalMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.normalMapAtlasMulAdd.xy + mat.normalMapAtlasMulAdd.zw, 0); - float4 baseColor = DEGAMMA(mat.baseColor /** baseColorMap*/); - float reflectance = mat.reflectance/* * surfaceMap.r*/; - float metalness = mat.metalness/* * surfaceMap.g*/; - float3 emissive = baseColor.rgb * mat.emissive /** surfaceMap.b*/; - float roughness = mat.roughness/* * normalMap.a*/; + float4 baseColor = DEGAMMA(mat.baseColor * baseColorMap); + float reflectance = mat.reflectance * surfaceMap.r; + float metalness = mat.metalness * surfaceMap.g; + float3 emissive = baseColor.rgb * mat.emissive * surfaceMap.b; + float roughness = mat.roughness /** normalMap.a*/; + float sss = mat.subsurfaceScattering; float3 albedo = ComputeAlbedo(baseColor, reflectance, metalness); float3 specular = ComputeF0(baseColor, reflectance, metalness); diff --git a/WickedEngine/tracedRenderingHF.hlsli b/WickedEngine/tracedRenderingHF.hlsli index 40dcddd2b..3f3613582 100644 --- a/WickedEngine/tracedRenderingHF.hlsli +++ b/WickedEngine/tracedRenderingHF.hlsli @@ -11,20 +11,6 @@ static const float INFINITE_RAYHIT = 1000000; static const float EPSILON = 0.0001f; -struct Material -{ - float4 baseColor; - float4 texMulAdd; - float roughness; - float reflectance; - float metalness; - float emissive; - float refractionIndex; - float subsurfaceScattering; - float normalMapStrength; - float parallaxOcclusionMapping; -}; - //struct Sphere //{ // float3 position; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index cfab28c3d..fc6ec1115 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -6780,7 +6780,107 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res assert(SUCCEEDED(hr)); } - static MaterialCB materialArray[1000] = {}; // todo realloc! + // Traced Scene Texture Atlas: + static Texture2D* atlasTexture = nullptr; + using namespace wiRectPacker; + static std::set sceneTextures; + static std::map storedTextures; + + for (Model* model : GetScene().models) + { + for (auto& iter : model->objects) + { + Object* object = iter; + Mesh* mesh = object->mesh; + + for (auto& subset : mesh->subsets) + { + Material* mat = subset.material; + + if (mat != nullptr) + { + sceneTextures.insert(mat->GetBaseColorMap()); + sceneTextures.insert(mat->GetSurfaceMap()); + sceneTextures.insert(mat->GetNormalMap()); + } + } + + } + + } + + bool repackAtlas = false; + for (Texture2D* tex : sceneTextures) + { + if (tex == nullptr) + { + continue; + } + + if (storedTextures.find(tex) == storedTextures.end()) + { + // we need to pack this decal texture into the atlas + rect_xywhf newRect = rect_xywhf(0, 0, tex->GetDesc().Width, tex->GetDesc().Height); + storedTextures[tex] = newRect; + + repackAtlas = true; + } + + } + + if (repackAtlas) + { + rect_xywhf** out_rects = new rect_xywhf*[storedTextures.size()]; + int i = 0; + for (auto& it : storedTextures) + { + out_rects[i] = &it.second; + i++; + } + + std::vector bins; + if (pack(out_rects, (int)storedTextures.size(), 16384, bins)) + { + assert(bins.size() == 1 && "Tracing atlas packing into single texture failed!"); + + SAFE_DELETE(atlasTexture); + + TextureDesc desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = (UINT)bins[0].size.w; + desc.Height = (UINT)bins[0].size.h; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = FORMAT_B8G8R8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = USAGE_DEFAULT; + desc.BindFlags = BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + device->CreateTexture2D(&desc, nullptr, &atlasTexture); + + for (UINT mip = 0; mip < atlasTexture->GetDesc().MipLevels; ++mip) + { + for (auto& it : storedTextures) + { + if (mip < it.first->GetDesc().MipLevels) + { + device->CopyTexture2D_Region(atlasTexture, mip, it.second.x >> mip, it.second.y >> mip, it.first, mip, threadID); + } + } + } + } + else + { + wiBackLog::post("Tracing atlas packing failed!"); + } + + SAFE_DELETE_ARRAY(out_rects); + } + + static TracedRenderingMaterial materialArray[1000] = {}; // todo realloc! static GPUBuffer* materialBuffer = nullptr; if (materialBuffer == nullptr) @@ -6792,7 +6892,7 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res materialBuffer = new GPUBuffer; desc.BindFlags = BIND_SHADER_RESOURCE; - desc.StructureByteStride = sizeof(MaterialCB); + desc.StructureByteStride = sizeof(TracedRenderingMaterial); desc.ByteWidth = desc.StructureByteStride * ARRAYSIZE(materialArray); desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; @@ -6816,12 +6916,40 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res for (auto& subset : mesh->subsets) { - materialArray[totalMaterials].Create(*subset.material); + MaterialCB mat; + mat.Create(*subset.material); + + // Copy base params: + materialArray[totalMaterials].baseColor = mat.baseColor; + materialArray[totalMaterials].texMulAdd = mat.texMulAdd; + materialArray[totalMaterials].roughness = mat.roughness; + materialArray[totalMaterials].reflectance = mat.reflectance; + materialArray[totalMaterials].metalness = mat.metalness; + materialArray[totalMaterials].emissive = mat.emissive; + materialArray[totalMaterials].refractionIndex = mat.refractionIndex; + materialArray[totalMaterials].subsurfaceScattering = mat.subsurfaceScattering; + materialArray[totalMaterials].normalMapStrength = mat.normalMapStrength; + materialArray[totalMaterials].parallaxOcclusionMapping = mat.normalMapStrength; + + // Add extended properties: + TextureDesc desc = atlasTexture->GetDesc(); + rect_xywhf rect; + + rect = storedTextures[subset.material->GetBaseColorMap()]; + materialArray[totalMaterials].baseColorAtlasMulAdd = XMFLOAT4((float)rect.w / (float)desc.Width, (float)rect.h / (float)desc.Height, (rect.x + 0.5f) / (float)desc.Width, (rect.y + 0.5f) / (float)desc.Height); + + rect = storedTextures[subset.material->GetSurfaceMap()]; + materialArray[totalMaterials].surfaceMapAtlasMulAdd = XMFLOAT4((float)rect.w / (float)desc.Width, (float)rect.h / (float)desc.Height, (rect.x + 0.5f) / (float)desc.Width, (rect.y + 0.5f) / (float)desc.Height); + + rect = storedTextures[subset.material->GetNormalMap()]; + materialArray[totalMaterials].normalMapAtlasMulAdd = XMFLOAT4((float)rect.w / (float)desc.Width, (float)rect.h / (float)desc.Height, (rect.x + 0.5f) / (float)desc.Width, (rect.y + 0.5f) / (float)desc.Height); + + totalMaterials++; } } } - device->UpdateBuffer(materialBuffer, materialArray, threadID, sizeof(MaterialCB) * totalMaterials); + device->UpdateBuffer(materialBuffer, materialArray, threadID, sizeof(TracedRenderingMaterial) * totalMaterials); // Begin raytrace @@ -6890,6 +7018,15 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res }; device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID); + if (atlasTexture != nullptr) + { + device->BindResource(CS, atlasTexture, TEXSLOT_ONDEMAND8, threadID); + } + else + { + device->BindResource(CS, wiTextureHelper::getInstance()->getWhite(), TEXSLOT_ONDEMAND8, threadID); + } + for (int bounce = 0; bounce < 8; ++bounce) { const int __readBufferID = bounce % 2; @@ -7113,6 +7250,8 @@ void wiRenderer::ManageDecalAtlas(GRAPHICSTHREAD threadID) { wiBackLog::post("Decal atlas packing failed!"); } + + SAFE_DELETE_ARRAY(out_rects); } rect_xywhf rect = storedTextures[decal->texture]; diff --git a/WickedEngine/wiTextureHelper.cpp b/WickedEngine/wiTextureHelper.cpp index c7cf225e4..a2c5933aa 100644 --- a/WickedEngine/wiTextureHelper.cpp +++ b/WickedEngine/wiTextureHelper.cpp @@ -186,14 +186,14 @@ Texture2D* wiTextureHelper::wiTextureHelperInstance::getColor(const wiColor& col unsigned char* data = new unsigned char[dataLength]; for (int i = 0; i < dataLength; i += 4) { - data[i] = color.r; + data[i] = color.b; data[i + 1] = color.g; - data[i + 2] = color.b; + data[i + 2] = color.r; data[i + 3] = color.a; } Texture2D* texture = nullptr; - if (FAILED(CreateTexture(texture, data, 1, 1, 4))) + if (FAILED(CreateTexture(texture, data, 1, 1, 4, FORMAT_B8G8R8A8_UNORM))) { delete[] data; return nullptr;