首先声明以下素材和shader代码都来自Kerry佬,我只做整理和学习之用,写此随笔是为了做个笔记方便以后查阅。
IBL,英文全称Image Based Lighting,即基于图像的照明,是一种通过采样图片从而模拟出光照的技术。
IBL不需要在shader中进行直接光源的光照计算,而是将周围环境提前做成一个CubeMap,或者用反射探针在unity中烘焙好。
采样CubeMap时,可根据粗糙度贴图等生成动态mipmap值,根据mipmap值来采样CubeMap,从而模拟出如金属表面有污渍的效果。
IBL镜面反射和漫反射都可模拟,两者区别在于:
1. 如下图,镜面反射选择Specular,漫反射选择Diffuse。
2. 当采样CubeMap时,镜面反射还是用视角方向基于法线的反射向量来采样,漫反射则可使用法线方向来采样。
shader如下:
1 Shader "MyURP/Kerry/IBL/URPIBLProbe" 2 { 3 Properties 4 { 5 //_MainTex ("Texture", 2D) = "white" {} 6 _CubeMap("Cube Map",Cube) = "white"{} 7 _Tint("Tint",Color) = (1,1,1,1) 8 _Expose("Expose",Float) = 1.0 9 _Rotate("Rotate",Range(0,360)) = 0 10 _NormalMap("Normal Map",2D) = "bump"{} 11 _NormalIntensity("Normal Intensity",Float) = 1.0 12 _AOMap("AO Map",2D) = "white"{} 13 _AOAdjust("AO Adjust",Range(0,1)) = 1 14 _RoughnessMap("Roughness Map",2D) = "black"{} 15 _RoughnessContrast("Roughness Contrast",Range(0.01,10)) = 1 16 _RoughnessBrightness("Roughness Brightness",Float) = 1 17 _RoughnessMin("Rough Min",Range(0,1)) = 0 18 _RoughnessMax("Rough Max",Range(0,1)) = 1 19 } 20 SubShader 21 { 22 Tags 23 { 24 "RenderType" = "Opaque" 25 "RenderPipeling" = "UniversalPipeline" 26 } 27 LOD 100 28 29 Pass 30 { 31 HLSLPROGRAM 32 #pragma vertex vert 33 #pragma fragment frag 34 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 35 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" 36 37 struct appdata 38 { 39 float4 vertex : POSITION; 40 float2 texcoord : TEXCOORD0; 41 float3 normal : NORMAL; 42 float4 tangent : TANGENT; 43 }; 44 45 struct v2f 46 { 47 float2 uv : TEXCOORD0; 48 float4 pos : SV_POSITION; 49 float3 normal_world : TEXCOORD1; 50 float3 pos_world : TEXCOORD2; 51 float3 tangent_world : TEXCOORD3; 52 float3 binormal_world : TEXCOORD4; 53 }; 54 55 //sampler2D _MainTex; 56 //float4 _MainTex_ST; 57 TEXTURECUBE(_CubeMap); SAMPLER(sampler_CubeMap); 58 float4 _Tint; 59 float _Expose; 60 61 TEXTURE2D(_NormalMap); SAMPLER(sampler_NormalMap); 62 float4 _NormalMap_ST; 63 float _NormalIntensity; 64 TEXTURE2D(_AOMap); SAMPLER(sampler_AOMap); 65 float _AOAdjust; 66 float _Rotate; 67 float _Roughness; 68 TEXTURE2D(_RoughnessMap); SAMPLER(sampler_RoughnessMap); 69 float _RoughnessContrast; 70 float _RoughnessBrightness; 71 float _RoughnessMin; 72 float _RoughnessMax; 73 74 float3 RotateAround(float degree, float3 target) 75 { 76 float rad = degree * PI / 180; 77 float2x2 m_rotate = float2x2(cos(rad), -sin(rad), 78 sin(rad), cos(rad)); 79 float2 dir_rotate = mul(m_rotate, target.xz); 80 target = float3(dir_rotate.x, target.y, dir_rotate.y); 81 return target; 82 } 83 84 inline float3 ACES_Tonemapping(float3 x) 85 { 86 float a = 2.51f; 87 float b = 0.03f; 88 float c = 2.43f; 89 float d = 0.59f; 90 float e = 0.14f; 91 float3 encode_color = saturate((x*(a*x + b)) / (x*(c*x + d) + e)); 92 return encode_color; 93 }; 94 95 v2f vert (appdata v) 96 { 97 v2f o; 98 o.pos = TransformObjectToHClip(v.vertex.xyz); 99 o.uv = v.texcoord * _NormalMap_ST.xy + _NormalMap_ST.zw; 100 o.pos_world = mul(unity_ObjectToWorld, v.vertex).xyz; 101 o.normal_world = normalize(mul(float4(v.normal, 0.0), unity_WorldToObject).xyz); 102 o.tangent_world = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz); 103 o.binormal_world = normalize(cross(o.normal_world, o.tangent_world)) * v.tangent.w; 104 return o; 105 } 106 107 half4 frag (v2f i) : SV_Target 108 { 109 half3 normal_dir = normalize(i.normal_world); 110 half3 normaldata = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap,sampler_NormalMap,i.uv)); 111 normaldata.xy = normaldata.xy* _NormalIntensity; 112 half3 tangent_dir = normalize(i.tangent_world); 113 half3 binormal_dir = normalize(i.binormal_world); 114 normal_dir = normalize(tangent_dir * normaldata.x + binormal_dir * normaldata.y + normal_dir * normaldata.z); 115 116 half ao = SAMPLE_TEXTURE2D(_AOMap, sampler_AOMap, i.uv).r; 117 ao = lerp(1.0,ao, _AOAdjust); 118 half3 view_dir = GetWorldSpaceNormalizeViewDir(i.pos_world); 119 half3 reflect_dir = reflect(-view_dir, normal_dir); 120 121 reflect_dir = RotateAround(_Rotate, reflect_dir); 122 123 float roughness = SAMPLE_TEXTURE2D(_RoughnessMap, sampler_RoughnessMap, i.uv).r; 124 roughness = saturate(pow(roughness, _RoughnessContrast) * _RoughnessBrightness); 125 roughness = lerp(_RoughnessMin, _RoughnessMax, roughness); 126 roughness = roughness * (1.7 - 0.7 * roughness); 127 float mip_level = roughness * 6.0; 128 129 half4 color_cubemap = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflect_dir, mip_level); 130 half3 env_color = DecodeHDREnvironment(color_cubemap, unity_SpecCube0_HDR);//确保在移动端能拿到HDR信息 131 half3 final_color = env_color * ao * _Tint.rgb * _Tint.rgb * _Expose; 132 //half3 final_color_linear = pow(final_color, 2.2); 133 //final_color = ACES_Tonemapping(final_color_linear); 134 //half3 final_color_gamma = pow(final_color, 1.0 / 2.2); 135 136 return float4(final_color, 1.0); 137 } 138 ENDHLSL 139 } 140 } 141 FallBack "Hidden/Universal Render Pipeline/FallbackError" 142 }
效果如下:
转载请注明出处:https://www.cnblogs.com/jietian331/p/17027723.html
标签:IBL,color,float,Shader,half3,Unity,world,dir,float3 From: https://www.cnblogs.com/jietian331/p/17027723.html