commanderbuffer学习(制作模型描边)转

转载自:使用CommandBuffer实现描边效果 - 简书 (jians//声明

CommandBuffer commandBuffer = new CommandBuffer();
//设置渲染目标
commandBuffer.SetRenderTarget(renderTexture);
commandBuffer.ClearRenderTarget(true,true,Color.black);
//设置渲染数据
commandBuffer.DrawRenderer( targetRenderer,material);
//将commandBuffer的渲染结果进行后期处理效果
commandBuffer.Bilt(renderTexture,DestTexture,material);
//向主camera中插入CommandBuffer
commandBuffer.AddCommandBuffer(CameraEvent.BeforeForwardOpaque,commandBuffer);
//用Graphics的方法调用绘制
Graphics.ExecuteCommandBuffer(CommandBuffer);
commanderBuffer方法:(五)CommandBuffer基本应用 - 81192 - 博客园 (cnblogs.com)

原理:将需要渲染的render绘制到一个RT上,再对这张RT乘个纯色,模糊后与原RT相减得到边框。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering;//描边,挂在camera上 public class StrokeController : MonoBehaviour { private CommandBuffer commandBuffer = null; public Material renderMat = null; private RenderTexture renderTex = null; public Material effectMat = null; public Material renderMatMono = null; // private Renderer targetEBO = null; private List<Renderer> targetList; public GameObject targetOBJ = null; public Color outLineColor = Color.black; //renderMat public Color objColor = Color.black; public int outLineSize = 4; public int BlurSize = 3; private void Start() { if(renderMat && targetOBJ != null) { Renderer[] rendererList = targetOBJ.GetComponentsInChildren<Renderer>(); targetList = new List<Renderer>(rendererList); commandBuffer = new CommandBuffer(); renderTex = RenderTexture.GetTemporary(Screen.width,Screen.height,0); commandBuffer.SetRenderTarget(renderTex); commandBuffer.ClearRenderTarget(true,true,Color.black); renderMatMono.SetColor("_outLineColor", objColor); foreach (var v in targetList) { v.material = renderMatMono; } foreach (var v in targetList) { commandBuffer.DrawRenderer(v, renderMat); } } else { enabled = false; } } private void OnEnable() { if(renderTex) { RenderTexture.ReleaseTemporary(renderTex); renderTex = null; } if(commandBuffer != null) { commandBuffer.Release(); commandBuffer = null; } } private void OnRenderImage(RenderTexture src, RenderTexture dest) { if(renderMat && renderTex && commandBuffer != null) { renderMat.SetColor("_outLineColor", outLineColor); Graphics.ExecuteCommandBuffer(commandBuffer); RenderTexture temp1 = RenderTexture.GetTemporary(src.width, src.height, 0); RenderTexture temp2 = RenderTexture.GetTemporary(src.width, src.height, 0); effectMat.SetInt("_outLineSize", outLineSize); Graphics.Blit(renderTex, temp1, effectMat, 0); Graphics.Blit(temp1, temp2, effectMat, 1); //设置模糊次数 for (int i = 0; i < BlurSize; i++) { Graphics.Blit(temp2, temp1, effectMat, 0); Graphics.Blit(temp1, temp2, effectMat, 1); } //将模糊后的图片减去commandBuffer中的实心剪影 effectMat.SetTexture("_renderTex", renderTex); //effectMat.SetTexture("_MainTex", renderTex); Graphics.Blit(temp2, temp1, effectMat, 2); //后期处理,叠入渲染成果 effectMat.SetTexture("_outLineTex", temp1); Graphics.Blit(src, dest, effectMat, 3); //释放RT RenderTexture.ReleaseTemporary(temp1); RenderTexture.ReleaseTemporary(temp2); } else { Graphics.Blit(src,dest); } } }

Shader "LZ/effectShader"

{

    Properties

    {

        _MainTex ("Texture", 2D) = "white" {}

        _outLineSize("outLineSize",int)=4

        //_outLineTex("outLineTex",2D)="black"{}

        //_renderTex("renderTex",2D)="black"{}

    }

 

    //Founction    

    CGINCLUDE

 

    float _outLineSize;

    sampler2D _MainTex;

    float4 _MainTex_TexelSize;

 

    struct a2v{

        float4 vertex:POSITION;

        float2 uv:TEXCOORD0;

    };

    struct v2f{

        float4 pos:SV_POSITION;

        float2 uv[5]:TEXCOORD0;

    };

 

    v2f vert_heng(a2v v){

        v2f o;

        o.pos = UnityObjectToClipPos(v.vertex);

        float2 uv=v.uv;

        o.uv[0] = uv;

        o.uv[1] = uv + float2(1,0) * _outLineSize * _MainTex_TexelSize.xy;

        o.uv[2] = uv + float2(-1,0) * _outLineSize * _MainTex_TexelSize.xy;

        o.uv[3] = uv + float2(2,0) * _outLineSize * _MainTex_TexelSize.xy;

        o.uv[4] = uv + float2(-2,0) * _outLineSize * _MainTex_TexelSize.xy;

        return o;

    }

 

    v2f vert_shu(a2v v){

        v2f o;

        o.pos = UnityObjectToClipPos(v.vertex);

        float2 uv=v.uv;

        o.uv[0] = uv;

        o.uv[1] = uv + float2(0,1) * _outLineSize * _MainTex_TexelSize.xy;

        o.uv[2] = uv + float2(0,-1) * _outLineSize * _MainTex_TexelSize.xy;

        o.uv[3] = uv + float2(0,2) * _outLineSize * _MainTex_TexelSize.xy;

        o.uv[4] = uv + float2(0,-2) * _outLineSize * _MainTex_TexelSize.xy;

        return o;

    }

 

    fixed4 frag(v2f i):SV_TARGET{

        float3 col = tex2D(_MainTex,i.uv[0]).xyz *0.4026;

        float3 col1 = tex2D(_MainTex,i.uv[1]).xyz *0.2442;

        float3 col2 = tex2D(_MainTex,i.uv[2]).xyz *0.2442;

        float3 col3 = tex2D(_MainTex,i.uv[3]).xyz *0.0545;

        float3 col4 = tex2D(_MainTex,i.uv[4]).xyz *0.0545;

        float3 finalCol = col+col1+col2+col3+col4;

        return fixed4(finalCol,1.0);

    }

 

    ENDCG

 

    SubShader

    {

        Cull Off ZWrite Off ZTest Always

 

        

 

        Pass{

            CGPROGRAM

            #include"UnityCG.cginc"

            #pragma vertex vert_heng

            #pragma fragment frag 

            ENDCG

        }

 

        Pass{

            CGPROGRAM

            #include"UnityCG.cginc"

            #pragma vertex vert_shu

            #pragma fragment frag 

            ENDCG

        }

 

//pass 2 ---renderTex------------------------------------------------------------------------------

        Pass

        {

            CGPROGRAM

            #pragma vertex vert

            #pragma fragment frag

 

            #include "UnityCG.cginc"

 

            struct appdata

            {

                float4 vertex : POSITION;

                float2 uv : TEXCOORD0;

            };

 

            struct v2f1

            {

                float2 uv : TEXCOORD0;

                float4 vertex : SV_POSITION;

            };

 

            v2f1 vert (appdata v)

            {

                v2f1 o;

                o.vertex = UnityObjectToClipPos(v.vertex);

                o.uv = v.uv;

                return o;

            }

 

            //sampler2D _MainTex;

            sampler2D _renderTex;

 

 

            fixed4 frag (v2f1 i) : SV_Target

            {

                

                float3 col= tex2D(_MainTex,i.uv).xyz;

                float3 commandCol=tex2D(_renderTex,i.uv).xyz;

                float3 finalCol=col-commandCol;

                return fixed4(finalCol,1.0);

            }

            ENDCG

        }

 

 

//pass3 add outlineTex--------------------------------------------------------------------------------------------------

 

        Pass

        {

            CGPROGRAM

            #pragma vertex vert

            #pragma fragment frag

 

            #include "UnityCG.cginc"

 

            struct appdata

            {

                float4 vertex : POSITION;

                float2 uv : TEXCOORD0;

            };

 

            struct v2f2

            {

                float2 uv : TEXCOORD0;

                float4 vertex : SV_POSITION;

            };

 

sampler2D _outLineTex;

 

            v2f2 vert (appdata v)

            {

                v2f2 o;

                o.vertex = UnityObjectToClipPos(v.vertex);

                o.uv = v.uv;

                return o;

            }

 

 

            fixed4 frag (v2f2 i) : SV_Target

            {

                fixed4 col = tex2D(_MainTex, i.uv);

                fixed4 lineCol=tex2D(_outLineTex,i.uv);

                col.xyz+=lineCol.xyz;

                return col;

            }

            ENDCG

        }

    }

}

 

 

Shader "LZ/effectShader"{    Properties    {        _MainTex ("Texture", 2D) = "white" {}        _outLineSize("outLineSize",int)=4        //_outLineTex("outLineTex",2D)="black"{}        //_renderTex("renderTex",2D)="black"{}    }
    //Founction        CGINCLUDE
    float _outLineSize;    sampler2D _MainTex;    float4 _MainTex_TexelSize;
    struct a2v{        float4 vertex:POSITION;        float2 uv:TEXCOORD0;    };    struct v2f{        float4 pos:SV_POSITION;        float2 uv[5]:TEXCOORD0;    };
    v2f vert_heng(a2v v){        v2f o;        o.pos = UnityObjectToClipPos(v.vertex);        float2 uv=v.uv;        o.uv[0] = uv;        o.uv[1] = uv + float2(1,0) * _outLineSize * _MainTex_TexelSize.xy;        o.uv[2] = uv + float2(-1,0) * _outLineSize * _MainTex_TexelSize.xy;        o.uv[3] = uv + float2(2,0) * _outLineSize * _MainTex_TexelSize.xy;        o.uv[4] = uv + float2(-2,0) * _outLineSize * _MainTex_TexelSize.xy;        return o;    }
    v2f vert_shu(a2v v){        v2f o;        o.pos = UnityObjectToClipPos(v.vertex);        float2 uv=v.uv;        o.uv[0] = uv;        o.uv[1] = uv + float2(0,1) * _outLineSize * _MainTex_TexelSize.xy;        o.uv[2] = uv + float2(0,-1) * _outLineSize * _MainTex_TexelSize.xy;        o.uv[3] = uv + float2(0,2) * _outLineSize * _MainTex_TexelSize.xy;        o.uv[4] = uv + float2(0,-2) * _outLineSize * _MainTex_TexelSize.xy;        return o;    }
    fixed4 frag(v2f i):SV_TARGET{        float3 col = tex2D(_MainTex,i.uv[0]).xyz *0.4026;        float3 col1 = tex2D(_MainTex,i.uv[1]).xyz *0.2442;        float3 col2 = tex2D(_MainTex,i.uv[2]).xyz *0.2442;        float3 col3 = tex2D(_MainTex,i.uv[3]).xyz *0.0545;        float3 col4 = tex2D(_MainTex,i.uv[4]).xyz *0.0545;        float3 finalCol = col+col1+col2+col3+col4;        return fixed4(finalCol,1.0);    }
    ENDCG
    SubShader    {        Cull Off ZWrite Off ZTest Always
        
        Pass{            CGPROGRAM            #include"UnityCG.cginc"            #pragma vertex vert_heng            #pragma fragment frag             ENDCG        }
        Pass{            CGPROGRAM            #include"UnityCG.cginc"            #pragma vertex vert_shu            #pragma fragment frag             ENDCG        }
//pass 2 ---renderTex------------------------------------------------------------------------------        Pass        {            CGPROGRAM            #pragma vertex vert            #pragma fragment frag
            #include "UnityCG.cginc"
            struct appdata            {                float4 vertex : POSITION;                float2 uv : TEXCOORD0;            };
            struct v2f1            {                float2 uv : TEXCOORD0;                float4 vertex : SV_POSITION;            };
            v2f1 vert (appdata v)            {                v2f1 o;                o.vertex = UnityObjectToClipPos(v.vertex);                o.uv = v.uv;                return o;            }
            //sampler2D _MainTex;            sampler2D _renderTex;

            fixed4 frag (v2f1 i) : SV_Target            {                                float3 col= tex2D(_MainTex,i.uv).xyz;                float3 commandCol=tex2D(_renderTex,i.uv).xyz;                float3 finalCol=col-commandCol;                return fixed4(finalCol,1.0);            }            ENDCG        }

//pass3 add outlineTex--------------------------------------------------------------------------------------------------
        Pass        {            CGPROGRAM            #pragma vertex vert            #pragma fragment frag
            #include "UnityCG.cginc"
            struct appdata            {                float4 vertex : POSITION;                float2 uv : TEXCOORD0;            };
            struct v2f2            {                float2 uv : TEXCOORD0;                float4 vertex : SV_POSITION;            };
sampler2D _outLineTex;
            v2f2 vert (appdata v)            {                v2f2 o;                o.vertex = UnityObjectToClipPos(v.vertex);                o.uv = v.uv;                return o;            }

            fixed4 frag (v2f2 i) : SV_Target            {                fixed4 col = tex2D(_MainTex, i.uv);                fixed4 lineCol=tex2D(_outLineTex,i.uv);                col.xyz+=lineCol.xyz;                return col;            }            ENDCG        }    }}

原文地址:https://www.cnblogs.com/mcyushao/p/15076133.html