Unity双面渲染shader.docx
- 文档编号:10209246
- 上传时间:2023-02-09
- 格式:DOCX
- 页数:13
- 大小:19.16KB
Unity双面渲染shader.docx
《Unity双面渲染shader.docx》由会员分享,可在线阅读,更多相关《Unity双面渲染shader.docx(13页珍藏版)》请在冰豆网上搜索。
Unity双面渲染shader
双面渲染shader
Unity内置的Shader,都是单面效果,想必导入Mesh的同学都碰到过这样的痛苦,布料飘起的背面部分看起来是空气,汽车透过车窗看到是路面...各种蛋疼。
有些文章教导大家把模型做出厚度来吧,这种做法实在太那个啥了......
其实用改写Shader的方法可以很方便的实现双面材质。
Unity里有3种Shader方式:
1.FixedFunctionShaders
2.VertexandFragmentShaders
3.SurfaceShaders
关于这部分的详细介绍,请参考官方的教程。
这三种方式里,都可以通过直接在Shader代码头部添加一个Culloff语句,实现强制双面渲染。
但是直接用Culloff的方式有个重大的缺陷,这材质从两面看无论贴图、颜色、反光、照明情况,都是一模一样的,这并不符合大多数实际情况的常识。
在第1和第2种Shader里,是可以通过在一个渲染子程序里用两个渲染Pass来实现双面不同效果的,这部分网上的资料也很多,写起来也很简单直接。
这里主要讨论的是第三种也是最常用的SurfaceShader的双面不同效果的实现。
SurfaceShader是不能写在Pass里的,所以要实现它的双面不同效果就要用其他变通的办法。
首先去Unity官方网站下载一个内置Shader的代码包,链接如下:
打开后看见一堆.shader文件,可以用任何文本编辑器打开。
可以看见系统内建的Shader基本都是Surface方式。
这里随便打开一个Normal-BumpSpec.Shader这是普通的高光-凹凸贴图材质
复制代码
1.Shader"BumpedSpecular"{
2.Properties{
3. _Color("MainColor",Color)=(1,1,1,1)
4. _SpecColor("SpecularColor",Color)=(0.5,0.5,0.5,1)
5. _Shininess("Shininess",Range(0.03,1))=0.078125
6. _MainTex("Base(RGB)Gloss(A)",2D)="white"{}
7. _BumpMap("Normalmap",2D)="bump"{}
8.}
9.SubShader{
10. Tags{"RenderType"="Opaque"}
11. LOD400
12.
13.CGPROGRAM
14.#pragmasurfacesurfBlinnPhong
15.
16.
17.sampler2D_MainTex;
18.sampler2D_BumpMap;
19.fixed4_Color;
20.half_Shininess;
21.
22.structInput{
23. float2uv_MainTex;
24. float2uv_BumpMap;
25.};
26.
27.voidsurf(InputIN,inoutSurfaceOutputo){
28. fixed4tex=tex2D(_MainTex,IN.uv_MainTex);
29. o.Albedo=tex.rgb*_Color.rgb;
30. o.Gloss=tex.a;
31. o.Alpha=tex.a*_Color.a;
32. o.Specular=_Shininess;
33. o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));
34.}
35.ENDCG
36.}
37.FallBack"Specular"
38.}
简单解说一下几个关键行:
第一行Shader"BumpedSpecular"指定了这个shader出现在Unity系统Shader菜单里的名字,如果要修改系统内建Shader的源代码,最好把这个名字改掉,否则和系统内建Shader重名啦。
我是这样写的:
Shader"Hog'sshaders/BumpSpec_Twoside",这个shader会出现在Hog'sshaders组里,系统会自动完成这个加载。
第二行Properties后面的一组以下划线开头的变量表示了这个渲染器需要设置的参数。
对于一个高光-凹凸材质来说,需要材质颜色、反光颜色、反光率、材质贴图和法线贴图,这5个变量就对应这5个东西啦,详细请参考系统手册。
在第11行LOD400后面加上一行:
Culloff,这个材质就会自动双面渲染了Culloff表示双面都渲染,不写默认是Cullback,不渲染背面。
你也可以写上Cullfront,不渲染正面。
改完这行,把第一行改成你希望的名字,把这个shader文件拷贝到工程的assets目录底下,系统就能自动加载啦。
效果如图:

双面是双面了,但是哪有两面是一样亮、一样高光区域的....,全透光的砖墙,这种双面很少会用到吧。
如何做到双面不同效果呢?
前面说了Surfaceshader是不能写两个pass渲染不同面的,但其实surface方式可以写多个渲染过程,根本不需要pass的概念,SurfaceShader可以这样写:
Callback
渲染正面的代码
Callfront
渲染反面的代码
就可以实现双面不同的控制了。
根据这个原理,其实我们只要把系统内建shader的源代码复制一份,就能实现另一面不同效果了。
以下供参考:
复制代码
1.Shader"Hog'sshaders/BumpSpec_Twoside"{
2.Properties{
3.//正面5个参数
4. _Color("MainColor",Color)=(1,1,1,1)
5. _SpecColor("SpecularColor",Color)=(0.5,0.5,0.5,1)
6. _Shininess("Shininess",Range(0.03,1))=0.078125
7. _MainTex("Base(RGB)Gloss(A)",2D)="white"{}
8. _BumpMap("Normalmap",2D)="bump"{}
9.//反面拷贝改名也是5个
10. _BackColor("BackMainColor",Color)=(1,1,1,1)
11. _BackSpecColor("BackSpecularColor",Color)=(0.5,0.5,0.5,1)
12. _BackShininess("BackShininess",Range(0.03,1))=0.078125
13. _BackMainTex("BackBase(RGB)Gloss(A)",2D)="white"{}
14. _BackBumpMap("BackNormalmap",2D)="bump"{}
15.}
16.SubShader{
17.Tags{"RenderType"="Opaque"}
18. LOD400
19. Cullback
20.//开始渲染正面
21.CGPROGRAM
22.//表明是surface渲染方式主渲染程序是surf光照模型是BLinnPhong
23.#pragmasurfacesurfBlinnPhong
24.
25.
26.sampler2D_MainTex;
27.sampler2D_BumpMap;
28.fixed4_Color;
29.half_Shininess;
30.
31.structInput{
32. float2uv_MainTex;
33. float2uv_BumpMap;
34.};
35.
36.voidsurf(InputIN,inoutSurfaceOutputo){
37. fixed4tex=tex2D(_MainTex,IN.uv_MainTex);
38. o.Albedo=tex.rgb*_Color.rgb;
39. o.Gloss=tex.a;
40. o.Alpha=tex.a*_Color.a;
41. o.Specular=_Shininess;
42. o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));}
43.ENDCG
44.
45.
46. Cullfront
47.//开始渲染反面其实和就是拷贝了一份正面渲染的代码除了变量名要改
48.CGPROGRAM
49.#pragmasurfacesurfBlinnPhong
50.
51.sampler2D_BackMainTex;
52.sampler2D_BackBumpMap;
53.fixed4_BackColor;
54.half_BackShininess;
55.
56.structInput{
57. float2uv_BackMainTex;
58. float2uv_BackBumpMap;
59.};
60.
61.voidsurf(InputIN,inoutSurfaceOutputo){
62. fixed4tex=tex2D(_BackMainTex,IN.uv_BackMainTex);
63. o.Albedo=tex.rgb*_BackColor.rgb;
64. o.Gloss=tex.a;
65. o.Alpha=tex.a*_BackColor.a;
66. o.Specular=_BackShininess;
67. o.Normal=UnpackNormal(tex2D(_BackBumpMap,IN.uv_BackBumpMap));}
68.ENDCG
69.}
70.FallBack"Specular"
71.}
这是个双面可以分别指定的高光-凹凸材质,注意几个要点:
properties部分只能出现一次,所以这是不能直接拷贝的。
因为要为双面指定不同的参数,双面的参数变量名肯定不能一样,这个论坛里都是程序猿,没必要多解释了。
我简单的把用于正面的5个参数前面都加上了一个Back用于反面。
在CG代码内部也要对应的应用相应的参数,反面的渲染代码就用刚才全部加了Back的那5个参数。
正面代码段用Cullback开始反面的代码用Cullfront开始
以下是渲染效果:

