浏览代码

Merge upstream/master

/main
Evgenii Golubev 6 年前
当前提交
b4708ef6
共有 26 个文件被更改,包括 600 次插入167 次删除
  1. 33
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl
  2. 11
      ScriptableRenderPipeline/Core/CoreRP/Utilities/CoreUtils.cs
  3. 170
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs
  4. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/GlobalDecalSettings.cs
  5. 1
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/HDLightEditor.Styles.cs
  6. 42
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/HDLightEditor.cs
  7. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/GlobalDecalSettingsUI.cs
  8. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/SerializedGlobalDecalSettings.cs
  9. 30
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
  10. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  11. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDUtils.cs
  12. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Light/HDAdditionalLightData.cs
  13. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs
  14. 18
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.hlsl
  15. 14
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DBufferManager.cs
  16. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs
  17. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs.hlsl
  18. 3
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl
  19. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl
  20. 103
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl
  21. 48
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl
  22. 33
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/Blit.shader
  23. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl
  24. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/SkyRenderingContext.cs
  25. 195
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Texture2DAtlas.cs
  26. 11
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Texture2DAtlas.cs.meta

33
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl


return float4(uv * 2.0 - 1.0, z, 1.0);
}
// draw procedural with 2 triangles has index order (0,1,2) (0,2,3)
// 0 - 0,0
// 1 - 0,1
// 2 - 1,1
// 3 - 1,0
float2 GetQuadTexCoord(uint vertexID)
{
uint topBit = vertexID >> 1;
uint botBit = (vertexID & 1);
float u = topBit;
float v = (topBit + botBit) & 1; // produces 0 for indices 0,3 and 1 for 1,2
#if UNITY_UV_STARTS_AT_TOP
v = 1.0 - v;
#endif
return float2(u, v);
}
// 0 - 0,1
// 1 - 0,0
// 2 - 1,0
// 3 - 1,1
float4 GetQuadVertexPosition(uint vertexID, float z = UNITY_NEAR_CLIP_VALUE)
{
uint topBit = vertexID >> 1;
uint botBit = (vertexID & 1);
float x = topBit;
float y = 1 - (topBit + botBit) & 1; // produces 1 for indices 0,3 and 0 for 1,2
return float4(x, y, z, 1.0);
}
#if !defined(SHADER_API_GLES)
// LOD dithering transition helper

11
ScriptableRenderPipeline/Core/CoreRP/Utilities/CoreUtils.cs


return mesh;
}
public static void DisplayUnsupportedAPIMessage()
{
Debug.LogError("Platform " + SystemInfo.operatingSystem + " with device " + SystemInfo.graphicsDeviceType.ToString() + " is not supported, no rendering will occur");
#if UNITY_EDITOR
foreach (UnityEditor.SceneView sv in Resources.FindObjectsOfTypeAll(typeof(UnityEditor.SceneView)))
sv.ShowNotification(new GUIContent("Platform " + SystemInfo.operatingSystem + " with device " + SystemInfo.graphicsDeviceType.ToString() + " is not supported, no rendering will occur"));
#endif
}
// Returns 'true' if "Animated Materials" are enabled for the view associated with the given camera.
public static bool AreAnimatedMaterialsEnabled(Camera camera)
{

170
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/DecalSystem.cs


using System.Collections.Generic;
using System;
using System.Collections.Generic;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;

{
public const int kInvalidIndex = -1;
public const int kDecalAtlasSize = 128;
public class DecalHandle
{
public DecalHandle(int index, int materialID)

}
}
public TextureCache2D TextureAtlas
{
get
{
if (m_DecalAtlas == null)
{
m_DecalAtlas = new TextureCache2D("DecalAtlas");
m_DecalAtlas.AllocTextureArray(2048, kDecalAtlasSize, kDecalAtlasSize, TextureFormat.ARGB32, true);
}
return m_DecalAtlas;
}
}
public Camera CurrentCamera
{
get

static public float[] m_BoundingDistances = new float[1];
private Dictionary<int, DecalSet> m_DecalSets = new Dictionary<int, DecalSet>();
private TextureCache2D m_DecalAtlas = null;
// current camera
private Camera m_Camera;

private Texture2DAtlas m_Atlas = null;
public bool m_AllocationSuccess = true;
public Texture2DAtlas Atlas
{
get
{
if (m_Atlas == null)
{
m_Atlas = new Texture2DAtlas(HDUtils.hdrpSettings.decalSettings.atlasWidth, HDUtils.hdrpSettings.decalSettings.atlasHeight, RenderTextureFormat.ARGB32);
}
return m_Atlas;
}
}
public class TextureScaleBias : IComparable
{
public Texture m_Texture = null;
public Vector4 m_ScaleBias = Vector4.zero;
public int CompareTo(object obj)
{
TextureScaleBias other = obj as TextureScaleBias;
int size = m_Texture.width * m_Texture.height;
int otherSize = other.m_Texture.width * other.m_Texture.height;
if(size > otherSize)
{
return -1;
}
else if( size < otherSize)
{
return 1;
}
else
{
return 0;
}
}
}
private List<TextureScaleBias> m_TextureList = new List<TextureScaleBias>();
private void InitializeMaterialValues()
public void InitializeMaterialValues()
m_DiffuseTexture = m_Material.GetTexture("_BaseColorMap");
m_NormalTexture = m_Material.GetTexture("_NormalMap");
m_MaskTexture = m_Material.GetTexture("_MaskMap");
m_Diffuse.m_Texture = m_Material.GetTexture("_BaseColorMap");
m_Normal.m_Texture = m_Material.GetTexture("_NormalMap");
m_Mask.m_Texture = m_Material.GetTexture("_MaskMap");
m_Blend = m_Material.GetFloat("_DecalBlend");
}

return m_NumResults;
}
private void GetDecalVolumeDataAndBound(Matrix4x4 decalToWorld, Matrix4x4 worldToView)
{
var influenceX = decalToWorld.GetColumn(0) * 0.5f;

normalToWorldBatch[instanceCount] = m_CachedNormalToWorld[decalIndex];
float fadeFactor = Mathf.Clamp((cullDistance - distanceToDecal) / (cullDistance * (1.0f - m_CachedDrawDistances[decalIndex].y)), 0.0f, 1.0f);
normalToWorldBatch[instanceCount].m03 = fadeFactor * m_Blend; // vector3 rotation matrix so bottom row and last column can be used for other data to save space
normalToWorldBatch[instanceCount].m13 = m_DiffuseTexIndex; // texture atlas indices needed for clustered
normalToWorldBatch[instanceCount].m23 = m_NormalTexIndex;
normalToWorldBatch[instanceCount].m33 = m_MaskTexIndex;
m_DecalDatas[m_DecalDatasCount].diffuseScaleBias = m_Diffuse.m_ScaleBias;
m_DecalDatas[m_DecalDatasCount].normalScaleBias = m_Normal.m_ScaleBias;
m_DecalDatas[m_DecalDatasCount].maskScaleBias = m_Mask.m_ScaleBias;
GetDecalVolumeDataAndBound(decalToWorldBatch[instanceCount], worldToView);
m_DecalDatasCount++;

}
}
void UpdateTextureCache(CommandBuffer cmd)
{
m_DiffuseTexIndex = (m_DiffuseTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_DiffuseTexture) : -1;
m_NormalTexIndex = (m_NormalTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_NormalTexture) : -1;
m_MaskTexIndex = (m_MaskTexture != null) ? instance.TextureAtlas.FetchSlice(cmd, m_MaskTexture) : -1;
}
public void RemoveFromTextureCache()
public void AddToTextureList(ref List<TextureScaleBias> textureList)
if (m_DiffuseTexture != null)
if(m_Diffuse.m_Texture != null)
instance.TextureAtlas.RemoveEntryFromSlice(m_DiffuseTexture);
textureList.Add(m_Diffuse);
if (m_NormalTexture != null)
if (m_Normal.m_Texture != null)
instance.TextureAtlas.RemoveEntryFromSlice(m_NormalTexture);
textureList.Add(m_Normal);
if (m_MaskTexture != null)
if (m_Mask.m_Texture != null)
instance.TextureAtlas.RemoveEntryFromSlice(m_MaskTexture);
textureList.Add(m_Mask);
public void UpdateCachedMaterialData(CommandBuffer cmd)
{
InitializeMaterialValues(); // refresh in case they changed in the UI
UpdateTextureCache(cmd);
}
public void RenderIntoDBuffer(CommandBuffer cmd)
{

private Matrix4x4[] m_CachedNormalToWorld = new Matrix4x4[kDecalBlockSize];
private Vector2[] m_CachedDrawDistances = new Vector2[kDecalBlockSize]; // x - draw distance, y - fade scale
private Material m_Material;
private Texture m_DiffuseTexture = null;
private Texture m_NormalTexture = null;
private Texture m_MaskTexture = null;
private int m_DiffuseTexIndex = -1;
private int m_NormalTexIndex = -1;
private int m_MaskTexIndex = -1;
TextureScaleBias m_Diffuse = new TextureScaleBias();
TextureScaleBias m_Normal = new TextureScaleBias();
TextureScaleBias m_Mask = new TextureScaleBias();
}
public DecalHandle AddDecal(Transform transform, float drawDistance, float fadeScale, Material material)

