Skip to content

Commit 779143b

Browse files
Hdrp/decal transparent mip selection 1222437 (#96)
* Improve MIP selection for decals to transparent * Add change logs * Communize Helper (ComputeTextureLOD{Bias?}(...) * Update * Rename * Comment * fix white space and 0.f Co-authored-by: Sebastien Lagarde <sebastien@unity3d.com>
1 parent f553011 commit 779143b

5 files changed

Lines changed: 46 additions & 42 deletions

File tree

Lines changed: 2 additions & 2 deletions
Loading

TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/None/1705_Decals-stress-test.png.meta

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -686,36 +686,37 @@ TEMPLATE_3_FLT(RangeRemap, min, max, t, return saturate((t - min) / (max - min))
686686
// Texture utilities
687687
// ----------------------------------------------------------------------------
688688

689-
float ComputeTextureLOD(float2 uvdx, float2 uvdy, float2 scale)
689+
float ComputeTextureLOD(float2 uvdx, float2 uvdy, float2 scale, float bias = 0.0)
690690
{
691691
float2 ddx_ = scale * uvdx;
692692
float2 ddy_ = scale * uvdy;
693-
float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
693+
float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
694694

695-
return max(0.5 * log2(d), 0.0);
695+
return max(0.5 * log2(d) - bias, 0.0);
696696
}
697697

698-
float ComputeTextureLOD(float2 uv)
698+
float ComputeTextureLOD(float2 uv, float bias = 0.0)
699699
{
700700
float2 ddx_ = ddx(uv);
701701
float2 ddy_ = ddy(uv);
702702

703-
return ComputeTextureLOD(ddx_, ddy_, 1.0);
703+
return ComputeTextureLOD(ddx_, ddy_, 1.0, bias);
704704
}
705705

706706
// x contains width, w contains height
707-
float ComputeTextureLOD(float2 uv, float2 texelSize)
707+
float ComputeTextureLOD(float2 uv, float2 texelSize, float bias = 0.0)
708708
{
709709
uv *= texelSize;
710710

711-
return ComputeTextureLOD(uv);
711+
return ComputeTextureLOD(uv, bias);
712712
}
713713

714714
// LOD clamp is optional and happens outside the function.
715-
float ComputeTextureLOD(float3 duvw_dx, float3 duvw_dy, float3 duvw_dz, float scale)
715+
float ComputeTextureLOD(float3 duvw_dx, float3 duvw_dy, float3 duvw_dz, float scale, float bias = 0.0)
716716
{
717717
float d = Max3(dot(duvw_dx, duvw_dx), dot(duvw_dy, duvw_dy), dot(duvw_dz, duvw_dz));
718-
return 0.5 * log2(d * (scale * scale));
718+
719+
return max(0.5f * log2(d * (scale * scale)) - bias, 0.0);
719720
}
720721

721722

com.unity.render-pipelines.high-definition/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
552552
- Diffusion Profile and Material references in HDRP materials are now correctly exported to unity packages. Note that the diffusion profile or the material references need to be edited once before this can work properly.
553553

554554
### Changed
555+
- Improve MIP selection for decals on Transparents
555556
- Color buffer pyramid is not allocated anymore if neither refraction nor distortion are enabled
556557
- Rename Emission Radius to Radius in UI in Point, Spot
557558
- Angular Diameter parameter for directional light is no longuer an advanced property

com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ DECLARE_DBUFFER_TEXTURE(_DBufferTexture);
1111
void ApplyBlendNormal(inout float4 dst, inout uint matMask, float2 texCoords, uint mapMask, float3x3 decalToWorld, float blend, float lod)
1212
{
1313
float4 src;
14-
src.xyz = mul(decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, _trilinear_clamp_sampler_DecalAtlas2D, texCoords, lod))) * 0.5f + 0.5f;
14+
src.xyz = mul(decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, _trilinear_clamp_sampler_DecalAtlas2D, texCoords, lod))) * 0.5 + 0.5;
1515
src.w = blend;
16-
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);
17-
dst.w = dst.w * (1.0f - src.w);
16+
dst.xyz = src.xyz * src.w + dst.xyz * (1.0 - src.w);
17+
dst.w = dst.w * (1.0 - src.w);
1818
matMask |= mapMask;
1919
}
2020

