浏览代码

Merge pull request #508 from Unity-Technologies/Fix-blend-mode

Update blend mode
/Yibing-Project-2
GitHub 7 年前
当前提交
f86a150a
共有 9 个文件被更改,包括 62 次插入41 次删除
  1. 2
      SampleScenes/HDTest/SkyFogTest/Lit_Transparent_Add.mat
  2. 2
      SampleScenes/HDTest/SkyFogTest/Lit_Transparent_Add_NoFog.mat
  3. 2
      SampleScenes/HDTest/SkyFogTest/Lit_Transparent_Alpha.mat
  4. 12
      SampleScenes/HDTest/SkyFogTest/Lit_Transparent_Multiply.mat
  5. 2
      SampleScenes/HDTest/SkyFogTest/Lit_Transparent_PreMultipliedAlpha.mat
  6. 39
      ScriptableRenderPipeline/HDRenderPipeline/Material/Material.hlsl
  7. 16
      ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs
  8. 24
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl
  9. 4
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl

2
SampleScenes/HDTest/SkyFogTest/Lit_Transparent_Add.mat


- _ZTestMode: 8
- _ZWrite: 0
m_Colors:
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.741}
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.5019608}
- _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0}
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}

2
SampleScenes/HDTest/SkyFogTest/Lit_Transparent_Add_NoFog.mat


- _ZTestMode: 8
- _ZWrite: 0
m_Colors:
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.741}
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.5019608}
- _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0}
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}

2
SampleScenes/HDTest/SkyFogTest/Lit_Transparent_Alpha.mat


- _ZTestMode: 8
- _ZWrite: 0
m_Colors:
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.741}
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.5019608}
- _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0}
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}

12
SampleScenes/HDTest/SkyFogTest/Lit_Transparent_Multiply.mat


m_PrefabInternal: {fileID: 0}
m_Name: Lit_Transparent_Multiply
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _BLENDMODE_MULTIPLY _BLENDMODE_PRESERVE_SPECULAR_LIGHTING _ENABLE_FOG_ON_TRANSPARENT
_NORMALMAP_TANGENT_SPACE _SURFACE_TYPE_TRANSPARENT
m_ShaderKeywords: _BLENDMODE_PRESERVE_SPECULAR_LIGHTING _BLENDMODE_PRE_MULTIPLY
_ENABLE_FOG_ON_TRANSPARENT _NORMALMAP_TANGENT_SPACE _SURFACE_TYPE_TRANSPARENT
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

- _AlphaCutoff: 0.5
- _AlphaCutoffEnable: 0
- _Anisotropy: 0
- _BlendMode: 3
- _BlendMode: 4
- _CoatCoverage: 1
- _CoatIOR: 0.5
- _CullMode: 2

- _DoubleSidedEnable: 0
- _DoubleSidedNormalMode: 1
- _Drag: 1
- _DstBlend: 0
- _DstBlend: 10
- _EmissiveColorMode: 1
- _EmissiveIntensity: 0
- _EnableBlendModeAccurateLighting: 1

- _Smoothness: 1
- _SmoothnessRemapMax: 1
- _SmoothnessRemapMin: 0
- _SrcBlend: 2
- _SrcBlend: 1
- _StencilRef: 2
- _Stiffness: 1
- _SubsurfaceProfile: 0

- _ZTestMode: 8
- _ZWrite: 0
m_Colors:
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.741}
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.5019608}
- _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0}
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}

2
SampleScenes/HDTest/SkyFogTest/Lit_Transparent_PreMultipliedAlpha.mat


- _ZTestMode: 8
- _ZWrite: 0
m_Colors:
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.741}
- _BaseColor: {r: 1, g: 0, b: 0, a: 0.5019608}
- _DoubleSidedConstants: {r: 1, g: 1, b: -1, a: 0}
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}

39
ScriptableRenderPipeline/HDRenderPipeline/Material/Material.hlsl