decalSet.RemoveDecal(handle);
if (decalSet.Count == 0)
{
decalSet.RemoveFromTextureCache();
m_DecalSets.Remove(key);
}
}

public void SetAtlas(CommandBuffer cmd)
{
cmd.SetGlobalTexture(HDShaderIDs._DecalAtlasID, TextureAtlas.GetTexCache());
cmd.SetGlobalTexture(HDShaderIDs._DecalAtlas2DID, Atlas.AtlasTexture);
}
public void AddTexture(CommandBuffer cmd, TextureScaleBias textureScaleBias)
{
if (textureScaleBias.m_Texture != null)
{
if (!Atlas.AddTexture(cmd, ref textureScaleBias.m_ScaleBias,textureScaleBias.m_Texture))
{
m_AllocationSuccess = false;
}
}
else
{
textureScaleBias.m_ScaleBias = Vector4.zero;
}
public void UpdateCachedMaterialData(CommandBuffer cmd)
public void UpdateCachedMaterialData()
//instance.m_AllocationSuccess = true;
m_TextureList.Clear();
pair.Value.UpdateCachedMaterialData(cmd);
pair.Value.InitializeMaterialValues();
pair.Value.AddToTextureList(ref m_TextureList);
}
}
public void UpdateTextureAtlas(CommandBuffer cmd)
{
m_AllocationSuccess = true;
foreach (TextureScaleBias textureScaleBias in m_TextureList)
{
AddTexture(cmd, textureScaleBias);
}
if (!m_AllocationSuccess) // texture failed to find space in the atlas
{
m_TextureList.Sort(); // sort the texture list largest to smallest for better packing
Atlas.ResetAllocator(); // clear all allocations
// try again
m_AllocationSuccess = true;
foreach (TextureScaleBias textureScaleBias in m_TextureList)
{
AddTexture(cmd, textureScaleBias);
}
if(!m_AllocationSuccess) // still failed to allocate, decal atlas size needs to increase
{
Debug.LogWarning("Decal texture atlas out of space, decals on transparent geometry might not render correctly, atlas size can be changed in HDRenderPipelineAsset");
}
}
}

public void Cleanup()
{
if (m_DecalAtlas != null)
m_DecalAtlas.Release();
if (m_Atlas != null)
m_Atlas.Release();
m_DecalAtlas = null;
m_Atlas = null;
}
}
}

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Decal/GlobalDecalSettings.cs


public class GlobalDecalSettings
{
public int drawDistance = 1000;
public int atlasSize = 8192;
public int atlasWidth = 4096;
public int atlasHeight = 4096;
}
}

1
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/HDLightEditor.Styles.cs


public readonly GUIContent shape = new GUIContent("Type", "Specifies the current type of light. Possible types are Directional, Spot, Point, Rectangle and Line lights.");
public readonly GUIContent[] shapeNames;
public readonly GUIContent enableSpotReflector = new GUIContent("Enable spot reflector", "When true it simulate a spot light with reflector (mean the intensity of the light will be more focus with narrower angle), otherwise light outside of the cone is simply absorbed (mean intensity is constent whatever the size of the cone).");
// Additional shadow data
public readonly GUIContent shadowResolution = new GUIContent("Resolution", "Controls the rendered resolution of the shadow maps. A higher resolution will increase the fidelity of shadows at the cost of GPU performance and memory usage.");

42
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Lighting/HDLightEditor.cs


public SerializedProperty affectSpecular;
public SerializedProperty lightTypeExtent;
public SerializedProperty spotLightShape;
public SerializedProperty enableSpotReflector;
public SerializedProperty shapeWidth;
public SerializedProperty shapeHeight;
public SerializedProperty aspectRatio;

affectSpecular = o.Find(x => x.affectSpecular),
lightTypeExtent = o.Find(x => x.lightTypeExtent),
spotLightShape = o.Find(x => x.spotLightShape),
enableSpotReflector = o.Find(x => x.enableSpotReflector),
shapeWidth = o.Find(x => x.shapeWidth),
shapeHeight = o.Find(x => x.shapeHeight),
aspectRatio = o.Find(x => x.aspectRatio),

if (spotLightShape == SpotLightShape.Cone)
{
settings.DrawSpotAngle();
EditorGUILayout.PropertyField(m_AdditionalLightData.enableSpotReflector, s_Styles.enableSpotReflector);
EditorGUILayout.Slider(m_AdditionalLightData.spotInnerPercent, 0f, 100f, s_Styles.spotInnerPercent);
}
// TODO : replace with angle and ratio

EditorGUILayout.PropertyField(m_AdditionalLightData.enableSpotReflector, s_Styles.enableSpotReflector);
EditorGUILayout.Slider(m_AdditionalLightData.aspectRatio, 0.05f, 20.0f, s_Styles.aspectRatioPyramid);
}
else if (spotLightShape == SpotLightShape.Box)

case LightShape.Spot:
// Spot should used conversion which take into account the angle, and thus the intensity vary with angle.
// This is not easy to manipulate for lighter, so we simply consider any spot light as just occluded point light. So reuse the same code.
settings.intensity.floatValue = LightUtils.ConvertPointLightIntensity(m_AdditionalLightData.punctualIntensity.floatValue);
// TODO: What to do with box shape ?
// var spotLightShape = (SpotLightShape)m_AdditionalLightData.spotLightShape.enumValueIndex;
var spotLightShape = (SpotLightShape)m_AdditionalLightData.spotLightShape.enumValueIndex;
if (m_AdditionalLightData.enableSpotReflector.boolValue)
{
if (spotLightShape == SpotLightShape.Cone)
{
settings.intensity.floatValue = LightUtils.ConvertSpotLightIntensity(m_AdditionalLightData.punctualIntensity.floatValue, settings.spotAngle.floatValue * Mathf.Deg2Rad, true );
}
else if (spotLightShape == SpotLightShape.Pyramid)
{
var aspectRatio = m_AdditionalLightData.aspectRatio.floatValue;
// Since the smallest angles is = to the fov, and we don't care of the angle order, simply make sure the aspect ratio is > 1
if ( aspectRatio < 1f ) aspectRatio = 1f/aspectRatio;
var angleA = settings.spotAngle.floatValue * Mathf.Deg2Rad;
var halfAngle = angleA * 0.5f; // half of the smallest angle
var length = Mathf.Tan(halfAngle); // half length of the smallest side of the rectangle
length *= aspectRatio; // half length of the bigest side of the rectangle
halfAngle = Mathf.Atan(length); // half of the bigest angle
var angleB = halfAngle * 2f;
settings.intensity.floatValue = LightUtils.ConvertFrustrumLightIntensity(m_AdditionalLightData.punctualIntensity.floatValue, angleA, angleB );
}
else // Box shape, fallback to punctual light.
{
settings.intensity.floatValue = LightUtils.ConvertPointLightIntensity(m_AdditionalLightData.punctualIntensity.floatValue);
}
}
else // Reflector disabled, fallback to punctual light.
{
settings.intensity.floatValue = LightUtils.ConvertPointLightIntensity(m_AdditionalLightData.punctualIntensity.floatValue);
}
break;
case LightShape.Rectangle:

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/GlobalDecalSettingsUI.cs


EditorGUILayout.LabelField(_.GetContent("Decals"), EditorStyles.boldLabel);
++EditorGUI.indentLevel;
EditorGUILayout.PropertyField(d.drawDistance, _.GetContent("Draw Distance"));
EditorGUILayout.PropertyField(d.atlasSize, _.GetContent("Atlas Size"));
EditorGUILayout.PropertyField(d.atlasWidth, _.GetContent("Atlas Width"));
EditorGUILayout.PropertyField(d.atlasHeight, _.GetContent("Atlas Height"));
--EditorGUI.indentLevel;
}
}

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/RenderLoopSettings/SerializedGlobalDecalSettings.cs


public SerializedProperty root;
public SerializedProperty drawDistance;
public SerializedProperty atlasSize;
public SerializedProperty atlasWidth;
public SerializedProperty atlasHeight;
public SerializedGlobalDecalSettings(SerializedProperty root)
{

atlasSize = root.Find((GlobalDecalSettings s) => s.atlasSize);
atlasWidth = root.Find((GlobalDecalSettings s) => s.atlasWidth);
atlasHeight = root.Find((GlobalDecalSettings s) => s.atlasHeight);
}
}
}

30
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs


m_ValidAPI = false;
return ;
}
}
m_Asset = asset;
m_GPUCopy = new GPUCopy(asset.renderPipelineResources.copyChannelCS);

RTHandle.Release(m_DebugColorPickerBuffer);
RTHandle.Release(m_DebugFullScreenTempBuffer);
m_DebugScreenSpaceTracingData.Release();
}

