Unity Shader转SP

前段时间研究了一下怎么把Unity的shader搬到SP,原因是:美术在SP中制作贴图,生成的美术资源放进Unity之后就完全是另一个样子了,来回修改非常麻烦。所以希望SP中就显示引擎里的效果。

我这方面是小白,所以把自己探索的过程也记录进去了。

首先通过观察sp自带的clay shader

1
2
3
4
// - Ambient and diffuse contribution
diffuseShadingOutput((ambient + NdV) * diffuse);
// - Specular contribution
specularShadingOutput(vec3(specular * pow(NdV, 64.0 * clayGloss)));

发现两点
1、这个shader里根本就没有用光照信息(NdV是Normal * View),以及发现clay shader调整光照方向并不会对光影效果产生变化,但它是不是完全和自带光照无关还需确认。
2、sp的shader提供了一些针对pbr不同通道的接口,但是不知道里面具体做了啥。

为了弄清楚这两点,尝试一下phong光照模型,只用diffuse和specular,ambient暂时不要。
按照clay shader的方法写了一个phong的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import lib-vectors.glsl
import lib-alpha.glsl
import lib-pbr.glsl
import lib-utils.glsl
//- Phong shader
//- ===========
//: param auto channel_basecolor
uniform sampler2D basecolor_tex;
//: param custom { "default": 0.5, "label": "Specular", "min": 0.001, "max": 1.0 }
uniform float specular;
//: param custom { "default": 0.5, "label": "Glossiness", "min": 0.001, "max": 1.0 }
uniform float gloss;
//- Entry point of the shader.
void shade(V2F inputs)
{
//- We generate local world space vectors
LocalVectors vectors = computeLocalFrame(inputs);
//- Simulate camera aligned lighting
float NdV = max(0.0, dot(vectors.normal, vectors.eye));
vec3 baseColor = getBaseColor(basecolor_tex, inputs.tex_coord);
//- Ambient and diffuse contribution
diffuseShadingOutput(NdV * baseColor);
//- Specular contribution
specularShadingOutput(specular * vec3(pow(NdV, 64.0 * gloss)));
}

按照这个写法写unity shader,并将Unity的颜色空间改为linear(因为SP中是默认Linear),而且将SP的天空盒光照强度变为0

1
2
3
4
5
6
7
8
9
10
// ...
fixed3 normalizedNormal = normalize(i.worldNormal);
fixed3 normalizedViewDir = normalize(i.worldViewDir);
float NdV = saturate(dot(normalizedNormal, normalizedViewDir));

fixed3 albedo = tex2D(_MainTex, i.uv);
fixed3 diffuse = albedo * NdV;
fixed3 specular = _Specular * pow(NdV, 64.0 * _Glossness);
return fixed4((diffuse + specular), 1);
// ...

看结果发现!几乎完全一样!

所以
1、ShadingOutput的接口貌似啥也没干,就是最后把几个接口的值相加输出,可以直接把自己的完整结果放进diffuseShadingOutput中
2、SP自带光照可以直接不要,只用自己的光照
所以理论上,只要把unity的shader翻译成glsl,并把光照参数手动写进去就好了。来试试看带光照的效果。

在之前shader的基础上加上光源。Unity使用一个平行光,SP中使用和Unity中一样的光照参数。

1
2
3
4
5
6
7
8
fixed3 halfDir = normalize(normalizedLightDir + normalizedViewDir);
float NdV = saturate(dot(normalizedNormal, normalizedViewDir));
float NdL = saturate(dot(normalizedNormal, normalizedLightDir));
float NdH = saturate(dot(normalizedNormal, halfDir));
fixed3 albedo = tex2D(_MainTex, i.uv);
fixed3 diffuse = albedo * NdL;
fixed3 specular = _Specular * pow(NdH, 64.0 * _Glossness);
return fixed4((diffuse + specular), 1);
1
2
3
4
5
6
7
8
9
10
// mainLight的参数做个对外接口,可调节
vec3 halfDir = normalize(mainLight.direction + vectors.eye);
float NdV = max(0.0, dot(vectors.normal, vectors.eye));
float NdL = max(0.0, dot(vectors.normal, mainLight.direction));
float NdH = max(0.0, dot(vectors.normal, halfDir));
vec3 baseColor = getBaseColor(basecolor_tex, inputs.tex_coord);
//- Ambient and diffuse contribution
diffuseShadingOutput(NdL * baseColor);
//- Specular contribution
specularShadingOutput(specular * vec3(pow(NdH, 64.0 * gloss)));

变换光源方向看看效果,可以发现达到了一致。