// - _ENABLE_FOG_ON_TRANSPARENT if fog is enable on transparent surface
//-----------------------------------------------------------------------------
// ApplyBlendMode function
//-----------------------------------------------------------------------------
float4 ApplyBlendMode(float3 diffuseLighting, float3 specularLighting, float opacity)
{
// ref: http://advances.realtimerendering.com/other/2016/naughty_dog/NaughtyDog_TechArt_Final.pdf
// Lit transparent object should have reflection and tramission.
// Transmission when not using "rough refraction mode" (with fetch in preblured background) is handled with blend mode.
// However reflection should not be affected by blend mode. For example a glass should still display reflection and not lose the highlight when blend
// This is the purpose of following function, "Cancel" the blend mode effect on the specular lighting but not on the diffuse lighting
#ifdef _BLENDMODE_PRESERVE_SPECULAR_LIGHTING
// In the case of _BLENDMODE_ALPHA the code should be float4(diffuseLighting + (specularLighting / max(opacity, 0.01)), opacity)
// However this have precision issue when reaching 0, so we change the blend mode and apply src * src_a inside the shader instead
#if defined(_BLENDMODE_ADD) || defined(_BLENDMODE_ALPHA)
return float4(diffuseLighting * opacity + specularLighting, opacity);
#else // defined(_BLENDMODE_MULTIPLY) || defined(_BLENDMODE_PRE_MULTIPLY)
return float4(diffuseLighting + specularLighting, opacity);
#endif
#else
#if defined(_BLENDMODE_ADD) || defined(_BLENDMODE_ALPHA)
return float4((diffuseLighting + specularLighting) * opacity, opacity);
#else // defined(_BLENDMODE_MULTIPLY) || defined(_BLENDMODE_PRE_MULTIPLY)
return float4(diffuseLighting + specularLighting, opacity);
#endif
#endif
}
float4 ApplyBlendMode(float3 color, float opacity)
{
return ApplyBlendMode(color, float3(0.0, 0.0, 0.0), opacity);
}
//-----------------------------------------------------------------------------
// This must be call after ApplyBlendMode to work correctly
float4 EvaluateAtmosphericScattering(PositionInputs posInput, float4 inputColor)
{
float4 result = inputColor;

#if defined(_BLENDMODE_ALPHA)
// Regular alpha blend only need a lerp to work
result.rgb = lerp(result.rgb, fog.rgb, fog.a);
// Regular alpha blend need to multiply fog color by opacity (as we do src * src_a inside the shader)
result.rgb = lerp(result.rgb, fog.rgb * result.a, fog.a);
#elif defined(_BLENDMODE_ADD)
// For additive, we just need to fade to black with fog density (black + background == background color == fog color)
result.rgb = result.rgb * (1.0 - fog.a);

// For Pre-Multiplied Alpha Blend, we need to multiply fog color by src alpha to match regular alpha blending formula.
result.rgb = lerp(result.rgb, fog.rgb * result.a, fog.a);
#endif
#else
// Evaluation of fog for opaque objects is currently done in a full screen pass independent from any material parameters.
// but this funtction is called in generic forward shader code so we need it to be neutral in this case.

16
ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs


public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
public static readonly int[] blendModeValues = Enum.GetValues(typeof(BlendMode)) as int[];
public static GUIContent alphaCutoffEnableText = new GUIContent("Alpha Cutoff Enable", "Threshold for alpha cutoff");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");

var mode = (BlendMode)blendMode.floatValue;
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(StylesBaseUnlit.blendModeText, (int)mode, StylesBaseUnlit.blendModeNames);
mode = (BlendMode)EditorGUILayout.IntPopup(StylesBaseUnlit.blendModeText, (int)mode, StylesBaseUnlit.blendModeNames, StylesBaseUnlit.blendModeValues);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Blend Mode");

switch (blendMode)
{
// Alpha
// color: src * src_a + dst * (1 - src_a)
// src * src_a is done in the shader as it allow to reduce precision issue when using _BLENDMODE_PRESERVE_SPECULAR_LIGHTING (See Material.hlsl)
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
// Additive
// color: src * src_a + dst
// src * src_a is done in the shader
// Multiplicative
// color: src * dst
// PremultipliedAlpha
// color: src * src_a + dst * (1 - src_a)
// src is supposed to have been multiplied by alpha in the texture on artists side.
case BlendMode.PremultipliedAlpha:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);

24
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl


#endif // TESSELLATION_ON
float4 ApplyBlendMode(float3 diffuseLighting, float3 specularLighting, float opacity)
{
// ref: http://advances.realtimerendering.com/other/2016/naughty_dog/NaughtyDog_TechArt_Final.pdf
// Lit transparent object should have reflection and tramission.
// Transmission when not using "rough refraction mode" (with fetch in preblured background) is handled with blend mode.
// However reflection should not be affected by blend mode. For example a glass should still display reflection and not lose the highlight when blend
// This is the purpose of following function, "Cancel" the blend mode effect on the specular lighting but not on the diffuse lighting
#ifdef _BLENDMODE_PRESERVE_SPECULAR_LIGHTING
#ifdef _BLENDMODE_ALPHA
return float4(diffuseLighting + (specularLighting / max(opacity, 0.01)), opacity);
#elif defined(_BLENDMODE_ADD) || defined(_BLENDMODE_PRE_MULTIPLY)
return float4(diffuseLighting * opacity + specularLighting, opacity);
#else
return float4(diffuseLighting + specularLighting, opacity);
#endif
#else
return float4(diffuseLighting + specularLighting, opacity);
#endif
}
void Frag(PackedVaryingsToPS packedInput,
out float4 outColor : SV_Target0
#ifdef _DEPTHOFFSET_ON

4
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl


#if SHADERPASS != SHADERPASS_FORWARD_UNLIT
#if SHADERPASS != SHADERPASS_FORWARD_UNLIT
#error SHADERPASS_is_not_correctly_define
#endif

BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData);
// TODO: we must not access bsdfData here, it break the genericity of the code!
float4 outColor = float4(bsdfData.color + builtinData.emissiveColor, builtinData.opacity);
float4 outColor = ApplyBlendMode(bsdfData.color + builtinData.emissiveColor, builtinData.opacity);
outColor = EvaluateAtmosphericScattering(posInput, outColor);
#ifdef DEBUG_DISPLAY

正在加载...
取消
保存