if (!IsSupportedPlatform())
{
Debug.LogError("Platform " + SystemInfo.operatingSystem + " with device " + SystemInfo.graphicsDeviceType.ToString() + " is not supported, no rendering will occur");
#if UNITY_EDITOR
foreach (UnityEditor.SceneView sv in Resources.FindObjectsOfTypeAll(typeof(UnityEditor.SceneView)))
sv.ShowNotification(new GUIContent("Platform " + SystemInfo.operatingSystem + " with device " + SystemInfo.graphicsDeviceType.ToString() + " is not supported, no rendering will occur"));
#endif
CoreUtils.DisplayUnsupportedAPIMessage();
return false;
}

{
DecalSystem.instance.EndCull();
m_DbufferManager.vsibleDecalCount = DecalSystem.m_DecalsVisibleThisFrame;
DecalSystem.instance.UpdateCachedMaterialData(cmd); // textures, alpha or fade distances could've changed
DecalSystem.instance.CreateDrawData(); // prepare data is separate from draw
DecalSystem.instance.UpdateCachedMaterialData(); // textures, alpha or fade distances could've changed
DecalSystem.instance.UpdateTextureAtlas(cmd); // as this is only used for transparent pass, would've been nice not to have to do this if no transparent renderers are visible
DecalSystem.instance.CreateDrawData(); // prepare data is separate from draw
}
}
renderContext.SetupCameraProperties(camera, m_FrameSettings.enableStereo);

// Depth texture is now ready, bind it.
cmd.SetGlobalTexture(HDShaderIDs._MainDepthTexture, GetDepthTexture());
// for alpha compositing, color is cleared to 0, alpha to 1
// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html
Color clearColor = new Color(0.0f, 0.0f, 0.0f, 1.0f);
HDUtils.SetRenderTarget(cmd, camera, m_DbufferManager.GetBuffersRTI(), m_CameraDepthStencilBuffer, ClearFlag.Color, clearColor);
// we need to do a separate clear for normals, because they are cleared to a different color
Color clearColorNormal = new Color(0.5f, 0.5f, 0.5f, 1.0f); // for normals 0.5 is neutral
m_DbufferManager.ClearNormalTargetAndHTile(cmd, camera, clearColorNormal);
m_DbufferManager.ClearTargets(cmd, camera);
HDUtils.SetRenderTarget(cmd, camera, m_DbufferManager.GetBuffersRTI(), m_CameraDepthStencilBuffer); // do not clear anymore
m_DbufferManager.SetHTile(m_DbufferManager.bufferCount, cmd);
DecalSystem.instance.RenderIntoDBuffer(cmd);

}
HDUtils.SetRenderTarget(cmd, hdCamera, m_CameraColorBuffer, m_CameraDepthStencilBuffer);
if (m_FrameSettings.enableDBuffer) // enable d-buffer flag value is being interpreted more like enable decals in general now that we have clustered
if ((m_FrameSettings.enableDBuffer) && (DecalSystem.m_DecalsVisibleThisFrame > 0)) // enable d-buffer flag value is being interpreted more like enable decals in general now that we have clustered
{
DecalSystem.instance.SetAtlas(cmd); // for clustered decals
}

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


// all decal properties
public static readonly int _NormalToWorldID = Shader.PropertyToID("_NormalToWorld");
public static readonly int _DecalAtlas2DID = Shader.PropertyToID("_DecalAtlas2D");
public static readonly int _DecalAtlasID = Shader.PropertyToID("_DecalAtlas");
public static readonly int _DecalHTileTexture = Shader.PropertyToID("_DecalHTileTexture");
public static readonly int _DecalIndexShift = Shader.PropertyToID("_DecalIndexShift");

public static readonly int _BlitTexture = Shader.PropertyToID("_BlitTexture");
public static readonly int _BlitScaleBias = Shader.PropertyToID("_BlitScaleBias");
public static readonly int _BlitMipLevel = Shader.PropertyToID("_BlitMipLevel");
public static readonly int _BlitScaleBiasRt = Shader.PropertyToID("_BlitScaleBiasRt");
public static readonly int _WorldScales = Shader.PropertyToID("_WorldScales");
public static readonly int _FilterKernels = Shader.PropertyToID("_FilterKernels");