一面是砖墙一面是木板。
。
蛋疼了没
这个模式下,双面也完全可以指定不同的材质,基本上你不用学习很多内建Shader和CG语法,通过简单的copy-paste就能组合出无穷的双面材质来了。
再提升一下,其实我们常用的双面效果,除了透明的材质以外,无非是两种:
一是反面和正面同样纹理,但是不需要高光、反射,只需要一个相对黯淡的被环境光照亮的材质,比如砖墙木盒衣服什么的
二是反面显示为单身或其他纹理,但也不需要高光、反射,只需要被环境光照亮,比如汽车内部建筑物内部等等。
第一种情况,反面可以沿用正面纹理,但是以普通的Diffuse方式着色
第二种情况,反面不指定或者单独指定纹理,也以普通的Diffuse方式着色
两种情况,反面的渲染都可以借用系统内建Shader的Diffuse渲染代码来实现,方式一的代码:
复制代码
1.Shader"Hog'sshaders/BumpSpec_Twoside1"{
2.Properties{
3. _Color("MainColor",Color)=(1,1,1,1)
4. _SpecColor("SpecularColor",Color)=(0.5,0.5,0.5,1)
5. _Shininess("Shininess",Range(0.03,1))=0.078125
6. _MainTex("Base(RGB)Gloss(A)",2D)="white"{}
7. _BumpMap("Normalmap",2D)="bump"{}
8. _BackColor("BackMainColor",Color)=(1,1,1,1)
9.}
10.SubShader{
11. Tags{"RenderType"="Opaque"}
12. LOD400
13. Cullback
14.
15.CGPROGRAM
16.#pragmasurfacesurfBlinnPhong
17.
18.
19.sampler2D_MainTex;
20.sampler2D_BumpMap;
21.fixed4_Color;
22.half_Shininess;
23.
24.structInput{
25. float2uv_MainTex;
26. float2uv_BumpMap;
27.};
28.
29.voidsurf(InputIN,inoutSurfaceOutputo){
30. fixed4tex=tex2D(_MainTex,IN.uv_MainTex);
31. o.Albedo=tex.rgb*_Color.rgb;
32. o.Gloss=tex.a;
33. o.Alpha=tex.a*_Color.a;
34. o.Specular=_Shininess;
35. o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));}
36.ENDCG
37.
38. Cullfront
39.
40.CGPROGRAM
41.#pragmasurfacesurfLambert
42.
43.sampler2D_MainTex;
44.fixed4_BackColor;
45.
46.structInput{
47. float2uv_MainTex;
48.};
49.
50.voidsurf(InputIN,inoutSurfaceOutputo){
51. fixed4c=tex2D(_MainTex,IN.uv_MainTex)*_BackColor;
52. o.Albedo=c.rgb;
53. o.Alpha=c.a;
54.}
55.ENDCG
56.}
57.FallBack"Specular"
58.}
反面渲染的运算就直接借用了系统的DiffuseShader,只不过纹理是沿用正面的纹理,只增加了一个反面的颜色变量用来模拟环境光亮度,与纹理混合实现反面效果。
渲染效果如下:

方式二代码:
复制代码
1.Shader"Hog'sshaders/BumpSpec_Twoside2"{
2.Properties{
3. _Color("MainColor",Color)=(1,1,1,1)
4. _SpecColor("SpecularColor",Color)=(0.5,0.5,0.5,1)
5. _Shininess("Shininess",Range(0.03,1))=0.078125
6. _MainTex("Base(RGB)Gloss(A)",2D)="white"{}
7. _BumpMap("Normalmap",2D)="bump"{}
8. _BackColor("BackMainColor",Color)=(1,1,1,1)
9. _BackMainTex("BackBase(RGB)Gloss(A)",2D)="white"{}
10.}
11.SubShader{
12. Tags{"RenderType"="Opaque"}
13. LOD400
14. Cullback
15.
16.CGPROGRAM
17.#pragmasurfacesurfBlinnPhong
18.
19.
20.sampler2D_MainTex;
21.sampler2D_BumpMap;
22.fixed4_Color;
23.half_Shininess;
24.
25.structInput{
26. float2uv_MainTex;
27. float2uv_BumpMap;
28.};
29.
30.voidsurf(InputIN,inoutSurfaceOutputo){
31. fixed4tex=tex2D(_MainTex,IN.uv_MainTex);
32. o.Albedo=tex.rgb*_Color.rgb;
33. o.Gloss=tex.a;
34. o.Alpha=tex.a*_Color.a;
35. o.Specular=_Shininess;
36. o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));}
37.ENDCG
38.
39. Cullfront
40.
41.CGPROGRAM
42.#pragmasurfacesurfLambert
43.
44.sampler2D_BackMainTex;
45.fixed4_BackColor;
46.
47.structInput{
48. float2uv_BackMainTex;
49.};
50.
51.voidsurf(InputIN,inoutSurfaceOutputo){
52. fixed4c=tex2D(_BackMainTex,IN.uv_BackMainTex)*_BackColor;
53. o.Albedo=c.rgb;
54. o.Alpha=c.a;
55.}
56.ENDCG
57.}
58.FallBack"Specular"
59.}
此方式下反面可以单独指定纹理,不指定就直接显示指定的反面颜色,渲染效果如下

以上只是介绍一个基本思想,在这个基础上能应该能衍生出无穷的变化。
对自定义shader有兴趣的可以参考系统手册和Nvidia的CG教学手册。
不过千万不要动不动就使用双面材质,因为会增加系统负荷,应该只用在需要的地方。
把以上代码起个名字另存为.shader文件,导入工程assets,就能直接使用。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Unity 双面 渲染 shader