new modern built-in rendering pipeline with it. For now you can look around if you're _really_ curious, but like said above, this is
not useful for any public Unity version yet.
There's a more detailed overview document here: [ScriptableRenderLoop google doc](https://docs.google.com/document/d/1e2jkr_-v5iaZRuHdnMrSv978LuJKYZhsIYnrDkNAuvQ/edit?usp=sharing)
There's a more detailed overview document here: [ScriptableRenderPipeline google doc](https://docs.google.com/document/d/1e2jkr_-v5iaZRuHdnMrSv978LuJKYZhsIYnrDkNAuvQ/edit?usp=sharing)
Did we mention it's a very WIP, no promises, may or might not ship feature, anything and everything in it can change? It totally is.
Perform the following instructions to get a working copy of SRP:
1. Download Unity version compatible with Github release (https://github.com/Unity-Technologies/ScriptableRenderPipeline/releases)
2. Launch
3. Create a new Unity project
4. Set `Color Space` to `Linear` in Player settings, Set Antialiasing to disable in Quality settings for all configuration (Fantastic and High), Set Anisotropic Textures to "Per Textures"
5. Close Unity
6. Execute the following commands (or use GitHub interface (ask us)):
> git submodule update --init --recursive --remote (This is to get the PostProcessing folder)
```
7. Re-open the project
8. In Graphic Settings, for render pipeline, setup the HDRenderPipelineAsset
Advice: It is recommended to make a copy of HDRenderPipelineAsset outside of the ScriptableRenderPipeline, so settings are not lost when merging. And setup this new created HDRenderPipelineAsset in GraphicSettings
// Volume is store as 3D texture with 4 R, G, B, X set of 4 coefficient store atlas in same 3D texture. X is use for occlusion.
// TODO: the packing here is inefficient as we will fetch values far away from each other and they may not fit into the cache - Suggest we pack only RGB continuously
// Volume is store as 3D texture with 4 R, G, B, Occ set of 4 coefficient store atlas in same 3D texture. Occ is use for occlusion.
// TODO: the packing here is inefficient as we will fetch values far away from each other and they may not fit into the cache - Suggest we pack RGB continuously
// Note: Legacy Unity behave like this for ShadowMask
// When you select ShadowMask in Lighting panel it recompile shaders on the fly with the SHADOW_MASK keyword.
// However there is no C# function that we can query to know what mode have been select in Lighting Panel and it will be wrong anyway. Lighting Panel setup what will be the next bake mode. But until light is bake, it is wrong.
// Currently to know if you need shadow mask you need to go through all visible lights (of CullResult), check the LightBakingOutput struct and look at lightmapBakeType/mixedLightingMode. If one light have shadow mask bake mode, then you need shadow mask features (i.e extra Gbuffer).
// It mean that when we build a standalone player, if we detect a light with bake shadow mask, we generate all shader variant (with and without shadow mask) and at runtime, when a bake shadow mask light is visible, we dynamically allocate an extra GBuffer and switch the shader.
// So the first thing to do is to go through all the light: PrepareLightsForGPU
// Forward opaque material always have a prepass (whether or not we use deferred, whether or not there is option like alpha test only) so we pass the right depth state here.
// TEMP: As we are in development and have not all the setup pass we still clear the color in emissive buffer and gbuffer, but this will be removed later.
// TODO: As we are in development and have not all the setup pass we still clear the color in emissive buffer and gbuffer, but this will be removed later.
// SSSSS algorithm need to know which pixels contribute to SSS and which doesn't. We could use the stencil for that but it mean that it will increase the cost of SSSSS
// A simpler solution is to add a slight contribution here that isn't visible (here we chose fp16 min (which is also fp11 and fp10 min).
// The SSSSS algorithm will check if diffuse lighting is black and discard the pixel if it is the case
/* Tag: SUPPORT_COMPUTE_CLUSTER_OPAQUE - Uncomment this if you want to do cluster opaque with compute shader (by default we support only fptl on opaque)
// SSSSS algorithm need to know which pixels contribute to SSS and which doesn't. We could use the stencil for that but it mean that it will increase the cost of SSSSS
// A simpler solution is to add a slight contribution here that isn't visible (here we chose fp16 min (which is also fp11 and fp10 min).
// The SSSSS algorithm will check if diffuse lighting is black and discard the pixel if it is the case
// Light bit mask must match LightDefinitions.s_LightFeatureMaskFlags value
Punctual=1<<8,
Area=1<<9,
Directional=1<<10,
Env=1<<11,
Sky=1<<12,
SSL=1<<13// If adding more light be sure to not overflow LightDefinitions.s_LightFeatureMaskFlags
Punctual=1<<12,
Area=1<<13,
Directional=1<<14,
Env=1<<15,
Sky=1<<16,
SSRefraction=1<<17,
SSReflection=1<<18,
// If adding more light be sure to not overflow LightDefinitions.s_LightFeatureMaskFlags
}
[GenerateHLSL]
publicstaticints_NumFeatureVariants=27;
// Following define the maximum number of bits use in each feature category.
publicstaticuints_LightFeatureMaskFlags=0xFF00;
publicstaticuints_MaterialFeatureMaskFlags=0x00FF;// don't use all bits just to be safe from signed and/or float conversions :/
publicstaticuints_LightFeatureMaskFlags=0xFFF000;
publicstaticuints_LightFeatureMaskFlagsOpaque=0xFFF000&~((uint)LightFeatureFlags.SSRefraction);// Opaque don't support screen space refraction
publicstaticuints_LightFeatureMaskFlagsTransparent=0xFFF000&~((uint)LightFeatureFlags.SSReflection);// Transparent don't support screen space reflection
publicstaticuints_MaterialFeatureMaskFlags=0x000FFF;// don't use all bits just to be safe from signed and/or float conversions :/
}
[GenerateHLSL]
intm_punctualLightCount=0;
intm_areaLightCount=0;
intm_lightCount=0;
boolm_enableBakeShadowMask=false;// Track if any light require shadow mask. In this case we will need to enable the keyword shadow mask
floatm_maxShadowDistance=0.0f;// Save value from shadow settings
// Following is an array of material of size eight for all combination of keyword: OUTPUT_SPLIT_LIGHTING - LIGHTLOOP_TILE_PASS - SHADOWS_SHADOWMASK - USE_FPTL_LIGHTLIST/USE_CLUSTERED_LIGHTLIST - DEBUG_DISPLAY
// TODO: Currently m_maxShadowDistance is based on shadow settings, but this value is define for a whole level. We should be able to change this value during gameplay
// Tag: SUPPORT_COMPUTE_CLUSTER_OPAQUE - Uncomment this if you want to do cluster opaque with compute shader (by default we support only fptl on opaque)
// Tag: SUPPORT_COMPUTE_CLUSTER_OPAQUE - Update the code with following comment this if you want to do cluster opaque with compute shader (by default we support only fptl on opaque)
// TODO: Update value like in ApplyDebugDisplaySettings() call. Sadly it is high likely that this will not be keep in sync. we really need to get rid of this by making global parameters visible to compute shaders
// TODO: Update value like in ApplyDebugDisplaySettings() call. Sadly it is high likely that this will not be keep in sync. we really need to get rid of this by making global parameters visible to compute shaders
// TODO: Don't know why but If we use Shader.GetGlobalTexture(HDShaderIDs._GBufferTexture0) instead of HDShaderIDs._GBufferTexture0 the screen start to flicker in SceneView...
// Need to investigate what is happening. But this may be unnecessary as development of SetGlobalTexture for compute shader have begin
// TODO: Don't know why but If we use Shader.GetGlobalTexture(HDShaderIDs._GBufferTexture0) instead of HDShaderIDs._GBufferTexture0 the screen start to flicker in SceneView...
// Need to investigate what is happening. But this may be unnecessary as development of SetGlobalTexture for compute shader have begin
// 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 && totalIblWeight < 1.0; ++i)
for (i = 0; i < envLightCount && reflectionHierarchyWeight < 1.0; ++i)
// Refraction probe and reflection probe will process exactly the same weight. It will be good for performance to be able to share this computation
// However it is hard to deal with the fact that reflectionHierarchyWeight and refractionHierarchyWeight have not the same values, they are independent
// The refraction probe is rarely used and happen only with sphere shape and high IOR. So we accept the slow path that use more simple code and
// doesn't affect the performance of the reflection which is more important.
// 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)
publicVector3bakeDiffuseLighting;// This is the result of sampling lightmap/lightprobe/proxyvolume
// Use for float instead of vector4 to ease the debug (no performance impact)
// Note: We have no way to remove these value automatically based on either SHADEROPTIONS_BAKED_SHADOW_MASK_ENABLE or s_BakedShadowMaskEnable here. Unless we make two structure... For now always keep this value
// HACK: GI Baking system relies on some properties existing in the shader ("_MainTex", "_Cutoff" and "_Color") for opacity handling, so we need to store our version of those parameters in the hard-coded name the GI baking system recognizes.
_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#pragma only_renderers d3d11 ps4 vulkan metal // TEMP: until we go further in dev
// #pragma enable_d3d11_debug_symbols
#pragma shader_feature _ALPHATEST_ON
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
// HACK: GI Baking system relies on some properties existing in the shader ("_MainTex", "_Cutoff" and "_Color") for opacity handling, so we need to store our version of those parameters in the hard-coded name the GI baking system recognizes.
_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
#pragma only_renderers d3d11 ps4 // TEMP: until we go further in dev
#pragma only_renderers d3d11 ps4 vulkan // TEMP: until we go further in dev
// #pragma enable_d3d11_debug_symbols
#pragma shader_feature _ALPHATEST_ON
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
publicstaticGUIContentsubsurfaceRadiusMapText=newGUIContent("Subsurface radius map (R)","Determines the range of the blur.");
publicstaticGUIContentthicknessText=newGUIContent("Thickness","If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
publicstaticGUIContentthicknessMapText=newGUIContent("Thickness map (R)","If subsurface scattering is enabled, low values allow some light to be transmitted through the object.");
publicstaticGUIContentthicknessRemapText=newGUIContent("Thickness Remap","Remaps values of the thickness map from [0, 1] to the specified range.");
// Clear Coat
publicstaticGUIContentcoatCoverageText=newGUIContent("Coat Coverage","Percentage of clear coat coverage");
publicstaticGUIContentperPixelDisplacementDetailsWarning=newGUIContent("For pixel displacement to work correctly, details and base map must use same UV mapping");
/* 26 */ LIGHT_FEATURE_MASK_FLAGS | MATERIAL_FEATURE_MASK_FLAGS, // Catch all case with MATERIAL_FEATURE_MASK_FLAGS is needed in case we disable material classification
/* 26 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIAL_FEATURE_MASK_FLAGS, // Catch all case with MATERIAL_FEATURE_MASK_FLAGS is needed in case we disable material classification
// This function require the 3 structure surfaceData, builtinData, bsdfData because it may require both the engine side data, and data that will not be store inside the gbuffer.
float invLenLV = rsqrt(max(2 * LdotV + 2, SMALL_FLT_VALUE)); // invLenLV = rcp(length(L + V)) - caution about the case where V and L are opposite, it can happen, use max to avoid this
// Note: Legacy Unity have two shadow mask mode. ShadowMask (ShadowMask contain static objects shadow and ShadowMap contain only dynamic objects shadow, final result is the minimun of both value)
// and ShadowMask_Distance (ShadowMask contain static objects shadow and ShadowMap contain everything and is blend with ShadowMask based on distance (Global distance setup in QualitySettigns)).
// HDRenderPipeline change this behavior. Only ShadowMask mode is supported but we support both blend with distance AND minimun of both value. Distance is control by light.
// The following code do this.
// The min handle the case of having only dynamic objects in the ShadowMap
// The second case for blend with distance is handled with ShadowDimmer. ShadowDimmer is define manually and by shadowDistance by light.
// With distance, ShadowDimmer become one and only the ShadowMask appear, we get the blend with distance behavior.
// In our case we don't use such a mechanism but need to keep the code quiet. We declare the value and always enable it.
// TODO: Fix the code in legacy unity so we can customize the beahvior for GI
_EmissionColor("Color", Color) = (1, 1, 1)
// HACK: GI Baking system relies on some properties existing in the shader ("_MainTex", "_Cutoff" and "_Color") for opacity handling, so we need to store our version of those parameters in the hard-coded name the GI baking system recognizes.
_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go futher in dev
#pragma only_renderers d3d11 ps4 vulkan metal // TEMP: until we go futher in dev
_TessellationShapeFactor("Tessellation shape factor", Range(0.0, 1.0)) = 0.75 // Only use with Phong
_TessellationBackFaceCullEpsilon("Tessellation back face epsilon", Range(-1.0, 0.0)) = -0.25
// TODO: Handle culling mode for backface culling
// HACK: GI Baking system relies on some properties existing in the shader ("_MainTex", "_Cutoff" and "_Color") for opacity handling, so we need to store our version of those parameters in the hard-coded name the GI baking system recognizes.
_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
#pragma only_renderers d3d11 ps4// TEMP: until we go futher in dev
#pragma only_renderers d3d11 ps4 vulkan// TEMP: until we go futher in dev
// TODO: We use GetAbsolutePositionWS(positionWS) to handle the camera relative case here but this should be part of the unity_ProbeVolumeWorldToObject matrix on C++ side (sadly we can't modify it for HDRenderPipeline...)
// This is a hack for GI. PVR looks in the shader for a texture named "_MainTex" to extract the opacity of the material for baking. In the same manner, "_Cutoff" and "_Color" are also necessary.
// Since we don't have those parameters in our shaders we need to provide a "fake" useless version of them with the right values for the GI to work.
// In our case we don't use such a mechanism but need to keep the code quiet. We declare the value and always enable it.
// TODO: Fix the code in legacy unity so we can customize the beahvior for GI
_EmissionColor("Color", Color) = (1, 1, 1)
// HACK: GI Baking system relies on some properties existing in the shader ("_MainTex", "_Cutoff" and "_Color") for opacity handling, so we need to store our version of those parameters in the hard-coded name the GI baking system recognizes.
_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#pragma only_renderers d3d11 ps4 vulkan metal // TEMP: until we go further in dev
StructuredBuffer<uint> g_vLightListMeshInst; // build on CPU if in use. direct lights first, then reflection probes. (don't support Buffer yet in unity, so using structured)