9
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDUtils.cs


}
}
public static void BlitQuad(CommandBuffer cmd, Texture source, Vector4 scaleBiasTex, Vector4 scaleBiasRT, int mipLevelTex, bool bilinear)
{
s_PropertyBlock.SetTexture(HDShaderIDs._BlitTexture, source);
s_PropertyBlock.SetVector(HDShaderIDs._BlitScaleBias, scaleBiasTex);
s_PropertyBlock.SetVector(HDShaderIDs._BlitScaleBiasRt, scaleBiasRT);
s_PropertyBlock.SetFloat(HDShaderIDs._BlitMipLevel, mipLevelTex);
cmd.DrawProcedural(Matrix4x4.identity, GetBlitMaterial(), bilinear ? 2 : 3, MeshTopology.Quads, 4, 1, s_PropertyBlock);
}
public static void BlitTexture(CommandBuffer cmd, RTHandle source, RTHandle destination, Vector4 scaleBias, float mipLevel, bool bilinear)
{
s_PropertyBlock.SetTexture(HDShaderIDs._BlitTexture, source);

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Light/HDAdditionalLightData.cs


// Only for Spotlight, should be hide for other light
public SpotLightShape spotLightShape = SpotLightShape.Cone;
// Only for Spotlight, should be hide for other light
public bool enableSpotReflector = false;
// Only for Rectangle/Line/box projector lights
public float shapeWidth = 0.5f;

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.cs


public void RenderDeferredDirectionalShadow(HDCamera hdCamera, RTHandle deferredShadowRT, RenderTargetIdentifier depthTexture, CommandBuffer cmd)
{
if (m_CurrentSunLight == null || m_CurrentSunLight.GetComponent<AdditionalShadowData>() == null)
if (m_CurrentSunLight == null || m_CurrentSunLight.GetComponent<AdditionalShadowData>() == null || m_CurrentSunLightShadowIndex < 0)
{
cmd.SetGlobalTexture(HDShaderIDs._DeferredShadowTexture, RuntimeUtilities.blackTexture);
return;

18
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/LightLoop.hlsl


if (featureFlags & LIGHTFEATUREFLAGS_SSREFRACTION)
EVALUATE_BSDF_ENV(envLightData, REFRACTION, refraction);
}
// Only apply the sky IBL if the sky texture is available
if ((featureFlags & LIGHTFEATUREFLAGS_SKY) && _EnvLightSkyEnabled)
{
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
// The sky data are generated on the fly so the compiler can optimize the code
EnvLightData envLightSky = InitSkyEnvLightData(0);
EVALUATE_BSDF_ENV(envLightSky, REFLECTION, reflection);
if (featureFlags & LIGHTFEATUREFLAGS_SSREFRACTION)
EVALUATE_BSDF_ENV(envLightSky, REFRACTION, refraction);
}
}
// Following loop iterations

context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
// Note: In case of IBL we are sorted from smaller to bigger projected solid angle bounds. We are not sorted by type so we can't do a 'while' approach like for area light.
for (i = 0; i < envLightCount && reflectionHierarchyWeight < 1.0; ++i)
for (i = 1; i < envLightCount && reflectionHierarchyWeight < 1.0; ++i)
{
uint envLightIndex = FETCHINDEX(i);
EVALUATE_BSDF_ENV(_EnvLightDatas[envLightIndex], REFLECTION, reflection);

// We reuse LIGHTFEATUREFLAGS_SSREFRACTION flag as refraction is mainly base on the screen. Would be aa waste to not use screen and only cubemap.
if (featureFlags & LIGHTFEATUREFLAGS_SSREFRACTION)
{
for (i = 0; i < envLightCount && refractionHierarchyWeight < 1.0; ++i)
for (i = 1; i < envLightCount && refractionHierarchyWeight < 1.0; ++i)
{
uint envLightIndex = FETCHINDEX(i);
EVALUATE_BSDF_ENV(_EnvLightDatas[envLightIndex], REFRACTION, refraction);

14
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DBufferManager.cs


RTHandle.Release(m_HTile);
}
public void ClearNormalTargetAndHTile(CommandBuffer cmd, HDCamera camera, Color clearColor)
public void ClearTargets(CommandBuffer cmd, HDCamera camera)
// index 1 is normals
HDUtils.SetRenderTarget(cmd, camera, m_RTs[1], ClearFlag.Color, clearColor);
// for alpha compositing, color is cleared to 0, alpha to 1
// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html
Color clearColor = new Color(0.0f, 0.0f, 0.0f, 1.0f);
Color clearColorNormal = new Color(0.5f, 0.5f, 0.5f, 1.0f); // for normals 0.5 is neutral
HDUtils.SetRenderTarget(cmd, camera, m_RTs[0], ClearFlag.Color, clearColor);
HDUtils.SetRenderTarget(cmd, camera, m_RTs[1], ClearFlag.Color, clearColorNormal);
HDUtils.SetRenderTarget(cmd, camera, m_RTs[2], ClearFlag.Color, clearColor);
HDUtils.SetRenderTarget(cmd, camera, m_HTile, ClearFlag.Color, CoreUtils.clearColorAllBlack);
}

if (frameSettings.enableDBuffer)
{
cmd.SetGlobalInt(HDShaderIDs._EnableDBuffer, vsibleDecalCount > 0 ? 1 : 0);
cmd.SetGlobalVector(HDShaderIDs._DecalAtlasResolution, new Vector2(DecalSystem.kDecalAtlasSize, DecalSystem.kDecalAtlasSize));
cmd.SetGlobalVector(HDShaderIDs._DecalAtlasResolution, new Vector2(HDUtils.hdrpSettings.decalSettings.atlasWidth, HDUtils.hdrpSettings.decalSettings.atlasHeight));
BindBufferAsTextures(cmd);
}
else

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs


{
public Matrix4x4 worldToDecal;
public Matrix4x4 normalToWorld;
public Vector4 diffuseScaleBias;
public Vector4 normalScaleBias;
public Vector4 maskScaleBias;
};
}

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.cs.hlsl


{
float4x4 worldToDecal;
float4x4 normalToWorld;
float4 diffuseScaleBias;
float4 normalScaleBias;
float4 maskScaleBias;
};
//

3
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/Decal.hlsl


TEXTURE2D_ARRAY(_DecalAtlas);
SAMPLER(sampler_DecalAtlas);
TEXTURE2D(_DecalAtlas2D);
SAMPLER(_trilinear_clamp_sampler_DecalAtlas2D);
// Must be in sync with RT declared in HDRenderPipeline.cs ::Rebuild
void EncodeIntoDBuffer( DecalSurfaceData surfaceData,
out DBufferType0 outDBuffer0,

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalData.hlsl


#include "CoreRP/ShaderLibrary/Packing.hlsl"
#include "CoreRP/ShaderLibrary/Sampling/SampleUVMapping.hlsl"
void GetSurfaceData(float2 texCoordDS, float4x4 decalToWorld, out DecalSurfaceData surfaceData)
void GetSurfaceData(float2 texCoordDS, float4x4 normalToWorld, out DecalSurfaceData surfaceData)
float totalBlend = clamp(decalToWorld[0][3], 0.0f, 1.0f);
float totalBlend = clamp(normalToWorld[0][3], 0.0f, 1.0f);
totalBlend = surfaceData.baseColor.w; // base alpha affects aall other channels;
totalBlend = surfaceData.baseColor.w; // base alpha affects all other channels;
surfaceData.normalWS.xyz = mul((float3x3)decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, texCoordDS))) * 0.5f + 0.5f;
surfaceData.normalWS.xyz = mul((float3x3)normalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, texCoordDS))) * 0.5f + 0.5f;
surfaceData.normalWS.w = totalBlend;
surfaceData.HTileMask |= DBUFFERHTILEBIT_NORMAL;
#endif

103
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Decal/DecalUtilities.hlsl


