文章目录
- 前言
- 一、SimpleLit片元着色器大体框架
-
- 1、传入 和 返回
- 2、GPU实例化部分
- 3、准备 BlinnPhong 光照模型计算需要的 SurfaceData
- 4、准备 BlinnPhong 光照模型计算需要的 InputData
- 5、进行 BlinnPhong 的计算、雾效颜色混合及透明度计算
- 二、准备SurfaceData
-
- 1、SurfaceData结构体包含什么:
- 2、初始化SurfaceData:
- 3、漫反射颜色及透明度计算
- 4、混合漫反射颜色 与 透明度
- 5、玻璃效果纹理采样、金属度、镜面反射颜色 及 光滑度
- 6、自发光纹理采样
- 在这里插入图片描述
- 三、准备InputData
-
- 1、InputData结构体包含什么
- 2、初始化InputData
- 1、法线贴图相关
- 2、视线向量计算 及计算前的向量归一化
- 3、阴影因子计算
- 4、额外灯相关计算
- 5、全局光照相关计算
- 6、光照贴图相关计算
前言
在上篇文章中,我们了解了Unity中URP下SimpleLit中的顶点着色器。
我们在这篇文章中,来了解一下Unity中URP下SimpleLit中的片元着色器。有助于我们之后写自己的光照Shader。
一、SimpleLit片元着色器大体框架
1、传入 和 返回
- 这里传入参数为 顶点着色器输出的Varyings结构体
- 返回结果用 out修饰来代替函数前的返回类型
2、GPU实例化部分
3、准备 BlinnPhong 光照模型计算需要的 SurfaceData
4、准备 BlinnPhong 光照模型计算需要的 InputData
5、进行 BlinnPhong 的计算、雾效颜色混合及透明度计算
由此可以看出:SimpleLit 的片元着色器中
我们最重要的部分是:
- 准备SurfaceData
- 准备InputData
- 最后 BlinnPhong 的计算
二、准备SurfaceData
1、SurfaceData结构体包含什么:
- albedo:漫反射颜色
- specular:镜面反射颜色
- metallic:金属度
- smoothness:平滑度
- normalTS:法线
- emission:自发光颜色
2、初始化SurfaceData:
3、漫反射颜色及透明度计算
- 透明度计算时,会把漫反射透明度 和 主颜色透明度进行相乘混合
- AlphaDiscard:对透明度做处理
4、混合漫反射颜色 与 透明度
- 用我们的漫反射颜色 与 主要颜色混合
- 用我们的透明度 与 输出颜色混合
5、玻璃效果纹理采样、金属度、镜面反射颜色 及 光滑度
6、自发光纹理采样
三、准备InputData
1、InputData结构体包含什么
- positionWS、positionCS:顶点在世界空间 和 齐次裁剪空间下的数据
- normalWS:世界空间下的法线数据
- viewDirectionWS:视线向量
- shadowCoord:阴影相关
- fogCoord:雾效混合因子
- vertexLighting:顶点光照颜色
- bakedGI:全局光照烘焙颜色
- shadowMask:阴影遮罩
- tangentToWorld:切线转化到世界空间的转化矩阵
2、初始化InputData
void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData)
{
inputData = (InputData)0;
inputData.positionWS = input.positionWS;
#ifdef _NORMALMAP
half3 viewDirWS = half3(input.normalWS.w, input.tangentWS.w, input.bitangentWS.w);
inputData.tangentToWorld = half3x3(input.tangentWS.xyz, input.bitangentWS.xyz, input.normalWS.xyz);
inputData.normalWS = TransformTangentToWorld(normalTS, inputData.tangentToWorld);
#else
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(inputData.positionWS);
inputData.normalWS = input.normalWS;
#endif
inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
viewDirWS = SafeNormalize(viewDirWS);
inputData.viewDirectionWS = viewDirWS;
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
inputData.shadowCoord = input.shadowCoord;
#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
#else
inputData.shadowCoord = float4(0, 0, 0, 0);
#endif
#ifdef _ADDITIONAL_LIGHTS_VERTEX
inputData.fogCoord = InitializeInputDataFog(float4(inputData.positionWS, 1.0), input.fogFactorAndVertexLight.x);
inputData.vertexLighting = input.fogFactorAndVertexLight.yzw;
#else
inputData.fogCoord = InitializeInputDataFog(float4(inputData.positionWS, 1.0), input.fogFactor);
inputData.vertexLighting = half3(0, 0, 0);
#endif
#if defined(DYNAMICLIGHTMAP_ON)
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.dynamicLightmapUV, input.vertexSH, inputData.normalWS);
#else
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.vertexSH, inputData.normalWS);
#endif
inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV);
#if defined(DEBUG_DISPLAY)
#if defined(DYNAMICLIGHTMAP_ON)
inputData.dynamicLightmapUV = input.dynamicLightmapUV.xy;
#endif
#if defined(LIGHTMAP_ON)
inputData.staticLightmapUV = input.staticLightmapUV;
#else
inputData.vertexSH = input.vertexSH;
#endif
#endif
}