目录

一、前言

二、“渲染两次”

三、本次成品介绍

四、第一次渲染代码

五、第二次渲染代码 

六、截止目前的所有代码

七、调整代码

八、总结 


一、前言

之前一直讲的shader文件中,都只写了一次CG代码。

为了大家对这部分的整体理解,我们这次渲染两次。

二、“渲染两次”

这个词是我造的~不是定义。

什么叫渲染两次?

渲染就是画画的意思,渲染两次就是画两次。这里用画画举例。

第一次画画。(如图1所示)

图1 第一次画画

这里如果用文字描述一下,就是画了一个绿色的三角形。


第二次画画。(如图2所示)

 

图2 第二次画画

 如果用语言形容就是,在中间画了一个橘黄色的圆形。


所以我们一套结构CG结构就是画了一幅画。(如图3所示)

不用太在意具体写的什么代码,主要注意一些标志

CGPROGRAM前面是一些准备工作,像之前的模版写入,深度写入之类的。

ENDCG就是结束了绘制

中间就是一些绘制过程,引入一些材料。

这个全过程就是一次画画的全过程。

图3 一套流程

 

 渲染两次的意思是,我可以在一个shader文件中写两套这个东西。

三、本次成品介绍

我们这次先画一个模型的黑影,但是这个黑影要比模型本身大一点。这个做法参考上节课的代码。

Unity | Shader基础知识(第二十一集:应用-怪兽膨胀、顶点着色器和表面着色器合并)_unity 顶点膨胀shader-CSDN博客

然后再正常把模型渲染上去,就可以给模型做一个阴影或者说边框。(如图4所示)

图4 成品

 

四、第一次渲染代码

我们第一次先画一个模型的黑影(如图4所示),

备注:模型还是用上节课的模型。代码还是用的上节课的思路。

图4 我是谁?带刺小盆栽~
 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所示)

图5 结果

这并不是我们想要的样子,为什么会都是黑色,因为黑色部分是膨胀的,比彩色的大,所以被藏在里面了。(如图6所示)你可以通过增加膨胀的系数在缝隙里面看见。

图6 缝隙

解决方案:把深度写入关掉。

不管是你在外面还是里面,都画出来。

代码如下。(如图7所示)

图7 深度写入

到这里一步我们就可以得到(如图8所示) 

图8 结果

但是下一步的麻烦就是,我把模型背面也渲染出来了。

解决方案:在渲染黑色自发光时,关掉深度写入,在渲染模型时(第二次画画时),打开深度写入。(如图9所示)

 

这样我们就可以得到我们想要的结果了。

八、总结 

本节想表达的重点:

1.渲染可以写好几次

2.每次渲染之前,可以去调节后面渲染的一些方式。本次案例用深度写入为例子。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