@@ -26,8 +26,8 @@ void ApplyBlendDiffuse(inout float4 dst, inout uint matMask, float2 texCoords, f
2626
}
2727
src.w *= blend;
2828
blend = src.w; // diffuse texture alpha affects all other channels
29-
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);
30-
dst.w = dst.w * (1.0f - src.w);
29+
dst.xyz = src.xyz * src.w + dst.xyz * (1.0 - src.w);
30+
dst.w = dst.w * (1.0 - src.w);
3131
matMask |= mapMask;
3232
}
3333

@@ -45,12 +45,12 @@ void ApplyBlendMask(inout float4 dbuffer2, inout float2 dbuffer3, inout uint mat
4545
src.z = scalingMAB.z * src.z;
4646
src.w = lerp(remappingAOS.z, remappingAOS.w, src.w);
4747
float maskBlend;
48-
if (blendParams.x == 1.0f) // normal blend source is mask blue channel
48+
if (blendParams.x == 1.0) // normal blend source is mask blue channel
4949
normalBlend = src.z * decalBlend;
5050
else
51-
normalBlend = albedoBlend; // normal blend source is albedo alpha
51+
normalBlend = albedoBlend; // normal blend source is albedo alpha
5252

53-
if (blendParams.y == 1.0f) // mask blend source is mask blue channel
53+
if (blendParams.y == 1.0) // mask blend source is mask blue channel
5454
maskBlend = src.z * decalBlend;
5555
else
5656
maskBlend = albedoBlend; // mask blend siurce is albedo alpha
@@ -102,31 +102,32 @@ void ApplyBlendMask(inout float4 dbuffer2, inout float2 dbuffer3, inout uint mat
102102
dbuffer3Mask = float2(1, 1); // M alpha, AO alpha
103103
}
104104

105-
dbuffer2.xyz = (dbuffer2Mask.xyz == 1) ? src.xyz * src.w + dbuffer2.xyz * (1.0f - src.w) : dbuffer2.xyz;
106-
dbuffer2.w = (dbuffer2Mask.w == 1) ? dbuffer2.w * (1.0f - src.w) : dbuffer2.w;
105+
dbuffer2.xyz = (dbuffer2Mask.xyz == 1) ? src.xyz * src.w + dbuffer2.xyz * (1.0 - src.w) : dbuffer2.xyz;
106+
dbuffer2.w = (dbuffer2Mask.w == 1) ? dbuffer2.w * (1.0 - src.w) : dbuffer2.w;
107107

108-
dbuffer3.xy = (dbuffer3Mask.xy == 1) ? dbuffer3.xy * (1.0f - src.w) : dbuffer3.xy;
108+
dbuffer3.xy = (dbuffer3Mask.xy == 1) ? dbuffer3.xy * (1.0 - src.w) : dbuffer3.xy;
109109

110110
matMask |= mapMask;
111111
}
112112

