added light color mask texture support
This commit is contained in:
+10
-1
@@ -319,7 +319,12 @@ void LightWindow::Create(EditorComponent* _editor)
|
||||
shadowResolutionComboBox.SetSelected(0);
|
||||
AddWidget(&shadowResolutionComboBox);
|
||||
|
||||
y += step * 0.5f;
|
||||
|
||||
tipLabel.Create("TipLabel");
|
||||
tipLabel.SetText("Tip: you can add a material to this entity, and the base color texture of it will be used to tint the light color.");
|
||||
tipLabel.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
tipLabel.SetSize(XMFLOAT2(100, 50));
|
||||
AddWidget(&tipLabel);
|
||||
|
||||
lensflare_Label.Create("Lens flare textures: ");
|
||||
lensflare_Label.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
@@ -590,6 +595,10 @@ void LightWindow::ResizeLayout()
|
||||
|
||||
y += jump;
|
||||
|
||||
add_fullwidth(tipLabel);
|
||||
|
||||
y += jump;
|
||||
|
||||
add_fullwidth(lensflare_Label);
|
||||
add_fullwidth(lensflare_Button[0]);
|
||||
add_fullwidth(lensflare_Button[1]);
|
||||
|
||||
@@ -28,6 +28,8 @@ public:
|
||||
wi::gui::ComboBox typeSelectorComboBox;
|
||||
wi::gui::ComboBox shadowResolutionComboBox;
|
||||
|
||||
wi::gui::Label tipLabel;
|
||||
|
||||
wi::gui::Label lensflare_Label;
|
||||
wi::gui::Button lensflare_Button[7];
|
||||
|
||||
|
||||
@@ -791,9 +791,6 @@ enum SHADER_ENTITY_FLAGS
|
||||
ENTITY_FLAG_CAPSULE_SHADOW_COLLIDER = 1 << 4,
|
||||
};
|
||||
|
||||
// Warning: the size of this structure directly affects shader performance.
|
||||
// Try to reduce it as much as possible!
|
||||
// Keep it aligned to 16 bytes for best performance!
|
||||
struct alignas(16) ShaderEntity
|
||||
{
|
||||
float3 position;
|
||||
@@ -874,11 +871,11 @@ struct alignas(16) ShaderEntity
|
||||
}
|
||||
inline min16uint GetMatrixIndex()
|
||||
{
|
||||
return indices & 0xFFFF;
|
||||
return indices & 0xFFF;
|
||||
}
|
||||
inline min16uint GetTextureIndex()
|
||||
{
|
||||
return indices >> 16u;
|
||||
return indices >> 12u;
|
||||
}
|
||||
inline bool IsCastingShadow()
|
||||
{
|
||||
@@ -958,8 +955,8 @@ struct alignas(16) ShaderEntity
|
||||
}
|
||||
inline void SetIndices(uint matrixIndex, uint textureIndex)
|
||||
{
|
||||
indices = matrixIndex & 0xFFFF;
|
||||
indices |= (textureIndex & 0xFFFF) << 16u;
|
||||
indices = matrixIndex & 0xFFF;
|
||||
indices |= (textureIndex & 0xFFFFF) << 12u;
|
||||
}
|
||||
inline void SetGravity(float value)
|
||||
{
|
||||
|
||||
@@ -156,6 +156,31 @@ inline uint2 unpack_pixel(uint value)
|
||||
return retVal;
|
||||
}
|
||||
|
||||
uint pack_unorm16x2(float2 value)
|
||||
{
|
||||
return uint(saturate(value.x) * 65535.0) | (uint(saturate(value.x) * 65535.0) << 16u);
|
||||
}
|
||||
uint2 pack_unorm16x4(float4 value)
|
||||
{
|
||||
return uint2(pack_unorm16x2(value.xy), pack_unorm16x2(value.zw));
|
||||
}
|
||||
float2 unpack_unorm16x2(uint value)
|
||||
{
|
||||
float2 retVal;
|
||||
retVal.x = (value & 0xFFFF) / 65535.0;
|
||||
retVal.y = (value >> 16u) / 65535.0;
|
||||
return retVal;
|
||||
}
|
||||
float4 unpack_unorm16x4(uint2 value)
|
||||
{
|
||||
float4 retVal;
|
||||
retVal.x = (value.x & 0xFFFF) / 65535.0;
|
||||
retVal.y = (value.x >> 16u) / 65535.0;
|
||||
retVal.z = (value.y & 0xFFFF) / 65535.0;
|
||||
retVal.w = (value.y >> 16u) / 65535.0;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T inverse_lerp(T value1, T value2, T pos)
|
||||
{
|
||||
|
||||
@@ -210,6 +210,14 @@ inline void light_point(in ShaderEntity light, in Surface surface, inout Lightin
|
||||
if (!any(light_color))
|
||||
return; // light color lost after shadow
|
||||
}
|
||||
|
||||
const uint maskTex = light.GetTextureIndex();
|
||||
[branch]
|
||||
if (maskTex > 0)
|
||||
{
|
||||
half4 mask = bindless_cubemaps_half4[descriptor_index(maskTex)].SampleLevel(sampler_linear_clamp, -LunnormalizedShadow, 0);
|
||||
light_color *= mask.rgb * mask.a;
|
||||
}
|
||||
|
||||
light_color *= attenuation_pointlight(dist2, range, range2);
|
||||
|
||||
@@ -295,7 +303,7 @@ inline void light_spot(in ShaderEntity light, in Surface surface, inout Lighting
|
||||
return; // outside spotlight cone
|
||||
|
||||
half3 light_color = light.GetColor().rgb * shadow_mask;
|
||||
|
||||
|
||||
[branch]
|
||||
if (light.IsCastingShadow() && surface.IsReceiveShadow())
|
||||
{
|
||||
@@ -317,6 +325,17 @@ inline void light_spot(in ShaderEntity light, in Surface surface, inout Lighting
|
||||
if (!any(light_color))
|
||||
return; // light color lost after shadow
|
||||
}
|
||||
|
||||
const uint maskTex = light.GetTextureIndex();
|
||||
[branch]
|
||||
if (maskTex > 0)
|
||||
{
|
||||
float4 shadow_pos = mul(load_entitymatrix(light.GetMatrixIndex() + 0), float4(surface.P, 1));
|
||||
shadow_pos.xyz /= shadow_pos.w;
|
||||
float2 shadow_uv = clipspace_to_uv(shadow_pos.xy);
|
||||
half4 mask = bindless_textures_half4[descriptor_index(maskTex)].SampleLevel(sampler_linear_clamp, shadow_uv, 0);
|
||||
light_color *= mask.rgb * mask.a;
|
||||
}
|
||||
|
||||
light_color *= attenuation_spotlight(dist2, range, range2, spot_factor, light.GetAngleScale(), light.GetAngleOffset());
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ float4 main(VertexToPixel input) : SV_TARGET
|
||||
|
||||
// dither ray start to help with undersampling:
|
||||
P = P + V * stepSize * dither(input.pos.xy);
|
||||
|
||||
const uint maskTex = light.GetTextureIndex();
|
||||
|
||||
// Perform ray marching to integrate light volume along view ray:
|
||||
[loop]
|
||||
@@ -66,6 +68,13 @@ float4 main(VertexToPixel input) : SV_TARGET
|
||||
{
|
||||
attenuation *= shadow_cube(light, Lunnormalized, input.pos.xy);
|
||||
}
|
||||
|
||||
[branch]
|
||||
if (maskTex > 0)
|
||||
{
|
||||
half4 mask = bindless_cubemaps_half4[descriptor_index(maskTex)].Sample(sampler_linear_clamp, -Lunnormalized);
|
||||
attenuation *= mask.rgb * mask.a;
|
||||
}
|
||||
|
||||
// Evaluate sample height for height fog calculation, given 0 for V:
|
||||
attenuation *= (half)g_xColor.y + GetFogAmount(cameraDistance - marchedDistance, P, 0);
|
||||
|
||||
@@ -87,6 +87,8 @@ float4 main(VertexToPixel input) : SV_TARGET
|
||||
|
||||
// dither ray start to help with undersampling:
|
||||
P = P + V * stepSize * dither(input.pos.xy);
|
||||
|
||||
const uint maskTex = light.GetTextureIndex();
|
||||
|
||||
// Perform ray marching to integrate light volume along view ray:
|
||||
[loop]
|
||||
@@ -119,6 +121,16 @@ float4 main(VertexToPixel input) : SV_TARGET
|
||||
attenuation *= shadow_2D(light, shadow_pos.xyz, shadow_uv.xy, 0, input.pos.xy);
|
||||
}
|
||||
}
|
||||
|
||||
[branch]
|
||||
if (maskTex > 0)
|
||||
{
|
||||
float4 shadow_pos = mul(load_entitymatrix(light.GetMatrixIndex() + 0), float4(P, 1));
|
||||
shadow_pos.xyz /= shadow_pos.w;
|
||||
float2 shadow_uv = shadow_pos.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f);
|
||||
half4 mask = bindless_textures_half4[descriptor_index(maskTex)].Sample(sampler_linear_clamp, shadow_uv);
|
||||
attenuation *= mask.rgb * mask.a;
|
||||
}
|
||||
|
||||
// Evaluate sample height for exponential fog calculation, given 0 for V:
|
||||
attenuation *= g_xColor.y + GetFogAmount(cameraDistance - marchedDistance, P, 0);
|
||||
|
||||
@@ -527,6 +527,23 @@ namespace wi::math
|
||||
}
|
||||
|
||||
|
||||
constexpr uint32_t pack_unorm16x2(float x, float y)
|
||||
{
|
||||
return uint32_t(saturate(x) * 65535.0f) | (uint32_t(saturate(y) * 65535.0f) << 16u);
|
||||
}
|
||||
constexpr uint32_t pack_unorm16x2(XMFLOAT2 value)
|
||||
{
|
||||
return pack_unorm16x2(value.x, value.y);
|
||||
}
|
||||
constexpr XMUINT2 pack_unorm16x4(float x, float y, float z, float w)
|
||||
{
|
||||
return XMUINT2(pack_unorm16x2(x, y), pack_unorm16x2(z, w));
|
||||
}
|
||||
constexpr XMUINT2 pack_unorm16x4(XMFLOAT4 value)
|
||||
{
|
||||
return pack_unorm16x4(value.x, value.y, value.z, value.w);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compute the intersection of a ray (Origin, Direction) with a triangle
|
||||
|
||||
+12
-14
@@ -4412,9 +4412,6 @@ void UpdatePerFrameData(
|
||||
shaderentity.SetDirection(light.direction);
|
||||
shaderentity.SetColor(float4(light.color.x * light.intensity, light.color.y * light.intensity, light.color.z * light.intensity, 1));
|
||||
|
||||
// mark as no shadow by default:
|
||||
shaderentity.indices = ~0;
|
||||
|
||||
const bool shadowmap = IsShadowsEnabled() && light.IsCastingShadow() && !light.IsStatic();
|
||||
const wi::rectpacker::Rect& shadow_rect = vis.visibleLightShadowRects[lightIndex];
|
||||
|
||||
@@ -4424,9 +4421,10 @@ void UpdatePerFrameData(
|
||||
shaderentity.shadowAtlasMulAdd.y = shadow_rect.h * atlas_dim_rcp.y;
|
||||
shaderentity.shadowAtlasMulAdd.z = shadow_rect.x * atlas_dim_rcp.x;
|
||||
shaderentity.shadowAtlasMulAdd.w = shadow_rect.y * atlas_dim_rcp.y;
|
||||
shaderentity.SetIndices(matrixCounter, 0);
|
||||
}
|
||||
|
||||
shaderentity.SetIndices(matrixCounter, 0);
|
||||
|
||||
const uint cascade_count = std::min((uint)light.cascade_distances.size(), MATRIXARRAY_COUNT - matrixCounter);
|
||||
shaderentity.SetShadowCascadeCount(cascade_count);
|
||||
|
||||
@@ -4491,21 +4489,21 @@ void UpdatePerFrameData(
|
||||
shaderentity.SetDirection(light.direction);
|
||||
shaderentity.SetColor(float4(light.color.x * light.intensity, light.color.y * light.intensity, light.color.z * light.intensity, 1));
|
||||
|
||||
// mark as no shadow by default:
|
||||
shaderentity.indices = ~0;
|
||||
|
||||
const bool shadowmap = IsShadowsEnabled() && light.IsCastingShadow() && !light.IsStatic();
|
||||
const wi::rectpacker::Rect& shadow_rect = vis.visibleLightShadowRects[lightIndex];
|
||||
|
||||
const uint maskTex = light.maskTexDescriptor < 0 ? 0 : light.maskTexDescriptor;
|
||||
|
||||
if (shadowmap)
|
||||
{
|
||||
shaderentity.shadowAtlasMulAdd.x = shadow_rect.w * atlas_dim_rcp.x;
|
||||
shaderentity.shadowAtlasMulAdd.y = shadow_rect.h * atlas_dim_rcp.y;
|
||||
shaderentity.shadowAtlasMulAdd.z = shadow_rect.x * atlas_dim_rcp.x;
|
||||
shaderentity.shadowAtlasMulAdd.w = shadow_rect.y * atlas_dim_rcp.y;
|
||||
shaderentity.SetIndices(matrixCounter, 0);
|
||||
}
|
||||
|
||||
shaderentity.SetIndices(matrixCounter, maskTex);
|
||||
|
||||
const float outerConeAngle = light.outerConeAngle;
|
||||
const float innerConeAngle = std::min(light.innerConeAngle, outerConeAngle);
|
||||
const float outerConeAngleCos = std::cos(outerConeAngle);
|
||||
@@ -4519,7 +4517,7 @@ void UpdatePerFrameData(
|
||||
shaderentity.SetAngleScale(lightAngleScale);
|
||||
shaderentity.SetAngleOffset(lightAngleOffset);
|
||||
|
||||
if (shadowmap)
|
||||
if (shadowmap || (maskTex > 0))
|
||||
{
|
||||
SHCAM shcam;
|
||||
CreateSpotLightShadowCam(light, shcam);
|
||||
@@ -4577,21 +4575,21 @@ void UpdatePerFrameData(
|
||||
shaderentity.SetDirection(light.direction);
|
||||
shaderentity.SetColor(float4(light.color.x * light.intensity, light.color.y * light.intensity, light.color.z * light.intensity, 1));
|
||||
|
||||
// mark as no shadow by default:
|
||||
shaderentity.indices = ~0;
|
||||
|
||||
const bool shadowmap = IsShadowsEnabled() && light.IsCastingShadow() && !light.IsStatic();
|
||||
const wi::rectpacker::Rect& shadow_rect = vis.visibleLightShadowRects[lightIndex];
|
||||
|
||||
const uint maskTex = light.maskTexDescriptor < 0 ? 0 : light.maskTexDescriptor;
|
||||
|
||||
if (shadowmap)
|
||||
{
|
||||
shaderentity.shadowAtlasMulAdd.x = shadow_rect.w * atlas_dim_rcp.x;
|
||||
shaderentity.shadowAtlasMulAdd.y = shadow_rect.h * atlas_dim_rcp.y;
|
||||
shaderentity.shadowAtlasMulAdd.z = shadow_rect.x * atlas_dim_rcp.x;
|
||||
shaderentity.shadowAtlasMulAdd.w = shadow_rect.y * atlas_dim_rcp.y;
|
||||
shaderentity.SetIndices(matrixCounter, 0);
|
||||
}
|
||||
|
||||
shaderentity.SetIndices(matrixCounter, maskTex);
|
||||
|
||||
if (shadowmap)
|
||||
{
|
||||
const float FarZ = 0.1f; // watch out: reversed depth buffer! Also, light near plane is constant for simplicity, this should match on cpu side!
|
||||
@@ -4660,7 +4658,7 @@ void UpdatePerFrameData(
|
||||
shaderentity.SetType(ENTITY_TYPE_COLLIDER_PLANE);
|
||||
shaderentity.position = collider.plane.origin;
|
||||
shaderentity.SetDirection(collider.plane.normal);
|
||||
shaderentity.SetIndices(matrixCounter, ~0u);
|
||||
shaderentity.SetIndices(matrixCounter, 0);
|
||||
matrixArray[matrixCounter++] = collider.plane.projection;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -4836,6 +4836,21 @@ namespace wi::scene
|
||||
break;
|
||||
}
|
||||
|
||||
light.maskTexDescriptor = -1;
|
||||
|
||||
const MaterialComponent* material = materials.GetComponent(entity);
|
||||
if (material != nullptr && material->textures[MaterialComponent::BASECOLORMAP].resource.IsValid())
|
||||
{
|
||||
const Texture& tex = material->textures[MaterialComponent::BASECOLORMAP].resource.GetTexture();
|
||||
if (
|
||||
(light.type == LightComponent::SPOT && !has_flag(tex.desc.misc_flags, ResourceMiscFlag::TEXTURECUBE)) ||
|
||||
(light.type == LightComponent::POINT && has_flag(tex.desc.misc_flags, ResourceMiscFlag::TEXTURECUBE))
|
||||
)
|
||||
{
|
||||
light.maskTexDescriptor = GetDevice()->GetDescriptorIndex(&tex, SubresourceType::SRV, material->textures[MaterialComponent::BASECOLORMAP].resource.GetTextureSRGBSubresource());
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
void Scene::RunParticleUpdateSystem(wi::jobsystem::context& ctx)
|
||||
|
||||
@@ -1220,6 +1220,7 @@ namespace wi::scene
|
||||
mutable int occlusionquery = -1;
|
||||
XMFLOAT4 rotation = XMFLOAT4(0, 0, 0, 1);
|
||||
XMFLOAT3 scale = XMFLOAT3(1, 1, 1);
|
||||
int maskTexDescriptor = -1;
|
||||
|
||||
wi::vector<wi::Resource> lensFlareRimTextures;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wi::version
|
||||
// minor features, major updates, breaking compatibility changes
|
||||
const int minor = 71;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 724;
|
||||
const int revision = 725;
|
||||
|
||||
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user