提高网站排名的软件,怎样做网站亮照亮标,小说网站建设方案书ppt,上海地产网站建Cook-Torrance模型是一个微表面光照模型#xff0c;认为物体的表面可以看作是由许多个理想的镜面反射体微小平面组成的。
单点反射镜面反射漫反射占比*漫反射
漫反射 基础色/Π
镜面反射DFG/4(NV)(NL)
D代表微平面分布函数#xff0c;描述的是法线与半角向量normalize(L… Cook-Torrance模型是一个微表面光照模型认为物体的表面可以看作是由许多个理想的镜面反射体微小平面组成的。
单点反射镜面反射漫反射占比*漫反射
漫反射 基础色/Π
镜面反射DFG/4(N·V)(N·L)
D代表微平面分布函数描述的是法线与半角向量normalize(LV)对齐的概率对齐程度越高反射程度越大。
F代表菲涅尔反射函数描述的是视线与法线的夹角越小时向镜面反射集中反之向漫反射集中。
G代表几何衰减系数源自微表面的自我遮蔽现象入射光线或反射光线会被凹凸表面遮挡越粗糙的材质表面越可能发生自我遮蔽
但是想要计算出微表面的光照单点反射当然是不够的对于一个点有多个角度会产生光照结果所以对于光照输入角度的积分是必须的。
输出光{单点反射*输入光*(N·V) }对于输入角度的积分
对于直接光的计算通常可以直接遍历所有光源计算即可但对于漫反射的计算通常会采用近似的方式因为运行时的积分计算是十分昂贵的。所以通常会使用近似函数或预计算采样的方式实现。
想要了解更多关于Cook-Torrance模型可以去知乎检索。
下面是具体实现代码
Shader Kerzh/PBRhlsl
{Properties{_TessellationUniform (Tessellation Uniform, Vector) (1,1,1,1) // 曲面细分系数默认1代表不做操作[Space(10)]_BaseColorTex (_BaseColorTex, 2D) white {}_MetallicTex (_MetallicTex, 2D) white {}_RoughnessTex (_RoughnessTex, 2D) white {}_EmissionTex (_EmissionTex, 2D) black {}//默认传入黑色即不存在自发光[Space(10)]_NormalTex (_NormalTex, 2D) bump {}//默认传入是(0.5,0.5,1)这是法线的标准颜色相当于一张没有影响的法线图_AOTex (_AOTex, 2D) white {} // 默认传入白色即不存在光线遮蔽[Space(10)][Toggle(ENABLE_BRDF_LUT)]_EnableBrdfLut(Enable BrdfLut,Float) 0_BRDFLut(BRDFLut,2D) black{}}SubShader{Tags { RenderPipeline UniversalRenderPipeline LightMode UniversalForward }Pass{HLSLPROGRAM#pragma vertex vert#pragma hull hull#pragma domain domain#pragma geometry geom#pragma fragment frag#pragma target 4.6#pragma shader_feature _ ENABLE_BRDF_LUT // _ 默认关闭是否使用预计算漫反射第二部分#pragma multi_compile _ADDITIONAL_LIGHTS_VERTEX // 用于激活VertexLighting方法中对次要光源的计算#include CommonHlslInc.hlsl#include CustomTessellation.hlsl#include Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl#include Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityInput.hlsl#include Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl#include Packages/com.unity.render-pipelines.core/ShaderLibrary/SphericalHarmonics.hlslsampler2D _MainTex;float4 _MainTex_ST;float _Value, _RangeValue;float4 _Color, _BaseColor;float _Metallic, _Roughness;sampler2D _BaseColorTex, _MetallicTex, _RoughnessTex;sampler2D _EmissionTex, _AOTex, _NormalTex;sampler2D _BRDFLut;float4 _Emission;#define Eplison 0.001 // 防曝光点//D 微平面分布函数 Trowbridge-Reitz模型float D_DistributionGGX(float3 N, float3 H, float Roughness){float a Roughness * Roughness;float a2 a * a;float NH max(dot(N, H), 0);float NH2 NH * NH;float nominator a2;float denominator (NH2 * (a2 - 1.0) 1.0);denominator PI * denominator * denominator;return nominator / max(denominator, Eplison); //防止分母为0}//G 几何衰减系数 Schlick-GGX模型float GeometrySchlickGGX(float NV, float Roughness){float r Roughness 1.0;float k r * r / 8.0;float nominator NV;float denominator k (1.0 - k) * NV;return nominator / max(denominator, Eplison); //防止分母为0}// 获取几何衰减系数float G_GeometrySmith(float3 N, float3 V, float Roughness){float NV max(dot(N, V), 0);float ggx GeometrySchlickGGX(NV, Roughness);return ggx;}//F -直接光float3 F_FrenelSchlick(float NV, float3 F0){return F0 (1.0 - F0) * pow(1.0 - NV, 5);}//F -间接光float3 FresnelSchlickRoughness(float NV, float3 F0, float Roughness){float s 1.0 - Roughness;return F0 (max(s.xxx, F0) - F0) * pow(1.0 - NV, 5.0);}//UE4中的近似计算函数 用于近似计算间接光漫反射第二部分float2 EnvBRDFApprox(float Roughness, float NoV){const half4 c0 { -1, -0.0275, -0.572, 0.022 };const half4 c1 { 1, 0.0425, 1.04, -0.04 };half4 r Roughness * c0 c1;half a004 min(r.x * r.x, exp2(-9.28 * NoV)) * r.x r.y;half2 AB half2(-1.04, 1.04) * a004 r.zw;return AB;}MeshData vert(MeshData input){return input;}//如果不正确配置会报错[domain(tri)] // 正在处理三角形 tri, quad, or isoline[outputcontrolpoints(3)] // 每个面片输出的顶点为3个[outputtopology(triangle_cw)] // 当创建三角形时应是顺时针还是逆时针这里应是顺时针 point, line, triangle_cw, or triangle_ccw[partitioning(integer)] // 如何细分切割面片 integer, pow2, fractional_even, or fractional_odd[patchconstantfunc(patchConstantFunction)] // 细分切割部分还必须提供函数处理每个面片调用一次MeshData hull (InputPatchMeshData, 3 patch, uint id : SV_OutputControlPointID) // 每个顶点调用一次如果是处理三角形就是调用三次{// 如果_TessellationUniform输入值为1不产生任何变化但当输入值为2时具体发生了什么// 对于一个三角形(因为我们配置的是处理三角形)根据三条边的二等分位置添加额外的一个顶点如果是3就是三等分位置添加两个顶点// 对于一个三角形(因为我们配置的是处理三角形)根据三条个顶点添加一个中心顶点// 根据patchConstantFunction赋值分配生成顶点的插值权重return patch[id];}// barycentricCoordinates分别代表各个点的插值权重,每个面片调用一次对细分后的三角顶点形进行处理(也就是说原顶点不经过此处理)[domain(tri)] // 正在处理三角形MeshData domain(TessellationFactors factors, OutputPatchMeshData, 3 patch, float3 barycentricCoordinates : SV_DomainLocation) {MeshData data; // 新的插值权重顶点#define MY_DOMAIN_PROGRAM_INTERPOLATE(fieldName) data.fieldName \patch[0].fieldName * barycentricCoordinates.x \patch[1].fieldName * barycentricCoordinates.y \patch[2].fieldName * barycentricCoordinates.z;//对所有信息利用插值权重进行插值计算MY_DOMAIN_PROGRAM_INTERPOLATE(vertex)MY_DOMAIN_PROGRAM_INTERPOLATE(normalTS)MY_DOMAIN_PROGRAM_INTERPOLATE(tangentTS)MY_DOMAIN_PROGRAM_INTERPOLATE(uv1)MY_DOMAIN_PROGRAM_INTERPOLATE(uv2)MY_DOMAIN_PROGRAM_INTERPOLATE(vertexColor)return data;}//最大的顶点数这里比如你要生成三个三角形面片那么一个面片需要三个顶点就是9个顶点一般来讲这里直接填多一点即可不过可能填太多了会导致内存占用[maxvertexcount(9)]void geom (triangle MeshData input[3],inout TriangleStreamVOutData triStream){//原样转换过去VOutData output[3];for(int i0;i3;i){VOutData p0;p0 FillBaseV2FData(input[i]);output[i] p0;}triStream.RestartStrip(); // 重新开始一个新的三角形triStream.Append(output[0]);triStream.Append(output[1]);triStream.Append(output[2]);}float4 frag(VOutData i) : SV_Target{float3 lightDirWS normalize(GetMainLight().direction);float3 viewDirWS normalize(GetWorldSpaceViewDir(i.posWS));float3 halfVectorWS normalize(viewDirWS lightDirWS);float2 uv i.uv1;// Normal Map ////这里我们采样到一个法线贴图向量是在切线空间下的我希望把他变换到世界空间所以我需要创建一个切线到世界的变换矩阵float3 NormalMap UnpackNormal(tex2D(_NormalTex, uv));//在创造一个转换矩阵时使用新坐标基在原空间中的向量构建这样的矩阵可以从原坐标系变换到新坐标系//所以这里想要构建一个从切线空间转换到到世界空间的矩阵虽然我们没有切线空间下的世界空间坐标但至少拥有世界空间下的切线坐标基//且世界空间下这三个坐标基正好是两两垂直的满足正交矩阵可以使用一个重要的性质矩阵的逆矩阵的转置//而这个矩阵的逆就是反向变换即我们最开始想要的切线空间到世界空间的变换。float3x3 TangentToWorldMatrix transpose(float3x3(i.tangentWS, normalize(i.bitangentWS), i.normalWS));float3 normalWS normalize(mul(TangentToWorldMatrix, NormalMap));// PBR 贴图采样 //float3 BaseColor tex2D(_BaseColorTex, uv);float Roughness tex2D(_RoughnessTex, uv).r;float Metallic tex2D(_MetallicTex, uv).r;float3 Emission tex2D(_EmissionTex, uv);float3 AO tex2D(_AOTex, uv);// Direct Light 直接光部分 ////Cook-Torrance BRDF模型float HV_WS saturate(dot(halfVectorWS, viewDirWS));float NV_WS saturate(dot(normalWS, viewDirWS));float NL_WS saturate(dot(normalWS, lightDirWS));float NH_WS saturate(dot(normalWS, halfVectorWS));//首先计算PBR三件套的DFG 要特别注意在这个PBR模型中直接光和间接光的F不同//微表面分布函数描述的法线与半角向量对齐的概率概率越大则反射越强float D D_DistributionGGX(normalWS, halfVectorWS, Roughness);//菲尼尔多影响高光和漫反射混合比例float3 F0 lerp(0.04, BaseColor, Metallic);//经验近似值float3 F F_FrenelSchlick(NV_WS, F0);//几何衰减系数源自微表面的自我遮蔽现象入射光线或反射光线会被凹凸表面遮挡越粗糙的材质表面越可能发生自我遮蔽float G G_GeometrySmith(normalWS, viewDirWS, Roughness);//还记得公式怎么写的吗//单点反射镜面反射占比*镜面反射漫反射占比*漫反射//漫反射 基础色/Π//镜面反射DFG/4(N·V)(N·L)//输出光{单点反射*输入光*(N·V)}对于输入角度的积分//------------------------------直接光-----漫反射------------------------------float3 Diffuse_Direct;//直接光漫反射--光源float3 Diffuse_Direct_lightSource BaseColor / PI;//直接光漫反射--比例用(1-F)(1-metallc)公式float3 KD_DirectLight;KD_DirectLight float3(1, 1, 1) - F;KD_DirectLight * 1 - Metallic;Diffuse_Direct Diffuse_Direct_lightSource * KD_DirectLight;//------------------------------直接光-----漫反射------------------------------//------------------------------直接光-----高光------------------------------float3 Specular_Direct;Specular_Direct (D * F * G)/max(4*NV_WS*NL_WS, Eplison);//------------------------------直接光-----高光------------------------------//获得输入光float3 lightInput VertexLighting(i.posWS, i.normalWS) GetMainLight().color; // 包含Mainlight和AdditionalLights的输入光//而对于直接光不用计算积分因为只有一个直接光。使用这个公式输出光{单点反射*输入光*(N·V)}对于输入角度的积分float3 DirectLightFinal (Diffuse_Direct Specular_Direct)* NL_WS * lightInput;// Indirect Light 间接光部分 ////------------------------------间接光-----漫反射------------------------------float3 Diffuse_Indirect;//间接光漫反射--比例用(1-F)(1-metallc)公式float3 KD_IndirectLight;//间接光 菲尼尔float3 F_IndirectLight FresnelSchlickRoughness(NV_WS, F0, Roughness);KD_IndirectLight float3(1, 1, 1) - F_IndirectLight;KD_IndirectLight * 1 - Metallic;//间接光漫反射--辐照度用球谐函数计算辐照度在urp下不需要额外设置光照探针烘焙float3 irradianceSH;//球谐基数real4 SHCoefficients[7]; // https://blog.csdn.net/qq_41835314/article/details/129991046SHCoefficients[0] unity_SHAr;SHCoefficients[1] unity_SHAg;SHCoefficients[2] unity_SHAb;SHCoefficients[3] unity_SHBr;SHCoefficients[4] unity_SHBg;SHCoefficients[5] unity_SHBb;SHCoefficients[6] unity_SHC;irradianceSH SampleSH9(SHCoefficients, normalWS); // 计算球谐辐照度//间接光漫反射--光源使用公式辐照度*BaseColor/PI 这里乘上辐照度相当于单点漫反射光源做了积分float3 Diffuse_Indirect_lightSource;Diffuse_Indirect_lightSource irradianceSH * BaseColor / PI;Diffuse_Indirect Diffuse_Indirect_lightSource * KD_IndirectLight; //通过辐照度求出间接光的漫反射//------------------------------间接光-----漫反射------------------------------//------------------------------间接光-----高光------------------------------float3 Specular_Indirect;//间接光高光分为两部分计算两部分为相乘关系第一部分是输入光的积分第二部分是数值模拟或预计算采样//间接光第一部分--输入光的积分mipmap采样反射探针获得近似结果AdditionalLightsfloat3 Specular_Indirect_lightSource_integral;// 间接光高光对于输入光积分的近似以cubemap的mipmap采样方式近似float3 R reflect(-viewDirWS, normalWS);//反射方向和计算mipmap进行采样float mip Roughness * (1.7 - 0.7 * Roughness) * UNITY_SPECCUBE_LOD_STEPS;//这里的unity_SpecCube0是反射探针最多访问两个最近的反射探针。float4 rgb_mip SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, R, mip);//解码mipmap采样后的探针数据,也就是间接光高光的积分近似unity_SpecCube0_HDR:HDR environment map decode instructionsSpecular_Indirect_lightSource_integral DecodeHDREnvironment(rgb_mip, unity_SpecCube0_HDR) VertexLighting(i.posWS, i.normalWS);//间接光第二部分--数值模拟或预计算采样float3 Specular_Indirect_PartTwo;#ifdef ENABLE_BRDF_LUT//预计算采样float2 env_brdf tex2D(_BRDFLut, float2(lerp(0, 0.99, NV), lerp(0, 0.99, Roughness))).rg;#else//数值近似float2 env_brdf EnvBRDFApprox(Roughness, NV_WS);#endifSpecular_Indirect_PartTwo F_IndirectLight * env_brdf.r env_brdf.g;Specular_Indirect Specular_Indirect_lightSource_integral * Specular_Indirect_PartTwo;//------------------------------间接光-----高光------------------------------//------------------------------间接光-----最后计算------------------------------float3 IndirectLightFinal (Diffuse_Indirect Specular_Indirect) * AO; //计算ao影响//------------------------------间接光-----最后计算------------------------------//------------------------------最终输出------------------------------float4 FinalColor 0;FinalColor.rgb DirectLightFinal IndirectLightFinal;FinalColor.rgb Emission;//添加自发光return FinalColor;}ENDHLSL}// 阴影投射Pass{Name ShadowCasterTags{LightMode ShadowCaster}// -------------------------------------// Render State CommandsZWrite OnZTest LEqualColorMask 0Cull[_Cull]HLSLPROGRAM#pragma target 2.0// -------------------------------------// Shader Stages#pragma vertex ShadowPassVertex#pragma fragment ShadowPassFragment// -------------------------------------// Material Keywords#pragma shader_feature_local_fragment _ALPHATEST_ON#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A//--------------------------------------// GPU Instancing#pragma multi_compile_instancing#include_with_pragmas Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl// -------------------------------------// Universal Pipeline keywords// -------------------------------------// Unity defined keywords#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW// -------------------------------------// Includes#include Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl#include Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlslENDHLSL}// 绘制到_CameraNormalsTexture纹理Pass{Name DepthNormalsTags{LightMode DepthNormals}// -------------------------------------// Render State CommandsZWrite OnCull[_Cull]HLSLPROGRAM#pragma target 2.0// -------------------------------------// Shader Stages#pragma vertex DepthNormalsVertex#pragma fragment DepthNormalsFragment// -------------------------------------// Material Keywords#pragma shader_feature_local _NORMALMAP#pragma shader_feature_local _PARALLAXMAP#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED#pragma shader_feature_local_fragment _ALPHATEST_ON#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A// -------------------------------------// Unity defined keywords#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE// -------------------------------------// Universal Pipeline keywords#include_with_pragmas Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl//--------------------------------------// GPU Instancing#pragma multi_compile_instancing#include_with_pragmas Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl// -------------------------------------// Includes#include Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl#include Packages/com.unity.render-pipelines.universal/Shaders/LitDepthNormalsPass.hlslENDHLSL}// 常规渲染过程中不使用仅用于光照贴图烘焙。Pass{Name MetaTags{LightMode Meta}// -------------------------------------// Render State CommandsCull OffHLSLPROGRAM#pragma target 2.0// -------------------------------------// Shader Stages#pragma vertex UniversalVertexMeta#pragma fragment UniversalFragmentMetaLit// -------------------------------------// Material Keywords#pragma shader_feature_local_fragment _SPECULAR_SETUP#pragma shader_feature_local_fragment _EMISSION#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP#pragma shader_feature_local_fragment _ALPHATEST_ON#pragma shader_feature_local_fragment _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED#pragma shader_feature_local_fragment _SPECGLOSSMAP#pragma shader_feature EDITOR_VISUALIZATION// -------------------------------------// Includes#include Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl#include Packages/com.unity.render-pipelines.universal/Shaders/LitMetaPass.hlslENDHLSL}}Fallback off
}
依赖库CustomTessellation.hlsl、CommonHlslInc.hlsl #ifndef CommonHlslInc
#define CommonHlslInc#include Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl//输入结构
struct MeshData
{float4 vertex : POSITION;float2 uv1 : TEXCOORD0;float2 uv2 : TEXCOORD1;float4 tangentTS :TANGENT;float3 normalTS : NORMAL;float4 vertexColor : COLOR;
};//传递结构
struct VOutData
{float4 pos : SV_POSITION; // 必须命名为pos 因为 TRANSFER_VERTEX_TO_FRAGMENT 是这么命名的为了正确地获取到Shadowfloat2 uv1 : TEXCOORD0;float2 uv2 : TEXCOORD1;float4 vertexColor : TEXCOORD2;float3 posOS : TEXCOORD3;float3 normalTS : TEXCOORD4;float3 tangentTS : TEXCOORD5;float3 posWS : TEXCOORD6;float3 normalWS : TEXCOORD7;float3 tangentWS : TEXCOORD8;float3 bitangentWS : TEXCOORD9;float3 posVS : TEXCOORD10;
};//传递结构赋值
VOutData FillBaseV2FData(MeshData input)
{VOutData output;output.pos TransformObjectToHClip(input.vertex);output.uv1 input.uv1;output.uv2 input.uv2;output.vertexColor input.vertexColor;output.posOS input.vertex.xyz;output.normalTS input.normalTS;output.tangentTS input.tangentTS;output.posWS mul(unity_ObjectToWorld, input.vertex);output.normalWS normalize(TransformObjectToWorldNormal(input.normalTS));output.tangentWS normalize(TransformObjectToWorldNormal(input.tangentTS));output.bitangentWS cross(output.normalWS, output.tangentWS) * input.tangentTS.w; //乘上input.tangentTS.w 是unity引擎的bug,有的模型是 1 有的模型是 -1必须这么写output.posVS TransformWorldToView(output.posWS);return output;
}
#endif#ifndef _CUSTOM_TESSELLATION_INCLUDED
#define _CUSTOM_TESSELLATION_INCLUDED// Tessellation programs based on this article by Catlike Coding:
// https://catlikecoding.com/unity/tutorials/advanced-rendering/tessellation/
// 关于参数的详细说明
// https://zhuanlan.zhihu.com/p/479792793#include Assets/TA/ShaderLib/HlslInclude/CommonHlslInc.hlsl//细分切割函数对于每个面片调用一次对于每一个面片比如三角形每条边需要一个切割因子内部需要一个切割因子
struct TessellationFactors {float edge[3] : SV_TessFactor; // 对应三条边的切割因子float inside : SV_InsideTessFactor; // 对应内部的切割因子
};float4 _TessellationUniform; // 细分因子当值为1时不发生细分切割。因子可以分别设置比如边因子是1内部因子是5那就不会在边上生成顶点会在中心生成五个顶点
//自定义的细分切割方法每个面片调用一次
TessellationFactors patchConstantFunction (InputPatchMeshData, 3 patch)
{TessellationFactors f;f.edge[0] _TessellationUniform.x;f.edge[1] _TessellationUniform.y;f.edge[2] _TessellationUniform.z;f.inside _TessellationUniform.w;return f;
}#endif在unity中配置天空盒适当设置后处理后效果大致如下 天空盒资源可以去这个网站下载HDRIs • Poly Haven