// GENERATED BY SHADER GRAPH // Question for shader graph: how to handle dynamic parameter data like matData0 that can change name // No guard header! #define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl #include "Lighting/Lighting.hlsl" // This include Material.hlsl #include "ShaderVariables.hlsl" // This files is generated by the ShaderGraph or written by hand // Note for ShaderGraph: // ShaderGraph should generate the vertex shader output to add the variable that may be required // For example if we require view vector in shader graph, the output must contain positionWS and we calcualte the view vector with it. // Still some input are mandatory depends on the type of loop. positionWS is mandatory in this current framework. So the ShaderGraph should always generate it. //------------------------------------------------------------------------------------- // variable declaration //------------------------------------------------------------------------------------- // Set of users variables float4 _BaseColor; sampler2D _BaseColorMap; float _Metalic; float _Smoothness; sampler2D _MaskMap; sampler2D _SpecularOcclusionMap; sampler2D _NormalMap; sampler2D _Heightmap; float _HeightScale; float _HeightBias; sampler2D _DiffuseLightingMap; float4 _EmissiveColor; sampler2D _EmissiveColorMap; float _EmissiveIntensity; float _SubSurfaceRadius; sampler2D _SubSurfaceRadiusMap; // float _Thickness; // sampler2D _ThicknessMap; // float _CoatCoverage; // sampler2D _CoatCoverageMap; // float _CoatRoughness; // sampler2D _CoatRoughnessMap; float _AlphaCutoff; //------------------------------------------------------------------------------------- // Lighting architecture //------------------------------------------------------------------------------------- // TODO: Check if we will have different Varyings based on different pass, not sure about that... // Forward struct Attributes { float3 positionOS : POSITION; float3 normalOS : NORMAL; float2 uv0 : TEXCOORD0; float4 tangentOS : TANGENT; }; struct Varyings { float4 positionHS; float3 positionWS; float2 texCoord0; float4 tangentToWorld[3]; // [3x3:tangentToWorld | 1x3:viewDirForParallax] #ifdef SHADER_STAGE_FRAGMENT #if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR) FRONT_FACE_TYPE cullFace; #endif #endif }; struct PackedVaryings { float4 positionHS : SV_Position; float4 interpolators[5] : TEXCOORD0; #ifdef SHADER_STAGE_FRAGMENT #if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR) FRONT_FACE_TYPE cullFace : FRONT_FACE_SEMATIC; #endif #endif }; // Function to pack data to use as few interpolator as possible, the ShaderGraph should generate these functions PackedVaryings PackVaryings(Varyings input) { PackedVaryings output; output.positionHS = input.positionHS; output.interpolators[0].xyz = input.positionWS.xyz; output.interpolators[0].w = input.texCoord0.x; output.interpolators[1] = input.tangentToWorld[0]; output.interpolators[2] = input.tangentToWorld[1]; output.interpolators[3] = input.tangentToWorld[2]; output.interpolators[4].x = input.texCoord0.y; output.interpolators[4].yzw = float3(0.0, 0.0, 0.0); return output; } Varyings UnpackVaryings(PackedVaryings input) { Varyings output; output.positionHS = input.positionHS; output.positionWS.xyz = input.interpolators[0].xyz; output.texCoord0.x = input.interpolators[0].w; output.texCoord0.y = input.interpolators[4].x; output.tangentToWorld[0] = input.interpolators[1]; output.tangentToWorld[1] = input.interpolators[2]; output.tangentToWorld[2] = input.interpolators[3]; #ifdef SHADER_STAGE_FRAGMENT #if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR) output.cullFace = input.cullFace; #endif #endif return output; } // TODO: Here we will also have all the vertex deformation (GPU skinning, vertex animation, morph target...) or we will need to generate a compute shaders instead (better! but require work to deal with unpacking like fp16) PackedVaryings VertDefault(Attributes input) { Varyings output; output.positionWS = TransformObjectToWorld(input.positionOS); // TODO deal with camera center rendering and instancing (This is the reason why we always perform tow steps transform to clip space + instancing matrix) output.positionHS = TransformWorldToHClip(output.positionWS); float3 normalWS = TransformObjectToWorldNormal(input.normalOS); output.texCoord0 = input.uv0; float4 tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w); float3x3 tangentToWorld = CreateTangentToWorld(normalWS, tangentWS.xyz, tangentWS.w); output.tangentToWorld[0].xyz = tangentToWorld[0]; output.tangentToWorld[1].xyz = tangentToWorld[1]; output.tangentToWorld[2].xyz = tangentToWorld[2]; output.tangentToWorld[0].w = 0; output.tangentToWorld[1].w = 0; output.tangentToWorld[2].w = 0; return PackVaryings(output); } //------------------------------------------------------------------------------------- // Fill SurfaceData/Lighting data function //------------------------------------------------------------------------------------- float3 TransformTangentToWorld(float3 normalTS, float4 tangentToWorld[3]) { // TODO check: do we need to normalize ? return normalize(mul(normalTS, float3x3(tangentToWorld[0].xyz, tangentToWorld[1].xyz, tangentToWorld[2].xyz))); } #if SHADER_STAGE_FRAGMENT void GetSurfaceAndBuiltinData(Varyings input, out SurfaceData surfaceData, out BuiltinData builtinData) { surfaceData.baseColor = tex2D(_BaseColorMap, input.texCoord0).rgb * _BaseColor.rgb; #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A float alpha = _BaseColor.a; #else float alpha = tex2D(_BaseColorMap, input.texCoord0).a * _BaseColor.a; #endif #ifdef _ALPHATEST_ON clip(alpha - _AlphaCutoff); #endif builtinData.opacity = alpha; #ifdef _SPECULAROCCLUSIONMAP // TODO: Do something. For now just take alpha channel surfaceData.specularOcclusion = tex2D(_SpecularOcclusionMap, input.texCoord0).a; #else // Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087 //surfaceData.specularOcclusion = saturate(1.0 + horizonFade * dot(r, input.tangentToWorld[2].xyz); // smooth it //surfaceData.specularOcclusion *= surfaceData.specularOcclusion; surfaceData.specularOcclusion = 1.0; #endif // TODO: think about using BC5 float3 vertexNormalWS = input.tangentToWorld[2].xyz; #ifdef _NORMALMAP #ifdef _NORMALMAP_TANGENT_SPACE float3 normalTS = UnpackNormalDXT5nm(tex2D(_NormalMap, input.texCoord0)); surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld); #else // Object space (TODO: We need to apply the world rotation here!) surfaceData.normalWS = tex2D(_NormalMap, input.texCoord0).rgb; #endif #else surfaceData.normalWS = vertexNormalWS; #endif #if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR) #ifdef _DOUBLESIDED_LIGHTING_FLIP float3 oppositeNormalWS = -surfaceData.normalWS; #else // Mirror the normal with the plane define by vertex normal float3 oppositeNormalWS = reflect(surfaceData.normalWS, vertexNormalWS); #endif // TODO : Test if GetOdddNegativeScale() is necessary here in case of normal map, as GetOdddNegativeScale is take into account in CreateTangentToWorld(); surfaceData.normalWS = IS_FRONT_VFACE(input.cullFace, GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS, -GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS); #endif #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A surfaceData.perceptualSmoothness = tex2D(_BaseColorMap, input.texCoord0).a; #elif defined(_MASKMAP) surfaceData.perceptualSmoothness = tex2D(_MaskMap, input.texCoord0).a; #else surfaceData.perceptualSmoothness = 1.0; #endif surfaceData.perceptualSmoothness *= _Smoothness; surfaceData.materialId = 0; // MaskMap is Metalic, Ambient Occlusion, (Optional) - emissive Mask, Optional - Smoothness (in alpha) #ifdef _MASKMAP surfaceData.metalic = tex2D(_MaskMap, input.texCoord0).r; surfaceData.ambientOcclusion = tex2D(_MaskMap, input.texCoord0).g; #else surfaceData.metalic = 1.0; surfaceData.ambientOcclusion = 1.0; #endif surfaceData.metalic *= _Metalic; surfaceData.tangentWS = float3(1.0, 0.0, 0.0); surfaceData.anisotropy = 0; surfaceData.specular = 0.04; surfaceData.subSurfaceRadius = 1.0; surfaceData.thickness = 0.0; surfaceData.subSurfaceProfile = 0; surfaceData.coatNormalWS = float3(1.0, 0.0, 0.0); surfaceData.coatPerceptualSmoothness = 1.0; surfaceData.specularColor = float3(0.0, 0.0, 0.0); // Builtin Data // TODO: Sample lightmap/lightprobe/volume proxy // This should also handle projective lightmap // Note that data input above can be use to sample into lightmap (like normal) builtinData.bakeDiffuseLighting = tex2D(_DiffuseLightingMap, input.texCoord0).rgb; // If we chose an emissive color, we have a dedicated texture for it and don't use MaskMap #ifdef _EMISSIVE_COLOR #ifdef _EMISSIVE_COLOR_MAP builtinData.emissiveColor = tex2D(_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor; #else builtinData.emissiveColor = _EmissiveColor; #endif #elif defined(_MASKMAP) // If we have a MaskMap, use emissive slot as a mask on baseColor builtinData.emissiveColor = surfaceData.baseColor * tex2D(_MaskMap, input.texCoord0).bbb; #else builtinData.emissiveColor = float3(0.0, 0.0, 0.0); #endif builtinData.emissiveIntensity = _EmissiveIntensity; builtinData.velocity = float2(0.0, 0.0); builtinData.distortion = float2(0.0, 0.0); builtinData.distortionBlur = 0.0; } void GetVaryingsDataDebug(uint paramId, Varyings input, inout float3 result, inout float outputIsLinear) { if (paramId == MaterialDebugDepth) { float linearDepth = frac(LinearEyeDepth(input.positionHS.z, _ZBufferParams) * 0.1); result = linearDepth.xxx; outputIsLinear = true; } else if (paramId == MaterialDebugTexCoord0) { result = float3(input.texCoord0, 0.0); outputIsLinear = true; } else if (paramId == MaterialDebugVertexNormalWS) { result = input.tangentToWorld[2].xyz * 0.5 + 0.5; outputIsLinear = true; } else if (paramId == MaterialDebugVertexTangentWS) { result = input.tangentToWorld[0].xyz * 0.5 + 0.5; outputIsLinear = true; } else if (paramId == MaterialDebugVertexBitangentWS) { result = input.tangentToWorld[1].xyz * 0.5 + 0.5; outputIsLinear = true; } } #endif // #if SHADER_STAGE_FRAGMENT