Unity Shader片段着色器使用基础详解

Unity Shader片段着色器使用基础详解

Unity中的Shader(着色器)用于控制游戏对象的渲染方式,让它们变得更加美观、细致。Shader分为顶点着色器和片段着色器,这篇攻略主要介绍Unity中片段着色器的使用基础,可以帮助开发者更加细致地控制对象的渲染方式。

Shader基础知识

在进入片段着色器的详细使用说明前,我们先来了解一些Shader的基础知识:

  • Shader程序:Shader程序是一个小型程序,它可以用来控制材质表面的渲染效果。在Unity中,Shader是由着色器语言编写的,可以用许多内置的和自定义的函数来描述。

  • ShaderLab语言:这是Unity的一种语言,它用于描述材质、纹理、渲染队列、某个材质的Shader和其它属性。它是一种易于阅读和编写的语言,并且易于维护。

  • Uniform变量:这种变量是可编程的,它的值可以被修改,而且在绘制物体时,它是不一样的,又称之为上传的变量。比如说,全局变量或者纹理。

有了以上的基础知识,我们就可以更好地理解Unity中片段着色器的使用方法。

片段着色器

片段着色器是一种Shader编程技巧,它用于描述一个像素的颜色和属性。它们的作用体现在单个像素上,包括光照模型、着色、透明度、阴影、反射和折射等效果。

片段着色器样例1

下面是一个Unity中片段着色器的基础代码:

Shader "Custom/MyFragmentShader" {
Properties {
    _MainTex ("Texture", 2D) = "white" {}
    _Color ("Color", Color) = (1,1,1,1)
}
SubShader {
    Tags {"Queue"="Transparent" "RenderType"="Opaque"}
    LOD 100

    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        struct appdata {
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };
        struct v2f {
            float2 uv : TEXCOORD0;
            float4 vertex : SV_POSITION;
        };

        sampler2D _MainTex;
        float4 _MainTex_ST;
        fixed4 _Color;

        v2f vert (appdata v) {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
            return o;
        }

        fixed4 frag (v2f i) : SV_Target {
            fixed4 col = tex2D(_MainTex, i.uv) * _Color;
            col.a = _Color.a * col.a;
            return col;
        }
        ENDCG
    }
}

在这个例子中,我们定义了一个名为“ Custom/MyFragmentShader”的着色器。在Properties区块中,我们定义了_MainTex(主纹理)和_Color(颜色)两个Uniform属性,同时它们的默认值分别为白色和纯白色。

在SubShader区块中,我们通过Tags指令定义了它们的渲染顺序和类型,并且设置了LOD(LOD表示level of details)

在内部的Pass语句中,我们定义了一个传递着色器的CGPROGRAM块,在这里我们定义了一个输入参数appdata和一个输出参数v2f。

vert函数定义了输入参数v并输出了v的顶点着色阶段的处理结果,同时重映射了_MainTex的uv坐标到图像的正确位置。固定函数TEXCOORD0包含了uv坐标, float4类型包含64位浮点数,表示精度很高的浮点坐标。