// Caution: We can't compute LOD inside a dynamic loop. The gradient are not accessible.
// we need to find a way to calculate mips. For now just fetch first mip of the decals
void ApplyBlendNormal(inout float4 dst, inout int matMask, float2 texCoords, int sliceIndex, int mapMask, float3x3 decalToWorld, float blend, float lod)
void ApplyBlendNormal(inout float4 dst, inout int matMask, float2 texCoords, int mapMask, float3x3 decalToWorld, float blend, float lod)
src.xyz = mul(decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D_ARRAY_LOD(_DecalAtlas, sampler_DecalAtlas, texCoords, sliceIndex, lod))) * 0.5f + 0.5f;
src.xyz = mul(decalToWorld, UnpackNormalmapRGorAG(SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, _trilinear_clamp_sampler_DecalAtlas2D, texCoords, lod))) * 0.5f + 0.5f;
src.w = blend;
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);
dst.w = dst.w * (1.0f - src.w);

void ApplyBlendDiffuse(inout float4 dst, inout int matMask, float2 texCoords, int sliceIndex, int mapMask, inout float blend, float lod)
void ApplyBlendDiffuse(inout float4 dst, inout int matMask, float2 texCoords, int mapMask, inout float blend, float lod)
float4 src = SAMPLE_TEXTURE2D_ARRAY_LOD(_DecalAtlas, sampler_DecalAtlas, texCoords, sliceIndex, lod);
float4 src = SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, _trilinear_clamp_sampler_DecalAtlas2D, texCoords, lod);
src.w *= blend;
blend = src.w; // diffuse texture alpha affects all other channels
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);

void ApplyBlendMask(inout float4 dst, inout int matMask, float2 texCoords, int sliceIndex, int mapMask, float blend, float lod)
void ApplyBlendMask(inout float4 dst, inout int matMask, float2 texCoords, int mapMask, float blend, float lod)
float4 src = SAMPLE_TEXTURE2D_ARRAY_LOD(_DecalAtlas, sampler_DecalAtlas, texCoords, sliceIndex, lod);
float4 src = SAMPLE_TEXTURE2D_LOD(_DecalAtlas2D, _trilinear_clamp_sampler_DecalAtlas2D, texCoords, lod);
src.z = src.w;
src.w = blend;
dst.xyz = src.xyz * src.w + dst.xyz * (1.0f - src.w);

float ComputeTextureLOD(float2 uvdx, float2 uvdy, float2 scale)
{
float2 ddx_ = scale * uvdx;
float2 ddy_ = scale * uvdy;
float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
return max(0.5 * log2(d), 0.0);
}
void AddDecalContribution(PositionInputs posInput, inout SurfaceData surfaceData, inout float alpha)
{
if(_EnableDBuffer)

decalCount = _DecalCount;
decalStart = 0;
#endif
uint i = 0;
UNITY_LOOP
for (i = 0; i < decalCount; i++)
// get world space ddx/ddy for adjacent pixels to be used later in mipmap lod calculation
float3 positionWSDdx = ddx(positionWS);
float3 positionWSDdy = ddy(positionWS);
for (uint i = 0; i < decalCount; i++)
positionDS = positionDS * float3(1.0, -1.0, 1.0) + float3(0.5, 0.0f, 0.5);
float decalBlend = decalData.normalToWorld[0][3];
int diffuseIndex = decalData.normalToWorld[1][3];
int normalIndex = decalData.normalToWorld[2][3];
int maskIndex = decalData.normalToWorld[3][3];
float lod = ComputeTextureLOD(positionDS.xz, _DecalAtlasResolution);
decalBlend = ((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f))) ? decalBlend : 0; // use blend of 0 instead of an 'if' because compiler moves the lod calculation inside the 'if' which causes incorrect values
// if any of the pixels in the 2x2 quad gets rejected
positionDS = positionDS * float3(1.0, -1.0, 1.0) + float3(0.5, 0.0f, 0.5); // decal clip space
if ((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f)))
{
// clamp by half a texel to avoid sampling neighboring textures in the atlas
float2 clampAmount = float2(0.5f / _DecalAtlasResolution.x, 0.5f / _DecalAtlasResolution.y);
float2 diffuseMin = decalData.diffuseScaleBias.zw + clampAmount; // offset into atlas is in .zw
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
float2 normalMin = decalData.normalScaleBias.zw + clampAmount;
float2 normalMax = decalData.normalScaleBias.zw + decalData.normalScaleBias.xy - clampAmount;
float2 maskMin = decalData.maskScaleBias.zw + clampAmount;
float2 maskMax = decalData.maskScaleBias.zw + decalData.maskScaleBias.xy - clampAmount;
float2 sampleDiffuse = clamp(positionDS.xz * decalData.diffuseScaleBias.xy + decalData.diffuseScaleBias.zw, diffuseMin, diffuseMax);
float2 sampleNormal = clamp(positionDS.xz * decalData.normalScaleBias.xy + decalData.normalScaleBias.zw, normalMin, normalMax);
float2 sampleMask = clamp(positionDS.xz * decalData.maskScaleBias.xy + decalData.maskScaleBias.zw, maskMin, maskMax);
// need to compute the mipmap LOD manually because we are sampling inside a loop
float3 positionDSDdx = mul(decalData.worldToDecal, float4(positionWSDdx, 0.0)).xyz; // transform the derivatives to decal space, any translation is irrelevant
float3 positionDSDdy = mul(decalData.worldToDecal, float4(positionWSDdy, 0.0)).xyz;
float2 sampleDiffuseDdx = positionDSDdx.xz * decalData.diffuseScaleBias.xy; // factor in the atlas scale
float2 sampleDiffuseDdy = positionDSDdy.xz * decalData.diffuseScaleBias.xy;
float lodDiffuse = ComputeTextureLOD(sampleDiffuseDdx, sampleDiffuseDdy, _DecalAtlasResolution);
float2 sampleNormalDdx = positionDSDdx.xz * decalData.normalScaleBias.xy;
float2 sampleNormalDdy = positionDSDdy.xz * decalData.normalScaleBias.xy;
float lodNormal = ComputeTextureLOD(sampleNormalDdx, sampleNormalDdy, _DecalAtlasResolution);
// Verified that lod calculation works with a test texture, looking at the shader code in Razor the lod calculation is outside the dynamic branches where the texture fetch happens,
// however compiler was placing it inside the branch that was rejecting the pixel, which was causing incorrect lod to be calculated for any 2x2 quad where any of the pixels were rejected,
// so had to use alpha blend of 0 instead of branching to solve that issue."
float2 sampleMaskDdx = positionDSDdx.xz * decalData.maskScaleBias.xy;
float2 sampleMaskDdy = positionDSDdy.xz * decalData.maskScaleBias.xy;
float lodMask = ComputeTextureLOD(sampleMaskDdx, sampleMaskDdy, _DecalAtlasResolution);
float decalBlend = decalData.normalToWorld[0][3];
if(diffuseIndex != -1)
{
ApplyBlendDiffuse(DBuffer0, mask, positionDS.xz, diffuseIndex, DBUFFERHTILEBIT_DIFFUSE, decalBlend, lod);
alpha = alpha < decalBlend ? decalBlend : alpha; // use decal alpha if it higher than transparent alpha
}
if((decalData.diffuseScaleBias.x > 0) && (decalData.diffuseScaleBias.y > 0))
{
ApplyBlendDiffuse(DBuffer0, mask, sampleDiffuse, DBUFFERHTILEBIT_DIFFUSE, decalBlend, lodDiffuse);
alpha = alpha < decalBlend ? decalBlend : alpha; // use decal alpha if it is higher than transparent alpha
}
if(normalIndex != -1)
{
ApplyBlendNormal(DBuffer1, mask, positionDS.xz, normalIndex, DBUFFERHTILEBIT_NORMAL, (float3x3)decalData.normalToWorld, decalBlend, lod);
}
if ((decalData.normalScaleBias.x > 0) && (decalData.normalScaleBias.y > 0))
{
ApplyBlendNormal(DBuffer1, mask, sampleNormal, DBUFFERHTILEBIT_NORMAL, (float3x3)decalData.normalToWorld, decalBlend, lodNormal);
}
if(maskIndex != -1)
{
ApplyBlendMask(DBuffer2, mask, positionDS.xz, maskIndex, DBUFFERHTILEBIT_MASK, decalBlend, lod);
if ((decalData.maskScaleBias.x > 0) && (decalData.maskScaleBias.y > 0))
{
ApplyBlendMask(DBuffer2, mask, sampleMask, DBUFFERHTILEBIT_MASK, decalBlend, lodMask);
}
}
}
#else

