Unity Shader转SP
Posted on
前段时间研究了一下怎么把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)));
|
变换光源方向看看效果,可以发现达到了一致。