diff --git a/Editor/LightWindow.cpp b/Editor/LightWindow.cpp
index 367aa2d25..ae4ffe1ee 100644
--- a/Editor/LightWindow.cpp
+++ b/Editor/LightWindow.cpp
@@ -13,7 +13,7 @@ LightWindow::LightWindow(wiGUI* gui) : GUI(gui)
float screenH = (float)wiRenderer::GetDevice()->GetScreenHeight();
lightWindow = new wiWindow(GUI, "Light Window");
- lightWindow->SetSize(XMFLOAT2(650, 500));
+ lightWindow->SetSize(XMFLOAT2(650, 520));
//lightWindow->SetEnabled(false);
GUI->AddWidget(lightWindow);
@@ -158,6 +158,19 @@ LightWindow::LightWindow(wiGUI* gui) : GUI(gui)
haloCheckBox->SetTooltip("Visualize light source emission");
lightWindow->AddWidget(haloCheckBox);
+ staticCheckBox = new wiCheckBox("Static: ");
+ staticCheckBox->SetPos(XMFLOAT2(x, y += step));
+ staticCheckBox->OnClick([&](wiEventArgs args) {
+ LightComponent* light = wiRenderer::GetScene().lights.GetComponent(entity);
+ if (light != nullptr)
+ {
+ light->SetStatic(args.bValue);
+ }
+ });
+ staticCheckBox->SetEnabled(false);
+ staticCheckBox->SetTooltip("Static lights will only be used for baking into lightmaps.");
+ lightWindow->AddWidget(staticCheckBox);
+
addLightButton = new wiButton("Add Light");
addLightButton->SetPos(XMFLOAT2(x, y += step));
addLightButton->SetSize(XMFLOAT2(150, 30));
diff --git a/Editor/LightWindow.h b/Editor/LightWindow.h
index 193f19bfe..0c1cb019e 100644
--- a/Editor/LightWindow.h
+++ b/Editor/LightWindow.h
@@ -33,6 +33,7 @@ public:
wiCheckBox* shadowCheckBox;
wiCheckBox* haloCheckBox;
wiCheckBox* volumetricsCheckBox;
+ wiCheckBox* staticCheckBox;
wiButton* addLightButton;
wiColorPicker* colorPicker;
wiComboBox* typeSelectorComboBox;
diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp
index 7e9180ecc..0cd2c890b 100644
--- a/Tests/Tests.cpp
+++ b/Tests/Tests.cpp
@@ -111,6 +111,7 @@ TestsRenderer::TestsRenderer()
testSelector->OnSelect([=](wiEventArgs args) {
// Reset all state that tests might have modified:
+ wiRenderer::GetDevice()->SetVSyncEnabled(true);
wiRenderer::SetToDrawGridHelper(false);
wiRenderer::SetTemporalAAEnabled(false);
wiRenderer::ClearWorld();
@@ -185,6 +186,7 @@ TestsRenderer::TestsRenderer()
RunSpriteTest();
break;
case 14:
+ wiRenderer::GetDevice()->SetVSyncEnabled(false); // turn off vsync if we can to accelerate the baking
wiRenderer::SetTemporalAAEnabled(true);
wiRenderer::LoadModel("../models/lightmap_bake_test.wiscene", XMMatrixTranslation(0, 0, 4));
break;
diff --git a/WickedEngine/ShaderInterop.h b/WickedEngine/ShaderInterop.h
index 12b259078..ac1567d6d 100644
--- a/WickedEngine/ShaderInterop.h
+++ b/WickedEngine/ShaderInterop.h
@@ -143,9 +143,11 @@ typedef XMINT4 int4;
#define ENTITY_TYPE_FORCEFIELD_POINT 200
#define ENTITY_TYPE_FORCEFIELD_PLANE 201
+#define ENTITY_FLAG_LIGHT_STATIC 1 << 0
+
struct ShaderEntityType
{
- uint type;
+ uint params;
float3 positionVS;
float range;
float3 directionVS;
@@ -159,6 +161,24 @@ struct ShaderEntityType
int additionalData_index;
float4 texMulAdd;
+ inline uint GetType()
+ {
+ return params & 0xFFFF;
+ }
+ inline uint GetFlags()
+ {
+ return (params >> 16) & 0xFFFF;
+ }
+
+ inline void SetType(uint type)
+ {
+ params = type & 0xFFFF; // also initializes to zero, so flags must be set after the type
+ }
+ inline void SetFlags(uint flags)
+ {
+ params |= (flags & 0xFFFF) << 16;
+ }
+
// Load uncompressed color:
inline float4 GetColor()
{
diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj b/WickedEngine/WickedEngine_SHADERS.vcxproj
index 45f306ccf..86111caca 100644
--- a/WickedEngine/WickedEngine_SHADERS.vcxproj
+++ b/WickedEngine/WickedEngine_SHADERS.vcxproj
@@ -668,9 +668,13 @@
Pixel
-
+
Pixel
+
+ Pixel
+ 5.0
+
Vertex
diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters
index f1114fa25..11d61f2bc 100644
--- a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters
+++ b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters
@@ -819,9 +819,6 @@
VS
-
- PS
-
CS
@@ -840,6 +837,12 @@
PS
+
+ PS
+
+
+ PS
+
diff --git a/WickedEngine/emittedparticle_simulateCS.hlsl b/WickedEngine/emittedparticle_simulateCS.hlsl
index 7670fc923..93c30baca 100644
--- a/WickedEngine/emittedparticle_simulateCS.hlsl
+++ b/WickedEngine/emittedparticle_simulateCS.hlsl
@@ -38,7 +38,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex)
uint forceFieldID = g_xFrame_ForceFieldArrayOffset + Gid;
ShaderEntityType forceField = EntityArray[forceFieldID];
- forceFields[Gid].type = (uint)forceField.type;
+ forceFields[Gid].type = (uint)forceField.GetType();
forceFields[Gid].position = forceField.positionWS;
forceFields[Gid].gravity = forceField.energy;
forceFields[Gid].range_inverse = forceField.range;
diff --git a/WickedEngine/forceFieldVisualizerPS.hlsl b/WickedEngine/forceFieldVisualizerPS.hlsl
index 9826e3088..92d66cc62 100644
--- a/WickedEngine/forceFieldVisualizerPS.hlsl
+++ b/WickedEngine/forceFieldVisualizerPS.hlsl
@@ -14,7 +14,7 @@ float4 main(PSIn input) : SV_TARGET
float4 color = forceField.energy < 0 ? float4(0, 0, 1, 1) : float4(1, 0, 0, 1);
- if (forceField.type == ENTITY_TYPE_FORCEFIELD_POINT)
+ if (forceField.GetType() == ENTITY_TYPE_FORCEFIELD_POINT)
{
// point-like forcefield:
float3 centerToPos = normalize(input.pos3D.xyz - forceField.positionWS.xyz);
diff --git a/WickedEngine/hairparticle_simulateCS.hlsl b/WickedEngine/hairparticle_simulateCS.hlsl
index 2c3086439..ff7c5ee80 100644
--- a/WickedEngine/hairparticle_simulateCS.hlsl
+++ b/WickedEngine/hairparticle_simulateCS.hlsl
@@ -28,7 +28,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn
uint forceFieldID = g_xFrame_ForceFieldArrayOffset + groupIndex;
ShaderEntityType forceField = EntityArray[forceFieldID];
- forceFields[groupIndex].type = (uint)forceField.type;
+ forceFields[groupIndex].type = (uint)forceField.GetType();
forceFields[groupIndex].position = forceField.positionWS;
forceFields[groupIndex].gravity = forceField.energy;
forceFields[groupIndex].range_inverse = forceField.range;
diff --git a/WickedEngine/lightCullingCS.hlsl b/WickedEngine/lightCullingCS.hlsl
index 6224948b0..cf47306aa 100644
--- a/WickedEngine/lightCullingCS.hlsl
+++ b/WickedEngine/lightCullingCS.hlsl
@@ -284,7 +284,12 @@ void main(ComputeShaderInput IN)
{
ShaderEntityType entity = EntityArray[i];
- switch (entity.type)
+ if (entity.GetFlags() & ENTITY_FLAG_LIGHT_STATIC)
+ {
+ continue; // static lights will be skipped here (they are used at lightmap baking)
+ }
+
+ switch (entity.GetType())
{
case ENTITY_TYPE_POINTLIGHT:
{
@@ -360,7 +365,7 @@ void main(ComputeShaderInput IN)
Sphere sphere = { entity.positionVS.xyz, entity.range };
if (SphereInsideFrustum(sphere, GroupFrustum, nearClipVS, maxDepthVS))
{
- if (entity.type == ENTITY_TYPE_DECAL)
+ if (entity.GetType() == ENTITY_TYPE_DECAL)
{
InterlockedAdd(t_decalCount, 1);
}
@@ -386,7 +391,7 @@ void main(ComputeShaderInput IN)
if (uDepthMask & ConstructEntityMask(minDepthVS, __depthRangeRecip, sphere))
#endif
{
- if (entity.type == ENTITY_TYPE_DECAL)
+ if (entity.GetType() == ENTITY_TYPE_DECAL)
{
InterlockedAdd(o_decalCount, 1);
}
@@ -529,7 +534,7 @@ void main(ComputeShaderInput IN)
LightingResult result = (LightingResult)0;
- switch (light.type)
+ switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
diff --git a/WickedEngine/objectHF.hlsli b/WickedEngine/objectHF.hlsli
index c580c8a41..fb994eb3e 100644
--- a/WickedEngine/objectHF.hlsli
+++ b/WickedEngine/objectHF.hlsli
@@ -205,9 +205,14 @@ inline void ForwardLighting(inout Surface surface, inout float3 diffuse, inout f
{
ShaderEntityType light = EntityArray[g_xFrame_LightArrayOffset + iterator];
+ if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC)
+ {
+ continue; // static lights will be skipped (they are used in lightmap baking)
+ }
+
LightingResult result = (LightingResult)0;
- switch (light.type)
+ switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
@@ -357,9 +362,14 @@ inline void TiledLighting(in float2 pixel, inout Surface surface, inout float3 d
{
ShaderEntityType light = EntityArray[EntityIndexList[startOffset + iterator]];
+ if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC)
+ {
+ continue; // static lights will be skipped (they are used in lightmap baking)
+ }
+
LightingResult result = (LightingResult)0;
- switch (light.type)
+ switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
diff --git a/WickedEngine/objectPS_voxelizer.hlsl b/WickedEngine/objectPS_voxelizer.hlsl
index cbb9126b2..f2b81ce55 100644
--- a/WickedEngine/objectPS_voxelizer.hlsl
+++ b/WickedEngine/objectPS_voxelizer.hlsl
@@ -25,9 +25,14 @@ void main(float4 pos : SV_POSITION, float3 N : NORMAL, float2 tex : TEXCOORD, fl
{
ShaderEntityType light = EntityArray[i];
+ if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC)
+ {
+ continue; // static lights will be skipped (they are used in lightmap baking)
+ }
+
LightingResult result = (LightingResult)0;
- switch (light.type)
+ switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
diff --git a/WickedEngine/raytrace_lightsamplingCS.hlsl b/WickedEngine/raytrace_lightsamplingCS.hlsl
index 118a67eaf..cb776762d 100644
--- a/WickedEngine/raytrace_lightsamplingCS.hlsl
+++ b/WickedEngine/raytrace_lightsamplingCS.hlsl
@@ -74,7 +74,7 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
float3 L = 0;
float dist = 0;
- switch (light.type)
+ switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
diff --git a/WickedEngine/renderlightmapPS_direct.hlsl b/WickedEngine/renderlightmapPS_direct.hlsl
new file mode 100644
index 000000000..b932cebfd
--- /dev/null
+++ b/WickedEngine/renderlightmapPS_direct.hlsl
@@ -0,0 +1,142 @@
+#define RAYTRACE_EXIT 128 // doing the path trace in pixel shader will hang the GPU for some reason if we don't set a cap on the trace loop...
+#include "globals.hlsli"
+#include "ShaderInterop_TracedRendering.h"
+#include "tracedRenderingHF.hlsli"
+#include "raySceneIntersectHF.hlsli"
+
+struct Input
+{
+ float4 pos : SV_POSITION;
+ float2 uv : TEXCOORD;
+ float3 pos3D : WORLDPOSITION;
+ float3 normal : NORMAL;
+};
+
+float4 main(Input input) : SV_TARGET
+{
+ float3 N = normalize(input.normal);
+ float2 uv = input.uv;
+ float seed = xTraceRandomSeed;
+ float3 P = input.pos3D;
+ float3 finalResult = 0;
+
+ [loop]
+ for (uint iterator = 0; iterator < g_xFrame_LightArrayCount; iterator++)
+ {
+ ShaderEntityType light = EntityArray[g_xFrame_LightArrayOffset + iterator];
+
+ if (!(light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC))
+ {
+ continue; // dynamic lights will not be baked into lightmap
+ }
+
+ LightingResult result = (LightingResult)0;
+
+ float3 L = 0;
+ float dist = 0;
+
+ switch (light.GetType())
+ {
+ case ENTITY_TYPE_DIRECTIONALLIGHT:
+ {
+ dist = INFINITE_RAYHIT;
+
+ float3 lightColor = light.GetColor().rgb*light.energy;
+
+ L = light.directionWS.xyz;
+
+ result.diffuse = lightColor;
+ }
+ break;
+ case ENTITY_TYPE_POINTLIGHT:
+ {
+ L = light.positionWS - P;
+ const float dist2 = dot(L, L);
+ dist = sqrt(dist2);
+
+ [branch]
+ if (dist < light.range)
+ {
+ L /= dist;
+
+ const float3 lightColor = light.GetColor().rgb*light.energy;
+
+ result.diffuse = lightColor;
+
+ const float range2 = light.range * light.range;
+ const float att = saturate(1.0 - (dist2 / range2));
+ const float attenuation = att * att;
+
+ result.diffuse *= attenuation;
+ }
+ }
+ break;
+ case ENTITY_TYPE_SPOTLIGHT:
+ {
+ L = light.positionWS - P;
+ const float dist2 = dot(L, L);
+ dist = sqrt(dist2);
+
+ [branch]
+ if (dist < light.range)
+ {
+ L /= dist;
+
+ const float3 lightColor = light.GetColor().rgb*light.energy;
+
+ const float SpotFactor = dot(L, light.directionWS);
+ const float spotCutOff = light.coneAngleCos;
+
+ [branch]
+ if (SpotFactor > spotCutOff)
+ {
+ result.diffuse = lightColor;
+
+ const float range2 = light.range * light.range;
+ const float att = saturate(1.0 - (dist2 / range2));
+ float attenuation = att * att;
+ attenuation *= saturate((1.0 - (1.0 - SpotFactor) * 1.0 / (1.0 - spotCutOff)));
+
+ result.diffuse *= attenuation;
+ }
+ }
+ }
+ break;
+ case ENTITY_TYPE_SPHERELIGHT:
+ {
+ }
+ break;
+ case ENTITY_TYPE_DISCLIGHT:
+ {
+ }
+ break;
+ case ENTITY_TYPE_RECTANGLELIGHT:
+ {
+ }
+ break;
+ case ENTITY_TYPE_TUBELIGHT:
+ {
+ }
+ break;
+ }
+
+ float NdotL = saturate(dot(L, N));
+
+ if (NdotL > 0 && dist > 0)
+ {
+ result.diffuse = max(0.0f, result.diffuse);
+
+ float3 sampling_offset = float3(rand(seed, uv), rand(seed, uv), rand(seed, uv)) * 2 - 1;
+
+ Ray newRay;
+ newRay.origin = P;
+ newRay.direction = L + sampling_offset * 0.025f;
+ newRay.direction_inverse = rcp(newRay.direction);
+ newRay.energy = 0;
+ bool hit = TraceSceneANY(newRay, dist);
+ finalResult = (hit ? 0 : NdotL) * (result.diffuse);
+ }
+ }
+
+ return max(0, float4(finalResult, xTraceUserData));
+}
diff --git a/WickedEngine/renderlightmapPS.hlsl b/WickedEngine/renderlightmapPS_indirect.hlsl
similarity index 96%
rename from WickedEngine/renderlightmapPS.hlsl
rename to WickedEngine/renderlightmapPS_indirect.hlsl
index b50faab1c..c937c87f3 100644
--- a/WickedEngine/renderlightmapPS.hlsl
+++ b/WickedEngine/renderlightmapPS_indirect.hlsl
@@ -37,12 +37,17 @@ float4 main(Input input) : SV_TARGET
{
ShaderEntityType light = EntityArray[g_xFrame_LightArrayOffset + iterator];
+ if (!(light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC))
+ {
+ continue; // dynamic lights will not be baked into lightmap
+ }
+
LightingResult result = (LightingResult)0;
float3 L = 0;
float dist = 0;
- switch (light.type)
+ switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h
index b8f77e899..1d86e8c0b 100644
--- a/WickedEngine/wiEnums.h
+++ b/WickedEngine/wiEnums.h
@@ -228,7 +228,8 @@ enum PSTYPES
PSTYPE_VOXELIZER,
PSTYPE_VOXEL,
PSTYPE_FORCEFIELDVISUALIZER,
- PSTYPE_RENDERLIGHTMAP,
+ PSTYPE_RENDERLIGHTMAP_INDIRECT,
+ PSTYPE_RENDERLIGHTMAP_DIRECT,
PSTYPE_LAST
};
// geometry shaders
diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp
index 27185bb98..c631b838c 100644
--- a/WickedEngine/wiRenderer.cpp
+++ b/WickedEngine/wiRenderer.cpp
@@ -125,7 +125,7 @@ struct VoxelizedSceneData
int numCones = 8;
float rayStepSize = 0.5f;
bool secondaryBounceEnabled = true;
- bool reflectionsEnabled = false;
+ bool reflectionsEnabled = true;
bool centerChangedThisFrame = true;
UINT mips = 7;
} voxelSceneData;
@@ -1110,7 +1110,8 @@ GraphicsPSO* PSO_lightvisualizer[LightComponent::LIGHTTYPE_COUNT] = {};
GraphicsPSO* PSO_volumetriclight[LightComponent::LIGHTTYPE_COUNT] = {};
GraphicsPSO* PSO_enviromentallight = nullptr;
-GraphicsPSO* PSO_renderlightmap = nullptr;
+GraphicsPSO* PSO_renderlightmap_indirect = nullptr;
+GraphicsPSO* PSO_renderlightmap_direct = nullptr;
enum SKYRENDERING
{
@@ -1967,7 +1968,8 @@ void LoadShaders()
pixelShaders[PSTYPE_VOXELIZER] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "objectPS_voxelizer.cso", wiResourceManager::PIXELSHADER));
pixelShaders[PSTYPE_VOXEL] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "voxelPS.cso", wiResourceManager::PIXELSHADER));
pixelShaders[PSTYPE_FORCEFIELDVISUALIZER] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "forceFieldVisualizerPS.cso", wiResourceManager::PIXELSHADER));
- pixelShaders[PSTYPE_RENDERLIGHTMAP] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "renderlightmapPS.cso", wiResourceManager::PIXELSHADER));
+ pixelShaders[PSTYPE_RENDERLIGHTMAP_INDIRECT] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "renderlightmapPS_indirect.cso", wiResourceManager::PIXELSHADER));
+ pixelShaders[PSTYPE_RENDERLIGHTMAP_DIRECT] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "renderlightmapPS_direct.cso", wiResourceManager::PIXELSHADER));
geometryShaders[GSTYPE_ENVMAP] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "envMapGS.cso", wiResourceManager::GEOMETRYSHADER));
geometryShaders[GSTYPE_ENVMAP_SKY] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "envMap_skyGS.cso", wiResourceManager::GEOMETRYSHADER));
@@ -2570,7 +2572,7 @@ void LoadShaders()
GraphicsPSODesc desc;
desc.il = vertexLayouts[VLTYPE_RENDERLIGHTMAP];
desc.vs = vertexShaders[VSTYPE_RENDERLIGHTMAP];
- desc.ps = pixelShaders[PSTYPE_RENDERLIGHTMAP];
+ desc.ps = pixelShaders[PSTYPE_RENDERLIGHTMAP_INDIRECT];
desc.rs = rasterizers[RSTYPE_DOUBLESIDED];
desc.bs = blendStates[BSTYPE_TRANSPARENT];
desc.dss = depthStencils[DSSTYPE_XRAY];
@@ -2579,8 +2581,24 @@ void LoadShaders()
desc.RTFormats[0] = RTFormat_lightmap_object;
desc.DSFormat = FORMAT_UNKNOWN;
- RECREATE(PSO_renderlightmap);
- device->CreateGraphicsPSO(&desc, PSO_renderlightmap);
+ RECREATE(PSO_renderlightmap_indirect);
+ device->CreateGraphicsPSO(&desc, PSO_renderlightmap_indirect);
+ }
+ {
+ GraphicsPSODesc desc;
+ desc.il = vertexLayouts[VLTYPE_RENDERLIGHTMAP];
+ desc.vs = vertexShaders[VSTYPE_RENDERLIGHTMAP];
+ desc.ps = pixelShaders[PSTYPE_RENDERLIGHTMAP_DIRECT];
+ desc.rs = rasterizers[RSTYPE_DOUBLESIDED];
+ desc.bs = blendStates[BSTYPE_TRANSPARENT];
+ desc.dss = depthStencils[DSSTYPE_XRAY];
+
+ desc.numRTs = 1;
+ desc.RTFormats[0] = RTFormat_lightmap_object;
+ desc.DSFormat = FORMAT_UNKNOWN;
+
+ RECREATE(PSO_renderlightmap_direct);
+ device->CreateGraphicsPSO(&desc, PSO_renderlightmap_direct);
}
for (int type = 0; type < SKYRENDERING_COUNT; ++type)
{
@@ -3731,7 +3749,7 @@ void UpdateRenderData(GRAPHICSTHREAD threadID)
const int shadowIndex = light.shadowMap_index;
- entityArray[entityCounter].type = light.GetType();
+ entityArray[entityCounter].SetType(light.GetType());
entityArray[entityCounter].positionWS = light.position;
XMStoreFloat3(&entityArray[entityCounter].positionVS, XMVector3TransformCoord(XMLoadFloat3(&entityArray[entityCounter].positionWS), viewMatrix));
entityArray[entityCounter].range = light.range;
@@ -3792,6 +3810,11 @@ void UpdateRenderData(GRAPHICSTHREAD threadID)
break;
}
+ if (light.IsStatic())
+ {
+ entityArray[entityCounter].SetFlags(ENTITY_FLAG_LIGHT_STATIC);
+ }
+
entityCounter++;
}
entityArrayCount_Lights = entityCounter - entityArrayOffset_Lights;
@@ -3818,7 +3841,7 @@ void UpdateRenderData(GRAPHICSTHREAD threadID)
continue;
}
- entityArray[entityCounter].type = ENTITY_TYPE_ENVMAP;
+ entityArray[entityCounter].SetType(ENTITY_TYPE_ENVMAP);
entityArray[entityCounter].positionWS = probe.position;
XMStoreFloat3(&entityArray[entityCounter].positionVS, XMVector3TransformCoord(XMLoadFloat3(&probe.position), viewMatrix));
entityArray[entityCounter].range = probe.range;
@@ -3849,7 +3872,7 @@ void UpdateRenderData(GRAPHICSTHREAD threadID)
}
const DecalComponent& decal = scene.decals[decalIndex];
- entityArray[entityCounter].type = ENTITY_TYPE_DECAL;
+ entityArray[entityCounter].SetType(ENTITY_TYPE_DECAL);
entityArray[entityCounter].positionWS = decal.position;
XMStoreFloat3(&entityArray[entityCounter].positionVS, XMVector3TransformCoord(XMLoadFloat3(&decal.position), viewMatrix));
entityArray[entityCounter].range = decal.range;
@@ -3877,7 +3900,7 @@ void UpdateRenderData(GRAPHICSTHREAD threadID)
const ForceFieldComponent& force = scene.forces[i];
- entityArray[entityCounter].type = force.type;
+ entityArray[entityCounter].SetType(force.type);
entityArray[entityCounter].positionWS = force.position;
entityArray[entityCounter].energy = force.gravity;
entityArray[entityCounter].range = 1.0f / max(0.0001f, force.range); // avoid division in shader
@@ -4330,7 +4353,7 @@ void DrawLights(const CameraComponent& camera, GRAPHICSTHREAD threadID)
for (uint32_t lightIndex : culling.culledLights)
{
const LightComponent& light = scene.lights[lightIndex];
- if (light.GetType() != type)
+ if (light.GetType() != type || light.IsStatic())
continue;
switch (type)
@@ -4774,7 +4797,7 @@ void DrawForShadowMap(const CameraComponent& camera, GRAPHICSTHREAD threadID, ui
for (uint32_t lightIndex : culling.culledLights)
{
const LightComponent& light = scene.lights[lightIndex];
- if (light.GetType() != type || !light.IsCastingShadow())
+ if (light.GetType() != type || !light.IsCastingShadow() || light.IsStatic())
{
continue;
}
@@ -7619,8 +7642,6 @@ void RenderObjectLightMap(ObjectComponent& object, bool updateBVHAndScene, GRAPH
instance->Create(transform.world);
device->InvalidateBufferAccess(&dynamicVertexBufferPools[threadID], threadID);
- device->BindGraphicsPSO(PSO_renderlightmap, threadID);
-
GPUBuffer* vbs[] = {
mesh.vertexBuffer_POS.get(),
mesh.vertexBuffer_ATL.get(),
@@ -7651,6 +7672,12 @@ void RenderObjectLightMap(ObjectComponent& object, bool updateBVHAndScene, GRAPH
device->BindConstantBuffer(VS, constantBuffers[CBTYPE_RAYTRACE], CB_GETBINDSLOT(TracedRenderingCB), threadID);
device->BindConstantBuffer(PS, constantBuffers[CBTYPE_RAYTRACE], CB_GETBINDSLOT(TracedRenderingCB), threadID);
+ // Render direct lighting part:
+ device->BindGraphicsPSO(PSO_renderlightmap_direct, threadID);
+ device->DrawIndexedInstanced((int)mesh.indices.size(), 1, 0, 0, 0, threadID);
+
+ // Render indirect lighting part:
+ device->BindGraphicsPSO(PSO_renderlightmap_indirect, threadID);
device->DrawIndexedInstanced((int)mesh.indices.size(), 1, 0, 0, 0, threadID);
object.lightmapIterationCount++;
diff --git a/WickedEngine/wiSceneSystem.h b/WickedEngine/wiSceneSystem.h
index 6c8cb5d34..be6fc5a7b 100644
--- a/WickedEngine/wiSceneSystem.h
+++ b/WickedEngine/wiSceneSystem.h
@@ -581,6 +581,7 @@ namespace wiSceneSystem
CAST_SHADOW = 1 << 0,
VOLUMETRICS = 1 << 1,
VISUALIZER = 1 << 2,
+ LIGHTMAPONLY_STATIC = 1 << 3,
};
uint32_t _flags = EMPTY;
XMFLOAT3 color = XMFLOAT3(1, 1, 1);
@@ -622,10 +623,12 @@ namespace wiSceneSystem
inline void SetCastShadow(bool value) { if (value) { _flags |= CAST_SHADOW; } else { _flags &= ~CAST_SHADOW; } }
inline void SetVolumetricsEnabled(bool value) { if (value) { _flags |= VOLUMETRICS; } else { _flags &= ~VOLUMETRICS; } }
inline void SetVisualizerEnabled(bool value) { if (value) { _flags |= VISUALIZER; } else { _flags &= ~VISUALIZER; } }
+ inline void SetStatic(bool value) { if (value) { _flags |= LIGHTMAPONLY_STATIC; } else { _flags &= ~LIGHTMAPONLY_STATIC; } }
inline bool IsCastingShadow() const { return _flags & CAST_SHADOW; }
inline bool IsVolumetricsEnabled() const { return _flags & VOLUMETRICS; }
inline bool IsVisualizerEnabled() const { return _flags & VISUALIZER; }
+ inline bool IsStatic() const { return _flags & LIGHTMAPONLY_STATIC; }
inline float GetRange() const { return range; }
diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp
index a3f690872..f923c4475 100644
--- a/WickedEngine/wiVersion.cpp
+++ b/WickedEngine/wiVersion.cpp
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 24;
// minor bug fixes, alterations, refactors, updates
- const int revision = 15;
+ const int revision = 16;
long GetVersion()
diff --git a/features.txt b/features.txt
index beb47f771..499467241 100644
--- a/features.txt
+++ b/features.txt
@@ -82,3 +82,5 @@ Volumetric light scattering
Smooth Particle Hydrodynamics (SPH) Fluid Simulation
GPU Path Tracing
Entity-Component System
+Lightmaps
+Lightmap baking with GPU Path Trace
diff --git a/models/lightmap_bake_test.wiscene b/models/lightmap_bake_test.wiscene
index 08c03cc9e..c2d96a68d 100644
Binary files a/models/lightmap_bake_test.wiscene and b/models/lightmap_bake_test.wiscene differ