48
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl


specularLighting *= 1.0 + bsdfData.fresnel0 * preLightData.energyCompensation;
#ifdef DEBUG_DISPLAY
switch(_DebugLightingMode)
if (_DebugLightingMode != 0)
switch (_DebugLightingMode)
{
diffuseLighting = lighting.direct.diffuse + bakeLightingData.bakeDiffuseLighting;
diffuseLighting = lighting.direct.diffuse + bakeLightingData.bakeDiffuseLighting;
diffuseLighting = indirectAmbientOcclusion;
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
diffuseLighting = indirectAmbientOcclusion;
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
diffuseLighting = specularOcclusion;
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
diffuseLighting = specularOcclusion;
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
#if GTAO_MULTIBOUNCE_APPROX
#if GTAO_MULTIBOUNCE_APPROX
diffuseLighting = GTAOMultiBounce(indirectAmbientOcclusion, bsdfData.diffuseColor);
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
diffuseLighting = GTAOMultiBounce(indirectAmbientOcclusion, bsdfData.diffuseColor);
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
diffuseLighting = GTAOMultiBounce(specularOcclusion, bsdfData.fresnel0);
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
break;
#endif
case DEBUGMIPMAPMODE_NONE:
diffuseLighting = bsdfData.diffuseColor;
diffuseLighting = GTAOMultiBounce(specularOcclusion, bsdfData.fresnel0);
#endif
{
{
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
}
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
}
}
else if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE)
{
diffuseLighting = bsdfData.diffuseColor;
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
}
#endif
}

33
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/Blit.shader


SamplerState sampler_PointClamp;
SamplerState sampler_LinearClamp;
uniform float4 _BlitScaleBias;
uniform float4 _BlitScaleBiasRt;
uniform float _BlitMipLevel;
struct Attributes

output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID) * _BlitScaleBias.xy + _BlitScaleBias.zw;
return output;
}
Varyings VertQuad(Attributes input)
{
Varyings output;
output.positionCS = GetQuadVertexPosition(input.vertexID) * float4(_BlitScaleBiasRt.x, _BlitScaleBiasRt.y, 1, 1) + float4(_BlitScaleBiasRt.z, _BlitScaleBiasRt.w, 0, 0);
output.positionCS.xy = output.positionCS.xy * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f); //convert to -1..1
output.texcoord = GetQuadTexCoord(input.vertexID) * _BlitScaleBias.xy + _BlitScaleBias.zw;
return output;
}
float4 FragNearest(Varyings input) : SV_Target
{

#pragma fragment FragBilinear
ENDHLSL
}
// 2: Nearest quad
Pass
{
ZWrite Off ZTest Always Blend Off Cull Off
HLSLPROGRAM
#pragma vertex VertQuad
#pragma fragment FragNearest
ENDHLSL
}
// 3: Bilinear quad
Pass
{
ZWrite Off ZTest Always Blend Off Cull Off
HLSLPROGRAM
#pragma vertex VertQuad
#pragma fragment FragBilinear
ENDHLSL
}
}
Fallback Off

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl


clip(1.0 - positionDS); // Clip value above one
DecalSurfaceData surfaceData;
float4x4 decalToWorld = UNITY_ACCESS_INSTANCED_PROP(matrix, _NormalToWorld);
GetSurfaceData(positionDS.xz, decalToWorld, surfaceData);
float4x4 normalToWorld = UNITY_ACCESS_INSTANCED_PROP(matrix, _NormalToWorld);
GetSurfaceData(positionDS.xz, normalToWorld, surfaceData);
// have to do explicit test since compiler behavior is not defined for RW resources and discard instructions
if((all(positionDS.xyz > 0.0f) && all(1.0f - positionDS.xyz > 0.0f)))

