added parallax corrected local envmaps

This commit is contained in:
turanszkij
2018-01-26 18:07:54 +00:00
parent 42fb7c0972
commit cada16cbd9
22 changed files with 352 additions and 121 deletions
+1 -1
View File
@@ -132,7 +132,7 @@ You can use the Renderer with the following functions, all of which are in the g
- DrawLine(Vector origin,end, opt Vector color)
- PutWaterRipple(String imagename, Vector position)
- PutDecal(Decal decal)
- PutEnvProbe(Vector pos, opt int resolution = 256)
- PutEnvProbe(Vector pos)
- ClearWorld()
- ReloadShaders(opt string path)
+2 -11
View File
@@ -1,8 +1,6 @@
#include "stdafx.h"
#include "EnvProbeWindow.h"
int resolution = 256;
EnvProbeWindow::EnvProbeWindow(wiGUI* gui) : GUI(gui)
{
probe = nullptr;
@@ -19,15 +17,8 @@ EnvProbeWindow::EnvProbeWindow(wiGUI* gui) : GUI(gui)
float x = 250, y = 0, step = 45;
resolutionSlider = new wiSlider(1, 4096, 256, 4096, "Resolution");
resolutionSlider->SetPos(XMFLOAT2(x, y += step));
resolutionSlider->OnSlide([](wiEventArgs args) {
resolution = (int)args.fValue;
});
envProbeWindow->AddWidget(resolutionSlider);
realTimeCheckBox = new wiCheckBox("RealTime: ");
realTimeCheckBox->SetPos(XMFLOAT2(470, y += step));
realTimeCheckBox->SetPos(XMFLOAT2(x, y += step));
realTimeCheckBox->SetEnabled(false);
realTimeCheckBox->OnClick([&](wiEventArgs args) {
if (probe != nullptr)
@@ -43,7 +34,7 @@ EnvProbeWindow::EnvProbeWindow(wiGUI* gui) : GUI(gui)
generateButton->OnClick([](wiEventArgs args) {
XMFLOAT3 pos;
XMStoreFloat3(&pos, XMVectorAdd(wiRenderer::getCamera()->GetEye(), wiRenderer::getCamera()->GetAt() * 4));
wiRenderer::PutEnvProbe(pos, resolution);
wiRenderer::PutEnvProbe(pos);
});
envProbeWindow->AddWidget(generateButton);
-1
View File
@@ -20,7 +20,6 @@ public:
wiWindow* envProbeWindow;
wiSlider* resolutionSlider;
wiCheckBox* realTimeCheckBox;
wiButton* generateButton;
wiButton* refreshButton;
+1 -3
View File
@@ -27,9 +27,7 @@
#define TEXSLOT_GBUFFER4 6
#define TEXSLOT_ENV_GLOBAL 7
#define TEXSLOT_ENV0 8
#define TEXSLOT_ENV1 9
#define TEXSLOT_ENV2 10
#define TEXSLOT_ENVMAPARRAY 8
#define TEXSLOT_DECALATLAS 11
#define TEXSLOT_SHADOWARRAY_2D 12
+1
View File
@@ -75,6 +75,7 @@ typedef XMINT4 int4;
#define ENTITY_TYPE_RECTANGLELIGHT 5
#define ENTITY_TYPE_TUBELIGHT 6
#define ENTITY_TYPE_DECAL 100
#define ENTITY_TYPE_ENVMAP 101
#define ENTITY_TYPE_FORCEFIELD_POINT 200
#define ENTITY_TYPE_FORCEFIELD_PLANE 201
+1 -1
View File
@@ -12,5 +12,5 @@ float4 main(VSOut_Sphere input) : SV_TARGET
float3 P = input.pos3D;
float3 N = normalize(input.nor);
float3 V = normalize(g_xCamera_CamPos - P);
return float4(DEGAMMA(texture_env0.Sample(sampler_linear_clamp,-reflect(V, N)).rgb),1);
return float4(texture_envmaparray.Sample(sampler_linear_clamp, float4(-reflect(V, N), g_xColor.x)).rgb, 1);
}
-2
View File
@@ -21,7 +21,5 @@ float4 main(PSIn input) : SV_TARGET
OBJECT_PS_FOG
OBJECT_PS_GAMMA
OBJECT_PS_OUT_FORWARD_SIMPLE
}
+25 -18
View File
@@ -5,25 +5,32 @@
// #define ENVMAP_CAMERA_BLEND
inline float3 EnvironmentReflection(in float3 N, in float3 V, in float3 P, in float roughness, in float3 f0)
{
float2 size0;
float mipLevels0;
texture_env0.GetDimensions(0, size0.x, size0.y, mipLevels0);
float2 size1;
float mipLevels1;
texture_env1.GetDimensions(0, size1.x, size1.y, mipLevels1);
// float2 size0;
// float mipLevels0;
// texture_env0.GetDimensions(0, size0.x, size0.y, mipLevels0);
// float2 size1;
// float mipLevels1;
// texture_env1.GetDimensions(0, size1.x, size1.y, mipLevels1);
// float3 ref = -reflect(V, N);
// float4 envCol0 = DEGAMMA(texture_env0.SampleLevel(sampler_linear_clamp, ref, roughness*mipLevels0));
// float4 envCol1 = DEGAMMA(texture_env1.SampleLevel(sampler_linear_clamp, ref, roughness*mipLevels1));
//#ifdef ENVMAP_CAMERA_BLEND
// float dist0 = distance(g_xCamera_CamPos, g_xFrame_GlobalEnvMap0);
// float dist1 = distance(g_xCamera_CamPos, g_xFrame_GlobalEnvMap1);
//#else
// float dist0 = distance(P, g_xFrame_GlobalEnvMap0);
// float dist1 = distance(P, g_xFrame_GlobalEnvMap1);
//#endif
// static const float blendStrength = 0.05f;
// float blend = clamp((dist0 - dist1)*blendStrength, -1, 1)*0.5f + 0.5f;
// float4 envCol = lerp(envCol0, envCol1, blend);
float2 size;
float mipLevels;
texture_env_global.GetDimensions(0, size.x, size.y, mipLevels);
float3 ref = -reflect(V, N);
float4 envCol0 = DEGAMMA(texture_env0.SampleLevel(sampler_linear_clamp, ref, roughness*mipLevels0));
float4 envCol1 = DEGAMMA(texture_env1.SampleLevel(sampler_linear_clamp, ref, roughness*mipLevels1));
#ifdef ENVMAP_CAMERA_BLEND
float dist0 = distance(g_xCamera_CamPos, g_xFrame_GlobalEnvMap0);
float dist1 = distance(g_xCamera_CamPos, g_xFrame_GlobalEnvMap1);
#else
float dist0 = distance(P, g_xFrame_GlobalEnvMap0);
float dist1 = distance(P, g_xFrame_GlobalEnvMap1);
#endif
static const float blendStrength = 0.05f;
float blend = clamp((dist0 - dist1)*blendStrength, -1, 1)*0.5f + 0.5f;
float4 envCol = lerp(envCol0, envCol1, blend);
float4 envCol = DEGAMMA(texture_env_global.SampleLevel(sampler_linear_clamp, ref, roughness*mipLevels));
float f90 = saturate(50.0 * dot(f0, 0.33));
float3 F = F_Schlick(f0, f90, abs(dot(N, V)) + 1e-5f);
+3 -5
View File
@@ -10,9 +10,7 @@ TEXTURE2D(texture_gbuffer2, float4, TEXSLOT_GBUFFER2)
TEXTURE2D(texture_gbuffer3, float4, TEXSLOT_GBUFFER3)
TEXTURE2D(texture_gbuffer4, float4, TEXSLOT_GBUFFER4)
TEXTURECUBE(texture_env_global, float4, TEXSLOT_ENV_GLOBAL)
TEXTURECUBE(texture_env0, float4, TEXSLOT_ENV0)
TEXTURECUBE(texture_env1, float4, TEXSLOT_ENV1)
TEXTURECUBE(texture_env2, float4, TEXSLOT_ENV2)
TEXTURECUBEARRAY(texture_envmaparray, float4, TEXSLOT_ENVMAPARRAY)
TEXTURE2D(texture_decalatlas, float4, TEXSLOT_DECALATLAS)
TEXTURE2DARRAY(texture_shadowarray_2d, float, TEXSLOT_SHADOWARRAY_2D)
TEXTURECUBEARRAY(texture_shadowarray_cube, float, TEXSLOT_SHADOWARRAY_CUBE)
@@ -69,6 +67,8 @@ CBUFFER(WorldCB, CBSLOT_RENDERER_WORLD)
bool g_xWorld_AdvancedRefractions;
uint3 g_xWorld_EntityCullingTileCount;
uint g_xWorld_TransparentShadowsEnabled;
uint g_xWorld_EnvProbeMipCount;
float3 xPadding_WorldCB;
};
CBUFFER(FrameCB, CBSLOT_RENDERER_FRAME)
{
@@ -91,8 +91,6 @@ CBUFFER(FrameCB, CBSLOT_RENDERER_FRAME)
float2 xPadding1_FrameCB;
float2 g_xFrame_TemporalAAJitter;
float2 g_xFrame_TemporalAAJitterPrev;
float3 g_xFrame_GlobalEnvMap0; float xPadding2_FrameCB;
float3 g_xFrame_GlobalEnvMap1; float xPadding3_FrameCB;
// The following are per frame properties for the main camera:
float4x4 g_xFrame_MainCamera_VP; // View*Projection
float4x4 g_xFrame_MainCamera_View;
@@ -1,4 +1,5 @@
#define DISABLE_DECALS
#define DISABLE_LOCALENVPMAPS
#include "globals.hlsli"
#include "objectHF.hlsli"
#include "hairparticleHF.hlsli"
+28 -7
View File
@@ -50,11 +50,13 @@ groupshared uint uDepthMask; // Harada Siggraph 2012 2.5D culling
groupshared uint o_ArrayLength;
groupshared uint o_Array[LDS_ENTITYCOUNT];
groupshared uint o_decalCount;
groupshared uint o_envmapCount;
// Transparent geometry entity lists.
groupshared uint t_ArrayLength;
groupshared uint t_Array[LDS_ENTITYCOUNT];
groupshared uint t_decalCount;
groupshared uint t_envmapCount;
// Add the entity to the visible entity list for opaque geometry.
void o_AppendEntity(uint entityIndex)
@@ -204,6 +206,8 @@ void main(ComputeShaderInput IN)
t_ArrayLength = 0;
o_decalCount = 0;
t_decalCount = 0;
o_envmapCount = 0;
t_envmapCount = 0;
uDepthMask = 0;
@@ -358,11 +362,20 @@ void main(ComputeShaderInput IN)
break;
#ifndef DEFERRED
case ENTITY_TYPE_DECAL:
case ENTITY_TYPE_ENVMAP:
{
Sphere sphere = { entity.positionVS.xyz, entity.range };
if (SphereInsideFrustum(sphere, GroupFrustum, nearClipVS, maxDepthVS))
{
InterlockedAdd(t_decalCount, 1);
if (entity.type == ENTITY_TYPE_DECAL)
{
InterlockedAdd(t_decalCount, 1);
}
else
{
InterlockedAdd(t_envmapCount, 1);
}
t_AppendEntity(i);
// unit AABB:
@@ -380,7 +393,15 @@ void main(ComputeShaderInput IN)
if (uDepthMask & ConstructEntityMask(minDepthVS, __depthRangeRecip, sphere))
#endif
{
InterlockedAdd(o_decalCount, 1);
if (entity.type == ENTITY_TYPE_DECAL)
{
InterlockedAdd(o_decalCount, 1);
}
else
{
InterlockedAdd(o_envmapCount, 1);
}
o_AppendEntity(i);
}
}
@@ -401,22 +422,22 @@ void main(ComputeShaderInput IN)
#ifndef DEFERRED
if (IN.groupIndex == 0)
{
o_EntityIndexList[exportStartOffset] = uint(min(o_ArrayLength & 0x00FFFFFF, MAX_SHADER_ENTITY_COUNT_PER_TILE - 1) | ((o_decalCount & 0x000000FF) << 24));
o_EntityIndexList[exportStartOffset] = uint(min(o_ArrayLength & 0x000FFFFF, MAX_SHADER_ENTITY_COUNT_PER_TILE - 1) | ((o_decalCount & 0x000000FF) << 24) | ((o_envmapCount & 0x0000000F) << 20));
}
else
#endif
if(IN.groupIndex == 1)
{
t_EntityIndexList[exportStartOffset] = uint(min(t_ArrayLength & 0x00FFFFFF, MAX_SHADER_ENTITY_COUNT_PER_TILE - 1) | ((t_decalCount & 0x000000FF) << 24));
t_EntityIndexList[exportStartOffset] = uint(min(t_ArrayLength & 0x000FFFFF, MAX_SHADER_ENTITY_COUNT_PER_TILE - 1) | ((t_decalCount & 0x000000FF) << 24) | ((t_envmapCount & 0x0000000F) << 20));
}
#ifndef DEFERRED
// Decals need sorting!
if (o_decalCount > 0)
// Decals and envmaps need sorting!
if (o_decalCount + o_envmapCount > 0)
{
o_BitonicSort(IN.groupIndex);
}
if (t_decalCount > 0)
if (t_decalCount + t_envmapCount > 0)
{
t_BitonicSort(IN.groupIndex);
}
+55 -2
View File
@@ -226,8 +226,9 @@ inline void TiledLighting(in float2 pixel, in float3 N, in float3 V, in float3 P
uint2 tileIndex = uint2(floor(pixel / TILED_CULLING_BLOCKSIZE));
uint startOffset = flatten2D(tileIndex, g_xWorld_EntityCullingTileCount.xy) * MAX_SHADER_ENTITY_COUNT_PER_TILE;
uint arrayProperties = EntityIndexList[startOffset];
uint arrayLength = arrayProperties & 0x00FFFFFF; // count of every element in the tile
uint arrayLength = arrayProperties & 0x000FFFFF; // count of every element in the tile
uint decalCount = (arrayProperties & 0xFF000000) >> 24; // count of just the decals in the tile
uint envmapCount = (arrayProperties & 0x00F00000) >> 20; // count of just the envmaps in the tile
startOffset += 1; // first element was the itemcount
uint iterator = 0;
@@ -274,8 +275,60 @@ inline void TiledLighting(in float2 pixel, in float3 N, in float3 V, in float3 P
}
albedo.rgb = lerp(albedo.rgb, decalAccumulation.rgb, decalAccumulation.a);
#endif
#endif // DISABLE_DECALS
#ifdef DISABLE_LOCALENVPMAPS
// local envmaps are disabled, set iterator to skip:
iterator += envmapCount;
#else
// local envmaps are enabled, loop through them and apply:
float4 envmapAccumulation = 0;
uint envmapArrayEnd = iterator + envmapCount;
float3 R = -reflect(V, N);
[loop]
for (; iterator < envmapArrayEnd; ++iterator)
{
ShaderEntityType probe = EntityArray[EntityIndexList[startOffset + iterator]];
float4x4 probeProjection = MatrixArray[probe.additionalData_index];
float3 clipSpace = mul(float4(P, 1), probeProjection).xyz;
float3 uvw = clipSpace.xyz*float3(0.5f, -0.5f, 0.5f) + 0.5f;
[branch]
if (!any(uvw - saturate(uvw)))
{
// Perform parallax correction of reflection ray (R):
float3 RayLS = mul(R, (float3x3)probeProjection);
float3 FirstPlaneIntersect = (float3(1, 1, 1) - clipSpace) / RayLS;
float3 SecondPlaneIntersect = (-float3(1, 1, 1) - clipSpace) / RayLS;
float3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect);
float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z));
float3 IntersectPositionWS = P + R * Distance;
float3 R_parallaxCorrected = IntersectPositionWS - probe.positionWS;
// Sample cubemap texture:
float3 envmapColor = texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(R_parallaxCorrected, probe.shadowBias), roughness * g_xWorld_EnvProbeMipCount).rgb; // shadowBias stores textureIndex here...
// blend out if close to any cube edge:
float edgeBlend = 1 - pow(saturate(max(abs(clipSpace.x), max(abs(clipSpace.y), abs(clipSpace.z)))), 8);
// perform manual blending of probes:
// NOTE: they are sorted top-to-bottom, but blending is performed bottom-to-top
envmapAccumulation.rgb = (1 - envmapAccumulation.a) * (edgeBlend*envmapColor) + envmapAccumulation.rgb;
envmapAccumulation.a = edgeBlend + (1 - edgeBlend) * envmapAccumulation.a;
// if the accumulation reached 1, we skip the rest of the probes:
iterator = envmapAccumulation.a < 1 ? iterator : envmapCount - 1;
}
}
float f90 = saturate(50.0 * dot(f0, 0.33));
float3 F = F_Schlick(f0, f90, abs(dot(N, V)) + 1e-5f);
specular += max(0, envmapAccumulation.rgb * F);
#endif // DISABLE_LOCALENVPMAPS
// And finally loop through and apply lights:
[loop]
for (; iterator < arrayLength; iterator++)
{
+1
View File
@@ -102,6 +102,7 @@ enum TEXTYPES
TEXTYPE_3D_VOXELRADIANCE,
TEXTYPE_3D_VOXELRADIANCE_HELPER,
TEXTYPE_2D_CLOUDS,
TEXTYPE_CUBEARRAY_ENVMAPARRAY,
TEXTYPE_LAST
};
+4 -4
View File
@@ -2763,7 +2763,7 @@ void GraphicsDevice_DX11::BindRenderTargetsUAVs(UINT NumViews, Texture* const *p
ZeroMemory(renderTargetViews, sizeof(renderTargetViews));
for (UINT i = 0; i < min(NumViews, 8); ++i)
{
if (arrayIndex < 0)
if (arrayIndex < 0 || ppRenderTargets[i]->additionalRTVs_DX11.empty())
{
renderTargetViews[i] = ppRenderTargets[i]->RTV_DX11;
}
@@ -2778,7 +2778,7 @@ void GraphicsDevice_DX11::BindRenderTargetsUAVs(UINT NumViews, Texture* const *p
ID3D11DepthStencilView* depthStencilView = nullptr;
if (depthStencilTexture != nullptr)
{
if (arrayIndex < 0)
if (arrayIndex < 0 || depthStencilTexture->additionalDSVs_DX11.empty())
{
depthStencilView = depthStencilTexture->DSV_DX11;
}
@@ -2807,7 +2807,7 @@ void GraphicsDevice_DX11::BindRenderTargets(UINT NumViews, Texture* const *ppRen
ZeroMemory(renderTargetViews, sizeof(renderTargetViews));
for (UINT i = 0; i < min(NumViews, 8); ++i)
{
if (arrayIndex < 0)
if (arrayIndex < 0 || ppRenderTargets[i]->additionalRTVs_DX11.empty())
{
renderTargetViews[i] = ppRenderTargets[i]->RTV_DX11;
}
@@ -2822,7 +2822,7 @@ void GraphicsDevice_DX11::BindRenderTargets(UINT NumViews, Texture* const *ppRen
ID3D11DepthStencilView* depthStencilView = nullptr;
if (depthStencilTexture != nullptr)
{
if (arrayIndex < 0)
if (arrayIndex < 0 || depthStencilTexture->additionalDSVs_DX11.empty())
{
depthStencilView = depthStencilTexture->DSV_DX11;
}
+25 -8
View File
@@ -3120,8 +3120,15 @@ namespace wiGraphicsTypes
void GraphicsDevice_DX12::BindRenderTargetsUAVs(UINT NumViews, Texture* const *ppRenderTargets, Texture2D* depthStencilTexture, GPUResource* const *ppUAVs, int slotUAV, int countUAV,
GRAPHICSTHREAD threadID, int arrayIndex)
{
//BindRenderTargets(NumViews, ppRenderTargets, depthStencilTexture, threadID, arrayIndex);
BindRenderTargets(NumViews, ppRenderTargets, depthStencilTexture, threadID, arrayIndex);
if (ppUAVs != nullptr)
{
for (int i = 0; i < countUAV; ++i)
{
BindUnorderedAccessResourceCS(ppUAVs[i], slotUAV + i, threadID, -1);
}
}
}
void GraphicsDevice_DX12::BindRenderTargets(UINT NumViews, Texture* const *ppRenderTargets, Texture2D* depthStencilTexture, GRAPHICSTHREAD threadID, int arrayIndex)
{
@@ -3130,12 +3137,13 @@ namespace wiGraphicsTypes
{
if (ppRenderTargets[i] != nullptr)
{
if (arrayIndex < 0)
if (arrayIndex < 0 || depthStencilTexture->additionalRTVs_DX12.empty())
{
descriptors[i] = *ppRenderTargets[i]->RTV_DX12;
}
else
{
assert(depthStencilTexture->additionalRTVs_DX12.size() > static_cast<size_t>(arrayIndex) && "Invalid rendertarget arrayIndex!");
descriptors[i] = *ppRenderTargets[i]->additionalRTVs_DX12[arrayIndex];
}
}
@@ -3144,12 +3152,13 @@ namespace wiGraphicsTypes
D3D12_CPU_DESCRIPTOR_HANDLE* DSV = nullptr;
if (depthStencilTexture != nullptr)
{
if (arrayIndex < 0)
if (arrayIndex < 0 || depthStencilTexture->additionalDSVs_DX12.empty())
{
DSV = depthStencilTexture->DSV_DX12;
}
else
{
assert(depthStencilTexture->additionalDSVs_DX12.size() > static_cast<size_t>(arrayIndex) && "Invalid depthstencil arrayIndex!");
DSV = depthStencilTexture->additionalDSVs_DX12[arrayIndex];
}
}
@@ -3220,7 +3229,7 @@ namespace wiGraphicsTypes
}
}
}
void GraphicsDevice_DX12::BindUnorderedAccessResourceCS(GPUResource* resource, int slot, GRAPHICSTHREAD threadID, int arrayIndex)
void GraphicsDevice_DX12::BindUnorderedAccessResource(SHADERSTAGE stage, GPUResource* resource, int slot, GRAPHICSTHREAD threadID, int arrayIndex)
{
if (resource != nullptr && resource->resource_DX12 != nullptr)
{
@@ -3228,28 +3237,36 @@ namespace wiGraphicsTypes
{
if (resource->UAV_DX12 != nullptr)
{
GetFrameResources().ResourceDescriptorsGPU[threadID]->update(CS, GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot,
GetFrameResources().ResourceDescriptorsGPU[threadID]->update(stage, GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot,
resource->UAV_DX12, device, GetDirectCommandList(threadID));
}
}
else
{
assert(resource->additionalUAVs_DX12.size() > static_cast<size_t>(arrayIndex) && "Invalid arrayIndex!");
GetFrameResources().ResourceDescriptorsGPU[threadID]->update(CS, GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot,
GetFrameResources().ResourceDescriptorsGPU[threadID]->update(stage, GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot,
resource->additionalUAVs_DX12[arrayIndex], device, GetDirectCommandList(threadID));
}
}
}
void GraphicsDevice_DX12::BindUnorderedAccessResourcesCS(GPUResource *const* resources, int slot, int count, GRAPHICSTHREAD threadID)
void GraphicsDevice_DX12::BindUnorderedAccessResources(SHADERSTAGE stage, GPUResource *const* resources, int slot, int count, GRAPHICSTHREAD threadID)
{
if (resources != nullptr)
{
for (int i = 0; i < count; ++i)
{
BindUnorderedAccessResourceCS(resources[i], slot + i, threadID, -1);
BindUnorderedAccessResource(stage, resources[i], slot + i, threadID, -1);
}
}
}
void GraphicsDevice_DX12::BindUnorderedAccessResourceCS(GPUResource* resource, int slot, GRAPHICSTHREAD threadID, int arrayIndex)
{
BindUnorderedAccessResource(CS, resource, slot, threadID, arrayIndex);
}
void GraphicsDevice_DX12::BindUnorderedAccessResourcesCS(GPUResource *const* resources, int slot, int count, GRAPHICSTHREAD threadID)
{
BindUnorderedAccessResources(CS, resources, slot, count, threadID);
}
void GraphicsDevice_DX12::UnBindResources(int slot, int num, GRAPHICSTHREAD threadID)
{
for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage)
+2
View File
@@ -184,6 +184,8 @@ namespace wiGraphicsTypes
virtual void ClearDepthStencil(Texture2D* pTexture, UINT ClearFlags, FLOAT Depth, UINT8 Stencil, GRAPHICSTHREAD threadID, int arrayIndex = -1) override;
virtual void BindResource(SHADERSTAGE stage, GPUResource* resource, int slot, GRAPHICSTHREAD threadID, int arrayIndex = -1) override;
virtual void BindResources(SHADERSTAGE stage, GPUResource *const* resources, int slot, int count, GRAPHICSTHREAD threadID) override;
void BindUnorderedAccessResource(SHADERSTAGE stage, GPUResource* resource, int slot, GRAPHICSTHREAD threadID, int arrayIndex = -1);
void BindUnorderedAccessResources(SHADERSTAGE stage, GPUResource *const* resources, int slot, int count, GRAPHICSTHREAD threadID);
virtual void BindUnorderedAccessResourceCS(GPUResource* resource, int slot, GRAPHICSTHREAD threadID, int arrayIndex = -1) override;
virtual void BindUnorderedAccessResourcesCS(GPUResource *const* resources, int slot, int count, GRAPHICSTHREAD threadID) override;
virtual void UnBindResources(int slot, int num, GRAPHICSTHREAD threadID) override;
+13
View File
@@ -1234,6 +1234,11 @@ void Scene::Update()
{
x->UpdateModel();
}
for (EnvironmentProbe* probe : environmentProbes)
{
probe->UpdateEnvProbe();
}
}
#pragma endregion
@@ -4517,3 +4522,11 @@ void ForceField::Serialize(wiArchive& archive)
}
}
#pragma endregion
#pragma region ENVIRONMENTPROBE
void EnvironmentProbe::UpdateEnvProbe()
{
bounds.createFromHalfWidth(XMFLOAT3(0, 0, 0), XMFLOAT3(1, 1, 1));
bounds = bounds.get(world);
}
#pragma endregion
+5 -3
View File
@@ -1188,13 +1188,15 @@ static const int RESOLUTION = 36;
static void CleanUpStatic();
};
struct EnvironmentProbe : public Transform
struct EnvironmentProbe : public Transform, public Cullable
{
wiRenderTarget cubeMap;
int textureIndex;
bool realTime;
bool isUpToDate;
EnvironmentProbe() :realTime(false), isUpToDate(false) {}
EnvironmentProbe() : textureIndex(-1), realTime(false), isUpToDate(false) {}
void UpdateEnvProbe();
};
struct ForceField : public Transform
{
+175 -43
View File
@@ -2921,24 +2921,6 @@ void wiRenderer::UpdatePerFrameData(float dt)
}
wiProfiler::GetInstance().EndRange(); // SPTree Update
// Environment probe sorting:
{
ZeroMemory(globalEnvProbes, sizeof(globalEnvProbes));
GetScene().environmentProbes.sort(
[&](EnvironmentProbe* a, EnvironmentProbe* b) {
return wiMath::DistanceSquared(a->translation, getCamera()->translation) < wiMath::DistanceSquared(b->translation, getCamera()->translation);
}
);
int envProbeInd = 0;
for (auto& x : GetScene().environmentProbes)
{
globalEnvProbes[envProbeInd] = x;
envProbeInd++;
if (envProbeInd >= ARRAYSIZE(globalEnvProbes))
break;
}
}
// Update Voxelization parameters:
if (spTree != nullptr)
{
@@ -3024,6 +3006,14 @@ void wiRenderer::UpdatePerFrameData(float dt)
}
}
for (EnvironmentProbe* probe : GetScene().environmentProbes)
{
if (culling.frustum.CheckBox(probe->bounds))
{
x.second.culledEnvProbes.push_back(probe);
}
}
spTree_lights->getVisible(culling.frustum, culling.culledLights, wiSPTree::SortType::SP_TREE_SORT_NONE);
if (GetVoxelRadianceEnabled())
@@ -3141,7 +3131,7 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
const FrameCulling& mainCameraCulling = frameCullings[getCamera()];
// Fill Light Array with lights + decals in the frustum:
// Fill Light Array with lights + envprobes + decals in the frustum:
{
const CulledList& culledLights = mainCameraCulling.culledLights;
@@ -3242,6 +3232,40 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
}
entityArrayCount_Lights = entityCounter - entityArrayOffset_Lights;
entityArrayOffset_EnvProbes = entityCounter;
for (EnvironmentProbe* probe : mainCameraCulling.culledEnvProbes)
{
if (probe->textureIndex < 0)
{
continue;
}
if (entityCounter == MAX_SHADER_ENTITY_COUNT)
{
assert(0); // too many entities!
entityCounter--;
break;
}
if (matrixCounter >= MATRIXARRAY_COUNT)
{
assert(0); // too many probes, can't upload the rest to matrixarray!
matrixCounter--;
break;
}
entityArray[entityCounter].type = ENTITY_TYPE_ENVMAP;
entityArray[entityCounter].positionWS = probe->translation;
XMStoreFloat3(&entityArray[entityCounter].positionVS, XMVector3TransformCoord(XMLoadFloat3(&probe->translation), viewMatrix));
entityArray[entityCounter].range = max(probe->scale.x, max(probe->scale.y, probe->scale.z)) * 2;
entityArray[entityCounter].shadowBias = (float)probe->textureIndex;
entityArray[entityCounter].additionalData_index = matrixCounter;
matrixArray[matrixCounter] = XMMatrixTranspose(XMMatrixInverse(nullptr, XMLoadFloat4x4(&probe->world)));
matrixCounter++;
entityCounter++;
}
entityArrayCount_EnvProbes = entityCounter - entityArrayOffset_EnvProbes;
entityArrayOffset_Decals = entityCounter;
for (Decal* decal : mainCameraCulling.culledDecals)
{
@@ -3447,15 +3471,8 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
// Render out of date environment probes:
RefreshEnvProbes(threadID);
// Bind environment probes:
{
GPUResource* envMaps[] = {
globalEnvProbes[0] == nullptr ? enviroMap : globalEnvProbes[0]->cubeMap.GetTexture(),
globalEnvProbes[1] == nullptr ? enviroMap : globalEnvProbes[1]->cubeMap.GetTexture(),
};
GetDevice()->BindResources(PS, envMaps, TEXSLOT_ENV0, ARRAYSIZE(envMaps), threadID);
GetDevice()->BindResources(CS, envMaps, TEXSLOT_ENV0, ARRAYSIZE(envMaps), threadID);
}
GetDevice()->BindResource(PS, enviroMap, TEXSLOT_ENV_GLOBAL, threadID);
GetDevice()->BindResource(PS, textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY], TEXSLOT_ENVMAPARRAY, threadID);
}
void wiRenderer::OcclusionCulling_Render(GRAPHICSTHREAD threadID)
{
@@ -3915,6 +3932,9 @@ void wiRenderer::DrawDebugEnvProbes(Camera* camera, GRAPHICSTHREAD threadID)
{
GetDevice()->EventBegin("Debug EnvProbes", threadID);
// Envmap spheres:
GetDevice()->BindPrimitiveTopology(TRIANGLELIST, threadID);
GetDevice()->BindGraphicsPSO(PSO_debug[DEBUGRENDERING_ENVPROBE], threadID);
@@ -3922,15 +3942,39 @@ void wiRenderer::DrawDebugEnvProbes(Camera* camera, GRAPHICSTHREAD threadID)
MiscCB sb;
for (auto& x : GetScene().environmentProbes)
{
sb.mTransform = XMMatrixTranspose(x->getMatrix());
sb.mColor = XMFLOAT4(1, 1, 1, 1);
sb.mTransform = XMMatrixTranspose(XMMatrixTranslation(x->translation.x, x->translation.y, x->translation.z));
sb.mColor = XMFLOAT4((float)x->textureIndex, 1, 1, 1);
GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_MISC], &sb, threadID);
GetDevice()->BindResource(PS, x->cubeMap.GetTexture(), TEXSLOT_ENV0, threadID);
GetDevice()->Draw(2880, 0, threadID); // uv-sphere
}
// Local proxy boxes:
GetDevice()->BindPrimitiveTopology(LINELIST, threadID);
GetDevice()->BindGraphicsPSO(PSO_debug[DEBUGRENDERING_CUBE], threadID);
GPUBuffer* vbs[] = {
&Cube::vertexBuffer,
};
const UINT strides[] = {
sizeof(XMFLOAT4) + sizeof(XMFLOAT4),
};
GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID);
GetDevice()->BindIndexBuffer(&Cube::indexBuffer, INDEXFORMAT_16BIT, 0, threadID);
for (auto& x : GetScene().environmentProbes)
{
sb.mTransform = XMMatrixTranspose(XMLoadFloat4x4(&x->world)*camera->GetViewProjection());
sb.mColor = XMFLOAT4(0, 1, 1, 1);
GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_MISC], &sb, threadID);
GetDevice()->DrawIndexed(24, 0, 0, threadID);
}
GetDevice()->EventEnd(threadID);
}
}
@@ -5430,8 +5474,42 @@ void wiRenderer::RefreshEnvProbes(GRAPHICSTHREAD threadID)
{
GetDevice()->EventBegin("EnvironmentProbe Refresh", threadID);
static const UINT envmapRes = 128;
static const UINT envmapCount = 16;
bool envmapTaken[envmapCount] = {};
// reconstruct envmap array status:
for (EnvironmentProbe* probe : GetScene().environmentProbes)
{
if (probe->textureIndex >= 0)
{
envmapTaken[probe->textureIndex] = true;
}
}
bool renderhappened = false;
for (EnvironmentProbe* probe : GetScene().environmentProbes)
{
if (probe->textureIndex < 0)
{
// need to take a free envmap texture slot:
bool found = false;
for (int i = 0; i < ARRAYSIZE(envmapTaken); ++i)
{
if (envmapTaken[i] == false)
{
probe->textureIndex = i;
found = true;
break;
}
}
if (!found)
{
// could not find free slot in envmap array, so skip this probe:
continue;
}
}
if (probe->isUpToDate)
{
continue;
@@ -5441,7 +5519,57 @@ void wiRenderer::RefreshEnvProbes(GRAPHICSTHREAD threadID)
probe->isUpToDate = true;
}
probe->cubeMap.Activate(threadID, 0, 0, 0, 1);
if (textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY] == nullptr)
{
Texture2DDesc desc;
desc.ArraySize = envmapCount * 6;
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_R16G16B16A16_FLOAT;
desc.Height = envmapRes;
desc.Width = envmapRes;
desc.MipLevels = 0;
desc.MiscFlags = RESOURCE_MISC_GENERATE_MIPS | RESOURCE_MISC_TEXTURECUBE;
desc.Usage = USAGE_DEFAULT;
textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY] = new Texture2D;
textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY]->RequestIndepententRenderTargetArraySlices(true);
HRESULT hr = GetDevice()->CreateTexture2D(&desc, nullptr, (Texture2D**)&textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY]);
assert(SUCCEEDED(hr));
}
static Texture2D* envrenderingDepthBuffer = nullptr;
if (envrenderingDepthBuffer == nullptr)
{
Texture2DDesc desc;
desc.ArraySize = 6;
desc.BindFlags = BIND_DEPTH_STENCIL;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_D16_UNORM;
desc.Height = envmapRes;
desc.Width = envmapRes;
desc.MipLevels = 1;
desc.MiscFlags = RESOURCE_MISC_TEXTURECUBE;
desc.Usage = USAGE_DEFAULT;
HRESULT hr = GetDevice()->CreateTexture2D(&desc, nullptr, &envrenderingDepthBuffer);
assert(SUCCEEDED(hr));
}
GetDevice()->BindRenderTargets(1, &textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY], envrenderingDepthBuffer, threadID, probe->textureIndex);
const float clearColor[4] = { 0,0,0,1 };
GetDevice()->ClearRenderTarget(textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY], clearColor, threadID, probe->textureIndex);
GetDevice()->ClearDepthStencil(envrenderingDepthBuffer, CLEAR_DEPTH, 0.0f, 0, threadID);
ViewPort VP;
VP.Height = envmapRes;
VP.Width = envmapRes;
VP.TopLeftX = 0;
VP.TopLeftY = 0;
VP.MinDepth = 0.0f;
VP.MaxDepth = 1.0f;
GetDevice()->BindViewports(1, &VP, threadID);
std::vector<SHCAM> cameras;
{
@@ -5471,7 +5599,7 @@ void wiRenderer::RefreshEnvProbes(GRAPHICSTHREAD threadID)
CameraCB camcb;
camcb.mCamPos = probe->translation; // only this will be used by envprobe rendering shaders the rest is read from cubemaprenderCB
GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_CAMERA], &cb, threadID);
GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_CAMERA], &camcb, threadID);
CulledList culledObjects;
@@ -5508,12 +5636,14 @@ void wiRenderer::RefreshEnvProbes(GRAPHICSTHREAD threadID)
GetDevice()->Draw(240, 0, threadID);
}
renderhappened = true;
}
probe->cubeMap.Deactivate(threadID);
GetDevice()->GenerateMips(probe->cubeMap.GetTexture(), threadID);
if (renderhappened)
{
GetDevice()->BindRenderTargets(0, nullptr, nullptr, threadID);
GetDevice()->GenerateMips(textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY], threadID);
}
GetDevice()->EventEnd(threadID);
@@ -5834,7 +5964,7 @@ void wiRenderer::ComputeTiledLightCulling(bool deferred, GRAPHICSTHREAD threadID
dispatchParams.numThreads[0] = dispatchParams.numThreadGroups[0] * TILED_CULLING_BLOCKSIZE;
dispatchParams.numThreads[1] = dispatchParams.numThreadGroups[1] * TILED_CULLING_BLOCKSIZE;
dispatchParams.numThreads[2] = 1;
dispatchParams.value0 = (UINT)(frameCullings[getCamera()].culledLights.size() + frameCullings[getCamera()].culledDecals.size());
dispatchParams.value0 = (UINT)(frameCullings[getCamera()].culledLights.size() + frameCullings[getCamera()].culledEnvProbes.size() + frameCullings[getCamera()].culledDecals.size());
device->UpdateBuffer(constantBuffers[CBTYPE_DISPATCHPARAMS], &dispatchParams, threadID);
device->BindConstantBuffer(CS, constantBuffers[CBTYPE_DISPATCHPARAMS], CB_GETBINDSLOT(DispatchParamsCB), threadID);
@@ -6155,6 +6285,11 @@ void wiRenderer::UpdateWorldCB(GRAPHICSTHREAD threadID)
value.mAdvancedRefractions = GetAdvancedRefractionsEnabled() ? 1 : 0;
value.mEntityCullingTileCount = GetEntityCullingTileCount();
value.mTransparentShadowsEnabled = TRANSPARENTSHADOWSENABLED;
value.mEnvProbeMipCount = 0;
if (textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY] != nullptr)
{
value.mEnvProbeMipCount = static_cast<Texture2D*>(textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY])->GetDesc().MipLevels;
}
if (memcmp(&prevcb[threadID], &value, sizeof(WorldCB)) != 0) // prevent overcommit
{
@@ -6185,8 +6320,6 @@ void wiRenderer::UpdateFrameCB(GRAPHICSTHREAD threadID)
cb.mSunEntityArrayIndex = GetSunArrayIndex();
cb.mTemporalAAJitter = temporalAAJitter;
cb.mTemporalAAJitterPrev = temporalAAJitterPrev;
cb.mGlobalEnvMap0 = globalEnvProbes[0] == nullptr ? XMFLOAT3(0, 0, 0) : globalEnvProbes[0]->translation;
cb.mGlobalEnvMap1 = globalEnvProbes[1] == nullptr ? XMFLOAT3(0, 0, 0) : globalEnvProbes[1]->translation;
auto camera = getCamera();
auto prevCam = prevFrameCam;
@@ -6854,11 +6987,10 @@ void wiRenderer::SynchronizeWithPhysicsEngine(float dt)
}
}
void wiRenderer::PutEnvProbe(const XMFLOAT3& position, int resolution)
void wiRenderer::PutEnvProbe(const XMFLOAT3& position)
{
EnvironmentProbe* probe = new EnvironmentProbe;
probe->transform(position);
probe->cubeMap.InitializeCube(resolution, true, RTFormat_envprobe, 0);
scene->environmentProbes.push_back(probe);
}
+5 -3
View File
@@ -141,6 +141,8 @@ public:
BOOL mAdvancedRefractions;
XMUINT3 mEntityCullingTileCount;
BOOL mTransparentShadowsEnabled;
UINT mEnvProbeMipCount;
XMFLOAT3 pad0;
};
CBUFFER(FrameCB, CBSLOT_RENDERER_FRAME)
{
@@ -163,8 +165,6 @@ public:
XMFLOAT2 pad1;
XMFLOAT2 mTemporalAAJitter;
XMFLOAT2 mTemporalAAJitterPrev;
XMFLOAT3 mGlobalEnvMap0; float pad2;
XMFLOAT3 mGlobalEnvMap1; float pad3;
XMMATRIX mVP;
XMMATRIX mView;
XMMATRIX mProj;
@@ -407,6 +407,7 @@ public:
std::vector<wiHairParticle*> culledHairParticleSystems;
CulledList culledLights;
std::list<Decal*> culledDecals;
std::list<EnvironmentProbe*> culledEnvProbes;
void Clear()
{
@@ -416,6 +417,7 @@ public:
culledHairParticleSystems.clear();
culledLights.clear();
culledDecals.clear();
culledEnvProbes.clear();
}
};
static std::unordered_map<Camera*, FrameCulling> frameCullings;
@@ -594,7 +596,7 @@ public:
static void LoadWorldInfo(const std::string& fileName);
static void LoadDefaultLighting();
static void PutEnvProbe(const XMFLOAT3& position, int resolution = 256);
static void PutEnvProbe(const XMFLOAT3& position);
static void CreateImpostor(Mesh* mesh);
+3 -8
View File
@@ -640,21 +640,16 @@ namespace wiRenderer_BindLua
{
XMFLOAT3 p;
XMStoreFloat3(&p, pos->vector);
int res = 256;
if (argc > 1)
{
res = wiLua::SGetInt(L, 2);
}
wiRenderer::PutEnvProbe(p,res);
wiRenderer::PutEnvProbe(p);
}
else
{
wiLua::SError(L, "PutEnvProbe(Vector pos, opt int resolution = 256) argument is not a Vector!");
wiLua::SError(L, "PutEnvProbe(Vector pos) argument is not a Vector!");
}
}
else
{
wiLua::SError(L, "PutEnvProbe(Vector pos, opt int resolution = 256) not enough arguments!");
wiLua::SError(L, "PutEnvProbe(Vector pos) not enough arguments!");
}
return 0;
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 14;
// minor bug fixes, alterations, refactors, updates
const int revision = 24;
const int revision = 25;
long GetVersion()