2023-05-08 15:56:10 +03:00

256 lines
8.0 KiB
Plaintext

/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
ANY KIND, either express or implied. See the License for the specific language governing
permissions and limitations under the License.
************************************************************************************/
// PBR Shader adapted from Standard (Metallic) that works in built-in and URP pipelines
// Supports 1 directional light without specular
Shader "Unlit/BasicPBR"
{
Properties
{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Texture", 2D) = "white" {}
_Metallic("Metallic", Range(0,1)) = 0
_Gloss("Gloss", Range(0,1)) = 0
[NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
[NoScaleOffset] _WetMap("Wet Map", 2D) = "black" {}
[Enum(UV0,0,UV1,1)] _WetMapUV("Wet Map UV Set", Float) = 1
// droplets for non-porous horizontal surfaces
[HideInInspector] _WetBumpMap("Wet Bump Map", 2D) = "bump" {}
[Toggle(VERTEX_COLOR_LIGHTMAP)] _VertexColorLightmap("Vertex Color Lightmap", Float) = 0
_VertexColorLightmapScale("Vertex Color Lightmap Scale", Float) = 1
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
fixed4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float3 tangentWS: TEXCOORD3;
float3 bitangentWS: TEXCOORD4;
float3 positionWS : TEXCOORD5;
fixed4 color : COLOR;
UNITY_FOG_COORDS(6)
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
// standard properties
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
fixed _Metallic;
fixed _Gloss;
sampler2D _WetMap;
half _WetMapUV;
sampler2D _WetBumpMap;
float _VertexColorLightmapScale;
// globals
float3 _BasicPBRLightDir;
fixed3 _BasicPBRLightColor;
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
o.uv1 = v.texcoord1;
o.positionWS = mul(unity_ObjectToWorld, v.vertex);
o.normalWS = normalize(UnityObjectToWorldNormal(v.normal));
o.tangentWS = normalize(mul(unity_ObjectToWorld, v.tangent).xyz);
o.bitangentWS = normalize(cross(o.normalWS, o.tangentWS.xyz));
o.color = v.color;
UNITY_TRANSFER_FOG(o, o.vertex);
return o;
}
// UnityStandardUtils.cginc#L46
half3 DiffuseAndSpecularFromMetallic(half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity)
{
specColor = lerp(unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
oneMinusReflectivity = oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
return albedo * oneMinusReflectivity;
}
// UnityImageBasedLighting.cginc#L522
half3 Unity_GlossyEnvironment(half3 reflectDir, half perceptualRoughness)
{
perceptualRoughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);
half mip = perceptualRoughness * 6;
half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflectDir, mip);
return DecodeHDR(rgbm, unity_SpecCube1_HDR);
}
inline half3 Pow4(half3 x)
{
return x * x * x * x;
}
// UnityStandardBRDF.cginc#L92
inline half3 FresnelLerp(half3 F0, half3 F90, half cosA)
{
half t = Pow4(1 - cosA);
return lerp(F0, F90, t);
}
// UnityStandardBRDF.cginc#L299
half SurfaceReduction(float perceptualRoughness)
{
float roughness = perceptualRoughness * perceptualRoughness;
#ifdef UNITY_COLORSPACE_GAMMA
return 1.0 - 0.28 * roughness * perceptualRoughness;
#else
return 1.0 / (roughness * roughness + 1.0);
#endif
}
// UnityStandardBRDF.cginc#L338
float3 Specular(float roughness, float3 normal, float3 viewDir)
{
half3 halfDir = normalize(-_BasicPBRLightDir + viewDir);
float nh = saturate(dot(normal, halfDir));
float lh = saturate(dot(_BasicPBRLightDir, halfDir));
float a = roughness * roughness;
float a2 = a * a;
float d = nh * nh * (a2 - 1.f) + 1.00001f;
#ifdef UNITY_COLORSPACE_GAMMA
float specularTerm = a / (max(0.32f, lh) * (1.5f + a) * d);
#else
float specularTerm = a2 / (max(0.1f, lh * lh) * (a + 0.5f) * (d * d) * 4);
#endif
#if defined (SHADER_API_MOBILE)
specularTerm = specularTerm - 1e-4f;
#endif
return specularTerm * 0.3f;
}
// https://seblagarde.wordpress.com/2013/04/14/water-drop-3b-physically-based-wet-surfaces/
void AddWater(float2 uv, float metalness, inout half3 diffuse, inout float smoothness, inout fixed4 bumpMap, float2 wsPos, float3 normalWS)
{
fixed wetMap = tex2D(_WetMap, uv).r;
float porosity = saturate((1 - smoothness) - 0.2);//saturate(((1-Gloss) - 0.5)) / 0.4 );
float factor = lerp(1, 0.2, (1 - metalness) * porosity);
float collectWater = max(0, normalWS.y);
diffuse *= lerp(1.0, factor, wetMap);
smoothness = lerp(smoothness, 0.95, saturate(wetMap * wetMap));// lerp(1, factor, 0.5 * wetMap));
bumpMap = lerp(bumpMap, tex2D(_WetBumpMap, wsPos * 20), wetMap * collectWater);
}
fixed4 frag(v2f i) : SV_Target
{
// BRDF texture inputs
fixed4 mainTex = tex2D(_MainTex, i.uv0);
float4 bumpMap = tex2D(_BumpMap, i.uv0);
// BEDF values
fixed3 albedo = mainTex.rgb * _Color.rgb;
float metalness = _Metallic;
float smoothness = _Gloss;
float oneMinusReflectivity;
float3 specColor;
float3 diffColor = DiffuseAndSpecularFromMetallic(albedo.rgb, metalness, /*out*/ specColor, /*out*/ oneMinusReflectivity);
AddWater((_WetMapUV == 0) ? i.uv0 : i.uv1, metalness, /*inout*/ diffColor, /*inout*/ smoothness, /*inout*/ bumpMap, i.positionWS.xz, i.normalWS);
float3x3 tangentMatrix = transpose(float3x3(i.tangentWS, i.bitangentWS, i.normalWS));
float3 normal = normalize(mul(tangentMatrix, UnpackNormal(bumpMap)));
float3 ambient =
#if VERTEX_COLOR_LIGHTMAP
i.color.rgb * _VertexColorLightmapScale;
#else
ShadeSH9(float4(normal, 1));
#endif
half nl = saturate(dot(normal, -_BasicPBRLightDir));
half3 diffuse = diffColor * (ambient + _BasicPBRLightColor * nl);
float perceptualRoughness = 1 - smoothness;
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.positionWS);
half nv = abs(dot(normal, viewDir));
float3 reflectDir = -reflect(viewDir, normal);
float3 specularGI = Unity_GlossyEnvironment(reflectDir, perceptualRoughness);
half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity));
half3 specular = SurfaceReduction(perceptualRoughness) * specularGI * FresnelLerp(specColor, grazingTerm, nv); +
+ Specular(perceptualRoughness, normal, viewDir) * specColor * nl * _BasicPBRLightColor;
// non BRDF texture inputs
half3 color = (diffuse + specular);
UNITY_APPLY_FOG(i.fogCoord, color);
return fixed4(color, 1);
}
ENDCG
SubShader
{
Tags{ "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Pass
{
Tags{ "LightMode" = "UniversalForward" }
CGPROGRAM
#pragma shader_feature VERTEX_COLOR_LIGHTMAP
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
ENDCG
}
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma shader_feature VERTEX_COLOR_LIGHTMAP
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
ENDCG
}
}
}