9
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/SkyRenderingContext.cs


{
if (skyContext.skyParametersHash != 0)
{
CoreUtils.ClearCubemap(cmd, m_SkyboxCubemapRT, Color.black, true);
if (m_SupportsConvolution)
using (new ProfilingSample(cmd, "Clear Sky Environment Pass"))
CoreUtils.ClearCubemap(cmd, m_SkyboxGGXCubemapRT, Color.black, true);
CoreUtils.ClearCubemap(cmd, m_SkyboxCubemapRT, Color.black, true);
if (m_SupportsConvolution)
{
CoreUtils.ClearCubemap(cmd, m_SkyboxGGXCubemapRT, Color.black, true);
}
}
skyContext.skyParametersHash = 0;

195
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Texture2DAtlas.cs


using System;
using System.Collections.Generic;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.Experimental.Rendering
{
public class AtlasAllocator
{
private class AtlasNode
{
public AtlasNode m_RightChild = null;
public AtlasNode m_BottomChild = null;
public Vector4 m_Rect = new Vector4(0,0,0,0); // x,y is width and height (scale) z,w offset into atlas (bias)
public AtlasNode Allocate(int width, int height)
{
// not a leaf node, try children
if(m_RightChild != null)
{
AtlasNode node = m_RightChild.Allocate(width, height);
if(node == null)
{
node = m_BottomChild.Allocate(width, height);
}
return node;
}
//leaf node, check for fit
if ((width <= m_Rect.x) && (height <= m_Rect.y))
{
// perform the split
m_RightChild = new AtlasNode();
m_BottomChild = new AtlasNode();
if (width > height) // logic to decide which way to split
{ // +--------+------+
m_RightChild.m_Rect.z = m_Rect.z + width; // | | |
m_RightChild.m_Rect.w = m_Rect.w; // +--------+------+
m_RightChild.m_Rect.x = m_Rect.x - width; // | |
m_RightChild.m_Rect.y = height; // | |
// +---------------+
m_BottomChild.m_Rect.z = m_Rect.z;
m_BottomChild.m_Rect.w = m_Rect.w + height;
m_BottomChild.m_Rect.x = m_Rect.x;
m_BottomChild.m_Rect.y = m_Rect.y - height;
}
else
{ // +---+-----------+
m_RightChild.m_Rect.z = m_Rect.z + width; // | | |
m_RightChild.m_Rect.w = m_Rect.w; // | | |
m_RightChild.m_Rect.x = m_Rect.x - width; // +---+ +
m_RightChild.m_Rect.y = m_Rect.y; // | | |
// +---+-----------+
m_BottomChild.m_Rect.z = m_Rect.z;
m_BottomChild.m_Rect.w = m_Rect.w + height;
m_BottomChild.m_Rect.x = width;
m_BottomChild.m_Rect.y = m_Rect.y - height;
}
m_Rect.x = width;
m_Rect.y = height;
return this;
}
return null;
}
public void Release()
{
if (m_RightChild != null)
{
m_RightChild.Release();
m_BottomChild.Release();
}
m_RightChild = null;
m_BottomChild = null;
}
}
private AtlasNode m_Root;
private int m_Width;
private int m_Height;
public AtlasAllocator(int width, int height)
{
m_Root = new AtlasNode();
m_Root.m_Rect.Set(width, height, 0, 0);
m_Width = width;
m_Height = height;
}
public bool Allocate(ref Vector4 result, int width, int height)
{
AtlasNode node = m_Root.Allocate(width, height);
if(node != null)
{
result = node.m_Rect;
return true;
}
else
{
result = Vector4.zero;
return false;
}
}
public void Release()
{
m_Root.Release();
m_Root = new AtlasNode();
m_Root.m_Rect.Set(m_Width, m_Height, 0, 0);
}
}
public class Texture2DAtlas
{
private RTHandle m_AtlasTexture = null;
private int m_Width;
private int m_Height;
private RenderTextureFormat m_Format;
private AtlasAllocator m_AtlasAllocator = null;
private Dictionary<IntPtr, Vector4> m_AllocationCache = new Dictionary<IntPtr, Vector4>();
public RTHandle AtlasTexture
{
get
{
return m_AtlasTexture;
}
}
public Texture2DAtlas(int width, int height, RenderTextureFormat format)
{
m_Width = width;
m_Height = height;
m_Format = format;
m_AtlasTexture = RTHandle.Alloc(m_Width,
m_Height,
1,
DepthBits.None,
m_Format,
FilterMode.Point,
TextureWrapMode.Clamp,
TextureDimension.Tex2D,
false,
false,
true,
false);
m_AtlasAllocator = new AtlasAllocator(width, height);
}
public void Release()
{
ResetAllocator();
RTHandle.Release(m_AtlasTexture);
}
public void ResetAllocator()
{
m_AtlasAllocator.Release();
m_AllocationCache.Clear();
}
public bool AddTexture(CommandBuffer cmd, ref Vector4 scaleBias, Texture texture)
{
IntPtr key = texture.GetNativeTexturePtr();
if (!m_AllocationCache.TryGetValue(key, out scaleBias))
{
int width = texture.width;
int height = texture.height;
if (m_AtlasAllocator.Allocate(ref scaleBias, width, height))
{
scaleBias.Scale(new Vector4(1.0f / m_Width, 1.0f / m_Height, 1.0f / m_Width, 1.0f / m_Height));
for (int mipLevel = 0; mipLevel < (texture as Texture2D).mipmapCount; mipLevel++)
{
cmd.SetRenderTarget(m_AtlasTexture, mipLevel);
HDUtils.BlitQuad(cmd, texture, new Vector4(1, 1, 0, 0), scaleBias, mipLevel, false);
}
m_AllocationCache.Add(key, scaleBias);
return true;
}
else
{
return false;
}
}
return true;
}
}
}

11
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Texture2DAtlas.cs.meta


fileFormatVersion: 2
guid: 081cfbdef2e1c014aa1d1c9aa16fb952
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存