113-
113+
// In order that the lod for with transpartent decal better match the lod for opaque decal
114+
// We use ComputeTextureLOD with bias == 0.5
114115
void EvalDecalMask(PositionInputs posInput, float3 positionRWSDdx, float3 positionRWSDdy, DecalData decalData,
115116
inout float4 DBuffer0, inout float4 DBuffer1, inout float4 DBuffer2, inout float2 DBuffer3, inout uint mask, inout float alpha)
116117
{
117118
// Get the relative world camera to decal matrix
118119
float4x4 worldToDecal = ApplyCameraTranslationToInverseMatrix(decalData.worldToDecal);
119120
float3 positionDS = mul(worldToDecal, float4(posInput.positionWS, 1.0)).xyz;
120-
positionDS = positionDS * float3(1.0, -1.0, 1.0) + float3(0.5, 0.5f, 0.5); // decal clip space
121-
if ((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f)))
121+
positionDS = positionDS * float3(1.0, -1.0, 1.0) + float3(0.5, 0.5, 0.5); // decal clip space
122+
if ((all(positionDS.xyz > 0.0) && all(1.0 - positionDS.xyz > 0.0)))
122123
{
123124
float2 uvScale = float2(decalData.normalToWorld[3][0], decalData.normalToWorld[3][1]);
124125
float2 uvBias = float2(decalData.normalToWorld[3][2], decalData.normalToWorld[3][3]);
125126
positionDS.xz = positionDS.xz * uvScale + uvBias;
126127
positionDS.xz = frac(positionDS.xz);
127128

128129
// clamp by half a texel to avoid sampling neighboring textures in the atlas
129-
float2 clampAmount = float2(0.5f / _DecalAtlasResolution.x, 0.5f / _DecalAtlasResolution.y);
130+
float2 clampAmount = float2(0.5 / _DecalAtlasResolution.x, 0.5 / _DecalAtlasResolution.y);
130131

131132
float2 diffuseMin = decalData.diffuseScaleBias.zw + clampAmount; // offset into atlas is in .zw
132133
float2 diffuseMax = decalData.diffuseScaleBias.zw + decalData.diffuseScaleBias.xy - clampAmount; // scale relative to full atlas size is in .xy so total texture extent in atlas is (1,1) * scale
@@ -147,15 +148,15 @@ void EvalDecalMask(PositionInputs posInput, float3 positionRWSDdx, float3 positi
147148

148149
float2 sampleDiffuseDdx = positionDSDdx.xz * decalData.diffuseScaleBias.xy; // factor in the atlas scale
149150
float2 sampleDiffuseDdy = positionDSDdy.xz * decalData.diffuseScaleBias.xy;
150-
float lodDiffuse = ComputeTextureLOD(sampleDiffuseDdx, sampleDiffuseDdy, _DecalAtlasResolution);
151+
float lodDiffuse = ComputeTextureLOD(sampleDiffuseDdx, sampleDiffuseDdy, _DecalAtlasResolution, 0.5);
151152

152-
float2 sampleNormalDdx = positionDSDdx.xz * decalData.normalScaleBias.xy;
153-
float2 sampleNormalDdy = positionDSDdy.xz * decalData.normalScaleBias.xy;
154-
float lodNormal = ComputeTextureLOD(sampleNormalDdx, sampleNormalDdy, _DecalAtlasResolution);
153+
float2 sampleNormalDdx = positionDSDdx.xz * decalData.normalScaleBias.xy;
154+
float2 sampleNormalDdy = positionDSDdy.xz * decalData.normalScaleBias.xy;
155+
float lodNormal = ComputeTextureLOD(sampleNormalDdx, sampleNormalDdy, _DecalAtlasResolution, 0.5);
155156

156-
float2 sampleMaskDdx = positionDSDdx.xz * decalData.maskScaleBias.xy;
157-
float2 sampleMaskDdy = positionDSDdy.xz * decalData.maskScaleBias.xy;
158-
float lodMask = ComputeTextureLOD(sampleMaskDdx, sampleMaskDdy, _DecalAtlasResolution);
157+
float2 sampleMaskDdx = positionDSDdx.xz * decalData.maskScaleBias.xy;
158+
float2 sampleMaskDdy = positionDSDdy.xz * decalData.maskScaleBias.xy;
159+
float lodMask = ComputeTextureLOD(sampleMaskDdx, sampleMaskDdy, _DecalAtlasResolution, 0.5);
159160

160161
float albedoBlend = decalData.normalToWorld[0][3];
161162
float4 src = decalData.baseColor;
@@ -165,9 +166,9 @@ void EvalDecalMask(PositionInputs posInput, float3 positionRWSDdx, float3 positi
165166
alpha = alpha < albedoBlend ? albedoBlend : alpha; // use decal alpha if it is higher than transparent alpha
166167

167168
float albedoContribution = decalData.normalToWorld[1][3];
168-
if (albedoContribution == 0.0f)
169+
if (albedoContribution == 0.0)
169170
{
170-
mask = 0; // diffuse will not get modified
171+
mask = 0; // diffuse will not get modified
171172
}
172173

173174
float normalBlend = albedoBlend;
@@ -208,13 +209,13 @@ DecalSurfaceData GetDecalSurfaceData(PositionInputs posInput, inout float alpha)
208209

209210
#if defined(_SURFACE_TYPE_TRANSPARENT) && defined(HAS_LIGHTLOOP) // forward transparent using clustered decals
210211
uint decalCount, decalStart;
211-
DBuffer0 = float4(0.0f, 0.0f, 0.0f, 1.0f);
212-
DBuffer1 = float4(0.5f, 0.5f, 0.5f, 1.0f);
213-
DBuffer2 = float4(0.0f, 0.0f, 0.0f, 1.0f);
212+
DBuffer0 = float4(0.0, 0.0, 0.0, 1.0);
213+
DBuffer1 = float4(0.5, 0.5, 0.5, 1.0);
214+
DBuffer2 = float4(0.0, 0.0, 0.0, 1.0);
214215
#ifdef DECALS_4RT
215-
DBuffer3 = float2(1.0f, 1.0f);
216+
DBuffer3 = float2(1.0, 1.0);
216217
#else
217-
float2 DBuffer3 = float2(1.0f, 1.0f);
218+
float2 DBuffer3 = float2(1.0, 1.0);
218219
#endif
219220

220221
#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER

0 commit comments

Comments
 (0)