挑战UnityShader学习之二_代码PBR写法_表面着色器2个结构体和4个方法

前面第一章我们知道了,UnityShader默认就使用pbr

以下,使用和分析的都是基于Surface Shader,表面着色器

这并不是什么一个特殊的着色器,或者是一个什么特效,只是一个“鸡肋”

UnityShader发展历史也和明显

  1. vf Shader
  2. sf Shader
  3. PBR x

第一章,我们用了一个搞不清楚是不是PBR的surface Shader,

所以我们再做了一下扩展,搞清楚到底不是PBR

具体手写Shader代码步骤如下

(其实漏了很多关键步骤,没兴趣的请直接跳去下面的光和Surf分项代码,比较全)

1.创建Shader,用Editor创建一个Surface Shader,名字随意

2.随便声明一下,有无lightmap并没有什么卵用,target3.0也不知道有什么卵用

//#pragma surface surf BlinnPhong //alpha:fade
#pragma surface surf BlinnPhong nodynlightmap
#pragma target 3.0

用到了BlinnPhong,则必须存在变量,就算不声明,也必须存在,内在的BlinnPhong(光线函数)估计会莫名奇妙的用上

(下面这么写是不行的,必须写上_SpecColor

	_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		//_SpecColor("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
		_Shininess("Smoothness", Range(0,1)) = 0.5

(.Normal也必须有)

//surf shader代码
float4 bumpColor = tex2D(_BumpMap, IN.uv_MainTex);
o.Normal = UnpackNormal(bumpColor).xyz;

3.必须改用SurfaceOutput,而不是Standard

void surf(Input IN, inout SurfaceOutput o){
		// Albedo comes from a texture tinted by color
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			o.Gloss = c.a;
			o.Specular = _Shininess;
			o.Alpha = c.a;
			
			//没什么卵用
			float4 bumpColor = tex2D(_BumpMap, IN.uv_MainTex);
			o.Normal = UnpackNormal(bumpColor).xyz;
		}

4.还可以支持vert, finalColor等方法,暂时没用上

自定义Lighting光照函数代码:

1.创建Shader

2.声明:

#pragma surface surf SelfMaskMap	alpha noshadow
//surf 和 SelfMaskMap其实是连着声明,相当于 surf() , LightingSelfMaskMap()

3.定义方法

inline half4 LightingSelfMaskMap(inout SurfaceOutput s, half3 viewDir, UnityGI gi){

    return half4(1, 1, 1, 1);
}

inline void LightingSelfMaskMap_GI(inout SurfaceOutput s, UnityGIInput data, inout UnityGI gi)
{
    //s.GIData = data;
}
fixed4 LightingSelfMaskMap(SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten){
	return half4(1, 1, 1, 1);
}

这2个截然不同的方法,唯一不同就是有无UNITYGI

所以,我们知道并不是单单声明就可以了,还需要方法配合

作为新手,会觉得很困惑:

  • 1个声明,2个写法
  • 错误提示不明确,也没定位哪行
  • 缺少文档

但是,作为程序老手,Shader能实现成这样,其实是相当”高级“的语法,虽然我之后会吐槽更多

写一个Lighting方法,如果参数含GI,会明确提示你缺一个_GI方法

也只有现代的node_js等框架会有这个提示,我并不是c++ c预言的链接,虽然看上去好像是

4.测试一下

(测试用了一个结构体 SurfaceOutput,至于各种结构体)

inline half4 LightingSelfMaskMap(inout SurfaceOutput s, half3 viewDir, UnityGI gi){

	//return half4(0.1, 0.1, 0.1, 1);
	return half4(s.Albedo,s.Alpha);
}

结构体可参考这:https://blog.csdn.net/avi9111/article/details/109730851

测试的结论,是lighting方法在surf方法后执行(虽然一般surf写最后,lighting都是插前面,一般的程序员都会这么干)

一般正常人的理解是surf相当于fragment。我们学图形学也是这么学的

正常的vf 顺序是

  • vertex Shader
  • commond buff,light等逻辑
  • fragment Shader

而sfShader的顺序非要是

  • vert
  • surf
  • Lighting

但其实官方声明的时候,都已经“暗示”了顺序(我盲测的,是不可能去看官方文档的,这辈子都不可能去看文档)

#pragma surface surf SelfMaskMap	alpha noshadow

我还没说,这种情况呢,这种是经典的坑新手情况

#pragma surface surf SelfMaskMap vert:vert	alpha noshadow

参考:

BlinnPhong函数

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

avi9111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值