Sebastien Lagarde
7 年前
当前提交
48c698bd
共有 36 个文件被更改,包括 173 次插入 和 2571 次删除
-
40ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
-
2ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs.meta
-
114ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/SSS Settings.asset
-
8ScriptableRenderPipeline/HDRenderPipeline/Material/Material.hlsl
-
25ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl
-
5ScriptableRenderPipeline/LightweightPipeline.meta
-
4Tests.meta
-
36Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/037_Shader_StandardParticleShaders/Standard Particle Shader/Scripts/LookAt.cs
-
10Tests/GraphicsTests/RenderPipeline/HDRenderPipeline/CommonAssets/Materials/ComplexMaterial/Textures.meta
-
43Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/035_Shader_TerrainShaders/Free_SpeedTrees/Broadleaves.obj
-
78Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/035_Shader_TerrainShaders/Free_SpeedTrees/Broadleaves.obj.meta
-
10SampleScenes/HDTest/TransparencyTest.meta
-
519ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/Vegetation.shader
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/Vegetation.shader.meta
-
269ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/VegetationData.hlsl
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/VegetationData.hlsl.meta
-
176ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/VegetationDataMeshModification.hlsl
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/VegetationDataMeshModification.hlsl.meta
-
21ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/VegetationProperties.hlsl
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/VegetationProperties.hlsl.meta
-
56ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/VegetationWind.hlsl
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation/VegetationWind.hlsl.meta
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Character.meta
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Eye.meta
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric.meta
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Hair.meta
-
327ScriptableRenderPipeline/HDRenderPipeline/Material/LightEvaluationShare1.hlsl
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/LightEvaluationShare1.hlsl.meta
-
881ScriptableRenderPipeline/HDRenderPipeline/Material/LightEvaluationShare2.hlsl
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/LightEvaluationShare2.hlsl.meta
-
10ScriptableRenderPipeline/HDRenderPipeline/Material/Vegetation.meta
|
|||
fileFormatVersion: 2 |
|||
guid: f9ca3ff6d08b48b42ae424159889f367 |
|||
guid: 4923a4700d4d643a9a862a74e04870b3 |
|||
timeCreated: 1509065726 |
|||
timeCreated: 1481548458 |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
/// </summary>
|
|||
|
|||
public class LookAt : MonoBehaviour { |
|||
|
|||
private Transform cam; |
|||
|
|||
// Use this for initialization
|
|||
/// </summary>
|
|||
|
|||
public class LookAt : MonoBehaviour { |
|||
|
|||
private Transform cam; |
|||
|
|||
// Use this for initialization
|
|||
cam = Camera.main.transform; |
|||
} |
|||
|
|||
// Update is called once per frame
|
|||
cam = Camera.main.transform; |
|||
} |
|||
|
|||
// Update is called once per frame
|
|||
transform.LookAt(cam); |
|||
} |
|||
} |
|||
transform.LookAt(cam); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ce883dc5ae95f394b8a00d0badafa35c |
|||
folderAsset: yes |
|||
timeCreated: 1509027998 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware |
|||
# File Created: 14.05.2014 09:45:05 |
|||
|
|||
# |
|||
# object diamond |
|||
# |
|||
|
|||
v 0.8296 -1.2260 0.0993 |
|||
v 0.0687 -0.9154 0.4403 |
|||
v -0.0157 -1.8703 0.1686 |
|||
v -0.8101 -1.2001 0.0993 |
|||
v 0.0000 0.0000 0.0000 |
|||
# 5 vertices |
|||
|
|||
vn -0.4082 0.0023 0.9129 |
|||
vn -0.0470 -0.1441 0.9884 |
|||
vn 0.0136 0.2725 0.9620 |
|||
vn 0.0136 0.2725 0.9620 |
|||
vn -0.0470 -0.1441 0.9884 |
|||
vn 0.5624 -0.1491 0.8133 |
|||
vn -0.4082 0.0023 0.9129 |
|||
vn 0.0064 -0.4331 0.9013 |
|||
vn -0.0470 -0.1441 0.9884 |
|||
vn -0.0470 -0.1441 0.9884 |
|||
vn 0.0064 -0.4331 0.9013 |
|||
vn 0.5624 -0.1491 0.8133 |
|||
# 12 vertex normals |
|||
|
|||
vt 0.0005 0.6554 0.2258 |
|||
vt 0.4641 0.4895 0.9995 |
|||
vt 0.5155 0.9995 0.3830 |
|||
vt 0.9995 0.6415 0.2258 |
|||
vt 0.5059 0.0005 0.0005 |
|||
# 5 texture coords |
|||
|
|||
g diamond |
|||
s 1 |
|||
f 1/1/1 2/2/2 3/3/3 |
|||
f 3/3/4 2/2/5 4/4/6 |
|||
f 1/1/7 5/5/8 2/2/9 |
|||
f 2/2/10 5/5/11 4/4/12 |
|||
# 4 faces |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: cf3c778055c27074b849beaac044a88b |
|||
timeCreated: 1452616724 |
|||
licenseType: Store |
|||
ModelImporter: |
|||
serializedVersion: 19 |
|||
fileIDToRecycleName: |
|||
100000: //RootNode |
|||
100002: diamond |
|||
400000: //RootNode |
|||
400002: diamond |
|||
2300000: diamond |
|||
3300000: diamond |
|||
4300000: diamond |
|||
materials: |
|||
importMaterials: 1 |
|||
materialName: 0 |
|||
materialSearch: 1 |
|||
animations: |
|||
legacyGenerateAnimations: 4 |
|||
bakeSimulation: 0 |
|||
resampleRotations: 1 |
|||
optimizeGameObjects: 0 |
|||
motionNodeName: |
|||
animationImportErrors: |
|||
animationImportWarnings: |
|||
animationRetargetingWarnings: |
|||
animationDoRetargetingWarnings: 0 |
|||
animationCompression: 1 |
|||
animationRotationError: 0.5 |
|||
animationPositionError: 0.5 |
|||
animationScaleError: 0.5 |
|||
animationWrapMode: 0 |
|||
extraExposedTransformPaths: [] |
|||
clipAnimations: [] |
|||
isReadable: 1 |
|||
meshes: |
|||
lODScreenPercentages: [] |
|||
globalScale: 1 |
|||
meshCompression: 0 |
|||
addColliders: 0 |
|||
importBlendShapes: 1 |
|||
swapUVChannels: 0 |
|||
generateSecondaryUV: 0 |
|||
useFileUnits: 1 |
|||
optimizeMeshForGPU: 1 |
|||
keepQuads: 0 |
|||
weldVertices: 1 |
|||
secondaryUVAngleDistortion: 8 |
|||
secondaryUVAreaDistortion: 15.000001 |
|||
secondaryUVHardAngle: 88 |
|||
secondaryUVPackMargin: 4 |
|||
useFileScale: 1 |
|||
tangentSpace: |
|||
normalSmoothAngle: 60 |
|||
normalImportMode: 0 |
|||
tangentImportMode: 3 |
|||
importAnimation: 1 |
|||
copyAvatar: 0 |
|||
humanDescription: |
|||
human: [] |
|||
skeleton: [] |
|||
armTwist: 0.5 |
|||
foreArmTwist: 0.5 |
|||
upperLegTwist: 0.5 |
|||
legTwist: 0.5 |
|||
armStretch: 0.05 |
|||
legStretch: 0.05 |
|||
feetSpacing: 0 |
|||
rootMotionBoneName: |
|||
hasTranslationDoF: 0 |
|||
lastHumanDescriptionAvatarSource: {instanceID: 0} |
|||
animationType: 0 |
|||
humanoidOversampling: 1 |
|||
additionalBone: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 7a6daa9d8dbc4904dae6deaa667846ef |
|||
folderAsset: yes |
|||
timeCreated: 1509455772 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "HDRenderPipeline/Vegetation" |
|||
{ |
|||
Properties |
|||
{ |
|||
// Following set of parameters represent the parameters node inside the MaterialGraph. |
|||
// They are use to fill a SurfaceData. With a MaterialGraph this should not exist. |
|||
|
|||
// Reminder. Color here are in linear but the UI (color picker) do the conversion sRGB to linear |
|||
_BaseColor("BaseColor", Color) = (1,1,1,1) |
|||
_BaseColorMap("BaseColorMap", 2D) = "white" {} |
|||
|
|||
_Metallic("_Metallic", Range(0.0, 1.0)) = 0 |
|||
_Smoothness("Smoothness", Range(0.0, 1.0)) = 1.0 |
|||
_MaskMap("MaskMap", 2D) = "white" {} |
|||
_SmoothnessRemapMin("SmoothnessRemapMin", Float) = 0.0 |
|||
_SmoothnessRemapMax("SmoothnessRemapMax", Float) = 1.0 |
|||
|
|||
_NormalMap("NormalMap", 2D) = "bump" {} // Tangent space normal map |
|||
_NormalMapOS("NormalMapOS", 2D) = "white" {} // Object space normal map - no good default value |
|||
_NormalScale("_NormalScale", Range(0.0, 2.0)) = 1 |
|||
|
|||
_BentNormalMap("_BentNormalMap", 2D) = "bump" {} |
|||
_BentNormalMapOS("_BentNormalMapOS", 2D) = "white" {} |
|||
|
|||
_HeightMap("HeightMap", 2D) = "black" {} |
|||
// Caution: Default value of _HeightAmplitude must be (_HeightMax - _HeightMin) * 0.01 |
|||
[HideInInspector] _HeightAmplitude("Height Amplitude", Float) = 0.02 // In world units. This will be computed in the UI. |
|||
_HeightMin("Heightmap Min", Float) = -1 |
|||
_HeightMax("Heightmap Max", Float) = 1 |
|||
_HeightCenter("Height Center", Range(0.0, 1.0)) = 0.5 // In texture space |
|||
|
|||
_DetailMap("DetailMap", 2D) = "black" {} |
|||
_DetailAlbedoScale("_DetailAlbedoScale", Range(0.0, 2.0)) = 1 |
|||
_DetailNormalScale("_DetailNormalScale", Range(0.0, 2.0)) = 1 |
|||
_DetailSmoothnessScale("_DetailSmoothnessScale", Range(0.0, 2.0)) = 1 |
|||
|
|||
_TangentMap("TangentMap", 2D) = "bump" {} |
|||
_TangentMapOS("TangentMapOS", 2D) = "white" {} |
|||
_Anisotropy("Anisotropy", Range(-1.0, 1.0)) = 0 |
|||
_AnisotropyMap("AnisotropyMap", 2D) = "white" {} |
|||
|
|||
_SubsurfaceProfile("Subsurface Profile", Int) = 0 |
|||
_SubsurfaceRadius("Subsurface Radius", Range(0.0, 1.0)) = 1.0 |
|||
_SubsurfaceRadiusMap("Subsurface Radius Map", 2D) = "white" {} |
|||
_Thickness("Thickness", Range(0.0, 1.0)) = 1.0 |
|||
_ThicknessMap("Thickness Map", 2D) = "white" {} |
|||
_ThicknessRemap("Thickness Remap", Vector) = (0, 1, 0, 0) |
|||
|
|||
_CoatCoverage("Coat Coverage", Range(0.0, 1.0)) = 1.0 |
|||
_CoatIOR("Coat IOR", Range(0.0, 1.0)) = 0.5 |
|||
|
|||
_SpecularColor("SpecularColor", Color) = (1, 1, 1, 1) |
|||
_SpecularColorMap("SpecularColorMap", 2D) = "white" {} |
|||
|
|||
// Following options are for the GUI inspector and different from the input parameters above |
|||
// These option below will cause different compilation flag. |
|||
[ToggleOff] _EnableSpecularOcclusion("Enable specular occlusion", Float) = 0.0 |
|||
|
|||
_EmissiveColor("EmissiveColor", Color) = (0, 0, 0) |
|||
_EmissiveColorMap("EmissiveColorMap", 2D) = "white" {} |
|||
_EmissiveIntensity("EmissiveIntensity", Float) = 0 |
|||
[ToggleOff] _AlbedoAffectEmissive("Albedo Affect Emissive", Float) = 0.0 |
|||
|
|||
_DistortionVectorMap("DistortionVectorMap", 2D) = "black" {} |
|||
[ToggleOff] _DistortionEnable("Enable Distortion", Float) = 0.0 |
|||
[ToggleOff] _DistortionDepthTest("Distortion Depth Test Enable", Float) = 1.0 |
|||
[Enum(Add, 0, Multiply, 1)] _DistortionBlendMode("Distortion Blend Mode", Int) = 0 |
|||
[HideInInspector] _DistortionSrcBlend("Distortion Blend Src", Int) = 0 |
|||
[HideInInspector] _DistortionDstBlend("Distortion Blend Dst", Int) = 0 |
|||
[HideInInspector] _DistortionBlurSrcBlend("Distortion Blur Blend Src", Int) = 0 |
|||
[HideInInspector] _DistortionBlurDstBlend("Distortion Blur Blend Dst", Int) = 0 |
|||
[HideInInspector] _DistortionBlurBlendMode("Distortion Blur Blend Mode", Int) = 0 |
|||
_DistortionScale("Distortion Scale", Float) = 1 |
|||
_DistortionBlurScale("Distortion Blur Scale", Float) = 1 |
|||
_DistortionBlurRemapMin("DistortionBlurRemapMin", Float) = 0.0 |
|||
_DistortionBlurRemapMax("DistortionBlurRemapMax", Float) = 1.0 |
|||
|
|||
[ToggleOff] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0 |
|||
_AlphaCutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 |
|||
|
|||
// Transparency |
|||
[Enum(None, 0, Plane, 1, Sphere, 2)]_RefractionMode("Refraction Mode", Int) = 0 |
|||
_IOR("Indice Of Refraction", Range(1.0, 2.5)) = 1.0 |
|||
_ThicknessMultiplier("Thickness Multiplier", Float) = 1.0 |
|||
_TransmittanceColor("Transmittance Color", Color) = (1.0, 1.0, 1.0) |
|||
_ATDistance("Transmittance Absorption Distance", Float) = 1.0 |
|||
[ToggleOff] _PreRefractionPass("PreRefractionPass", Float) = 0.0 |
|||
|
|||
// Stencil state |
|||
[HideInInspector] _StencilRef("_StencilRef", Int) = 2 // StencilLightingUsage.RegularLighting (fixed at compile time) |
|||
|
|||
// Blending state |
|||
[HideInInspector] _SurfaceType("__surfacetype", Float) = 0.0 |
|||
[HideInInspector] _BlendMode("__blendmode", Float) = 0.0 |
|||
[HideInInspector] _SrcBlend("__src", Float) = 1.0 |
|||
[HideInInspector] _DstBlend("__dst", Float) = 0.0 |
|||
[HideInInspector] _ZWrite("__zw", Float) = 1.0 |
|||
[HideInInspector] _CullMode("__cullmode", Float) = 2.0 |
|||
[HideInInspector] _ZTestMode("_ZTestMode", Int) = 8 |
|||
|
|||
[ToggleOff] _EnableFogOnTransparent("Enable Fog", Float) = 1.0 |
|||
[ToggleOff] _EnableBlendModePreserveSpecularLighting("Enable Blend Mode Preserve Specular Lighting", Float) = 1.0 |
|||
|
|||
[ToggleOff] _DoubleSidedEnable("Double sided enable", Float) = 0.0 |
|||
[Enum(None, 0, Mirror, 1, Flip, 2)] _DoubleSidedNormalMode("Double sided normal mode", Float) = 1 |
|||
[HideInInspector] _DoubleSidedConstants("_DoubleSidedConstants", Vector) = (1, 1, -1, 0) |
|||
|
|||
[Enum(UV0, 0, Planar, 4, TriPlanar, 5)] _UVBase("UV Set for base", Float) = 0 |
|||
_TexWorldScale("Scale to apply on world coordinate", Float) = 1.0 |
|||
[HideInInspector] _InvTilingScale("Inverse tiling scale = 2 / (abs(_BaseColorMap_ST.x) + abs(_BaseColorMap_ST.y))", Float) = 1 |
|||
[HideInInspector] _UVMappingMask("_UVMappingMask", Color) = (1, 0, 0, 0) |
|||
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace("NormalMap space", Float) = 0 |
|||
|
|||
[Enum(Subsurface Scattering, 0, Standard, 1, Anisotropy, 2, ClearCoat, 3, Specular Color, 4)] _MaterialID("MaterialId", Int) = 1 // MaterialId.RegularLighting |
|||
|
|||
[Enum(None, 0, Vertex displacement, 1, Pixel displacement, 2)] _DisplacementMode("DisplacementMode", Int) = 0 |
|||
[ToggleOff] _DisplacementLockObjectScale("displacement lock object scale", Float) = 1.0 |
|||
[ToggleOff] _DisplacementLockTilingScale("displacement lock tiling scale", Float) = 1.0 |
|||
[ToggleOff] _DepthOffsetEnable("Depth Offset View space", Float) = 0.0 |
|||
|
|||
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5 |
|||
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15 |
|||
_PPDLodThreshold("Start lod to fade out the POM effect", Range(0.0, 16.0)) = 5 |
|||
_PPDPrimitiveLength("Primitive length for POM", Float) = 1 |
|||
_PPDPrimitiveWidth("Primitive width for POM", Float) = 1 |
|||
[HideInInspector] _InvPrimScale("Inverse primitive scale for non-planar POM", Vector) = (1, 1, 0, 0) |
|||
|
|||
[Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _UVDetail("UV Set for detail", Float) = 0 |
|||
[HideInInspector] _UVDetailsMappingMask("_UVDetailsMappingMask", Color) = (1, 0, 0, 0) |
|||
[ToggleOff] _LinkDetailsWithBase("LinkDetailsWithBase", Float) = 1.0 |
|||
[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1 |
|||
|
|||
// Wind |
|||
[ToggleOff] _EnableWind("Enable Wind", Float) = 0.0 |
|||
_InitialBend("Initial Bend", float) = 1.0 |
|||
_Stiffness("Stiffness", float) = 1.0 |
|||
_Drag("Drag", float) = 1.0 |
|||
_ShiverDrag("Shiver Drag", float) = 0.2 |
|||
_ShiverDirectionality("Shiver Directionality", Range(0.0, 1.0)) = 0.5 |
|||
|
|||
//------------------------------------------------------- |
|||
//Windup Vegetation Wind |
|||
_VegNoise("Noise", 2D) = "white" {} |
|||
_VegWindMask("Wind Mask", 2D) = "white" {} |
|||
_VegPivot("Pivot", Vector) = (0, 0, 0, 0) |
|||
_VegStiffness("Stiffness", Range(0.1, 3.0)) = 1.0 |
|||
_VegAssistantDirectional("Assistant Directional", Vector) = (0, 0, 0, 0) |
|||
_VegWindDirection("Wind Direction", Vector) = (0, 0, 0, 0) |
|||
_VegWindIntensity("Wind Intensity", Range(0.0, 1.0)) = 1.0 |
|||
_VegWindSpeed("Wind Speed", Range(0.0, 2.0)) = 1.0 |
|||
_VegDetailVariation("Detail Variation", Range(0.0, 100.0)) = 1.0 |
|||
_VegLeafShakeScale("Leaf Shake Scale", Range(0.01, 8.0)) = 1.0 |
|||
_VegLeafShakeSpeed("Leaf Shake Speed", Range(0.0, 1.0)) = 1.0 |
|||
_VegLeafShakePower("Leaf Shake Power", Range(0.0, 3.0)) = 1.0 |
|||
_VegPerLeafBendScale("Per-Leaf Bend Scale", Range(0.01, 3.0)) = 1.0 |
|||
_VegPerLeafBendSpeed("Per-Leaf Bend Speed", Range(0.0, 1.0)) = 1.0 |
|||
_VegPerLeafBendPower("Per-Leaf Bend Power", Range(0.0, 5.0)) = 1.0 |
|||
//------------------------------------------------------- |
|||
|
|||
// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor" |
|||
// value that exist to identify if the GI emission need to be enabled. |
|||
// 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 |
|||
} |
|||
|
|||
HLSLINCLUDE |
|||
|
|||
#pragma target 4.5 |
|||
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go futher in dev |
|||
//#pragma enable_d3d11_debug_symbols |
|||
|
|||
//------------------------------------------------------------------------------------- |
|||
// Variant |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
#pragma shader_feature _ALPHATEST_ON |
|||
#pragma shader_feature _DEPTHOFFSET_ON |
|||
#pragma shader_feature _DOUBLESIDED_ON |
|||
#pragma shader_feature _ _VERTEX_DISPLACEMENT _PIXEL_DISPLACEMENT |
|||
#pragma shader_feature _VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE |
|||
#pragma shader_feature _DISPLACEMENT_LOCK_TILING_SCALE |
|||
#pragma shader_feature _PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE |
|||
#pragma shader_feature _VERTEX_WIND |
|||
#pragma shader_feature _ _REFRACTION_PLANE _REFRACTION_SPHERE |
|||
|
|||
#pragma shader_feature _ _MAPPING_PLANAR _MAPPING_TRIPLANAR |
|||
#pragma shader_feature _NORMALMAP_TANGENT_SPACE |
|||
#pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3 |
|||
|
|||
#pragma shader_feature _NORMALMAP |
|||
#pragma shader_feature _MASKMAP |
|||
#pragma shader_feature _BENTNORMALMAP |
|||
#pragma shader_feature _EMISSIVE_COLOR_MAP |
|||
#pragma shader_feature _ENABLESPECULAROCCLUSION |
|||
#pragma shader_feature _HEIGHTMAP |
|||
#pragma shader_feature _TANGENTMAP |
|||
#pragma shader_feature _ANISOTROPYMAP |
|||
#pragma shader_feature _DETAIL_MAP |
|||
#pragma shader_feature _SUBSURFACE_RADIUS_MAP |
|||
#pragma shader_feature _THICKNESSMAP |
|||
#pragma shader_feature _SPECULARCOLORMAP |
|||
|
|||
// Keyword for transparent |
|||
#pragma shader_feature _SURFACE_TYPE_TRANSPARENT |
|||
#pragma shader_feature _ _BLENDMODE_ALPHA _BLENDMODE_ADD _BLENDMODE_MULTIPLY _BLENDMODE_PRE_MULTIPLY |
|||
#pragma shader_feature _BLENDMODE_PRESERVE_SPECULAR_LIGHTING |
|||
#pragma shader_feature _ENABLE_FOG_ON_TRANSPARENT |
|||
|
|||
// MaterialId are used as shader feature to allow compiler to optimize properly |
|||
// 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 |
|||
#pragma shader_feature _ _MATID_SSS _MATID_ANISO _MATID_SPECULAR _MATID_CLEARCOAT |
|||
|
|||
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON |
|||
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED |
|||
#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON |
|||
// enable dithering LOD crossfade |
|||
#pragma multi_compile _ LOD_FADE_CROSSFADE |
|||
// TODO: We should have this keyword only if VelocityInGBuffer is enable, how to do that ? |
|||
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON |
|||
|
|||
//------------------------------------------------------------------------------------- |
|||
// Define |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl |
|||
// Use surface gradient normal mapping as it handle correctly triplanar normal mapping and multiple UVSet |
|||
#define SURFACE_GRADIENT |
|||
// This shader support vertex modification |
|||
#define HAVE_VERTEX_MODIFICATION |
|||
|
|||
//------------------------------------------------------------------------------------- |
|||
// Include |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
#include "../../../Core/ShaderLibrary/Common.hlsl" |
|||
#include "../../../Core/ShaderLibrary/Wind.hlsl" |
|||
#include "../../ShaderPass/FragInputs.hlsl" |
|||
#include "../../ShaderPass/ShaderPass.cs.hlsl" |
|||
|
|||
|
|||
//------------------------------------------------------------------------------------- |
|||
// variable declaration |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
#include "../../Material/Lit/LitProperties.hlsl" |
|||
|
|||
// All our shaders use same name for entry point |
|||
#pragma vertex Vert |
|||
#pragma fragment Frag |
|||
|
|||
ENDHLSL |
|||
|
|||
SubShader |
|||
{ |
|||
Pass |
|||
{ |
|||
Name "GBuffer" // Name is not used |
|||
Tags { "LightMode" = "GBuffer" } // This will be only for opaque object based on the RenderQueue index |
|||
|
|||
Cull [_CullMode] |
|||
|
|||
Stencil |
|||
{ |
|||
Ref [_StencilRef] |
|||
Comp Always |
|||
Pass Replace |
|||
} |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#define ATTRIBUTES_NEED_TEXCOORD0 |
|||
#define ATTRIBUTES_NEED_COLOR |
|||
|
|||
#define SHADERPASS SHADERPASS_GBUFFER |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Material/Material.hlsl" |
|||
#include "../Lit/ShaderPass/LitSharePass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassGBuffer.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
// This pass is the same as GBuffer only it does not do alpha test (the clip instruction is removed) |
|||
// This is due to the fact that on GCN, any shader with a clip instruction cannot benefit from HiZ so when we do a prepass, in order to get the most performance, we need to make a special case in the subsequent GBuffer pass. |
|||
Pass |
|||
{ |
|||
Name "GBufferWithPrepass" // Name is not used |
|||
Tags { "LightMode" = "GBufferWithPrepass" } // This will be only for opaque object based on the RenderQueue index |
|||
|
|||
Cull [_CullMode] |
|||
|
|||
Stencil |
|||
{ |
|||
Ref [_StencilRef] |
|||
Comp Always |
|||
Pass Replace |
|||
} |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#define SHADERPASS SHADERPASS_GBUFFER |
|||
#define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Material/Material.hlsl" |
|||
#include "../Lit/ShaderPass/LitSharePass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassGBuffer.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Name "GBufferDebugDisplay" // Name is not used |
|||
Tags{ "LightMode" = "GBufferDebugDisplay" } // This will be only for opaque object based on the RenderQueue index |
|||
|
|||
Cull [_CullMode] |
|||
|
|||
Stencil |
|||
{ |
|||
Ref [_StencilRef] |
|||
Comp Always |
|||
Pass Replace |
|||
} |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#define DEBUG_DISPLAY |
|||
#define SHADERPASS SHADERPASS_GBUFFER |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Debug/DebugDisplay.hlsl" |
|||
#include "../../Material/Material.hlsl" |
|||
#include "../Lit/ShaderPass/LitSharePass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassGBuffer.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
// Extracts information for lightmapping, GI (emission, albedo, ...) |
|||
// This pass it not used during regular rendering. |
|||
Pass |
|||
{ |
|||
Name "META" |
|||
Tags{ "LightMode" = "Meta" } |
|||
|
|||
Cull Off |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
// Lightmap memo |
|||
// DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light, |
|||
// both direct and indirect lighting) will hand up in the "regular" lightmap->LIGHTMAP_ON. |
|||
|
|||
#define SHADERPASS SHADERPASS_LIGHT_TRANSPORT |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Material/Material.hlsl" |
|||
#include "../Lit/ShaderPass/LitSharePass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassLightTransport.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Name "ShadowCaster" |
|||
Tags{ "LightMode" = "ShadowCaster" } |
|||
|
|||
Cull[_CullMode] |
|||
|
|||
ZClip Off |
|||
ZWrite On |
|||
ZTest LEqual |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
//Need to force reading of uv + color for vertex animated shadows. |
|||
#define ATTRIBUTES_NEED_TEXCOORD0 |
|||
#define ATTRIBUTES_NEED_COLOR |
|||
|
|||
#define SHADERPASS SHADERPASS_SHADOWS |
|||
#define USE_LEGACY_UNITY_MATRIX_VARIABLES |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Material/Material.hlsl" |
|||
#include "../Lit/ShaderPass/LitDepthPass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Name "DepthOnly" |
|||
Tags{ "LightMode" = "DepthOnly" } |
|||
|
|||
Cull[_CullMode] |
|||
|
|||
ZWrite On |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#define SHADERPASS SHADERPASS_DEPTH_ONLY |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Material/Material.hlsl" |
|||
#include "../Lit/ShaderPass/LitDepthPass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Name "Motion Vectors" |
|||
Tags{ "LightMode" = "MotionVectors" } // Caution, this need to be call like this to setup the correct parameters by C++ (legacy Unity) |
|||
|
|||
Cull[_CullMode] |
|||
|
|||
ZWrite Off // TODO: Test Z equal here. |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#define SHADERPASS SHADERPASS_VELOCITY |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Material/Material.hlsl" |
|||
#include "../Lit/ShaderPass/LitVelocityPass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassVelocity.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Name "Distortion" // Name is not used |
|||
Tags { "LightMode" = "DistortionVectors" } // This will be only for transparent object based on the RenderQueue index |
|||
|
|||
Blend [_DistortionSrcBlend] [_DistortionDstBlend], [_DistortionBlurSrcBlend] [_DistortionBlurDstBlend] |
|||
BlendOp Add, [_DistortionBlurBlendOp] |
|||
ZTest [_ZTestMode] |
|||
ZWrite off |
|||
Cull [_CullMode] |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#define SHADERPASS SHADERPASS_DISTORTION |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Material/Material.hlsl" |
|||
#include "../Lit/ShaderPass/LitDistortionPass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassDistortion.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Name "Forward" // Name is not used |
|||
Tags { "LightMode" = "Forward" } // This will be only for transparent object based on the RenderQueue index |
|||
|
|||
Blend [_SrcBlend] [_DstBlend] |
|||
ZWrite [_ZWrite] |
|||
Cull [_CullMode] |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#define SHADERPASS SHADERPASS_FORWARD |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Lighting/Forward.hlsl" |
|||
// TEMP until pragma work in include |
|||
#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS |
|||
|
|||
#include "../../Lighting/Lighting.hlsl" |
|||
#include "../Lit/ShaderPass/LitSharePass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassForward.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Name "ForwardDebugDisplay" // Name is not used |
|||
Tags{ "LightMode" = "ForwardDebugDisplay" } // This will be only for transparent object based on the RenderQueue index |
|||
|
|||
Blend[_SrcBlend][_DstBlend] |
|||
ZWrite[_ZWrite] |
|||
Cull[_CullMode] |
|||
|
|||
HLSLPROGRAM |
|||
|
|||
#define DEBUG_DISPLAY |
|||
#define SHADERPASS SHADERPASS_FORWARD |
|||
#include "../../ShaderVariables.hlsl" |
|||
#include "../../Debug/DebugDisplay.hlsl" |
|||
#include "../../Lighting/Forward.hlsl" |
|||
// TEMP until pragma work in include |
|||
#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS |
|||
|
|||
#include "../../Lighting/Lighting.hlsl" |
|||
#include "../Lit/ShaderPass/LitSharePass.hlsl" |
|||
#include "VegetationData.hlsl" |
|||
#include "../../ShaderPass/ShaderPassForward.hlsl" |
|||
|
|||
ENDHLSL |
|||
} |
|||
} |
|||
|
|||
CustomEditor "Experimental.Rendering.HDPipeline.VegetationGUI" |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ff1b756ebf5550048bed17a617e8f5b0 |
|||
timeCreated: 1509479425 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#include "../../../Core/ShaderLibrary/SampleUVMapping.hlsl" |
|||
#include "../MaterialUtilities.hlsl" |
|||
|
|||
//------------------------------------------------------------------------------------- |
|||
// Fill SurfaceData/Builtin data function |
|||
//------------------------------------------------------------------------------------- |
|||
|
|||
// TODO: move this function to commonLighting.hlsl once validated it work correctly |
|||
float GetSpecularOcclusionFromBentAO(float3 V, float3 bentNormalWS, SurfaceData surfaceData) |
|||
{ |
|||
// Retrieve cone angle |
|||
// Ambient occlusion is cosine weighted, thus use following equation. See slide 129 |
|||
float cosAv = sqrt(1.0 - surfaceData.ambientOcclusion); |
|||
float roughness = max(PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness), 0.01); // Clamp to 0.01 to avoid edge cases |
|||
float cosAs = exp2(-3.32193 * Sqr(roughness)); |
|||
float cosB = dot(bentNormalWS, reflect(-V, surfaceData.normalWS)); |
|||
|
|||
return SphericalCapIntersectionSolidArea(cosAv, cosAs, cosB) / (TWO_PI * (1.0 - cosAs)); |
|||
} |
|||
|
|||
void GetBuiltinData(FragInputs input, SurfaceData surfaceData, float alpha, float3 bentNormalWS, float depthOffset, out BuiltinData builtinData) |
|||
{ |
|||
// Builtin Data |
|||
builtinData.opacity = alpha; |
|||
|
|||
// TODO: Sample lightmap/lightprobe/volume proxy |
|||
// This should also handle projective lightmap |
|||
builtinData.bakeDiffuseLighting = SampleBakedGI(input.positionWS, bentNormalWS, input.texCoord1, input.texCoord2); |
|||
|
|||
// It is safe to call this function here as surfaceData have been filled |
|||
// We want to know if we must enable transmission on GI for SSS material, if the material have no SSS, this code will be remove by the compiler. |
|||
BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData); |
|||
if (bsdfData.enableTransmission) |
|||
{ |
|||
// For now simply recall the function with inverted normal, the compiler should be able to optimize the lightmap case to not resample the directional lightmap |
|||
// however it will not optimize the lightprobe case due to the proxy volume relying on dynamic if (we rely must get right of this dynamic if), not a problem for SH9, but a problem for proxy volume. |
|||
// TODO: optimize more this code. |
|||
// Add GI transmission contribution by resampling the GI for inverted vertex normal |
|||
builtinData.bakeDiffuseLighting += SampleBakedGI(input.positionWS, -input.worldToTangent[2], input.texCoord1, input.texCoord2) * bsdfData.transmittance; |
|||
} |
|||
|
|||
// Emissive Intensity is only use here, but is part of BuiltinData to enforce UI parameters as we want the users to fill one color and one intensity |
|||
builtinData.emissiveIntensity = _EmissiveIntensity; // We still store intensity here so we can reuse it with debug code |
|||
|
|||
builtinData.emissiveColor = _EmissiveColor * builtinData.emissiveIntensity * lerp(float3(1.0, 1.0, 1.0), surfaceData.baseColor.rgb, _AlbedoAffectEmissive); |
|||
#ifdef _EMISSIVE_COLOR_MAP |
|||
builtinData.emissiveColor *= SAMPLE_TEXTURE2D(_EmissiveColorMap, sampler_EmissiveColorMap, input.texCoord0).rgb; |
|||
#endif |
|||
|
|||
builtinData.velocity = float2(0.0, 0.0); |
|||
|
|||
#if (SHADERPASS == SHADERPASS_DISTORTION) || defined(DEBUG_DISPLAY) |
|||
float3 distortion = SAMPLE_TEXTURE2D(_DistortionVectorMap, sampler_DistortionVectorMap, input.texCoord0).rgb; |
|||
builtinData.distortion = distortion.rg * _DistortionScale; |
|||
builtinData.distortionBlur = clamp(distortion.b * _DistortionBlurScale, 0.0, 1.0) * (_DistortionBlurRemapMax - _DistortionBlurRemapMin) + _DistortionBlurRemapMin; |
|||
#else |
|||
builtinData.distortion = float2(0.0, 0.0); |
|||
builtinData.distortionBlur = 0.0; |
|||
#endif |
|||
|
|||
builtinData.depthOffset = depthOffset; |
|||
} |
|||
|
|||
// Struct that gather UVMapping info of all layers + common calculation |
|||
// This is use to abstract the mapping that can differ on layers |
|||
struct LayerTexCoord |
|||
{ |
|||
#ifndef LAYERED_LIT_SHADER |
|||
UVMapping base; |
|||
UVMapping details; |
|||
#else |
|||
// Regular texcoord |
|||
UVMapping base0; |
|||
UVMapping base1; |
|||
UVMapping base2; |
|||
UVMapping base3; |
|||
|
|||
UVMapping details0; |
|||
UVMapping details1; |
|||
UVMapping details2; |
|||
UVMapping details3; |
|||
|
|||
// Dedicated for blend mask |
|||
UVMapping blendMask; |
|||
#endif |
|||
|
|||
// Store information that will be share by all UVMapping |
|||
float3 vertexNormalWS; // TODO: store also object normal map for object triplanar |
|||
float3 triplanarWeights; |
|||
|
|||
#ifdef SURFACE_GRADIENT |
|||
// tangent basis for each UVSet - up to 4 for now |
|||
float3 vertexTangentWS0, vertexBitangentWS0; |
|||
float3 vertexTangentWS1, vertexBitangentWS1; |
|||
float3 vertexTangentWS2, vertexBitangentWS2; |
|||
float3 vertexTangentWS3, vertexBitangentWS3; |
|||
#endif |
|||
}; |
|||
|
|||
#ifdef SURFACE_GRADIENT |
|||
void GenerateLayerTexCoordBasisTB(FragInputs input, inout LayerTexCoord layerTexCoord) |
|||
{ |
|||
float3 vertexNormalWS = input.worldToTangent[2]; |
|||
|
|||
layerTexCoord.vertexTangentWS0 = input.worldToTangent[0]; |
|||
layerTexCoord.vertexBitangentWS0 = input.worldToTangent[1]; |
|||
|
|||
// TODO: We should use relative camera position here - This will be automatic when we will move to camera relative space. |
|||
float3 dPdx = ddx_fine(input.positionWS); |
|||
float3 dPdy = ddy_fine(input.positionWS); |
|||
|
|||
float3 sigmaX = dPdx - dot(dPdx, vertexNormalWS) * vertexNormalWS; |
|||
float3 sigmaY = dPdy - dot(dPdy, vertexNormalWS) * vertexNormalWS; |
|||
//float flipSign = dot(sigmaY, cross(vertexNormalWS, sigmaX) ) ? -1.0 : 1.0; |
|||
float flipSign = dot(dPdy, cross(vertexNormalWS, dPdx)) < 0.0 ? -1.0 : 1.0; // gives same as the commented out line above |
|||
|
|||
// TODO: Optimize! The compiler will not be able to remove the tangent space that are not use because it can't know due to our UVMapping constant we use for both base and details |
|||
// To solve this we should track which UVSet is use for normal mapping... Maybe not as simple as it sounds |
|||
SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord1, layerTexCoord.vertexTangentWS1, layerTexCoord.vertexBitangentWS1); |
|||
#if defined(_REQUIRE_UV2) || defined(_REQUIRE_UV3) |
|||
SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord2, layerTexCoord.vertexTangentWS2, layerTexCoord.vertexBitangentWS2); |
|||
#endif |
|||
#if defined(_REQUIRE_UV3) |
|||
SurfaceGradientGenBasisTB(vertexNormalWS, sigmaX, sigmaY, flipSign, input.texCoord3, layerTexCoord.vertexTangentWS3, layerTexCoord.vertexBitangentWS3); |
|||
#endif |
|||
} |
|||
#endif |
|||
|
|||
#ifndef LAYERED_LIT_SHADER |
|||
|
|||
// Want to use only one sampler for normalmap/bentnormalmap either we use OS or TS. And either we have normal map or bent normal or both. |
|||
#ifdef _NORMALMAP_TANGENT_SPACE |
|||
#if defined(_NORMALMAP) |
|||
#define SAMPLER_NORMALMAP_IDX sampler_NormalMap |
|||
#elif defined(_BENTNORMALMAP) |
|||
#define SAMPLER_NORMALMAP_IDX sampler_BentNormalMap |
|||
#endif |
|||
#else |
|||
#if defined(_NORMALMAP) |
|||
#define SAMPLER_NORMALMAP_IDX sampler_NormalMapOS |
|||
#elif defined(_BENTNORMALMAP) |
|||
#define SAMPLER_NORMALMAP_IDX sampler_BentNormalMapOS |
|||
#endif |
|||
#endif |
|||
|
|||
#define SAMPLER_DETAILMAP_IDX sampler_DetailMap |
|||
#define SAMPLER_MASKMAP_IDX sampler_MaskMap |
|||
#define SAMPLER_HEIGHTMAP_IDX sampler_HeightMap |
|||
|
|||
#define SAMPLER_SUBSURFACE_RADIUSMAP_IDX sampler_SubsurfaceRadiusMap |
|||
#define SAMPLER_THICKNESSMAP_IDX sampler_ThicknessMap |
|||
|
|||
// include LitDataIndividualLayer to define GetSurfaceData |
|||
#define LAYER_INDEX 0 |
|||
#define ADD_IDX(Name) Name |
|||
#define ADD_ZERO_IDX(Name) Name |
|||
#ifdef _NORMALMAP |
|||
#define _NORMALMAP_IDX |
|||
#endif |
|||
#ifdef _NORMALMAP_TANGENT_SPACE |
|||
#define _NORMALMAP_TANGENT_SPACE_IDX |
|||
#endif |
|||
#ifdef _DETAIL_MAP |
|||
#define _DETAIL_MAP_IDX |
|||
#endif |
|||
#ifdef _SUBSURFACE_RADIUS_MAP |
|||
#define _SUBSURFACE_RADIUS_MAP_IDX |
|||
#endif |
|||
#ifdef _THICKNESSMAP |
|||
#define _THICKNESSMAP_IDX |
|||
#endif |
|||
#ifdef _MASKMAP |
|||
#define _MASKMAP_IDX |
|||
#endif |
|||
#ifdef _BENTNORMALMAP |
|||
#define _BENTNORMALMAP_IDX |
|||
#endif |
|||
#include "../Lit/LitDataIndividualLayer.hlsl" |
|||
|
|||
// This maybe call directly by tessellation (domain) shader, thus all part regarding surface gradient must be done |
|||
// in function with FragInputs input as parameters |
|||
// layerTexCoord must have been initialize to 0 outside of this function |
|||
void GetLayerTexCoord(float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3, |
|||
float3 positionWS, float3 vertexNormalWS, inout LayerTexCoord layerTexCoord) |
|||
{ |
|||
layerTexCoord.vertexNormalWS = vertexNormalWS; |
|||
layerTexCoord.triplanarWeights = ComputeTriplanarWeights(vertexNormalWS); |
|||
|
|||
int mappingType = UV_MAPPING_UVSET; |
|||
#if defined(_MAPPING_PLANAR) |
|||
mappingType = UV_MAPPING_PLANAR; |
|||
#elif defined(_MAPPING_TRIPLANAR) |
|||
mappingType = UV_MAPPING_TRIPLANAR; |
|||
#endif |
|||
|
|||
// Be sure that the compiler is aware that we don't use UV1 to UV3 for main layer so it can optimize code |
|||
ComputeLayerTexCoord( texCoord0, texCoord1, texCoord2, texCoord3, float4(1.0, 0.0, 0.0, 0.0), _UVDetailsMappingMask, |
|||
_BaseColorMap_ST.xy, _BaseColorMap_ST.zw, _DetailMap_ST.xy, _DetailMap_ST.zw, 1.0, _LinkDetailsWithBase, |
|||
positionWS, _TexWorldScale, |
|||
mappingType, layerTexCoord); |
|||
} |
|||
|
|||
// This is call only in this file |
|||
// layerTexCoord must have been initialize to 0 outside of this function |
|||
void GetLayerTexCoord(FragInputs input, inout LayerTexCoord layerTexCoord) |
|||
{ |
|||
#ifdef SURFACE_GRADIENT |
|||
GenerateLayerTexCoordBasisTB(input, layerTexCoord); |
|||
#endif |
|||
|
|||
GetLayerTexCoord( input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3, |
|||
input.positionWS, input.worldToTangent[2].xyz, layerTexCoord); |
|||
} |
|||
|
|||
#include "../Lit/LitDataDisplacement.hlsl" |
|||
|
|||
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData) |
|||
{ |
|||
#ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group |
|||
LODDitheringTransition(posInput.unPositionSS, unity_LODFade.x); |
|||
#endif |
|||
|
|||
ApplyDoubleSidedFlipOrMirror(input); // Apply double sided flip on the vertex normal |
|||
|
|||
LayerTexCoord layerTexCoord; |
|||
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord); |
|||
GetLayerTexCoord(input, layerTexCoord); |
|||
|
|||
float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord); |
|||
|
|||
#ifdef _DEPTHOFFSET_ON |
|||
ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput); |
|||
#endif |
|||
|
|||
// We perform the conversion to world of the normalTS outside of the GetSurfaceData |
|||
// so it allow us to correctly deal with detail normal map and optimize the code for the layered shaders |
|||
float3 normalTS; |
|||
float3 bentNormalTS; |
|||
float3 bentNormalWS; |
|||
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData, normalTS, bentNormalTS); |
|||
GetNormalWS(input, V, normalTS, surfaceData.normalWS); |
|||
// Use bent normal to sample GI if available |
|||
#ifdef _BENTNORMALMAP |
|||
GetNormalWS(input, V, bentNormalTS, bentNormalWS); |
|||
#else |
|||
bentNormalWS = surfaceData.normalWS; |
|||
#endif |
|||
|
|||
// By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. |
|||
// If user provide bent normal then we process a better term |
|||
#if defined(_BENTNORMALMAP) && defined(_ENABLESPECULAROCCLUSION) |
|||
// If we have bent normal and ambient occlusion, process a specular occlusion |
|||
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData); |
|||
#elif defined(_MASKMAP) |
|||
surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(dot(surfaceData.normalWS, V), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); |
|||
#else |
|||
surfaceData.specularOcclusion = 1.0; |
|||
#endif |
|||
|
|||
// This is use with anisotropic material |
|||
surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); |
|||
|
|||
// Caution: surfaceData must be fully initialize before calling GetBuiltinData |
|||
GetBuiltinData(input, surfaceData, alpha, bentNormalWS, depthOffset, builtinData); |
|||
} |
|||
|
|||
#include "VegetationDataMeshModification.hlsl" |
|||
|
|||
#endif // #ifndef LAYERED_LIT_SHADER |
|
|||
fileFormatVersion: 2 |
|||
guid: 5b0a17e7a97f28a4db53bcf95737633f |
|||
timeCreated: 1509483930 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
float3 GetVertexDisplacement(float3 positionWS, float3 normalWS, float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3, float4 vertexColor) |
|||
{ |
|||
// This call will work for both LayeredLit and Lit shader |
|||
LayerTexCoord layerTexCoord; |
|||
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord); |
|||
GetLayerTexCoord(texCoord0, texCoord1, texCoord2, texCoord3, positionWS, normalWS, layerTexCoord); |
|||
|
|||
// TODO: do this algorithm for lod fetching as lod not available in vertex/domain shader |
|||
// http://www.sebastiansylvan.com/post/the-problem-with-tessellation-in-directx-11/ |
|||
float lod = 0.0; |
|||
return ComputePerVertexDisplacement(layerTexCoord, vertexColor, lod) * normalWS; |
|||
} |
|||
|
|||
#include "VegetationWind.hlsl" |
|||
|
|||
void ApplyVertexModification(AttributesMesh input, float3 normalWS, inout float3 positionWS) |
|||
{ |
|||
#if defined(_VERTEX_DISPLACEMENT) |
|||
|
|||
positionWS += GetVertexDisplacement(positionWS, normalWS, |
|||
#ifdef ATTRIBUTES_NEED_TEXCOORD0 |
|||
input.uv0, |
|||
#else |
|||
float2(0.0, 0.0), |
|||
#endif |
|||
#ifdef ATTRIBUTES_NEED_TEXCOORD1 |
|||
input.uv1, |
|||
#else |
|||
float2(0.0, 0.0), |
|||
#endif |
|||
#ifdef ATTRIBUTES_NEED_TEXCOORD2 |
|||
input.uv2, |
|||
#else |
|||
float2(0.0, 0.0), |
|||
#endif |
|||
#ifdef ATTRIBUTES_NEED_TEXCOORD3 |
|||
input.uv3, |
|||
#else |
|||
float2(0.0, 0.0), |
|||
#endif |
|||
#ifdef ATTRIBUTES_NEED_COLOR |
|||
input.color |
|||
#else |
|||
float4(0.0, 0.0, 0.0, 0.0) |
|||
#endif |
|||
); |
|||
#endif |
|||
|
|||
#ifdef _VERTEX_WIND |
|||
float3 rootWP = mul(GetObjectToWorldMatrix(), float4(0, 0, 0, 1)).xyz; |
|||
ApplyWindDisplacement(positionWS, normalWS, rootWP, _Stiffness, _Drag, _ShiverDrag, _ShiverDirectionality, _InitialBend, input.color.a, _Time); |
|||
#endif |
|||
|
|||
//Main entry point to custom Windup vegetation wind |
|||
//------------------------------------------------- |
|||
#if defined(ATTRIBUTES_NEED_TEXCOORD0) && defined(ATTRIBUTES_NEED_COLOR) |
|||
ApplyVegetationWind(positionWS, input.positionOS, normalWS, input.uv0, input.color, _Time); |
|||
#endif |
|||
//------------------------------------------------- |
|||
} |
|||
|
|||
#ifdef TESSELLATION_ON |
|||
|
|||
float4 GetTessellationFactors(float3 p0, float3 p1, float3 p2, float3 n0, float3 n1, float3 n2) |
|||
{ |
|||
float maxDisplacement = GetMaxDisplacement(); |
|||
|
|||
|
|||
// For tessellation we want to process tessellation factor always from the point of view of the camera (to be consistent and avoid Z-fight). |
|||
// For the culling part however we want to use the current view (shadow view). |
|||
// Thus the following code play with both. |
|||
|
|||
#if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_SHADOWS) |
|||
bool frustumCulledCurrentView = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])_FrustumPlanes); // _FrustumPlanes are primary camera planes |
|||
bool frustumCulledMainView = false; |
|||
#else |
|||
bool frustumCulledCurrentView = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])unity_CameraWorldClipPlanes); // unity_CameraWorldClipPlanes is set by legacy Unity in case of shadow and contain shadow view plan |
|||
// In the case of shadow, we don't want to tessellate anything that is not seen by the main view frustum. It can result in minor popping of tessellation into a shadow but we can't afford it anyway. |
|||
bool frustumCulledMainView = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])_FrustumPlanes); |
|||
#endif |
|||
|
|||
bool faceCull = false; |
|||
|
|||
#ifndef _DOUBLESIDED_ON |
|||
if (_TessellationBackFaceCullEpsilon > -0.99) // Is backface culling enabled ? |
|||
{ |
|||
// Handle transform mirroring (like negative scaling) |
|||
// Caution: don't change p1/p2 directly as it is use later |
|||
float3 backfaceP1 = unity_WorldTransformParams.w < 0.0 ? p2 : p1; |
|||
float3 backfaceP2 = unity_WorldTransformParams.w < 0.0 ? p1 : p2; |
|||
|
|||
faceCull = BackFaceCullTriangle(p0, backfaceP1, backfaceP2, _TessellationBackFaceCullEpsilon, GetCurrentViewPosition()); // Use shadow view |
|||
} |
|||
#endif |
|||
|
|||
if (frustumCulledCurrentView || faceCull) |
|||
{ |
|||
// Settings factor to 0 will kill the triangle |
|||
return float4(0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
|
|||
// See comment above: |
|||
// During shadow passes, we decide that anything outside the main view frustum should not be tessellated. |
|||
if (frustumCulledMainView) |
|||
{ |
|||
return float4(1.0, 1.0, 1.0, 1.0); |
|||
} |
|||
|
|||
// We use the parameters of the primary (scene view) camera in order |
|||
// to have identical tessellation levels for both the scene view and |
|||
// shadow views. Otherwise, depth comparisons become meaningless! |
|||
float3 tessFactor = float3(1.0, 1.0, 1.0); |
|||
|
|||
// Adaptive screen space tessellation |
|||
if (_TessellationFactorTriangleSize > 0.0) |
|||
{ |
|||
// return a value between 0 and 1 |
|||
tessFactor *= GetScreenSpaceTessFactor( p0, p1, p2, _ViewProjMatrix, _ScreenSize, _TessellationFactorTriangleSize); // Use primary camera view |
|||
} |
|||
|
|||
// Distance based tessellation |
|||
if (_TessellationFactorMaxDistance > 0.0) |
|||
{ |
|||
float3 distFactor = GetDistanceBasedTessFactor(p0, p1, p2, GetPrimaryCameraPosition(), _TessellationFactorMinDistance, _TessellationFactorMaxDistance); // Use primary camera view |
|||
// We square the disance factor as it allow a better percptual descrease of vertex density. |
|||
tessFactor *= distFactor * distFactor; |
|||
} |
|||
|
|||
tessFactor *= _TessellationFactor; |
|||
|
|||
// TessFactor below 1.0 have no effect. At 0 it kill the triangle, so clamp it to 1.0 |
|||
tessFactor.xyz = float3(max(1.0, tessFactor.x), max(1.0, tessFactor.y), max(1.0, tessFactor.z)); |
|||
|
|||
return CalcTriEdgeTessFactors(tessFactor); |
|||
} |
|||
|
|||
// tessellationFactors |
|||
// x - 1->2 edge |
|||
// y - 2->0 edge |
|||
// z - 0->1 edge |
|||
// w - inside tessellation factor |
|||
void ApplyTessellationModification(VaryingsMeshToDS input, float3 normalWS, inout float3 positionWS) |
|||
{ |
|||
#if defined(_TESSELLATION_DISPLACEMENT) |
|||
|
|||
positionWS += GetVertexDisplacement(positionWS, normalWS, |
|||
#ifdef VARYINGS_DS_NEED_TEXCOORD0 |
|||
input.texCoord0, |
|||
#else |
|||
float2(0.0, 0.0), |
|||
#endif |
|||
#ifdef VARYINGS_DS_NEED_TEXCOORD1 |
|||
input.texCoord1, |
|||
#else |
|||
float2(0.0, 0.0), |
|||
#endif |
|||
#ifdef VARYINGS_DS_NEED_TEXCOORD2 |
|||
input.texCoord2, |
|||
#else |
|||
float2(0.0, 0.0), |
|||
#endif |
|||
#ifdef VARYINGS_DS_NEED_TEXCOORD3 |
|||
input.texCoord3, |
|||
#else |
|||
float2(0.0, 0.0), |
|||
#endif |
|||
#ifdef VARYINGS_DS_NEED_COLOR |
|||
input.color |
|||
#else |
|||
float4(0.0, 0.0, 0.0, 0.0) |
|||
#endif |
|||
); |
|||
#endif // _TESSELLATION_DISPLACEMENT |
|||
} |
|||
|
|||
#endif // #ifdef TESSELLATION_ON |
|
|||
fileFormatVersion: 2 |
|||
guid: d90d65d4c99d26c4e92f6677ac35cbba |
|||
timeCreated: 1509484407 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
TEXTURE2D(_VegNoise); |
|||
SAMPLER2D(sampler_VegNoise); |
|||
|
|||
TEXTURE2D(_VegWindMask); |
|||
SAMPLER2D(sampler_VegWindMask); |
|||
|
|||
CBUFFER_START(_PerMaterial) |
|||
float4 _VegPivot; |
|||
float _VegStiffness; |
|||
float4 _VegAssistantDirectional; |
|||
float4 _VegWindDirection; |
|||
float _VegWindIntensity; |
|||
float _VegWindSpeed; |
|||
float _VegDetailVariation; |
|||
float _VegLeafShakeScale; |
|||
float _VegLeafShakeSpeed; |
|||
float _VegLeafShakePower; |
|||
float _VegPerLeafBendScale; |
|||
float _VegPerLeafBendSpeed; |
|||
float _VegPerLeafBendPower; |
|||
CBUFFER_END |
|
|||
fileFormatVersion: 2 |
|||
guid: b9abd5b973633b846b6119a4ec8e8a54 |
|||
timeCreated: 1509484592 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#include "VegetationProperties.hlsl" |
|||
|
|||
void ApplyVegetationWind( inout float3 positionWS, |
|||
float3 positionOS, |
|||
float3 normalW, |
|||
float2 texcoord, |
|||
float4 weights, |
|||
float4 time) |
|||
{ |
|||
float3 normalWS = TransformObjectToWorldNormal(normalW); |
|||
float3 windDir = normalize(_VegWindDirection.xyz); |
|||
float windSpeedWS = _VegWindSpeed * time.y * 3.0; |
|||
|
|||
float vertexToPivotDist = distance(positionOS, float3(0.0, 0.0, 0.0)); |
|||
float distOffset = vertexToPivotDist / 128.0; |
|||
|
|||
float3 posToPivot = positionWS.xyz - _VegPivot.xyz; |
|||
float3 shiftPivot = _VegPivot.xyz + normalize(posToPivot) * vertexToPivotDist * (1.0 + weights.x); |
|||
float3 posToShiftPivot = positionWS.xyz - shiftPivot.xyz; |
|||
|
|||
float3 shiftPivotDistOffset = distance(positionOS, shiftPivot) / 64.0; |
|||
float3 axis = cross(posToShiftPivot, windDir); |
|||
|
|||
float4 noiseUV = time.yyyy * 0.05f; |
|||
//float4 noise = tex2Dlod(sampler_VegNoise, float4(noiseUV.x, 0.5, 0.0, 0.0)); |
|||
//#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) |
|||
float4 noise = SAMPLE_TEXTURE2D_LOD(_VegNoise, sampler_VegNoise, float2(noiseUV.x, 0.5), 0.0); |
|||
|
|||
half rad = radians(sin(windSpeedWS + (distOffset + shiftPivotDistOffset) / _VegStiffness) * distOffset * _VegWindIntensity * noise.x); |
|||
half radAssist = radians(sin(windSpeedWS) * distOffset * _VegWindIntensity * noise.x); |
|||
|
|||
float3x3 rP = float3x3(axis.x * axis.x * (1.0f - cos(rad)) + cos(rad), axis.x * axis.y * (1.0f - cos(rad)) + axis.z * sin(rad), axis.x * axis.z * (1.0f - cos(rad)) - axis.y * sin(rad), |
|||
axis.x * axis.y * (1.0f - cos(rad)) - axis.z * sin(rad), axis.y * axis.y * (1.0f - cos(rad)) + cos(rad), axis.y * axis.z * (1.0f - cos(rad)) + axis.x * sin(rad), |
|||
axis.x * axis.z * (1.0f - cos(rad)) + axis.y * sin(rad), axis.y * axis.z * (1.0f - cos(rad)) - axis.x * sin(rad), axis.z * axis.z * (1.0f - cos(rad)) + cos(rad)); |
|||
|
|||
float3x3 rPAssist = float3x3(_VegAssistantDirectional.x * _VegAssistantDirectional.x * (1.0f - cos(radAssist)) + cos(radAssist), _VegAssistantDirectional.x * _VegAssistantDirectional.y * (1.0f - cos(radAssist)) + _VegAssistantDirectional.z * sin(radAssist), _VegAssistantDirectional.x * _VegAssistantDirectional.z * (1.0f - cos(radAssist)) - _VegAssistantDirectional.y * sin(radAssist), |
|||
_VegAssistantDirectional.x * _VegAssistantDirectional.y * (1.0f - cos(radAssist)) - _VegAssistantDirectional.z * sin(radAssist), _VegAssistantDirectional.y * _VegAssistantDirectional.y * (1.0f - cos(radAssist)) + cos(radAssist), _VegAssistantDirectional.y * _VegAssistantDirectional.z * (1.0f - cos(radAssist)) + _VegAssistantDirectional.x * sin(radAssist), |
|||
_VegAssistantDirectional.x * _VegAssistantDirectional.z * (1.0f - cos(radAssist)) + _VegAssistantDirectional.y * sin(radAssist), _VegAssistantDirectional.y * _VegAssistantDirectional.z * (1.0f - cos(radAssist)) - _VegAssistantDirectional.x * sin(radAssist), _VegAssistantDirectional.z * _VegAssistantDirectional.z * (1.0f - cos(radAssist)) + cos(radAssist)); |
|||
|
|||
float detailVariation = weights.g * _VegDetailVariation; |
|||
|
|||
float3 leafShakeDeform = sin((positionWS / _VegLeafShakeScale + windSpeedWS * 5.0 * _VegLeafShakeSpeed) + detailVariation); |
|||
leafShakeDeform = clamp(leafShakeDeform, -1.0, 1.0); |
|||
leafShakeDeform *= _VegWindIntensity * noise * (1.0 + weights.g); |
|||
float4 perLeafMask = SAMPLE_TEXTURE2D_LOD(_VegWindMask, sampler_VegWindMask, float2(texcoord.x, texcoord.y), 0.0); |
|||
leafShakeDeform *= (normalWS * perLeafMask.r + (-normalWS) * perLeafMask.g) * _VegLeafShakePower; |
|||
|
|||
float3 perLeafBending = sin((positionWS / _VegPerLeafBendScale + windSpeedWS * 3.0 * _VegPerLeafBendSpeed) * (windDir+_VegAssistantDirectional) + detailVariation + shiftPivotDistOffset / 0.5); |
|||
perLeafBending *= _VegWindIntensity * noise; |
|||
perLeafBending = float3(0.0, perLeafBending.y, 0.0f); |
|||
perLeafBending *= weights.b * perLeafMask.b * (1.0 + weights.g) * _VegPerLeafBendPower; |
|||
|
|||
float3 rPAssistpos = mul(rPAssist, positionOS); |
|||
float3 pos = mul(rP, rPAssistpos) + perLeafBending + leafShakeDeform; |
|||
positionWS = mul(UNITY_MATRIX_M, float4(pos, 1.0)).xyz; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fa32c39574d2ed444880dfb634c62aba |
|||
timeCreated: 1509485943 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: e358ae90302a03e409bc067e832525c5 |
|||
folderAsset: yes |
|||
timeCreated: 1509071155 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 99b28ae1899c34841bb5edf61823d22d |
|||
folderAsset: yes |
|||
timeCreated: 1504677840 |
|||
licenseType: Free |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 6bee56a72daba3d479259196d046864c |
|||
folderAsset: yes |
|||
timeCreated: 1504677840 |
|||
licenseType: Free |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: dfab746be3b7dc34ebec9f9c63bc9a74 |
|||
folderAsset: yes |
|||
timeCreated: 1504677840 |
|||
licenseType: Free |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
|
|||
|
|||
// Sampler use by area light, gaussian pyramid, ambient occlusion etc... |
|||
SamplerState s_linear_clamp_sampler; |
|||
SamplerState s_trilinear_clamp_sampler; |
|||
|
|||
// Rough refraction texture |
|||
// Color pyramid (width, height, lodcount, Unused) |
|||
TEXTURE2D(_GaussianPyramidColorTexture); |
|||
// Depth pyramid (width, height, lodcount, Unused) |
|||
TEXTURE2D(_PyramidDepthTexture); |
|||
|
|||
CBUFFER_START(UnityGaussianPyramidParameters) |
|||
float4 _GaussianPyramidColorMipSize; |
|||
float4 _PyramidDepthMipSize; |
|||
CBUFFER_END |
|||
|
|||
// Ambient occlusion texture |
|||
TEXTURE2D(_AmbientOcclusionTexture); |
|||
|
|||
CBUFFER_START(UnityAmbientOcclusionParameters) |
|||
float4 _AmbientOcclusionParam; // xyz occlusion color, w directLightStrenght |
|||
CBUFFER_END |
|||
|
|||
// TODO: This one should be set into a constant Buffer at pass frequency (with _Screensize) |
|||
TEXTURE2D(_PreIntegratedFGD); |
|||
TEXTURE2D_ARRAY(_LtcData); // We pack the 3 Ltc data inside a texture array |
|||
#define LTC_GGX_MATRIX_INDEX 0 // RGBA |
|||
#define LTC_DISNEY_DIFFUSE_MATRIX_INDEX 1 // RGBA |
|||
#define LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX 2 // RGB, A unused |
|||
#define LTC_LUT_SIZE 64 |
|||
#define LTC_LUT_SCALE ((LTC_LUT_SIZE - 1) * rcp(LTC_LUT_SIZE)) |
|||
#define LTC_LUT_OFFSET (0.5 * rcp(LTC_LUT_SIZE)) |
|||
|
|||
#define MIN_N_DOT_V 0.0001 // The minimum value of 'NdotV' |
|||
|
|||
#ifdef WANT_SSS_CODE |
|||
// Subsurface scattering specific constant |
|||
#define SSS_WRAP_ANGLE (PI/12) // Used for wrap lighting |
|||
#define SSS_WRAP_LIGHT cos(PI/2 - SSS_WRAP_ANGLE) |
|||
|
|||
CBUFFER_START(UnitySSSParameters) |
|||
uint _EnableSSSAndTransmission; // Globally toggles subsurface and transmission scattering on/off |
|||
uint _TexturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter |
|||
uint _TransmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular |
|||
// Old SSS Model >>> |
|||
uint _UseDisneySSS; |
|||
float4 _HalfRcpVariancesAndWeights[SSS_N_PROFILES][2]; // 2x Gaussians in RGB, A is interpolation weights |
|||
// <<< Old SSS Model |
|||
// Use float4 to avoid any packing issue between compute and pixel shaders |
|||
float4 _ThicknessRemaps[SSS_N_PROFILES]; // R: start, G = end - start, BA unused |
|||
float4 _ShapeParams[SSS_N_PROFILES]; // RGB = S = 1 / D, A = filter radius |
|||
float4 _TransmissionTints[SSS_N_PROFILES]; // RGB = 1/4 * color, A = unused |
|||
CBUFFER_END |
|||
#endif |
|||
|
|||
void ApplyDebugToSurfaceData(inout SurfaceData surfaceData) |
|||
{ |
|||
#ifdef DEBUG_DISPLAY |
|||
if (_DebugLightingMode == DEBUGLIGHTINGMODE_SPECULAR_LIGHTING) |
|||
{ |
|||
bool overrideSmoothness = _DebugLightingSmoothness.x != 0.0; |
|||
float overrideSmoothnessValue = _DebugLightingSmoothness.y; |
|||
|
|||
if (overrideSmoothness) |
|||
{ |
|||
surfaceData.perceptualSmoothness = overrideSmoothnessValue; |
|||
} |
|||
} |
|||
|
|||
if (_DebugLightingMode == DEBUGLIGHTINGMODE_DIFFUSE_LIGHTING) |
|||
{ |
|||
surfaceData.baseColor = _DebugLightingAlbedo.xyz; |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// Debug method (use to display values) |
|||
//----------------------------------------------------------------------------- |
|||
|
|||
void GetSurfaceDataDebug(uint paramId, SurfaceData surfaceData, inout float3 result, inout bool needLinearToSRGB) |
|||
{ |
|||
GetGeneratedSurfaceDataDebug(paramId, surfaceData, result, needLinearToSRGB); |
|||
} |
|||
|
|||
void GetBSDFDataDebug(uint paramId, BSDFData bsdfData, inout float3 result, inout bool needLinearToSRGB) |
|||
{ |
|||
GetGeneratedBSDFDataDebug(paramId, bsdfData, result, needLinearToSRGB); |
|||
} |
|||
|
|||
#ifdef WANT_SSS_CODE |
|||
void FillMaterialIdSSSData(float3 baseColor, int subsurfaceProfile, float subsurfaceRadius, float thickness, inout BSDFData bsdfData) |
|||
{ |
|||
bsdfData.diffuseColor = baseColor; |
|||
|
|||
bsdfData.fresnel0 = 0.028; // TODO take from subsurfaceProfile instead |
|||
bsdfData.subsurfaceProfile = subsurfaceProfile; |
|||
bsdfData.subsurfaceRadius = subsurfaceRadius; |
|||
bsdfData.thickness = _ThicknessRemaps[subsurfaceProfile].x + _ThicknessRemaps[subsurfaceProfile].y * thickness; |
|||
|
|||
uint transmissionMode = BitFieldExtract(_TransmissionFlags, 2u, 2u * subsurfaceProfile); |
|||
|
|||
bsdfData.enableTransmission = transmissionMode != SSS_TRSM_MODE_NONE && (_EnableSSSAndTransmission > 0); |
|||
bsdfData.useThinObjectMode = transmissionMode == SSS_TRSM_MODE_THIN; |
|||
|
|||
bool performPostScatterTexturing = IsBitSet(_TexturingModeFlags, subsurfaceProfile); |
|||
|
|||
#if defined(SHADERPASS) && (SHADERPASS == SHADERPASS_LIGHT_TRANSPORT) // In case of GI pass don't modify the diffuseColor |
|||
bool enableSssAndTransmission = false; |
|||
#elif defined(SHADERPASS) && (SHADERPASS == SHADERPASS_SUBSURFACE_SCATTERING) |
|||
bool enableSssAndTransmission = true; |
|||
#else |
|||
bool enableSssAndTransmission = _EnableSSSAndTransmission != 0; |
|||
#endif |
|||
|
|||
if (enableSssAndTransmission) // If we globally disable SSS effect, don't modify diffuseColor |
|||
{ |
|||
// We modify the albedo here as this code is used by all lighting (including light maps and GI). |
|||
if (performPostScatterTexturing) |
|||
{ |
|||
#if !defined(SHADERPASS) || (SHADERPASS != SHADERPASS_SUBSURFACE_SCATTERING) |
|||
bsdfData.diffuseColor = float3(1.0, 1.0, 1.0); |
|||
#endif |
|||
} |
|||
else |
|||
{ |
|||
bsdfData.diffuseColor = sqrt(bsdfData.diffuseColor); |
|||
} |
|||
} |
|||
|
|||
if (bsdfData.enableTransmission) |
|||
{ |
|||
if (_UseDisneySSS) |
|||
{ |
|||
bsdfData.transmittance = ComputeTransmittance(_ShapeParams[subsurfaceProfile].rgb, |
|||
_TransmissionTints[subsurfaceProfile].rgb, |
|||
bsdfData.thickness, bsdfData.subsurfaceRadius); |
|||
} |
|||
else |
|||
{ |
|||
bsdfData.transmittance = ComputeTransmittanceJimenez(_HalfRcpVariancesAndWeights[subsurfaceProfile][0].rgb, |
|||
_HalfRcpVariancesAndWeights[subsurfaceProfile][0].a, |
|||
_HalfRcpVariancesAndWeights[subsurfaceProfile][1].rgb, |
|||
_HalfRcpVariancesAndWeights[subsurfaceProfile][1].a, |
|||
_TransmissionTints[subsurfaceProfile].rgb, |
|||
bsdfData.thickness, bsdfData.subsurfaceRadius); |
|||
} |
|||
|
|||
bsdfData.transmittance *= bsdfData.diffuseColor; // Premultiply |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
// For image based lighting, a part of the BSDF is pre-integrated. |
|||
// This is done both for specular and diffuse (in case of DisneyDiffuse) |
|||
void GetPreIntegratedFGD(float NdotV, float perceptualRoughness, float3 fresnel0, out float3 specularFGD, out float diffuseFGD, out float reflectivity) |
|||
{ |
|||
// Pre-integrate GGX FGD |
|||
// Integral{BSDF * <N,L> dw} = |
|||
// Integral{(F0 + (1 - F0) * (1 - <V,H>)^5) * (BSDF / F) * <N,L> dw} = |
|||
// F0 * Integral{(BSDF / F) * <N,L> dw} + |
|||
// (1 - F0) * Integral{(1 - <V,H>)^5 * (BSDF / F) * <N,L> dw} = |
|||
// (1 - F0) * x + F0 * y = lerp(x, y, F0) |
|||
// Pre integrate DisneyDiffuse FGD: |
|||
// z = DisneyDiffuse |
|||
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, s_linear_clamp_sampler, float2(NdotV, perceptualRoughness), 0).xyz; |
|||
|
|||
specularFGD = lerp(preFGD.xxx, preFGD.yyy, fresnel0); |
|||
|
|||
#ifdef LIT_DIFFUSE_LAMBERT_BRDF |
|||
diffuseFGD = 1.0; |
|||
#else |
|||
// Remap from the [0, 1] to the [0.5, 1.5] range. |
|||
diffuseFGD = preFGD.z + 0.5; |
|||
#endif |
|||
|
|||
reflectivity = preFGD.y; |
|||
} |
|||
|
|||
// Precomputed lighting data to send to the various lighting functions |
|||
struct PreLightData |
|||
{ |
|||
// General |
|||
float NdotV; // Geometric version (could be negative) |
|||
|
|||
// GGX |
|||
float partLambdaV; |
|||
float energyCompensation; |
|||
float TdotV; |
|||
float BdotV; |
|||
|
|||
// IBL |
|||
float3 iblDirWS; // Dominant specular direction, used for IBL in EvaluateBSDF_Env() |
|||
float iblMipLevel; |
|||
|
|||
float3 specularFGD; // Store preconvoled BRDF for both specular and diffuse |
|||
float diffuseFGD; |
|||
|
|||
// Area lights (17 VGPRs) |
|||
float3x3 orthoBasisViewNormal; // Right-handed view-dependent orthogonal basis around the normal (6x VGPRs) |
|||
float3x3 ltcTransformDiffuse; // Inverse transformation for Lambertian or Disney Diffuse (4x VGPRs) |
|||
float3x3 ltcTransformSpecular; // Inverse transformation for GGX (4x VGPRs) |
|||
float ltcMagnitudeDiffuse; |
|||
float3 ltcMagnitudeFresnel; |
|||
}; |
|||
|
|||
PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfData) |
|||
{ |
|||
PreLightData preLightData; |
|||
|
|||
preLightData.NdotV = dot(bsdfData.normalWS, V); // Store the unaltered (geometric) version |
|||
float NdotV = preLightData.NdotV; |
|||
|
|||
// In the case of IBL we want shift a bit the normal that are not toward the viewver to reduce artifact |
|||
float3 iblNormalWS = GetViewShiftedNormal(bsdfData.normalWS, V, NdotV, MIN_N_DOT_V); // Use non clamped NdotV |
|||
float3 iblR = reflect(-V, iblNormalWS); |
|||
|
|||
NdotV = max(NdotV, MIN_N_DOT_V); // Use the modified (clamped) version |
|||
|
|||
// GGX aniso |
|||
if (bsdfData.materialId == MATERIALID_LIT_ANISO) |
|||
{ |
|||
preLightData.TdotV = dot(bsdfData.tangentWS, V); |
|||
preLightData.BdotV = dot(bsdfData.bitangentWS, V); |
|||
preLightData.partLambdaV = GetSmithJointGGXAnisoPartLambdaV(preLightData.TdotV, preLightData.BdotV, NdotV, bsdfData.roughnessT, bsdfData.roughnessB); |
|||
|
|||
// For GGX aniso and IBL we have done an empirical (eye balled) approximation compare to the reference. |
|||
// We use a single fetch, and we stretch the normal to use based on various criteria. |
|||
// result are far away from the reference but better than nothing |
|||
// For positive anisotropy values: tangent = highlight stretch (anisotropy) direction, bitangent = grain (brush) direction. |
|||
float3 grainDirWS = (bsdfData.anisotropy >= 0) ? bsdfData.bitangentWS : bsdfData.tangentWS; |
|||
// Reduce stretching for (perceptualRoughness < 0.2). |
|||
float stretch = abs(bsdfData.anisotropy) * saturate(5 * bsdfData.perceptualRoughness); |
|||
// NOTE: If we follow the theory we should use the modified normal for the different calculation implying a normal (like NdotV) and use iblNormalWS |
|||
// into function like GetSpecularDominantDir(). However modified normal is just a hack. The goal is just to stretch a cubemap, no accuracy here. |
|||
// With this in mind and for performance reasons we chose to only use modified normal to calculate R. |
|||
float3 anisoIblNormalWS = GetAnisotropicModifiedNormal(grainDirWS, iblNormalWS, V, stretch); |
|||
iblR = reflect(-V, anisoIblNormalWS); |
|||
} |
|||
else // GGX iso |
|||
{ |
|||
preLightData.TdotV = 0; |
|||
preLightData.BdotV = 0; |
|||
preLightData.partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, bsdfData.roughness); |
|||
iblR = reflect(-V, iblNormalWS); |
|||
} |
|||
|
|||
float reflectivity; |
|||
|
|||
// IBL |
|||
GetPreIntegratedFGD(NdotV, bsdfData.perceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD, reflectivity); |
|||
|
|||
// Note: this is a ad-hoc tweak. |
|||
float iblRoughness, iblPerceptualRoughness; |
|||
|
|||
if (bsdfData.materialId == MATERIALID_LIT_ANISO) |
|||
{ |
|||
// Use the min roughness, and bias it for higher values of anisotropy and roughness. |
|||
float roughnessBias = 0.075 * bsdfData.anisotropy * bsdfData.roughness; |
|||
iblRoughness = saturate(min(bsdfData.roughnessT, bsdfData.roughnessB) + roughnessBias); |
|||
iblPerceptualRoughness = RoughnessToPerceptualRoughness(iblRoughness); |
|||
} |
|||
else |
|||
{ |
|||
iblRoughness = bsdfData.roughness; |
|||
iblPerceptualRoughness = bsdfData.perceptualRoughness; |
|||
} |
|||
|
|||
preLightData.iblDirWS = GetSpecularDominantDir(iblNormalWS, iblR, iblRoughness, NdotV); |
|||
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(iblPerceptualRoughness); |
|||
|
|||
#ifdef LIT_USE_GGX_ENERGY_COMPENSATION |
|||
// Ref: Practical multiple scattering compensation for microfacet models. |
|||
// We only apply the formulation for metals. |
|||
// For dielectrics, the change of reflectance is negligible. |
|||
// We deem the intensity difference of a couple of percent for high values of roughness |
|||
// to not be worth the cost of another precomputed table. |
|||
// Note: this formulation bakes the BSDF non-symmetric! |
|||
preLightData.energyCompensation = 1.0 / reflectivity - 1.0; |
|||
#else |
|||
preLightData.energyCompensation = 0.0; |
|||
#endif // LIT_USE_GGX_ENERGY_COMPENSATION |
|||
|
|||
// Area light |
|||
// UVs for sampling the LUTs |
|||
float theta = FastACos(NdotV); // For Area light - UVs for sampling the LUTs |
|||
float2 uv = LTC_LUT_OFFSET + LTC_LUT_SCALE * float2(bsdfData.perceptualRoughness, theta * INV_HALF_PI); |
|||
|
|||
// Note we load the matrix transpose (avoid to have to transpose it in shader) |
|||
#ifdef LIT_DIFFUSE_LAMBERT_BRDF |
|||
preLightData.ltcTransformDiffuse = k_identity3x3; |
|||
#else |
|||
// Get the inverse LTC matrix for Disney Diffuse |
|||
preLightData.ltcTransformDiffuse = 0.0; |
|||
preLightData.ltcTransformDiffuse._m22 = 1.0; |
|||
preLightData.ltcTransformDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_DISNEY_DIFFUSE_MATRIX_INDEX, 0); |
|||
#endif |
|||
|
|||
// Get the inverse LTC matrix for GGX |
|||
// Note we load the matrix transpose (avoid to have to transpose it in shader) |
|||
preLightData.ltcTransformSpecular = 0.0; |
|||
preLightData.ltcTransformSpecular._m22 = 1.0; |
|||
preLightData.ltcTransformSpecular._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_GGX_MATRIX_INDEX, 0); |
|||
|
|||
// Construct a right-handed view-dependent orthogonal basis around the normal |
|||
preLightData.orthoBasisViewNormal[0] = normalize(V - bsdfData.normalWS * preLightData.NdotV); |
|||
preLightData.orthoBasisViewNormal[2] = bsdfData.normalWS; |
|||
preLightData.orthoBasisViewNormal[1] = normalize(cross(preLightData.orthoBasisViewNormal[2], preLightData.orthoBasisViewNormal[0])); |
|||
|
|||
float3 ltcMagnitude = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX, 0).rgb; |
|||
float ltcGGXFresnelMagnitudeDiff = ltcMagnitude.r; // The difference of magnitudes of GGX and Fresnel |
|||
float ltcGGXFresnelMagnitude = ltcMagnitude.g; |
|||
float ltcDisneyDiffuseMagnitude = ltcMagnitude.b; |
|||
|
|||
#ifdef LIT_DIFFUSE_LAMBERT_BRDF |
|||
preLightData.ltcMagnitudeDiffuse = 1; |
|||
#else |
|||
preLightData.ltcMagnitudeDiffuse = ltcDisneyDiffuseMagnitude; |
|||
#endif |
|||
|
|||
// TODO: the fit seems rather poor. The scaling factor of 0.5 allows us |
|||
// to match the reference for rough metals, but further darkens dielectrics. |
|||
preLightData.ltcMagnitudeFresnel = bsdfData.fresnel0 * ltcGGXFresnelMagnitudeDiff + (float3)ltcGGXFresnelMagnitude; |
|||
|
|||
return preLightData; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 0f24f4070ad17d14196c6ed72276a144 |
|||
timeCreated: 1504900828 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#ifdef HAS_LIGHTLOOP |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// Lighting structure for light accumulation |
|||
//----------------------------------------------------------------------------- |
|||
|
|||
// These structure allow to accumulate lighting accross the Lit material |
|||
// AggregateLighting is init to zero and transfer to EvaluateBSDF, but the LightLoop can't access its content. |
|||
struct DirectLighting |
|||
{ |
|||
float3 diffuse; |
|||
float3 specular; |
|||
}; |
|||
|
|||
struct IndirectLighting |
|||
{ |
|||
float3 specularReflected; |
|||
float3 specularTransmitted; |
|||
}; |
|||
|
|||
struct AggregateLighting |
|||
{ |
|||
DirectLighting direct; |
|||
IndirectLighting indirect; |
|||
}; |
|||
|
|||
void AccumulateDirectLighting(DirectLighting src, inout AggregateLighting dst) |
|||
{ |
|||
dst.direct.diffuse += src.diffuse; |
|||
dst.direct.specular += src.specular; |
|||
} |
|||
|
|||
void AccumulateIndirectLighting(IndirectLighting src, inout AggregateLighting dst) |
|||
{ |
|||
dst.indirect.specularReflected += src.specularReflected; |
|||
dst.indirect.specularTransmitted += src.specularTransmitted; |
|||
} |
|||
|
|||
#ifdef WANT_SSS_CODE |
|||
// Currently, we only model diffuse transmission. Specular transmission is not yet supported. |
|||
// We assume that the back side of the object is a uniformly illuminated infinite plane |
|||
// with the reversed normal (and the view vector) of the current sample. |
|||
float3 EvaluateTransmission(BSDFData bsdfData, float intensity, float shadow) |
|||
{ |
|||
// For low thickness, we can reuse the shadowing status for the back of the object. |
|||
shadow = bsdfData.useThinObjectMode ? shadow : 1; |
|||
|
|||
float backLight = intensity * shadow; |
|||
|
|||
return backLight * bsdfData.transmittance; // Premultiplied with the diffuse color |
|||
} |
|||
#endif |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// EvaluateBSDF_Directional (supports directional and box projector lights) |
|||
//----------------------------------------------------------------------------- |
|||
|
|||
float4 EvaluateCookie_Directional(LightLoopContext lightLoopContext, DirectionalLightData lightData, |
|||
float3 lighToSample) |
|||
{ |
|||
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the near plane. |
|||
// 'lightData.right' and 'lightData.up' are pre-scaled on CPU. |
|||
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward); |
|||
float3 positionLS = mul(lighToSample, transpose(lightToWorld)); |
|||
float2 positionNDC = positionLS.xy; |
|||
|
|||
bool isInBounds; |
|||
|
|||
// Remap the texture coordinates from [-1, 1]^2 to [0, 1]^2. |
|||
float2 coord = positionNDC * 0.5 + 0.5; |
|||
|
|||
if (lightData.tileCookie) |
|||
{ |
|||
// Tile the texture if the 'repeat' wrap mode is enabled. |
|||
coord = frac(coord); |
|||
isInBounds = true; |
|||
} |
|||
else |
|||
{ |
|||
isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1.0 - positionLS.z) <= 1.0; |
|||
} |
|||
|
|||
// We let the sampler handle tiling or clamping to border. |
|||
// Note: tiling (the repeat mode) is not currently supported. |
|||
float4 cookie = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex); |
|||
|
|||
cookie.a = isInBounds ? cookie.a : 0.0; |
|||
|
|||
return cookie; |
|||
} |
|||
|
|||
DirectLighting EvaluateBSDF_Directional( LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, PreLightData preLightData, |
|||
DirectionalLightData lightData, BSDFData bsdfData) |
|||
{ |
|||
DirectLighting lighting; |
|||
ZERO_INITIALIZE(DirectLighting, lighting); |
|||
|
|||
float3 positionWS = posInput.positionWS; |
|||
|
|||
float3 L = -lightData.forward; // Lights are pointing backward in Unity |
|||
float NdotL = dot(bsdfData.normalWS, L); |
|||
float illuminance = saturate(NdotL); |
|||
|
|||
float shadow = 1.0; |
|||
|
|||
[branch] if (lightData.shadowIndex >= 0) |
|||
{ |
|||
#ifdef _SURFACE_TYPE_TRANSPARENT |
|||
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS); |
|||
#else |
|||
shadow = LOAD_TEXTURE2D(_DeferredShadowTexture, posInput.unPositionSS).x; |
|||
#endif |
|||
illuminance *= shadow; |
|||
} |
|||
|
|||
[branch] if (lightData.cookieIndex >= 0) |
|||
{ |
|||
float3 lightToSurface = positionWS - lightData.positionWS; |
|||
float4 cookie = EvaluateCookie_Directional(lightLoopContext, lightData, lightToSurface); |
|||
|
|||
// Premultiply. |
|||
lightData.color *= cookie.rgb; |
|||
lightData.diffuseScale *= cookie.a; |
|||
lightData.specularScale *= cookie.a; |
|||
} |
|||
|
|||
[branch] if (illuminance > 0.0) |
|||
{ |
|||
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular); |
|||
|
|||
lighting.diffuse *= illuminance * lightData.diffuseScale; |
|||
lighting.specular *= illuminance * lightData.specularScale; |
|||
} |
|||
|
|||
#ifdef WANT_SSS_CODE |
|||
[branch] if (bsdfData.enableTransmission) |
|||
{ |
|||
// We apply wrapped lighting instead of the regular Lambertian diffuse |
|||
// to compensate for approximations within EvaluateTransmission(). |
|||
float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT); |
|||
|
|||
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|||
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow); |
|||
} |
|||
#endif |
|||
|
|||
// Save ALU by applying 'lightData.color' only once. |
|||
lighting.diffuse *= lightData.color; |
|||
lighting.specular *= lightData.color; |
|||
|
|||
return lighting; |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// EvaluateBSDF_Punctual (supports spot, point and projector lights) |
|||
//----------------------------------------------------------------------------- |
|||
|
|||
float4 EvaluateCookie_Punctual(LightLoopContext lightLoopContext, LightData lightData, |
|||
float3 lighToSample) |
|||
{ |
|||
int lightType = lightData.lightType; |
|||
|
|||
// Translate and rotate 'positionWS' into the light space. |
|||
// 'lightData.right' and 'lightData.up' are pre-scaled on CPU. |
|||
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward); |
|||
float3 positionLS = mul(lighToSample, transpose(lightToWorld)); |
|||
|
|||
float4 cookie; |
|||
|
|||
[branch] if (lightType == GPULIGHTTYPE_POINT) |
|||
{ |
|||
cookie = SampleCookieCube(lightLoopContext, positionLS, lightData.cookieIndex); |
|||
} |
|||
else |
|||
{ |
|||
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the plane at 1m distance. |
|||
// Box projector lights require no perspective division. |
|||
float perspectiveZ = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? positionLS.z : 1; |
|||
float2 positionNDC = positionLS.xy / perspectiveZ; |
|||
bool isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1 - positionLS.z) <= 1; |
|||
|
|||
// Remap the texture coordinates from [-1, 1]^2 to [0, 1]^2. |
|||
float2 coord = positionNDC * 0.5 + 0.5; |
|||
|
|||
// We let the sampler handle clamping to border. |
|||
cookie = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex); |
|||
cookie.a = isInBounds ? cookie.a : 0; |
|||
} |
|||
|
|||
return cookie; |
|||
} |
|||
|
|||
float GetPunctualShapeAttenuation(LightData lightData, float3 L, float distSq) |
|||
{ |
|||
// Note: lightData.invSqrAttenuationRadius is 0 when applyRangeAttenuation is false |
|||
float attenuation = GetDistanceAttenuation(distSq, lightData.invSqrAttenuationRadius); |
|||
// Reminder: lights are oriented backward (-Z) |
|||
return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset); |
|||
} |
|||
|
|||
DirectLighting EvaluateBSDF_Punctual( LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, |
|||
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType) |
|||
{ |
|||
DirectLighting lighting; |
|||
ZERO_INITIALIZE(DirectLighting, lighting); |
|||
|
|||
float3 positionWS = posInput.positionWS; |
|||
int lightType = GPULightType; |
|||
|
|||
// All punctual light type in the same formula, attenuation is neutral depends on light type. |
|||
// light.positionWS is the normalize light direction in case of directional light and invSqrAttenuationRadius is 0 |
|||
// mean dot(unL, unL) = 1 and mean GetDistanceAttenuation() will return 1 |
|||
// For point light and directional GetAngleAttenuation() return 1 |
|||
|
|||
float3 lightToSurface = positionWS - lightData.positionWS; |
|||
float3 unL = -lightToSurface; |
|||
float distSq = dot(unL, unL); |
|||
float dist = sqrt(distSq); |
|||
float3 L = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? unL * rsqrt(distSq) : -lightData.forward; |
|||
float NdotL = dot(bsdfData.normalWS, L); |
|||
float illuminance = saturate(NdotL); |
|||
|
|||
float attenuation = GetPunctualShapeAttenuation(lightData, L, distSq); |
|||
|
|||
// Premultiply. |
|||
lightData.diffuseScale *= attenuation; |
|||
lightData.specularScale *= attenuation; |
|||
|
|||
float shadow = 1.0; |
|||
|
|||
[branch] if (lightData.shadowIndex >= 0) |
|||
{ |
|||
// TODO: make projector lights cast shadows. |
|||
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal); |
|||
float4 L_dist = { L, dist }; |
|||
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L_dist, posInput.unPositionSS); |
|||
shadow = lerp(1.0, shadow, lightData.shadowDimmer); |
|||
illuminance *= shadow; |
|||
} |
|||
|
|||
#ifdef VOLUMETRIC_SHADOWING_ENABLED |
|||
float volumetricShadow = Transmittance(OpticalDepthHomogeneous(preLightData.globalFogExtinction, dist)); |
|||
|
|||
// Premultiply. |
|||
lightData.diffuseScale *= volumetricShadow; |
|||
lightData.specularScale *= volumetricShadow; |
|||
#endif |
|||
|
|||
// Projector lights always have a cookies, so we can perform clipping inside the if(). |
|||
[branch] if (lightData.cookieIndex >= 0) |
|||
{ |
|||
float4 cookie = EvaluateCookie_Punctual(lightLoopContext, lightData, lightToSurface); |
|||
|
|||
// Premultiply. |
|||
lightData.color *= cookie.rgb; |
|||
lightData.diffuseScale *= cookie.a; |
|||
lightData.specularScale *= cookie.a; |
|||
} |
|||
|
|||
[branch] if (illuminance > 0.0) |
|||
{ |
|||
bsdfData.roughness = max(bsdfData.roughness, lightData.minRoughness); // Simulate that a punctual light have a radius with this hack |
|||
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular); |
|||
|
|||
lighting.diffuse *= illuminance * lightData.diffuseScale; |
|||
lighting.specular *= illuminance * lightData.specularScale; |
|||
} |
|||
|
|||
#ifdef WANT_SSS_CODE |
|||
[branch] if (bsdfData.enableTransmission) |
|||
{ |
|||
// We apply wrapped lighting instead of the regular Lambertian diffuse |
|||
// to compensate for approximations within EvaluateTransmission(). |
|||
float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT); |
|||
|
|||
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|||
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow); |
|||
} |
|||
#endif |
|||
|
|||
// Save ALU by applying 'lightData.color' only once. |
|||
lighting.diffuse *= lightData.color; |
|||
lighting.specular *= lightData.color; |
|||
|
|||
return lighting; |
|||
} |
|||
|
|||
#include "Lit\LitReference.hlsl" |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// EvaluateBSDF_Line - Approximation with Linearly Transformed Cosines |
|||
//----------------------------------------------------------------------------- |
|||
|
|||
DirectLighting EvaluateBSDF_Line( LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, |
|||
PreLightData preLightData, LightData lightData, BSDFData bsdfData) |
|||
{ |
|||
DirectLighting lighting; |
|||
ZERO_INITIALIZE(DirectLighting, lighting); |
|||
|
|||
float3 positionWS = posInput.positionWS; |
|||
|
|||
#ifdef LIT_DISPLAY_REFERENCE_AREA |
|||
IntegrateBSDF_LineRef(V, positionWS, preLightData, lightData, bsdfData, |
|||
lighting.diffuse, lighting.specular); |
|||
#else |
|||
float len = lightData.size.x; |
|||
float3 T = lightData.right; |
|||
|
|||
float3 unL = lightData.positionWS - positionWS; |
|||
|
|||
// Pick the major axis of the ellipsoid. |
|||
float3 axis = lightData.right; |
|||
|
|||
// We define the ellipsoid s.t. r1 = (r + len / 2), r2 = r3 = r. |
|||
// TODO: This could be precomputed. |
|||
float radius = rsqrt(lightData.invSqrAttenuationRadius); |
|||
float invAspectRatio = radius / (radius + (0.5 * len)); |
|||
|
|||
// Compute the light attenuation. |
|||
float intensity = GetEllipsoidalDistanceAttenuation(unL, lightData.invSqrAttenuationRadius, |
|||
axis, invAspectRatio); |
|||
|
|||
// Terminate if the shaded point is too far away. |
|||
if (intensity == 0.0) |
|||
return lighting; |
|||
|
|||
lightData.diffuseScale *= intensity; |
|||
lightData.specularScale *= intensity; |
|||
|
|||
// Translate the light s.t. the shaded point is at the origin of the coordinate system. |
|||
lightData.positionWS -= positionWS; |
|||
|
|||
// TODO: some of this could be precomputed. |
|||
float3 P1 = lightData.positionWS - T * (0.5 * len); |
|||
float3 P2 = lightData.positionWS + T * (0.5 * len); |
|||
|
|||
// Rotate the endpoints into the local coordinate system. |
|||
P1 = mul(P1, transpose(preLightData.orthoBasisViewNormal)); |
|||
P2 = mul(P2, transpose(preLightData.orthoBasisViewNormal)); |
|||
|
|||
// Compute the binormal in the local coordinate system. |
|||
float3 B = normalize(cross(P1, P2)); |
|||
|
|||
float ltcValue; |
|||
|
|||
// Evaluate the diffuse part |
|||
{ |
|||
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformDiffuse); |
|||
ltcValue *= lightData.diffuseScale; |
|||
lighting.diffuse = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue); |
|||
} |
|||
|
|||
#ifdef WANT_SSS_CODE |
|||
[branch] if (bsdfData.enableTransmission) |
|||
{ |
|||
// Flip the view vector and the normal. The bitangent stays the same. |
|||
float3x3 flipMatrix = float3x3(-1, 0, 0, |
|||
0, 1, 0, |
|||
0, 0, -1); |
|||
|
|||
// Use the Lambertian approximation for performance reasons. |
|||
// The matrix multiplication should not generate any extra ALU on GCN. |
|||
ltcValue = LTCEvaluate(P1, P2, B, mul(flipMatrix, k_identity3x3)); |
|||
ltcValue *= lightData.diffuseScale; |
|||
|
|||
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|||
lighting.diffuse += EvaluateTransmission(bsdfData, ltcValue, 1); |
|||
} |
|||
#endif |
|||
|
|||
// Evaluate the specular part |
|||
{ |
|||
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformSpecular); |
|||
ltcValue *= lightData.specularScale; |
|||
lighting.specular += preLightData.ltcMagnitudeFresnel * ltcValue; |
|||
} |
|||
|
|||
// Save ALU by applying 'lightData.color' only once. |
|||
lighting.diffuse *= lightData.color; |
|||
lighting.specular *= lightData.color; |
|||
#endif // LIT_DISPLAY_REFERENCE_AREA |
|||
|
|||
return lighting; |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// EvaluateBSDF_Area - Approximation with Linearly Transformed Cosines |
|||
//----------------------------------------------------------------------------- |
|||
|
|||
// #define ELLIPSOIDAL_ATTENUATION |
|||
|
|||
DirectLighting EvaluateBSDF_Rect( LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, |
|||
PreLightData preLightData, LightData lightData, BSDFData bsdfData) |
|||
{ |
|||
DirectLighting lighting; |
|||
ZERO_INITIALIZE(DirectLighting, lighting); |
|||
|
|||
float3 positionWS = posInput.positionWS; |
|||
|
|||
#ifdef LIT_DISPLAY_REFERENCE_AREA |
|||
IntegrateBSDF_AreaRef(V, positionWS, preLightData, lightData, bsdfData, |
|||
lighting.diffuse, lighting.specular); |
|||
#else |
|||
float3 unL = lightData.positionWS - positionWS; |
|||
|
|||
[branch] |
|||
if (dot(lightData.forward, unL) >= 0.0001) |
|||
{ |
|||
// The light is back-facing. |
|||
return lighting; |
|||
} |
|||
|
|||
// Rotate the light direction into the light space. |
|||
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, -lightData.forward); |
|||
unL = mul(unL, transpose(lightToWorld)); |
|||
|
|||
// TODO: This could be precomputed. |
|||
float halfWidth = lightData.size.x * 0.5; |
|||
float halfHeight = lightData.size.y * 0.5; |
|||
|
|||
// Define the dimensions of the attenuation volume. |
|||
// TODO: This could be precomputed. |
|||
float radius = rsqrt(lightData.invSqrAttenuationRadius); |
|||
float3 invHalfDim = rcp(float3(radius + halfWidth, |
|||
radius + halfHeight, |
|||
radius)); |
|||
|
|||
// Compute the light attenuation. |
|||
#ifdef ELLIPSOIDAL_ATTENUATION |
|||
// The attenuation volume is an axis-aligned ellipsoid s.t. |
|||
// r1 = (r + w / 2), r2 = (r + h / 2), r3 = r. |
|||
float intensity = GetEllipsoidalDistanceAttenuation(unL, invHalfDim); |
|||
#else |
|||
// The attenuation volume is an axis-aligned box s.t. |
|||
// hX = (r + w / 2), hY = (r + h / 2), hZ = r. |
|||
float intensity = GetBoxDistanceAttenuation(unL, invHalfDim); |
|||
#endif |
|||
|
|||
// Terminate if the shaded point is too far away. |
|||
if (intensity == 0.0) |
|||
return lighting; |
|||
|
|||
lightData.diffuseScale *= intensity; |
|||
lightData.specularScale *= intensity; |
|||
|
|||
// Translate the light s.t. the shaded point is at the origin of the coordinate system. |
|||
lightData.positionWS -= positionWS; |
|||
|
|||
float4x3 lightVerts; |
|||
|
|||
// TODO: some of this could be precomputed. |
|||
lightVerts[0] = lightData.positionWS + lightData.right * halfWidth + lightData.up * halfHeight; |
|||
lightVerts[1] = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight; |
|||
lightVerts[2] = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight; |
|||
lightVerts[3] = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight; |
|||
|
|||
// Rotate the endpoints into the local coordinate system. |
|||
lightVerts = mul(lightVerts, transpose(preLightData.orthoBasisViewNormal)); |
|||
|
|||
float ltcValue; |
|||
|
|||
// Evaluate the diffuse part |
|||
{ |
|||
// Polygon irradiance in the transformed configuration. |
|||
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformDiffuse)); |
|||
ltcValue *= lightData.diffuseScale; |
|||
lighting.diffuse = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue); |
|||
} |
|||
|
|||
#ifdef WANT_SSS_CODE |
|||
[branch] if (bsdfData.enableTransmission) |
|||
{ |
|||
// Flip the view vector and the normal. The bitangent stays the same. |
|||
float3x3 flipMatrix = float3x3(-1, 0, 0, |
|||
0, 1, 0, |
|||
0, 0, -1); |
|||
|
|||
// Use the Lambertian approximation for performance reasons. |
|||
// The matrix multiplication should not generate any extra ALU on GCN. |
|||
float3x3 ltcTransform = mul(flipMatrix, k_identity3x3); |
|||
|
|||
// Polygon irradiance in the transformed configuration. |
|||
ltcValue = PolygonIrradiance(mul(lightVerts, ltcTransform)); |
|||
ltcValue *= lightData.diffuseScale; |
|||
|
|||
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass. |
|||
lighting.diffuse += EvaluateTransmission(bsdfData, ltcValue, 1); |
|||
} |
|||
#endif |
|||
|
|||
// Evaluate the specular part |
|||
{ |
|||
// Polygon irradiance in the transformed configuration. |
|||
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformSpecular)); |
|||
ltcValue *= lightData.specularScale; |
|||
lighting.specular += preLightData.ltcMagnitudeFresnel * ltcValue; |
|||
} |
|||
|
|||
// Save ALU by applying 'lightData.color' only once. |
|||
lighting.diffuse *= lightData.color; |
|||
lighting.specular *= lightData.color; |
|||
#endif // LIT_DISPLAY_REFERENCE_AREA |
|||
|
|||
return lighting; |
|||
} |
|||
|
|||
DirectLighting EvaluateBSDF_Area( LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, |
|||
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType) |
|||
{ |
|||
if (GPULightType == GPULIGHTTYPE_LINE) |
|||
{ |
|||
return EvaluateBSDF_Line(lightLoopContext, V, posInput, preLightData, lightData, bsdfData); |
|||
} |
|||
else |
|||
{ |
|||
return EvaluateBSDF_Rect(lightLoopContext, V, posInput, preLightData, lightData, bsdfData); |
|||
} |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// EvaluateBSDF_SSLighting for screen space lighting |
|||
// ---------------------------------------------------------------------------- |
|||
|
|||
IndirectLighting EvaluateBSDF_SSReflection(LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, |
|||
PreLightData preLightData, BSDFData bsdfData, |
|||
inout float hierarchyWeight) |
|||
{ |
|||
IndirectLighting lighting; |
|||
ZERO_INITIALIZE(IndirectLighting, lighting); |
|||
|
|||
// TODO |
|||
|
|||
return lighting; |
|||
} |
|||
|
|||
IndirectLighting EvaluateBSDF_SSRefraction(LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, |
|||
PreLightData preLightData, BSDFData bsdfData, |
|||
inout float hierarchyWeight) |
|||
{ |
|||
IndirectLighting lighting; |
|||
ZERO_INITIALIZE(IndirectLighting, lighting); |
|||
|
|||
#if HAS_REFRACTION |
|||
// Refraction process: |
|||
// 1. Depending on the shape model, we calculate the refracted point in world space and the optical depth |
|||
// 2. We calculate the screen space position of the refracted point |
|||
// 3. If this point is available (ie: in color buffer and point is not in front of the object) |
|||
// a. Get the corresponding color depending on the roughness from the gaussian pyramid of the color buffer |
|||
// b. Multiply by the transmittance for absorption (depends on the optical depth) |
|||
|
|||
float3 refractedBackPointWS = float3(0.0, 0.0, 0.0); |
|||
float opticalDepth = 0.0; |
|||
|
|||
uint2 depthSize = uint2(_PyramidDepthMipSize.xy); |
|||
|
|||
// For all refraction approximation, to calculate the refracted point in world space, |
|||
// we approximate the scene as a plane (back plane) with normal -V at the depth hit point. |
|||
// (We avoid to raymarch the depth texture to get the refracted point.) |
|||
#if defined(_REFRACTION_PLANE) |
|||
// Plane shape model: |
|||
// We approximate locally the shape of the object as a plane with normal {bsdfData.normalWS} at {bsdfData.positionWS} |
|||
// with a thickness {bsdfData.thickness} |
|||
|
|||
// Refracted ray |
|||
float3 R = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior); |
|||
|
|||
// Get the depth of the approximated back plane |
|||
float pyramidDepth = LOAD_TEXTURE2D_LOD(_PyramidDepthTexture, posInput.positionSS * (depthSize >> 2), 2).r; |
|||
float depth = LinearEyeDepth(pyramidDepth, _ZBufferParams); |
|||
|
|||
// Distance from point to the back plane |
|||
float distFromP = depth - posInput.depthVS; |
|||
|
|||
// Optical depth within the thin plane |
|||
opticalDepth = bsdfData.thickness / dot(R, -bsdfData.normalWS); |
|||
|
|||
// The refracted ray exiting the thin plane is the same as the incident ray (parallel interfaces and same ior) |
|||
float VoR = dot(-V, R); |
|||
float VoN = dot(V, bsdfData.normalWS); |
|||
refractedBackPointWS = posInput.positionWS + R * opticalDepth - V * (distFromP - VoR * opticalDepth); |
|||
|
|||
#elif defined(_REFRACTION_SPHERE) |
|||
// Sphere shape model: |
|||
// We approximate locally the shape of the object as sphere, that is tangent to the shape. |
|||
// The sphere has a diameter of {bsdfData.thickness} |
|||
// The center of the sphere is at {bsdfData.positionWS} - {bsdfData.normalWS} * {bsdfData.thickness} |
|||
// |
|||
// So the light is refracted twice: in and out of the tangent sphere |
|||
|
|||
// Get the depth of the approximated back plane |
|||
float pyramidDepth = LOAD_TEXTURE2D_LOD(_PyramidDepthTexture, posInput.positionSS * (depthSize >> 2), 2).r; |
|||
float depth = LinearEyeDepth(pyramidDepth, _ZBufferParams); |
|||
|
|||
// Distance from point to the back plane |
|||
float depthFromPosition = depth - posInput.depthVS; |
|||
|
|||
// First refraction (tangent sphere in) |
|||
// Refracted ray |
|||
float3 R1 = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior); |
|||
// Center of the tangent sphere |
|||
float3 C = posInput.positionWS - bsdfData.normalWS * bsdfData.thickness * 0.5; |
|||
|
|||
// Second refraction (tangent sphere out) |
|||
float NoR1 = dot(bsdfData.normalWS, R1); |
|||
// Optical depth within the sphere |
|||
opticalDepth = -NoR1 * bsdfData.thickness; |
|||
// Out hit point in the tangent sphere |
|||
float3 P1 = posInput.positionWS + R1 * opticalDepth; |
|||
// Out normal |
|||
float3 N1 = normalize(C - P1); |
|||
// Out refracted ray |
|||
float3 R2 = refract(R1, N1, bsdfData.ior); |
|||
float N1oR2 = dot(N1, R2); |
|||
float VoR1 = dot(V, R1); |
|||
|
|||
// Refracted source point |
|||
refractedBackPointWS = P1 - R2 * (depthFromPosition - NoR1 * VoR1 * bsdfData.thickness) / N1oR2; |
|||
|
|||
#endif |
|||
|
|||
// Calculate screen space coordinates of refracted point in back plane |
|||
float4 refractedBackPointCS = mul(_ViewProjMatrix, float4(refractedBackPointWS, 1.0)); |
|||
float2 refractedBackPointSS = ComputeScreenSpacePosition(refractedBackPointCS); |
|||
float refractedBackPointDepth = LinearEyeDepth(LOAD_TEXTURE2D_LOD(_PyramidDepthTexture, refractedBackPointSS * depthSize, 0).r, _ZBufferParams); |
|||
|
|||
// Exit if texel is out of color buffer |
|||
// Or if the texel is from an object in front of the object |
|||
if (refractedBackPointDepth < posInput.depthVS |
|||
|| any(refractedBackPointSS < 0.0) |
|||
|| any(refractedBackPointSS > 1.0)) |
|||
{ |
|||
// Do nothing and don't update the hierarchy weight so we can fall back on refraction probe |
|||
return lighting; |
|||
} |
|||
|
|||
// Map the roughness to the correct mip map level of the color pyramid |
|||
float mipLevel = PerceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness, uint(_GaussianPyramidColorMipSize.z)); |
|||
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, refractedBackPointSS, mipLevel).rgb; |
|||
|
|||
// Beer-Lamber law for absorption |
|||
float3 transmittance = exp(-bsdfData.absorptionCoefficient * opticalDepth); |
|||
lighting.specularTransmitted *= transmittance; |
|||
|
|||
float weight = 1.0; |
|||
UpdateLightingHierarchyWeights(hierarchyWeight, weight); // Shouldn't be needed, but safer in case we decide to change hiearchy priority |
|||
lighting.specularTransmitted *= weight; |
|||
#else |
|||
// No refraction, no need to go further |
|||
hierarchyWeight = 1.0; |
|||
#endif |
|||
|
|||
return lighting; |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// EvaluateBSDF_Env |
|||
// ---------------------------------------------------------------------------- |
|||
|
|||
// _preIntegratedFGD and _CubemapLD are unique for each BRDF |
|||
IndirectLighting EvaluateBSDF_Env( LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, |
|||
PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData, int envShapeType, int GPUImageBasedLightingType, |
|||
inout float hierarchyWeight) |
|||
{ |
|||
IndirectLighting lighting; |
|||
ZERO_INITIALIZE(IndirectLighting, lighting); |
|||
#if !HAS_REFRACTION |
|||
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION) |
|||
return lighting; |
|||
#endif |
|||
|
|||
float3 envLighting = float3(0.0, 0.0, 0.0); |
|||
float3 positionWS = posInput.positionWS; |
|||
float weight = 1.0; |
|||
|
|||
#ifdef LIT_DISPLAY_REFERENCE_IBL |
|||
|
|||
envLighting = IntegrateSpecularGGXIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData); |
|||
|
|||
// TODO: Do refraction reference (is it even possible ?) |
|||
|
|||
|
|||
// #ifdef LIT_DIFFUSE_LAMBERT_BRDF |
|||
// envLighting += IntegrateLambertIBLRef(lightData, V, bsdfData); |
|||
// #else |
|||
// envLighting += IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData); |
|||
// #endif |
|||
|
|||
weight = 1.0; |
|||
|
|||
#else |
|||
|
|||
// TODO: factor this code in common, so other material authoring don't require to rewrite everything, |
|||
// TODO: test the strech from Tomasz |
|||
// float shrinkedRoughness = AnisotropicStrechAtGrazingAngle(bsdfData.roughness, bsdfData.perceptualRoughness, NdotV); |
|||
|
|||
// Guideline for reflection volume: In HDRenderPipeline we separate the projection volume (the proxy of the scene) from the influence volume (what pixel on the screen is affected) |
|||
// However we add the constrain that the shape of the projection and influence volume is the same (i.e if we have a sphere shape projection volume, we have a shape influence). |
|||
// It allow to have more coherence for the dynamic if in shader code. |
|||
// Users can also chose to not have any projection, in this case we use the property minProjectionDistance to minimize code change. minProjectionDistance is set to huge number |
|||
// that simulate effect of no shape projection |
|||
|
|||
float3 R = preLightData.iblDirWS; |
|||
|
|||
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION) |
|||
{ |
|||
// This is the same code than what is use in screen space refraction |
|||
// TODO: put this code into a function |
|||
#if defined(_REFRACTION_PLANE) |
|||
R = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior); |
|||
#elif defined(_REFRACTION_SPHERE) |
|||
float3 R1 = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior); |
|||
// Center of the tangent sphere |
|||
float3 C = posInput.positionWS - bsdfData.normalWS * bsdfData.thickness * 0.5; |
|||
// Second refraction (tangent sphere out) |
|||
float NoR1 = dot(bsdfData.normalWS, R1); |
|||
// Optical depth within the sphere |
|||
float opticalDepth = -NoR1 * bsdfData.thickness; |
|||
// Out hit point in the tangent sphere |
|||
float3 P1 = posInput.positionWS + R1 * opticalDepth; |
|||
// Out normal |
|||
float3 N1 = normalize(C - P1); |
|||
// Out refracted ray |
|||
R = refract(R1, N1, bsdfData.ior); |
|||
#endif |
|||
} |
|||
|
|||
// In Unity the cubemaps are capture with the localToWorld transform of the component. |
|||
// This mean that location and orientation matter. So after intersection of proxy volume we need to convert back to world. |
|||
|
|||
// CAUTION: localToWorld is the transform use to convert the cubemap capture point to world space (mean it include the offset) |
|||
// the center of the bounding box is thus in locals space: positionLS - offsetLS |
|||
// We use this formulation as it is the one of legacy unity that was using only AABB box. |
|||
float3x3 worldToLocal = transpose(float3x3(lightData.right, lightData.up, lightData.forward)); // worldToLocal assume no scaling |
|||
float3 positionLS = positionWS - lightData.positionWS; |
|||
positionLS = mul(positionLS, worldToLocal).xyz - lightData.offsetLS; // We want to calculate the intersection from the center of the bounding box. |
|||
|
|||
// Note: using envShapeType instead of lightData.envShapeType allow to make compiler optimization in case the type is know (like for sky) |
|||
if (envShapeType == ENVSHAPETYPE_SPHERE) |
|||
{ |
|||
// 1. First process the projection |
|||
float3 dirLS = mul(R, worldToLocal); |
|||
float sphereOuterDistance = lightData.innerDistance.x + lightData.blendDistance; |
|||
float dist = SphereRayIntersectSimple(positionLS, dirLS, sphereOuterDistance); |
|||
dist = max(dist, lightData.minProjectionDistance); // Setup projection to infinite if requested (mean no projection shape) |
|||
// We can reuse dist calculate in LS directly in WS as there is no scaling. Also the offset is already include in lightData.positionWS |
|||
R = (positionWS + dist * R) - lightData.positionWS; |
|||
|
|||
// 2. Process the influence |
|||
float distFade = max(length(positionLS) - lightData.innerDistance.x, 0.0); |
|||
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero |
|||
} |
|||
else if (envShapeType == ENVSHAPETYPE_BOX) |
|||
{ |
|||
float3 dirLS = mul(R, worldToLocal); |
|||
float3 boxOuterDistance = lightData.innerDistance + float3(lightData.blendDistance, lightData.blendDistance, lightData.blendDistance); |
|||
float dist = BoxRayIntersectSimple(positionLS, dirLS, -boxOuterDistance, boxOuterDistance); |
|||
dist = max(dist, lightData.minProjectionDistance); // Setup projection to infinite if requested (mean no projection shape) |
|||
// No need to normalize for fetching cubemap |
|||
// We can reuse dist calculate in LS directly in WS as there is no scaling. Also the offset is already include in lightData.positionWS |
|||
R = (positionWS + dist * R) - lightData.positionWS; |
|||
|
|||
// TODO: add distance based roughness |
|||
|
|||
// Influence volume |
|||
// Calculate falloff value, so reflections on the edges of the volume would gradually blend to previous reflection. |
|||
float distFade = DistancePointBox(positionLS, -lightData.innerDistance, lightData.innerDistance); |
|||
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero |
|||
} |
|||
|
|||
// Smooth weighting |
|||
weight = Smoothstep01(weight); |
|||
|
|||
float3 F = 1.0; |
|||
|
|||
float4 preLD = SampleEnv(lightLoopContext, lightData.envIndex, R, preLightData.iblMipLevel); |
|||
envLighting += F * preLD.rgb * preLightData.specularFGD; |
|||
|
|||
#endif |
|||
|
|||
UpdateLightingHierarchyWeights(hierarchyWeight, weight); |
|||
|
|||
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION) |
|||
lighting.specularReflected = envLighting * weight; |
|||
else |
|||
lighting.specularTransmitted = envLighting * weight; |
|||
|
|||
return lighting; |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// PostEvaluateBSDF |
|||
// ---------------------------------------------------------------------------- |
|||
|
|||
void PostEvaluateBSDF( LightLoopContext lightLoopContext, |
|||
float3 V, PositionInputs posInput, |
|||
PreLightData preLightData, BSDFData bsdfData, float3 bakeDiffuseLighting, AggregateLighting lighting, |
|||
out float3 diffuseLighting, out float3 specularLighting) |
|||
{ |
|||
// Use GTAOMultiBounce approximation for ambient occlusion (allow to get a tint from the baseColor) |
|||
#define GTAO_MULTIBOUNCE_APPROX 1 |
|||
|
|||
// Note: When we ImageLoad outside of texture size, the value returned by Load is 0 (Note: On Metal maybe it clamp to value of texture which is also fine) |
|||
// We use this property to have a neutral value for AO that doesn't consume a sampler and work also with compute shader (i.e use ImageLoad) |
|||
// We store inverse AO so neutral is black. So either we sample inside or outside the texture it return 0 in case of neutral |
|||
|
|||
// Ambient occlusion use for indirect lighting (reflection probe, baked diffuse lighting) |
|||
float indirectAmbientOcclusion = 1.0 - LOAD_TEXTURE2D(_AmbientOcclusionTexture, posInput.unPositionSS).x; |
|||
// Ambient occlusion use for direct lighting (directional, punctual, area) |
|||
float directAmbientOcclusion = lerp(1.0, indirectAmbientOcclusion, _AmbientOcclusionParam.w); |
|||
|
|||
// Add indirect diffuse + emissive (if any) - Ambient occlusion is multiply by emissive which is wrong but not a big deal |
|||
#if GTAO_MULTIBOUNCE_APPROX |
|||
bakeDiffuseLighting *= GTAOMultiBounce(indirectAmbientOcclusion, bsdfData.diffuseColor); |
|||
#else |
|||
bakeDiffuseLighting *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), indirectAmbientOcclusion); |
|||
#endif |
|||
|
|||
float specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, indirectAmbientOcclusion, bsdfData.roughness); |
|||
// Try to mimic multibounce with specular color. Not the point of the original formula but ok result. |
|||
// Take the min of screenspace specular occlusion and visibility cone specular occlusion |
|||
#if GTAO_MULTIBOUNCE_APPROX |
|||
lighting.indirect.specularReflected *= GTAOMultiBounce(min(bsdfData.specularOcclusion, specularOcclusion), bsdfData.fresnel0); |
|||
#else |
|||
lighting.indirect.specularReflected *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), min(bsdfData.specularOcclusion, specularOcclusion)); |
|||
#endif |
|||
|
|||
// TODO: we could call a function like PostBSDF that will apply albedo and divide by PI once for the loop |
|||
|
|||
lighting.direct.diffuse *= |
|||
#if GTAO_MULTIBOUNCE_APPROX |
|||
GTAOMultiBounce(directAmbientOcclusion, bsdfData.diffuseColor); |
|||
#else |
|||
lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), directAmbientOcclusion); |
|||
#endif |
|||
|
|||
diffuseLighting = lighting.direct.diffuse + bakeDiffuseLighting; |
|||
// If refraction is enable we use the transmittanceMask to lerp between current diffuse lighting and refraction value |
|||
// Physically speaking, it should be transmittanceMask should be 1, but for artistic reasons, we let the value vary |
|||
#if HAS_REFRACTION |
|||
diffuseLighting = lerp(diffuseLighting, lighting.indirect.specularTransmitted, bsdfData.transmittanceMask); |
|||
#endif |
|||
|
|||
specularLighting = lighting.direct.specular + lighting.indirect.specularReflected; |
|||
// Rescale the GGX to account for the multiple scattering. |
|||
specularLighting *= 1.0 + bsdfData.fresnel0 * preLightData.energyCompensation; |
|||
|
|||
#ifdef DEBUG_DISPLAY |
|||
if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_OCCLUSION_FROM_SSAO) |
|||
{ |
|||
diffuseLighting = indirectAmbientOcclusion; |
|||
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting |
|||
} |
|||
else if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_OCCLUSION_FROM_SSAO) |
|||
{ |
|||
diffuseLighting = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, indirectAmbientOcclusion, bsdfData.roughness); |
|||
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting |
|||
} |
|||
#if GTAO_MULTIBOUNCE_APPROX |
|||
else if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_GTAO_FROM_SSAO) |
|||
{ |
|||
diffuseLighting = GTAOMultiBounce(indirectAmbientOcclusion, bsdfData.diffuseColor); |
|||
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting |
|||
} |
|||
else if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_GTAO_FROM_SSAO) |
|||
{ |
|||
diffuseLighting = GTAOMultiBounce(specularOcclusion, bsdfData.fresnel0); |
|||
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting |
|||
} |
|||
#endif |
|||
#endif |
|||
} |
|||
|
|||
#endif // #ifdef HAS_LIGHTLOOP |
|
|||
fileFormatVersion: 2 |
|||
guid: a5ae278c101d602428cf78a26d2444e9 |
|||
timeCreated: 1504900828 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d528849495b23584f85182d370ce3e97 |
|||
folderAsset: yes |
|||
timeCreated: 1509471263 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue