近期的一些错误汇总——UnityShader学习笔记


自言自语

最近学习和工作中写的几个shader虽然都完成了,但过程着实让我感到难受和尴尬。因为前学后忘,导致很多压根儿没想到的小错误犯了。这种小错误排查起来还贼费劲。今天就做简单汇总。以备后续查阅警醒自己。

1、忘记pragma相应的灯光文件算法

一次在写一个PBR框架的shader中,发现自己怎么都无法得到一个正确的NdotL的表现 一行行return Debug之后 才发现是自己因为自己手撸shader没找模板起步 所以漏掉了一个关键的 pragma语句 导致得到的灯光向量错误。

//正常shader结构中 如果使用的是 前向渲染,那么必须要指明其lightmode 几句关键的话语不能忘记.要在相应的pass中写上如下语句  注意是Pass中

Tags{"LightMode" = "forwardBase"}

//之后也别忘记要得到正确的lightDir还要写上编译语句
#pragma multi_compile_fwdbase
//如果是多光源
#pragma multi_compile_fwdadd
//尽管URP下已经可以一个pass内进行多光源计算了 但builltin下还是得这么写

如上问题,全部写好后 才能使用

float3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));

这样的语句 否则得到的光源方向是不正确的。当然 不写上面的语句也可以得到光源方向 那就是直接算吧

平行光就是

//向量节省点开销只用half3就行 注意大小写区别
half3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

//点光源或者spot光源

half3 lightDir = normalize(_WorldSpaceLightPos0.xyz - worldPos.xyz);

当然使用这两句话 还是得有一个条件 要引入Unity ShaderLab里的一个头文件

#include “UnityCG.cginc”

2、传参的时候的错误

之前在写shader的过程中,使用Unity内置的函数时,没有太注意传入参数的类型。侥幸的是竟然也一直没有遇到什么问题。然后随着写的越来越多。早前埋下的不注意传参类型的后果就越来越多。
比如昨天晚上写一个视差效果,就怎么都无法得到正确的视角方向。也是一顿return Debug 找到问题是出在了视角方向 viewDir上。当就不知道为什么。 后来今天请教有经验的大佬。找到了问题所在是自己再获得worldPos时,使用UnityObjectToWorldPos()内置函数传入的参数类型不正确。要传入的是float4的类型的顶点参数 结果我传入的是 v.vertex.xyz.导致顶点的w分量丢失。这样转换的时候就会出现齐次坐标空间的问题 以及顶点的深度问题吧
正确的写法如下 顺便一并写出常用内置函数的传参类型

· Builltin


以下是常用内置函数的传参类型 builltin管线常用函数如下

```csharp
float3 mul(unity_OjbectToWorld,float4 v); //这个要求传float4类型 就一定得是float4类型。。
float3 UnityWorldSpaceLightDir(float4 v); //这个要求传float4类型 但是写个float3类型也是可以的。。 
float3 UnityWorldSpaceViewDir(float4 v);
float3 ObjSpaceLightDir(float4 v); //注意这里是Obj 而不是Object   shit
float3 ObjSpaceViewDir(float4 v);

float3 UntiyObjectToWorldNormal(float3 normal);
float3 UnityObjectToWorldDir(float3 Dir);
float3 UnityWorldToObjectDir(float3 Dir);

float4  mul(unity_WorldToLight, float4(i.worldpos, 1)); //把世界空间下的顶点转换到光源空间下返回的xyzw四个分量 

UNITY_LIGHT_ATTENUATION(atten,i,float3(worldPos)) //这句宏  最后一个参数是个三维的参数. 有时候忘记会直接传个四位的参数进来.这里要注意

· URP Universal Render Pipeline

URP下的顶点数据都是float3类型中进行计算 w分量被单独用作他用 不参与计算了 相应变量的数学习惯也有所改变 以 OS ObjectSpace 和 WS WorldSpace 来区分仅仅为习惯 不是强制 不过再引用一些内置函数的时候还是尊重这个习惯比较好

float3 GetVertexPositionInputs(float3 positionOS); 
//举例使用方法
VertexPositionInputs input = GetVertexPositionInputs(v.vertex.xyz);
o.pos = input.positionCS;
float3 posWS = input.positionWS;

float3 GetVertexNormalInputs(float3 normalOS);

VertexNormalInputs normalinput = GetVertexNormalInputs(v.normal);
o.normal = normalinput.normalOS;
float3 normalWS = normalinput.normalWS;



嗯暂且就先记录这么多 日后有犯错的地方 再继续更新

总结

凡事还是不能马虎大意,操之过急.仔细谨慎,严格规范.才能从总的学习时间线上提升效率.不然因为这些疏漏的小错误 耽误很多时间. 自勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值