目录
一、前言
之前一直讲的shader文件中,都只写了一次CG代码。
为了大家对这部分的整体理解,我们这次渲染两次。
二、“渲染两次”
这个词是我造的~不是定义。
什么叫渲染两次?
渲染就是画画的意思,渲染两次就是画两次。这里用画画举例。
第一次画画。(如图1所示)
![](https://i-blog.csdnimg.cn/direct/7e84f9059e4d4383a2d966386d6121f7.png)
这里如果用文字描述一下,就是画了一个绿色的三角形。
第二次画画。(如图2所示)
![](https://i-blog.csdnimg.cn/direct/f7c292b9aaab4e60a0f22c8505201754.png)
如果用语言形容就是,在中间画了一个橘黄色的圆形。
所以我们一套结构CG结构就是画了一幅画。(如图3所示)
不用太在意具体写的什么代码,主要注意一些标志
CGPROGRAM前面是一些准备工作,像之前的模版写入,深度写入之类的。
ENDCG就是结束了绘制
中间就是一些绘制过程,引入一些材料。
这个全过程就是一次画画的全过程。
![](https://i-blog.csdnimg.cn/direct/cd3dbf0becc742f38442dd7cf59b5db4.png)
渲染两次的意思是,我可以在一个shader文件中写两套这个东西。
三、本次成品介绍
我们这次先画一个模型的黑影,但是这个黑影要比模型本身大一点。这个做法参考上节课的代码。
Unity | Shader基础知识(第二十一集:应用-怪兽膨胀、顶点着色器和表面着色器合并)_unity 顶点膨胀shader-CSDN博客
然后再正常把模型渲染上去,就可以给模型做一个阴影或者说边框。(如图4所示)
![](https://i-blog.csdnimg.cn/direct/a0f42e1c53ab405bb22d85960b716b0e.png)
四、第一次渲染代码
我们第一次先画一个模型的黑影(如图4所示),
备注:模型还是用上节课的模型。代码还是用的上节课的思路。
![](https://i-blog.csdnimg.cn/direct/6f44a7cc761b496d850f8b7b08f7febf.png)
Properties
{
//模型的贴图
_MainTex ("Texture", 2D) = "white" {}
//边框的大小(膨胀的大了,边框就大,反之就小)
_Outline ("Outline Width", Range(0.002,0.1)) = 0.005
//边框的颜色,我们要做黑影,所以就先来个黑色
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
}
SubShader
{
CGPROGRAM
//引用,同上一集
#pragma surface surf Lambert vertex:vert
//承接上面素材,略
sampler2D _MainTex;
float4 _OutlineColor;
float _Outline;
void vert(inout appdata_full v)
{
//让原本的顶点在法线的方向上增加一点位置,
这样影子就会变大
v.vertex.xyz += v.normal * _Outline;
}
//其实目前代码里都没用到,但因为用了表面着色器,必须写
struct Input
{
float2 uv_MainTex;
};
void surf(Input IN,inout SurfaceOutput o)
{
//我们把颜色直接给到自发光
//备注:这里给到贴图也是可以的,但自发光要更亮一点,可以自己试
o.Emission = _OutlineColor.rgb;
}
ENDCG
}
这样我们第一次渲染就画好了。
五、第二次渲染代码
到了ENDCG以后,就是这次画已经画完了,接下来我们再画模型真正的样子。
第二次不需要膨胀,所以顶点那部分就不用加了,直接把颜色上上去。这部分讲太多遍了,就不详解了。
CGPROGRAM
#pragma surface surf Lambert
struct Input{
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf(Input IN, inout SurfaceOutput o)
{
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
六、截止目前的所有代码
Shader "Unlit/019"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Outline ("Outline Width", Range(0.002,0.1)) = 0.005
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
}
SubShader
{
//第一套渲染-------------------------------------
CGPROGRAM
#pragma surface surf Lambert vertex:vert
struct Input
{
float2 uv_MainTex;
};
sampler2D _MainTex;
float4 _OutlineColor;
float _Outline;
void vert(inout appdata_full v)
{
v.vertex.xyz += v.normal * _Outline;
}
void surf(Input IN,inout SurfaceOutput o)
{
o.Emission = _OutlineColor.rgb;
}
ENDCG
//第二套渲染--------------------------------------
CGPROGRAM
#pragma surface surf Lambert
struct Input{
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf(Input IN, inout SurfaceOutput o)
{
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
}
到这里我只是想证明给你们,渲染可以在后面加的,并不是只能写在那一个里面。
七、调整代码
到现在为止,我们渲染出来的结果。(如图5所示)
![](https://i-blog.csdnimg.cn/direct/6d9e273751304fbebd083f70c9607522.png)
这并不是我们想要的样子,为什么会都是黑色,因为黑色部分是膨胀的,比彩色的大,所以被藏在里面了。(如图6所示)你可以通过增加膨胀的系数在缝隙里面看见。
![](https://i-blog.csdnimg.cn/direct/b2d16dbb3567474f934296906e00aece.png)
解决方案:把深度写入关掉。
不管是你在外面还是里面,都画出来。
代码如下。(如图7所示)
![](https://i-blog.csdnimg.cn/direct/a27e7faf6e6342999616d47c3f6abc07.png)
到这里一步我们就可以得到(如图8所示)
![](https://i-blog.csdnimg.cn/direct/e7d6670f503547d885dbe25253ba57a1.png)
但是下一步的麻烦就是,我把模型背面也渲染出来了。
解决方案:在渲染黑色自发光时,关掉深度写入,在渲染模型时(第二次画画时),打开深度写入。(如图9所示)
这样我们就可以得到我们想要的结果了。
八、总结
本节想表达的重点:
1.渲染可以写好几次
2.每次渲染之前,可以去调节后面渲染的一些方式。本次案例用深度写入为例子。