问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Unity3D Shader教程:为精灵创建自定义着色器

创作时间:
作者:
@小白创作中心

Unity3D Shader教程:为精灵创建自定义着色器

引用
CSDN
1.
https://blog.csdn.net/sinat_25415095/article/details/120255583

在Unity3D中,精灵(Sprite)的渲染方式与3D物体的渲染方式非常相似。本文将介绍如何为精灵创建自定义着色器,重点讲解如何支持镜像和顶点颜色。

1. 概要

在 Unity 中,精灵的渲染方式与 3d物体的渲染方式非常相似。大部分工作由精灵渲染器(Sprite Renderer)组件完成。我将稍微介绍一下组件正在做什么以及我们如何更改着色器以执行默认精灵渲染器正在执行的一些操作。

本教程将建立在我们之前制作的透明着色器的基础上,因此您最好先了解它。

2. 场景设置

为了使用Sprite Shader,我将场景更改得更简单,使用正交相机,用精灵渲染器替换了之前示例中使用的立方体,并将我使用的图像转换为Sprite(精灵图)。

3. 更改着色器

通过上面场景的更改以及透明材质被放入精灵渲染器的材质槽(Material),似乎已经可以正常工作了。

精灵渲染器(Sprite Renderer)组件根据我们的图像自动生成一个网格并设置它的 UV 坐标,这样精灵图就像我们习惯的 3d 模型一样渲染。Sprite Renderer还将精灵渲染器的颜色放入生成网格的顶点颜色中,并在我们激活翻转 X 或 Y 时将顶点翻转。Sprite Renderer还与Unity的渲染管道(Renderer Pipeline)通信,因此具有更高排序层(Sorting Layer)的精灵将稍后渲染并绘制在顶部。

但我们的着色器目前不支持镜像和顶点颜色,所以让我们解决这个问题。

当我们翻转它时我们的精灵消失(并在我们在 x 和 y 翻转它时重新出现)的原因是x 轴翻转,Sprite Renderer是将其绕 y 轴旋转 180°,然后我们看到背面它以及由于称为“背面剔除”的优化,精灵图的背面不会被渲染。通常背面剔除是好的,因为当我们看不到对象的内部时,就不需要渲染背面。而且因为背面的法线背对着相机,无论怎样背面的光照通常都是错误的。

但是在这里,我们不必担心这两个问题,精灵没有可以优化的“内部”,我们也不做光照,所以我们可以禁用背面剔除。我们可以在SubShader或Pass中做到这一点。

Cull off

为了获得顶点颜色,我们将一个新的 4维向量(red, green, blue, alpha) 添加到我们的输入结构和顶点着色器到片段着色器中,变量名设置为color。 然后在顶点着色器中我们将输入结构体的颜色传递到的 v2f 结构,并在片段着色器中将我们的返回颜色与它相乘;

struct appdata{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
    fixed4 color : COLOR;
};
struct v2f{
    float4 position : SV_POSITION;
    float2 uv : TEXCOORD0;
    fixed4 color : COLOR;
};
v2f vert(appdata v){
    v2f o;
    o.position = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    o.color = v.color;
    return o;
}
fixed4 frag(v2f i) : SV_TARGET{
    fixed4 col = tex2D(_MainTex, i.uv);
    col *= _Color;
    col *= i.color;
    return col;
}

通过这些更改,着色器现在将按照我们的预期运行,我们可以扩展它以执行我们将来感兴趣的其他事情。

完整Shader如下。

Shader "Tutorial/007_Sprite"{
    Properties{
        _Color ("Tint", Color) = (0, 0, 0, 1)
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader{
        Tags{ 
            "RenderType"="Transparent" 
            "Queue"="Transparent"
        }
        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite off
        Cull off
        Pass{
            CGPROGRAM
            #include "UnityCG.cginc"
            #pragma vertex vert
            #pragma fragment frag
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;
            struct appdata{
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                fixed4 color : COLOR;
            };
            struct v2f{
                float4 position : SV_POSITION;
                float2 uv : TEXCOORD0;
                fixed4 color : COLOR;
            };
            v2f vert(appdata v){
                v2f o;
                o.position = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.color = v.color;
                return o;
            }
            fixed4 frag(v2f i) : SV_TARGET{
                fixed4 col = tex2D(_MainTex, i.uv);
                col *= _Color;
                col *= i.color;
                return col;
            }
            ENDCG
        }
    }
}

当然,Sprite Renderer组件做的远不止这些,它还准备网格以便Sprite Sheet(精灵表)、polygon sprites(多边形精灵)和Animation(动画)与我们的着色器一起使用。

Unity自带的精灵着色器已经实现但我们自己的Shader还未实现的功能包括instancing(实例化)、pixel snapping(像素捕捉)和就一个外部 alpha 通道。由于这些要么太复杂要么很少有人使用,所以在这里我决定暂时不实现它们 。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号