publicstaticGUIContenttransparentDepthPrepassEnableText=newGUIContent("Enable transparent depth prepass","It allow to to fill depth buffer to improve sorting");
publicstaticGUIContenttransparentDepthPostpassEnableText=newGUIContent("Enable transparent depth postpass","It allow to fill depth buffer for postprocess effect like DOF");
publicstaticGUIContenttransparentBackfaceEnableText=newGUIContent("Enable back then front rendering","It allow to better sort transparent mesh by first rendering back faces then front faces in two separate drawcall");
publicstaticGUIContenttransparentSortPriorityText=newGUIContent("Transparent Sort Priority","Allow to define priority (from -100 to +100) to solve sorting issue with transparent");
publicstaticGUIContentenableTransparentFogText=newGUIContent("Enable fog","Enable fog on transparent material");
publicstaticGUIContentenableBlendModePreserveSpecularLightingText=newGUIContent("Blend preserve specular lighting","Blend mode will only affect diffuse lighting, allowing correct specular lighting (reflection) on transparent object");
// This is the main command buffer used for the frame.
// TODO: Try to arrange code so we can trigger this call earlier and use async compute here to run sky convolution during other passes (once we move convolution shader to compute).
// Caution: RenderDebug need to take into account that we have flip the screen (so anything capture before the flip will be flipped)
RenderDebug(hdCamera,cmd);
// Make sure to unbind every render texture here because in the next iteration of the loop we might have to reallocate render texture (if the camera size is different)
// We render first the opaque object as opaque alpha tested are more costly to render and could be reject by early-z (but not Hi-z as it is disable with clip instruction)
// This is handled automatically with the RenderQueue value (OpaqueAlphaTested have a different value and thus are sorted after Opaque)
// The material display debug perform sRGBToLinear conversion as the final blit currently hardcode a linearToSrgb conversion. As when we read with color picker this is not done,
// we perform it inside the color picker shader. But we shouldn't do it for HDR buffer.
// Everything we have capture is flipped (as it happen before FinalPass/postprocess/Blit. So if we are not in SceneView
// (i.e. we have perform a flip, we need to flip the input texture) + we need to handle the case were we debug a fullscreen pass that have already perform the flip
FrameSettingsm_FrameSettings=newFrameSettings();// This are the defaultFrameSettings for all the camera and apply to sceneView, public to be visible in the inspector
// Not serialized, not visible, the settings effectively used
// In HD we don't expose HDRenderQueue instead we create as much value as needed in the enum for our different pass
// and use inspector to manipulate the value.
// In the case of transparent we want to use RenderQueue to help with sorting. We define a neutral value for the RenderQueue and priority going from -X to +X
// going from -X to +X instead of 0 to +X as builtin Unity is better for artists as they can decide late to sort behind or in front of the scene.
// IMPORTANT: In case of foward or gbuffer pass all enable flags are statically know at compile time, so the compiler can do compile time optimization
bsdfData.materialFeatures = surfaceData.materialFeatures | MATERIALFEATUREFLAGS_LIT_STANDARD; // Not really needed but for consistency with deferred path
// However in practice we keep parity between deferred and forward, so we should contrain the various features.
// The UI is in charge of setuping the constrain not the code, so if users is forward only and want full power, it is easy to unleash by some UI change
// However in practice we keep parity between deferred and forward, so we should constrain the various features.
// The UI is in charge of setuping the constrain, not the code. So if users is forward only and want unleash power, it is easy to unleash by some UI change
// For standard we have chose to always encode fresnel0. Even when we use metal/baseColor parametrization. This avoid
// compiler optimization problem that was using VGPR to deal with the various combination of metal non metal.
// For SSS, we move diffusionProfile(4) / subsurfaceMask(4) in GBuffer0.a so the forward SSS code only need to write into one RT
// and the SSS postprocess only need to read one RT
// We duplicate diffusionProfile / subsurfaceMask in GBuffer2.b so the compiler don't need to read the GBuffer0 before PostEvaluateBSDF
// The lighting code have been adapted to only apply diffuseColor at the end.
// This save VGPR as we don' need to keep the GBuffer0 value in register.
// The layout is also design to only require one RT for the material classification. All the material feature flags are deduced from GBuffer2.
// Encode SurfaceData (BSDF parameters) into GBuffer
// Must be in sync with RT declared in HDRenderPipeline.cs ::Rebuild
void EncodeIntoGBuffer( SurfaceData surfaceData,
ApplyDebugToSurfaceData(surfaceData);
// RT0 - 8:8:8:8 sRGB
// Warning: the contents are later overwritten for Standard and SSS!
// We store perceptualRoughness instead of roughness because it save a sqrt ALU when decoding
// (as we want both perceptualRoughness and roughness for the lighting due to Disney Diffuse model)
// Encode normal on 20bit with oct compression + 2bit of sign
// To have more precision encode the sign of xy in a separate uint
// To have better precision encode the sign of XY separately.
// We store perceptualRoughness instead of roughness because it is perceptually linear.
// mettalic will be store on 4 bit and store special value when not used
int metallic15 = int(surfaceData.metallic * (GBUFFER_LIT_ANISOTROPIC_UPPER_BOUND + 0.5)); // Remap to [0..12] range. 13, 14, 15 are special value
uint materialFeatureId;
// IMPORTANT: In case of foward or gbuffer pass materialFeatures is statically know at compile time, so the compiler can do compile time optimization
// Currently material features SpecularColor, Iridescence, SubsurfaceScattering/Transmission, Anisotropy are mutually exclusive due to Gbuffer constrain
// The priority of feature is handled in the code here and reflect in the UI (see LitUI.cs)
// Process SSS and Transmission together as they encode almost the same data, negligible cost
metallic15 = GBUFFER_LIT_SSS_OR_TRANSMISSION;
// Special case: For SSS we will store the profile id and the subsurface radius at the location of the specular occlusion (in alpha channel of GBuffer0)
// and we will move the specular occlusion in GBuffer2. This is an optimization for SSSSS and have no other side effect as specular occlusion is always used
// during lighting pass when other buffer (Gbuffer0, 1, 2) and read anyway.
// Reminder that during GBuffer pass we know statically material materialFeatures
if ((surfaceData.materialFeatures & (MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION)) == (MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING | MATERIALFEATUREFLAGS_LIT_TRANSMISSION))
materialFeatureId = GBUFFER_LIT_TRANSMISSION_SSS;
else if ((surfaceData.materialFeatures & MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING) == MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING)
materialFeatureId = GBUFFER_LIT_SSS;
else
materialFeatureId = GBUFFER_LIT_TRANSMISSION;
// We perform the same encoding for SSS and transmission even if not used as it is the same cost
// Note that regarding EncodeIntoSSSBuffer, as the lit.shader IS the deferred shader (and the SSS fullscreen pass is based on deferred encoding),
// it know the details of the encoding, so it is fine to assume here how SSSBuffer0 is encoded
// For the SSS feature, the alpha channel is overwritten with (diffusionProfile | subsurfaceMask).
// It is done so that the SSS pass only has to read a single G-Buffer 0.
// We move specular occlusion to the red channel of the G-Buffer 2.
// Always assign even if not used, DIFFUSION_PROFILE_NEUTRAL_ID is 0
// Note: we have ZERO_INITIALIZE the struct, so bsdfData.diffusionProfile == DIFFUSION_PROFILE_NEUTRAL_ID, bsdfData.anisotropy == 0, bsdfData.subsurfaceMask == 0 etc...
// TODO: deal with camera center rendering and instancing (This is the reason why we always perform two steps transform to clip space + instancing matrix)