fixed decal atlas leaking
This commit is contained in:
@@ -18,51 +18,69 @@ void main(int3 DTid : SV_DispatchThreadID)
|
||||
|
||||
output[writecoord] = input.Load(int3(readcoord, xCopySrcMIP));
|
||||
|
||||
// wrapped borders:
|
||||
// border expansion:
|
||||
const bool wrap = xCopyBorderExpandStyle == 1;
|
||||
int2 readoffset;
|
||||
|
||||
// left
|
||||
if (readcoord.x == 0)
|
||||
{
|
||||
output[writecoord + int2(-1, 0)] = input.Load(int3(readcoord + int2(xCopySrcSize.x - 1, 0), xCopySrcMIP));
|
||||
readoffset = wrap ? int2(xCopySrcSize.x - 1, 0) : 0;
|
||||
|
||||
output[writecoord + int2(-1, 0)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP));
|
||||
|
||||
// top left
|
||||
if (readcoord.y == 0)
|
||||
{
|
||||
output[writecoord + int2(-1, -1)] = input.Load(int3(readcoord + int2(xCopySrcSize.x - 1, xCopySrcSize.x - 1), xCopySrcMIP));
|
||||
readoffset = wrap ? int2(xCopySrcSize.x - 1, xCopySrcSize.x - 1) : 0;
|
||||
|
||||
output[writecoord + int2(-1, -1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP));
|
||||
}
|
||||
}
|
||||
// right
|
||||
if (readcoord.x == xCopySrcSize.x - 1)
|
||||
{
|
||||
output[writecoord + int2(1, 0)] = input.Load(int3(readcoord + int2(-xCopySrcSize.x + 1, 0), xCopySrcMIP));
|
||||
readoffset = wrap ? int2(-xCopySrcSize.x + 1, 0) : 0;
|
||||
|
||||
output[writecoord + int2(1, 0)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP));
|
||||
|
||||
// bottom right
|
||||
if (readcoord.y == xCopySrcSize.y - 1)
|
||||
{
|
||||
output[writecoord + int2(1, 1)] = input.Load(int3(readcoord + int2(-xCopySrcSize.x + 1, -xCopySrcSize.x + 1), xCopySrcMIP));
|
||||
readoffset = wrap ? int2(-xCopySrcSize.x + 1, -xCopySrcSize.x + 1) : 0;
|
||||
|
||||
output[writecoord + int2(1, 1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP));
|
||||
}
|
||||
}
|
||||
|
||||
// top
|
||||
if (readcoord.y == 0)
|
||||
{
|
||||
output[writecoord + int2(0, -1)] = input.Load(int3(readcoord + int2(0, xCopySrcSize.x - 1), xCopySrcMIP));
|
||||
readoffset = wrap ? int2(0, xCopySrcSize.x - 1) : 0;
|
||||
|
||||
output[writecoord + int2(0, -1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP));
|
||||
|
||||
// top right
|
||||
if (readcoord.x == xCopySrcSize.x - 1)
|
||||
{
|
||||
output[writecoord + int2(1, -1)] = input.Load(int3(readcoord + int2(-xCopySrcSize.x + 1, xCopySrcSize.x - 1), xCopySrcMIP));
|
||||
readoffset = wrap ? int2(-xCopySrcSize.x + 1, xCopySrcSize.x - 1) : 0;
|
||||
|
||||
output[writecoord + int2(1, -1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP));
|
||||
}
|
||||
}
|
||||
// bottom
|
||||
if (readcoord.y == xCopySrcSize.y - 1)
|
||||
{
|
||||
output[writecoord + int2(0, 1)] = input.Load(int3(readcoord + int2(0, -xCopySrcSize.x + 1), xCopySrcMIP));
|
||||
readoffset = wrap ? int2(0, -xCopySrcSize.x + 1) : 0;
|
||||
|
||||
output[writecoord + int2(0, 1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP));
|
||||
|
||||
// bottom left
|
||||
if (readcoord.x == 0)
|
||||
{
|
||||
output[writecoord + int2(-1, 1)] = input.Load(int3(readcoord + int2(xCopySrcSize.x - 1, -xCopySrcSize.x + 1), xCopySrcMIP));
|
||||
readoffset = wrap ? int2(xCopySrcSize.x - 1, -xCopySrcSize.x + 1) : 0;
|
||||
|
||||
output[writecoord + int2(-1, 1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ inline void TiledLighting(in float2 pixel, inout Surface surface, inout float3 d
|
||||
// mipmapping needs to be performed by hand:
|
||||
float2 decalDX = mul(P_dx, (float3x3)decalProjection).xy * decal.texMulAdd.xy;
|
||||
float2 decalDY = mul(P_dy, (float3x3)decalProjection).xy * decal.texMulAdd.xy;
|
||||
float4 decalColor = texture_decalatlas.SampleGrad(sampler_objectshader, uvw.xy*decal.texMulAdd.xy + decal.texMulAdd.zw, decalDX, decalDY);
|
||||
float4 decalColor = texture_decalatlas.SampleGrad(sampler_linear_clamp, uvw.xy*decal.texMulAdd.xy + decal.texMulAdd.zw, decalDX, decalDY);
|
||||
// blend out if close to cube Z:
|
||||
float edgeBlend = 1 - pow(saturate(abs(clipSpacePos.z)), 8);
|
||||
decalColor.a *= edgeBlend;
|
||||
|
||||
+74
-58
@@ -6907,7 +6907,7 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res
|
||||
std::vector<bin> bins;
|
||||
if (pack(out_rects, (int)storedTextures.size(), 16384, bins))
|
||||
{
|
||||
assert(bins.size() == 1 && "Tracing atlas packing into single texture failed!");
|
||||
assert(bins.size() == 1 && "The regions won't fit into the texture!");
|
||||
|
||||
SAFE_DELETE(atlasTexture);
|
||||
|
||||
@@ -7306,6 +7306,8 @@ void wiRenderer::ManageDecalAtlas(GRAPHICSTHREAD threadID)
|
||||
}
|
||||
|
||||
static Texture2D* atlasTexture = nullptr;
|
||||
bool repackAtlas = false;
|
||||
const int atlasClampBorder = 1;
|
||||
|
||||
using namespace wiRectPacker;
|
||||
static std::map<Texture2D*, rect_xywhf> storedTextures;
|
||||
@@ -7321,67 +7323,73 @@ void wiRenderer::ManageDecalAtlas(GRAPHICSTHREAD threadID)
|
||||
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);
|
||||
rect_xywhf newRect = rect_xywhf(0, 0, tex->GetDesc().Width + atlasClampBorder * 2, tex->GetDesc().Height + atlasClampBorder * 2);
|
||||
storedTextures[tex] = newRect;
|
||||
|
||||
rect_xywhf** out_rects = new rect_xywhf*[storedTextures.size()];
|
||||
int i = 0;
|
||||
for (auto& it : storedTextures)
|
||||
{
|
||||
out_rects[i] = &it.second;
|
||||
i++;
|
||||
}
|
||||
|
||||
std::vector<bin> bins;
|
||||
if (pack(out_rects, (int)storedTextures.size(), 16384, bins))
|
||||
{
|
||||
assert(bins.size() == 1 && "Decal 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 = 6;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = USAGE_DEFAULT;
|
||||
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
atlasTexture = new Texture2D;
|
||||
atlasTexture->RequestIndependentUnorderedAccessResourcesForMIPs(true);
|
||||
|
||||
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);
|
||||
|
||||
// This is better because it implements format conversion so we can use multiple decal source texture formats in the atlas:
|
||||
CopyTexture2D(atlasTexture, mip, it.second.x >> mip, it.second.y >> mip, it.first, mip, threadID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wiBackLog::post("Decal atlas packing failed!");
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(out_rects);
|
||||
repackAtlas = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3.) Assign atlas buckets to decals:
|
||||
// 3.) Update atlas texture if it is invalidated:
|
||||
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<bin> bins;
|
||||
if (pack(out_rects, (int)storedTextures.size(), 16384, bins))
|
||||
{
|
||||
assert(bins.size() == 1 && "The regions won't fit into the texture!");
|
||||
|
||||
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 = 0;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = USAGE_DEFAULT;
|
||||
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
atlasTexture = new Texture2D;
|
||||
atlasTexture->RequestIndependentUnorderedAccessResourcesForMIPs(true);
|
||||
|
||||
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);
|
||||
|
||||
// This is better because it implements format conversion so we can use multiple decal source texture formats in the atlas:
|
||||
CopyTexture2D(atlasTexture, mip, (it.second.x >> mip) + atlasClampBorder, (it.second.y >> mip) + atlasClampBorder, it.first, mip, threadID, BORDEREXPAND_CLAMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wiBackLog::post("Decal atlas packing failed!");
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(out_rects);
|
||||
}
|
||||
|
||||
// 4.) Assign atlas buckets to decals:
|
||||
for (Model* model : GetScene().models)
|
||||
{
|
||||
if (model->decals.empty())
|
||||
@@ -7391,8 +7399,16 @@ void wiRenderer::ManageDecalAtlas(GRAPHICSTHREAD threadID)
|
||||
{
|
||||
if (decal->texture != nullptr)
|
||||
{
|
||||
const TextureDesc& desc = atlasTexture->GetDesc();
|
||||
|
||||
rect_xywhf rect = storedTextures[decal->texture];
|
||||
TextureDesc desc = atlasTexture->GetDesc();
|
||||
|
||||
// eliminate border expansion:
|
||||
rect.x += atlasClampBorder;
|
||||
rect.y += atlasClampBorder;
|
||||
rect.w -= atlasClampBorder * 2;
|
||||
rect.h -= atlasClampBorder * 2;
|
||||
|
||||
decal->atlasMulAdd = XMFLOAT4((float)rect.w / (float)desc.Width, (float)rect.h / (float)desc.Height, (float)rect.x / (float)desc.Width, (float)rect.y / (float)desc.Height);
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user