frag`函数定义了输入参数i并输出了颜色。在这个函数中,我们首先获取_MainTex的颜色,然后将它与颜色变量_Color进行乘法运算,最后将颜色的Alpha通道值设置为变量_Color的Alpha值,最终返回这个颜色值。

这么一看,Unity中的片段着色器相比OpenGL,其着色代码相对比较简单易用。

片段着色器样例2

现在,我们来看一个更复杂一点的例子。这个例子中,我们要使用屏幕空间反射技术让我们的地面反射画面中的物体。

Shader "Custom/ShaderExample" {
Properties {
    [HDR] _ReflColor ("Reflection Color", Color) = (1, 1, 1, 1)
    _DiffuseColor ("Diffuse Color", Color) = (1, 1, 1, 1)
    _MainTex ("Base (RGB)", 2D) = "white" {}
}

SubShader {
    Tags { "RenderType"="Opaque" }
    CGPROGRAM
    #pragma surface surf Standard

    struct Input {
        float2 uv_MainTex; 
    };

    half4 _ReflColor;
    half4 _DiffuseColor;
    sampler2D _MainTex;
    float4 _MainTex_ST;

    void surf (Input IN, inout SurfaceOutputStandard o) 
    {
        o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * _DiffuseColor.rgb;
        o.Metallic = 0.5;
        o.Smoothness = 0.5;
        o.Normal = float3(0,0,1);
        o.Emission = _ReflColor.rgb * tex2D(_MainTex, reflect(IN.uv_MainTex, o.Normal)).rgb;
        o.Alpha = 1;
    }
    ENDCG
} 
FallBack "Diffuse"

在这个例子中,我们定义了一个名为“ Custom/ShaderExample”的着色器。在Properties区块中,我们定义了三个Uniform属性:_ReflColor_DiffuseColor的颜色属性以及_MainTex的主纹理属性。

在SubShader区块中,我们通过Tags指令定义这个着色器的渲染类型为不透明的。在此后的CGPROGRAM块中,我们使用了 #pragma surface surf Standard 指令来使用Standard Shader Surface Functions。

这里的函数 surf(Input IN, inout SurfaceOutputStandard o)用于将输入的Mesh顶点所对应的表面输出为SurfaceOutputStandard的实例化对象,后续的混合、渲染、反射和折射拆分都是在o的实例上操作。

在这个例子中,我们使用了反射矩阵传入INPUT并用其获取屏幕空间反射的纹理坐标来改变当前表面的反射色。我们通过纹理采样方式tex2D把纹理坐标的颜色值结合DiffusColor和Diffuse纹理纹理颜色进行混合。

Shader的局限性

使用Unity内置的Shader是可以在游戏中实现很多复杂效果的。但是,由于Shader编程需要对OpenGL或Metal等底层渲染API有一定的了解,所以它对于新手来说可能有些陌生。同时,由于Shader的执行是在GPU上完成的,所以在某些情况下,Shader的执行会占用大量的系统资源,从而降低游戏的帧率。

另外,对于非高端设备的手机来说,也可能会出现一些兼容性问题,特别是一些老旧的手机。因此,在制作游戏时,我们需要对不同的设备进行适当的优化。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Unity Shader片段着色器使用基础详解 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • C#中实现可变参数实例

    为在C#中实现可变参数的实例,我们需要用到可变参数语法中的 params 关键字。使用 params 关键字可以使方法参数的数量可变,并且可以进行重载。 下面是实现可变参数的步骤: 在方法参数列表中使用 params 关键字,该关键字后跟一个数组类型,表示该方法可以接收任意数量的该数组类型的参数。 public void AddNumbers(params …

    C# 2023年6月6日
    00
  • 【开源游戏】Legends-Of-Heroes 基于ET 7.2的双端C#(.net7 + Unity3d)多人在线英雄联盟风格的球球大作战游戏。

    Legends-Of-Heroes 一个LOL风格的球球大作战游戏,基于ET7.2,使用状态同步  Main 基于C#双端框架[ET7.2],同步到ET主干详情请看日志。(https://github.com/egametang/ET) 注意:已经升级.Net7,请安装.Net7 SDK. 此游戏为ET7.2的一个实践项目demo,玩法主要是球球大作战类型的…

    C# 2023年5月9日
    00
  • abp(net core)+easyui+efcore实现仓储管理系统——模块管理升级(六十)

    Abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+easyui+efcore实现仓储管理系统——解决方案介绍(二) abp(net core)+easyui+efcore实现仓储管理系统——领域层创建实体(三)…

    C# 2023年4月18日
    00
  • C#基于简单工厂模式实现的计算器功能示例

    C#基于简单工厂模式实现的计算器功能示例 概述 本文将介绍如何基于简单工厂模式实现一个计算器功能的示例。我们会通过编写C#代码来实现一个简单的计算器,能够支持加、减、乘、除四种运算。 简单工厂模式 在讲解示例之前,我们先来了解一下简单工厂模式。简单工厂模式是一种创建型设计模式,它提供了一个工厂方法来创建对象。这种模式可以被认为是实现了基本的对象创建的代码复用…

    C# 2023年6月7日
    00
  • C#中ManualResetEvent用法详解

    以下是关于“C#中ManualResetEvent用法详解”的完整攻略。 概述 ManualResetEvent 是一个同步基元,它允许一个或多个线程等待信号,然后再继续执行。当 WaitOne 方法被调用时,会阻塞线程直到接收到信号,然后线程被唤醒并继续执行。 ManualResetEvent 主要由两个方法 WaitOne() 和 Set() 组成。Wa…

    C# 2023年6月1日
    00
  • .net4.5使用async和await异步编程实例

    .NET4.5使用async和await异步编程实例攻略 1. 什么是异步编程 在单线程程序中,当某个任务需要较长的时间才能完成时,程序会一直等待该任务完成后才能继续执行下面的代码,这会导致程序的执行效率变低,用户体验不佳。 异步编程通过将耗时操作放入另外的线程中处理,让主线程继续执行其他任务,从而提高程序的执行效率,改善用户体验。 2. async和awa…

    C# 2023年5月31日
    00
  • C# 中const,readonly,static的使用小结

    下面是对于“C#中const,readonly,static的使用小结”的详细讲解。 前言 在C#开发中,我们常常会使用const,readonly和static这三个关键字,它们都可以用来定义变量,但具有不同的作用。 const const是常量的意思,其特点是在编译时期已经固定下来了,不可改变。 在C#中,const定义的变量必须在声明时初始化,而且只能…

    C# 2023年5月15日
    00
  • C#实现写入文本文件内容的方法

    当需要将数据写入本地文本文件时,常用的语言之一是C#。C# 为文件读写提供了方便易用的功能,使得将数据写入文本文件变得十分简单。以下是如何使用 C# 实现写入文本文件内容的方法: 1. 语法 C# 提供了 StreamWriter 类,用于将文本数据写入文件。它在 System.IO 命名空间下。 使用 StreamWriter 类之前,需要先创建一个文本文…

    C# 2023年6月1日
    00
合作推广
合作推广
分享本页
返回顶部