diff --git a/WickedEngine/ShaderInterop_Utility.h b/WickedEngine/ShaderInterop_Utility.h index 162697070..b9a1bf267 100644 --- a/WickedEngine/ShaderInterop_Utility.h +++ b/WickedEngine/ShaderInterop_Utility.h @@ -4,9 +4,11 @@ CBUFFER(CopyTextureCB, CBSLOT_RENDERER_UTILITY) { - uint2 xCopyDest; - uint xCopySrcMIP; - uint padding0; + int2 xCopyDest; + int2 xCopySrcSize; + int xCopySrcMIP; + int xCopyBorderExpandStyle; + int2 padding0; }; #endif //_SHADERINTEROP_UTILITY_H_ diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj b/WickedEngine/WickedEngine_SHADERS.vcxproj index 71aee08bb..935f57378 100644 --- a/WickedEngine/WickedEngine_SHADERS.vcxproj +++ b/WickedEngine/WickedEngine_SHADERS.vcxproj @@ -70,7 +70,11 @@ Pixel - + + Compute + 5.0 + + Compute 5.0 diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters index 9bfebabe4..0a16c93e4 100644 --- a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters +++ b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters @@ -756,7 +756,10 @@ CS - + + CS + + CS diff --git a/WickedEngine/copytexture2D_unorm4CS.hlsl b/WickedEngine/copytexture2D_unorm4CS.hlsl new file mode 100644 index 000000000..bbfa3ec01 --- /dev/null +++ b/WickedEngine/copytexture2D_unorm4CS.hlsl @@ -0,0 +1,20 @@ +#include "globals.hlsli" +#include "ShaderInterop_Utility.h" + +TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); + +RWTEXTURE2D(output, unorm float4, 0); + +[numthreads(8, 8, 1)] +void main( int3 DTid : SV_DispatchThreadID ) +{ + if (DTid.x >= xCopySrcSize.x || DTid.y >= xCopySrcSize.y) + { + return; + } + + const int2 readcoord = DTid.xy; + const int2 writecoord = DTid.xy + xCopyDest; + + output[writecoord] = input.Load(int3(readcoord, xCopySrcMIP)); +} diff --git a/WickedEngine/copytexture2D_unorm4_borderexpandCS.hlsl b/WickedEngine/copytexture2D_unorm4_borderexpandCS.hlsl new file mode 100644 index 000000000..3e14211b2 --- /dev/null +++ b/WickedEngine/copytexture2D_unorm4_borderexpandCS.hlsl @@ -0,0 +1,68 @@ +#include "globals.hlsli" +#include "ShaderInterop_Utility.h" + +TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); + +RWTEXTURE2D(output, unorm float4, 0); + +[numthreads(8, 8, 1)] +void main(int3 DTid : SV_DispatchThreadID) +{ + if (DTid.x >= xCopySrcSize.x || DTid.y >= xCopySrcSize.y) + { + return; + } + + const int2 readcoord = DTid.xy; + const int2 writecoord = DTid.xy + xCopyDest; + + output[writecoord] = input.Load(int3(readcoord, xCopySrcMIP)); + + // wrapped borders: + + // left + if (readcoord.x == 0) + { + output[writecoord + int2(-1, 0)] = input.Load(int3(readcoord + int2(xCopySrcSize.x - 1, 0), xCopySrcMIP)); + + // top left + if (readcoord.y == 0) + { + output[writecoord + int2(-1, -1)] = input.Load(int3(readcoord + int2(xCopySrcSize.x - 1, xCopySrcSize.x - 1), xCopySrcMIP)); + } + } + // right + if (readcoord.x == xCopySrcSize.x - 1) + { + output[writecoord + int2(1, 0)] = input.Load(int3(readcoord + int2(-xCopySrcSize.x + 1, 0), 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)); + } + } + + // top + if (readcoord.y == 0) + { + output[writecoord + int2(0, -1)] = input.Load(int3(readcoord + int2(0, xCopySrcSize.x - 1), 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)); + } + } + // bottom + if (readcoord.y == xCopySrcSize.y - 1) + { + output[writecoord + int2(0, 1)] = input.Load(int3(readcoord + int2(0, -xCopySrcSize.x + 1), xCopySrcMIP)); + + // bottom left + if (readcoord.x == 0) + { + output[writecoord + int2(-1, 1)] = input.Load(int3(readcoord + int2(xCopySrcSize.x - 1, -xCopySrcSize.x + 1), xCopySrcMIP)); + } + } +} diff --git a/WickedEngine/copytexture2Dregion_unorm4CS.hlsl b/WickedEngine/copytexture2Dregion_unorm4CS.hlsl deleted file mode 100644 index 639030d96..000000000 --- a/WickedEngine/copytexture2Dregion_unorm4CS.hlsl +++ /dev/null @@ -1,12 +0,0 @@ -#include "globals.hlsli" -#include "ShaderInterop_Utility.h" - -TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); - -RWTEXTURE2D(output, unorm float4, 0); - -[numthreads(8, 8, 1)] -void main( uint3 DTid : SV_DispatchThreadID ) -{ - output[DTid.xy + xCopyDest] = input.Load(uint3(DTid.xy, xCopySrcMIP)); -} diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h index 0672c0017..b86ca611f 100644 --- a/WickedEngine/wiEnums.h +++ b/WickedEngine/wiEnums.h @@ -270,7 +270,8 @@ enum CSTYPES CSTYPE_GENERATEMIPCHAIN2D_GAUSSIAN, CSTYPE_GENERATEMIPCHAIN3D_SIMPLEFILTER, CSTYPE_GENERATEMIPCHAIN3D_GAUSSIAN, - CSTYPE_COPYTEXTURE2DREGION_UNORM4, + CSTYPE_COPYTEXTURE2D_UNORM4, + CSTYPE_COPYTEXTURE2D_UNORM4_BORDEREXPAND, CSTYPE_SKINNING, CSTYPE_SKINNING_LDS, CSTYPE_CLOUDGENERATOR, diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 0a02a5a22..a475874dc 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1476,7 +1476,8 @@ void wiRenderer::LoadShaders() computeShaders[CSTYPE_GENERATEMIPCHAIN2D_GAUSSIAN] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "generateMIPChain2D_GaussianCS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_GENERATEMIPCHAIN3D_SIMPLEFILTER] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "generateMIPChain3D_SimpleFilterCS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_GENERATEMIPCHAIN3D_GAUSSIAN] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "generateMIPChain3D_GaussianCS.cso", wiResourceManager::COMPUTESHADER)); - computeShaders[CSTYPE_COPYTEXTURE2DREGION_UNORM4] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "copytexture2Dregion_unorm4CS.cso", wiResourceManager::COMPUTESHADER)); + computeShaders[CSTYPE_COPYTEXTURE2D_UNORM4] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "copytexture2D_unorm4CS.cso", wiResourceManager::COMPUTESHADER)); + computeShaders[CSTYPE_COPYTEXTURE2D_UNORM4_BORDEREXPAND] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "copytexture2D_unorm4_borderexpandCS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_SKINNING] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "skinningCS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_SKINNING_LDS] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "skinningCS_LDS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_CLOUDGENERATOR] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "cloudGeneratorCS.cso", wiResourceManager::COMPUTESHADER)); @@ -6336,7 +6337,7 @@ void wiRenderer::GenerateMipChain(Texture3D* texture, MIPGENFILTER filter, GRAPH GetDevice()->EventEnd(threadID); } -void wiRenderer::CopyTexture2D_Region(Texture2D* dst, UINT DstMIP, UINT DstX, UINT DstY, Texture2D* src, UINT SrcMIP, GRAPHICSTHREAD threadID) +void wiRenderer::CopyTexture2D(Texture2D* dst, UINT DstMIP, UINT DstX, UINT DstY, Texture2D* src, UINT SrcMIP, GRAPHICSTHREAD threadID, BORDEREXPANDSTYLE borderExpand) { GraphicsDevice* device = GetDevice(); @@ -6348,12 +6349,22 @@ void wiRenderer::CopyTexture2D_Region(Texture2D* dst, UINT DstMIP, UINT DstX, UI device->EventBegin("CopyTexture2D_Region_UNORM4", threadID); - device->BindComputePSO(CPSO[CSTYPE_COPYTEXTURE2DREGION_UNORM4], threadID); + if (borderExpand == BORDEREXPAND_DISABLE) + { + device->BindComputePSO(CPSO[CSTYPE_COPYTEXTURE2D_UNORM4], threadID); + } + else + { + device->BindComputePSO(CPSO[CSTYPE_COPYTEXTURE2D_UNORM4_BORDEREXPAND], threadID); + } CopyTextureCB cb; cb.xCopyDest.x = DstX; cb.xCopyDest.y = DstY; + cb.xCopySrcSize.x = desc_src.Width >> SrcMIP; + cb.xCopySrcSize.y = desc_src.Height >> SrcMIP; cb.xCopySrcMIP = SrcMIP; + cb.xCopyBorderExpandStyle = (uint)borderExpand; device->UpdateBuffer(constantBuffers[CBTYPE_COPYTEXTURE], &cb, threadID); device->BindConstantBuffer(CS, constantBuffers[CBTYPE_COPYTEXTURE], CB_GETBINDSLOT(CopyTextureCB), threadID); @@ -6370,9 +6381,7 @@ void wiRenderer::CopyTexture2D_Region(Texture2D* dst, UINT DstMIP, UINT DstX, UI device->BindUnorderedAccessResourceCS(dst, 0, threadID); } - UINT mipW = desc_src.Width >> SrcMIP; - UINT mipH = desc_src.Height >> SrcMIP; - device->Dispatch((UINT)ceilf((float)mipW / 8.0f), (UINT)ceilf((float)mipH / 8.0f), 1, threadID); + device->Dispatch((UINT)ceilf((float)cb.xCopySrcSize.x / 8.0f), (UINT)ceilf((float)cb.xCopySrcSize.y / 8.0f), 1, threadID); device->UnBindUnorderedAccessResources(0, 1, threadID); @@ -6866,6 +6875,7 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res bool repackAtlas = false; static std::map storedTextures; + const int atlasWrapBorder = 1; for (Texture2D* tex : sceneTextures) { if (tex == nullptr) @@ -6876,7 +6886,7 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res 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 + atlasWrapBorder * 2, tex->GetDesc().Height + atlasWrapBorder * 2); storedTextures[tex] = newRect; repackAtlas = true; @@ -6919,7 +6929,7 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res for (auto& it : storedTextures) { - CopyTexture2D_Region(atlasTexture, 0, it.second.x, it.second.y, it.first, 0, threadID); + CopyTexture2D(atlasTexture, 0, it.second.x + atlasWrapBorder, it.second.y + atlasWrapBorder, it.first, 0, threadID, BORDEREXPAND_WRAP); } } else @@ -6985,9 +6995,6 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res const TextureDesc& desc = atlasTexture->GetDesc(); rect_xywhf rect; - // shrink a bit to avoid overfiltering atlas boundary: - const float pixelOffset = -0.5f; - if (subset.material->GetBaseColorMap() != nullptr) { @@ -6997,8 +7004,13 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res { rect = storedTextures[wiTextureHelper::getInstance()->getWhite()]; } - materialArray[totalMaterials].baseColorAtlasMulAdd = XMFLOAT4(((float)rect.w - pixelOffset) / (float)desc.Width, ((float)rect.h - pixelOffset) / (float)desc.Height, - ((float)rect.x + pixelOffset) / (float)desc.Width, ((float)rect.y + pixelOffset) / (float)desc.Height); + // eliminate border expansion: + rect.x += atlasWrapBorder; + rect.y += atlasWrapBorder; + rect.w -= atlasWrapBorder * 2; + rect.h -= atlasWrapBorder * 2; + materialArray[totalMaterials].baseColorAtlasMulAdd = 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); @@ -7010,8 +7022,13 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res { rect = storedTextures[wiTextureHelper::getInstance()->getWhite()]; } - materialArray[totalMaterials].surfaceMapAtlasMulAdd = XMFLOAT4(((float)rect.w - pixelOffset) / (float)desc.Width, ((float)rect.h - pixelOffset) / (float)desc.Height, - ((float)rect.x + pixelOffset) / (float)desc.Width, ((float)rect.y + pixelOffset) / (float)desc.Height); + // eliminate border expansion: + rect.x += atlasWrapBorder; + rect.y += atlasWrapBorder; + rect.w -= atlasWrapBorder * 2; + rect.h -= atlasWrapBorder * 2; + materialArray[totalMaterials].surfaceMapAtlasMulAdd = 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); @@ -7024,8 +7041,13 @@ void wiRenderer::DrawTracedScene(Camera* camera, wiGraphicsTypes::Texture2D* res rect = storedTextures[wiTextureHelper::getInstance()->getNormalMapDefault()]; } - materialArray[totalMaterials].normalMapAtlasMulAdd = XMFLOAT4(((float)rect.w - pixelOffset) / (float)desc.Width, ((float)rect.h - pixelOffset) / (float)desc.Height, - ((float)rect.x + pixelOffset) / (float)desc.Width, ((float)rect.y + pixelOffset) / (float)desc.Height); + // eliminate border expansion: + rect.x += atlasWrapBorder; + rect.y += atlasWrapBorder; + rect.w -= atlasWrapBorder * 2; + rect.h -= atlasWrapBorder * 2; + materialArray[totalMaterials].normalMapAtlasMulAdd = 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); totalMaterials++; @@ -7345,7 +7367,7 @@ void wiRenderer::ManageDecalAtlas(GRAPHICSTHREAD threadID) //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_Region(atlasTexture, mip, it.second.x >> mip, it.second.y >> mip, it.first, mip, threadID); + CopyTexture2D(atlasTexture, mip, it.second.x >> mip, it.second.y >> mip, it.first, mip, threadID); } } } diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index a8b18dd76..cb31e4003 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -512,8 +512,16 @@ public: static void GenerateMipChain(wiGraphicsTypes::Texture2D* texture, MIPGENFILTER filter, GRAPHICSTHREAD threadID); static void GenerateMipChain(wiGraphicsTypes::Texture3D* texture, MIPGENFILTER filter, GRAPHICSTHREAD threadID); + enum BORDEREXPANDSTYLE + { + BORDEREXPAND_DISABLE, + BORDEREXPAND_WRAP, + BORDEREXPAND_CLAMP, + }; // Performs copy operation even between different texture formats - static void CopyTexture2D_Region(wiGraphicsTypes::Texture2D* dst, UINT DstMIP, UINT DstX, UINT DstY, wiGraphicsTypes::Texture2D* src, UINT SrcMIP, GRAPHICSTHREAD threadID); + // Can also expand border region according to desired sampler func + static void CopyTexture2D(wiGraphicsTypes::Texture2D* dst, UINT DstMIP, UINT DstX, UINT DstY, wiGraphicsTypes::Texture2D* src, UINT SrcMIP, GRAPHICSTHREAD threadID, + BORDEREXPANDSTYLE borderExpand = BORDEREXPAND_DISABLE); // dst: Texture2D with unordered access, the output will be written to this // refinementCount: 0: auto select, 1: perfect noise, greater numbers: smoother clouds, slower processing diff --git a/WickedEngine/wiTextureHelper.cpp b/WickedEngine/wiTextureHelper.cpp index c7cf225e4..e138f52b1 100644 --- a/WickedEngine/wiTextureHelper.cpp +++ b/WickedEngine/wiTextureHelper.cpp @@ -182,7 +182,8 @@ Texture2D* wiTextureHelper::wiTextureHelperInstance::getColor(const wiColor& col return colorTextures[color.rgba]; } - static const int dataLength = 1 * 1 * 4; + static const int dim = 1; + static const int dataLength = dim * dim * 4; unsigned char* data = new unsigned char[dataLength]; for (int i = 0; i < dataLength; i += 4) { @@ -193,7 +194,7 @@ Texture2D* wiTextureHelper::wiTextureHelperInstance::getColor(const wiColor& col } Texture2D* texture = nullptr; - if (FAILED(CreateTexture(texture, data, 1, 1, 4))) + if (FAILED(CreateTexture(texture, data, dim, dim, 4))) { delete[] data; return nullptr;