Unity_Shader入门详解

这篇具有很好参考价值的文章主要介绍了Unity_Shader入门详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、创建Shader

在Unity中创建Shader,有Stander Shader、Unlit Shader、Image Effect Shader、Compute Shader、Ray Tracing Shader

Stander Shader:Unity内置的标准着色器,支持高光、透明度、法线贴图等特性,比如金属,塑料,木材,皮肤,也支持光照、阴影、反射、折射、透明雾化等...

Unlit Shader:不受光照影响的着色器,适用于简单的2d,2d游戏,或者性能优化,比如常用于UI、例子、线条,比较轻量级,在移动设备应用比较多

Image Effect Shader:用于在渲染场景后对画面的后处理,比如实现模糊,色彩调整,边缘检测等效果

Compute Shader:一种运行在GPU上的着色器,可以用于高性能的计算任务

Ray Tracing Shader:实现光追的着色器,实现高质量的反射,折射,阴影等

其中前两种着色器被广泛使用

二、编写

创建一个新的标准着色器,分块进行分析

Shader "Custom/MyFirstShader"
{
    //Properties声明了着色器的属性变量。这个着色器有四个属性,分别是颜色,二维纹理,光泽度,金属度
    Properties
    {
        //颜色属性
        _Color ("Color", Color) = (1,1,1,1)
        //二维纹理属性
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        //光泽度
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        //金属质感
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }

     //这是一个子着色器,它定义了渲染该着色器时使用的材质类型和LOD
    SubShader
    {
        
        Tags { "RenderType"="Opaque" }

        //定义了该子着色器的LOD级别,它决定了在渲染远处的物体时使用的着色器质量。
        LOD 200


        //这个块包含了使用Cg/HLSL编写的着色器程序
        CGPROGRAM

        // 该段指定使用标准的表面着色器,并开启去所有类型光源的阴影
        #pragma surface surf Standard fullforwardshadows

        // 着色器模型3.0
        #pragma target 3.0

         //定义一个采样器,用于采样该着色器主纹理
        sampler2D _MainTex;

        //定义了一个输入结构体,它包含了从几何体传递到着色器的数据。
        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;

        half _Metallic;

        fixed4 _Color;

        // 这两行代码包含了一个实例缓冲区,允许使用着色器来渲染大量的实例
        UNITY_INSTANCING_BUFFER_START(Props)
        UNITY_INSTANCING_BUFFER_END(Props)

        //这个函数使用传入的几何体数据和着色器变量来计算表面的属性输出
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // 这行代码从主纹理中采样颜色值,并乘以着色器中定义的颜色值
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

            //设置表面的属性输出,包括反射率、光泽度、金属度和透明度
            o.Albedo = c.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    //如果当前着色器不能被使用,就会使用Unity默认的"Diffuse"着色器来代替。这样可以确保在任何情况下都能够正常渲染场景。
    FallBack "Diffuse"
}

可以看出主要有两大部分

1:Properties(属性)

一个Shader可以包含多个属性,这些属性是可以暴漏在Inspector窗口的,常见的属性包括:

  • _Color:颜色属性,可以用来定义材质的基本颜色

在Unity中,颜色可以用四个字母RGBA来表示,每个值都在0-1之间

R:红色的强度

G:绿色的强度

B:蓝色的强度

A:透明度,0-1逐渐不透明 

  • _MainTex:纹理属性,可以用来定义材质的主纹理,常见的纹理贴图如下

BumpMap:设置法线贴图

MatallicGlossMap:设置金属度和光滑度贴图

ParallaxMap:视差贴图

OcclusionMap: 用于设置遮挡贴图。

EmissionMap: 用于设置发光贴图。

DetailMask: 用于设置细节纹理的遮罩贴图。

拿MainTex举例,在本例中我们的主贴图的设置如下:

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

Albedo(RGB):Albedo表示物体的基础颜色,RGB表示纹理包含RGB通道的颜色信息

2D是表示这是2D纹理

white是纹理的默认值

  • _Glossiness:光滑度属性,可以用来控制材质的表面光滑度

Glossiness 是用于控制物体表面光泽度的属性,值范围为 0 到 1,0 表示非常粗糙(无光泽),1 表示非常光滑(高光泽)。

  • _Metallic:金属度属性,可以用来控制材质的金属度

金属度和上面的光泽度都是可以在0-1范围进行调整的

  • _BumpMap:凹凸贴图属性,可以用来定义材质的凹凸程度
    _BumpMap ("Normal Map", 2D) = "bump" {}
    _BumpScale ("Normal Scale", Range(0, 1)) = 1.0
  • _Parallax:视差贴图属性,可以用来定义材质的视差效果
        _ParallaxMap ("Parallax Map", 2D) = "white" {}
        _Parallax ("Parallax", Range(0, 0.2)) = 0.05
  • _EmissionColor:自发光颜色属性,可以用来定义材质的自发光颜色
_EmissionColor ("Emission Color", Color) = (0, 0, 0, 0)
  • _RimColor:边缘颜色属性,可以用来定义材质边缘的颜色
  • _RimPower:边缘亮度属性,可以用来控制材质边缘的亮度
        _RimPower ("Rim Power", Range(0.1, 10.0)) = 3.0
        _RimColor ("Rim Color", Color) = (1,1,1,1)

在Properties中加如RimPower和RimColor,控制边缘的颜色和亮度

在Properties中加入边缘属性以后,还需要在子着色器中进行使用

  • _OutlineColor:轮廓线颜色属性,可以用来定义材质的轮廓线颜色
  • _OutlineWidth:轮廓线宽度属性,可以用来定义材质的轮廓线宽度

比如它们可以这么设置:

Properties
    {
        // 设置轮廓宽度
        _OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.01
        // 设置轮廓颜色
        _OutlineColor ("Outline Color", Color) = (0,0,0,1)
    }

就代表了轮廓的宽度和颜色

2:SubShader(子着色器)

在Shader文件中,Properties中声明的一些属性,还需要在子着色器中进行实现(比如贴图和颜色),而比如金属和光滑度则不需要,因为已经默认实现了

子着色器中是通过CG程序访问的,CG程序是unity内置的着色器语言,用于编写GPU程序

在一个子着色器中,我们同时使用了CG/HLSL语言来编写

同样一个Shader也可以包含多个子着色器

我们举一个边缘发光的例子来详细解释一下子着色器的作用

Shader "Custom/Outline" {
    Properties {
        _OutlineColor ("Outline Color", Color) = (1,1,1,1)
        _OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.01
    }

    SubShader {
        Tags { "RenderType"="Opaque" }

        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float4 _OutlineColor;
            float _OutlineWidth;

            struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);

                // Expand the vertex position by the outline width in screen space
                o.vertex.xy += _OutlineWidth * o.vertex.w * UnityObjectToClipPos(float4(1, 1, 0, 0));

                return o;
            }

            fixed4 frag (v2f i) : SV_Target {
                // If the pixel is not on the edge, make it transparent
                if (ddx(i.vertex.xy) != 0 || ddy(i.vertex.xy) != 0) {
                    discard;
                }

                // Otherwise, set the pixel color to the outline color
                return _OutlineColor;
            }
            ENDCG
        }
    }

    FallBack "Diffuse"
}

这段代码中,我们定义了两个属性,一个是边缘的深度,一个是边缘的颜色

然后Tag选择了RenderType(渲染类型),其实在Shader里面我们有很多种的Tag可以选择,而且在Tag里面可以多选,比如:

Tags {
    "Queue"="Transparent"
    "RenderType"="Opaque, MyRenderType"
}

Tag有很多种,常见的Tag比如:

  渲染类型(RenderType)、渲染队列(Queue)、光照模式(Lighting)、渲染状态(RenderState)

RanderType有如下几种:

Opaque:用于不透明的对象和材质

Transparent:用于透明对象和材质。

TransparentCutout:用于具有透明度的对象,但其透明度可以由一个阈值来切断。

Background:用于背景图像,一般是不透明的。

Overlay:用于叠加材质,通常用于添加光晕或其它效果。

TreeOpaque:用于树木对象的不透明部分。

TreeTransparentCutout:用于树木对象的透明部分。

TreeBillboard:用于树木对象的Billboard部分。

Queue是来指定绘制顺序和优先级的,有如下几种:

BackGround:背景,通常是天空和或者其他背景元素

Geomety:一般的几何物体,包含场景中的大部分物体

AlphaTest、Transparent、Overley(覆盖物)

Lighting表示渲染顺序,有前置渲染和延迟渲染

Forward渲染是每个物体都分别渲染,并且每个像素被光照多次,适用于移动端和低端PC

Deferred Rendering是所有集合体都会被先渲染一次,然后光照信息被存储在G-buffer中,再对G-buffer进行光照计算,这种方法需要更高的GPU

RenderState表示渲染的状态,有如下几种

Cull:剔除状态,可选Back,Front,Off三种剔除状态

ZTest:深度测试状态,可选Less,Greater,LEqual

ZWrite:深度写入状态,可选On/Off

Blend:混合状态可选Zero,One,SrcColor,EstColor等

Offset:偏移状态,可选Factor,Units

然后在子着色器中我们定义了一个Pass,可以说Pass是我们与GPU进行沟通的桥梁,它包含一组着色器程序、渲染状态和其他参数,表示一次渲染的操作

首先:#pragma vertex vert
           #pragma fragment frag

这两个指令用于指定哪些函数应该作为顶点着色器和比像素着色器

顶点着色器计算每个顶点的最终位置和纹理信息,颜色

像素着色器则为每个像素计算最终的颜色值

除了顶点着色器和像素着色器外,还有几何着色器(Geometey shader)、外壳着色器(hull shader)、细分着色器(Domain shader)、计算着色器(Compute shader)

声明的方法就是#pragma + 着色器名称 +自己的命名

其次:float4 _OutlineColor;
           float _OutlineWidth;

也就是在属性中声明的属性值,这里要在着色器中,使用所以需要在此处声明一下

接着:

struct appdata {
                float4 vertex : POSITION;
            };

声明一个叫appdate的结构体,里面有一个名为vertex的float4的变量,Position表示这个变量是存储该顶点的信息位置,在实际的顶点数据中,可能不仅仅有position,还可能会有法线,颜色等等,都可以在该结构体中声明,比如:

struct appdata {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float4 color : COLOR;
};

接着:

struct v2f {
                float4 vertex : SV_POSITION;
            };

这个结构体和上一个类似,不过这里的SV_POSITION是表示经过顶点着色器计算后的顶点屏幕空间位置

继续:

v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.vertex.xy += _OutlineWidth * o.vertex.w * UnityObjectToClipPos(float4(1, 1, 0, 0));

                return o;
            }

首先这是一个名为vert,返回值为v2f的顶点着色器函数,接受的参数是appdate类型,我们之前定义了一个appdate的结构体,所以说参数是存储的顶点数据

首先实例化了经过顶点着色器计算后的v2f类型的结构体o,UnityObjectToClipPos()是一个Unity函数,它将对象空间中的点转换为剪裁空间中的点,在这里我们使用该函数将传入的顶点位置从对象空间转换为剪裁空间,并将其保存到 o.vertex 中,作为 vert() 函数的返回值。

#这里我们要声明一点,为什么要进行空间裁剪呢?

3D图形学中,我们需要把三维坐标系中的顶点投影到二维平面,这个过程叫投影,在图形学中,通常采用裁剪空间( Clip Space)来进行投影,举个例子,裁剪空间其实就是一个类似摄像机镜头的视锥体,这个视锥体的顶点就是摄像机的位置,当场景中的物体进入这个视锥体时,就会被渲染到屏幕上。

最后一步:

fixed4 frag (v2f i) : SV_Target {
                // If the pixel is not on the edge, make it transparent
                if (ddx(i.vertex.xy) != 0 || ddy(i.vertex.xy) != 0) {
                    discard;
                }

                // Otherwise, set the pixel color to the outline color
                return _OutlineColor;
            }
            ENDCG

这是一个名为frag的函数,参数就是经过处理顶点着色器的v2f结构体,也就是经过了空间裁剪的顶点屏幕空间位置,返回值是一个fixed4 数据类型,包含四个浮点数的向量,使用定点数而不是浮点数来表示颜色和坐标等数据可以提高性能和精度,因为定点数在硬件中的处理速度比浮点数快,并且可以避免一些精度误差。

:SV_Target表示,将该颜色输出到当前渲染目标。

if (ddx(i.vertex.xy) != 0 || ddy(i.vertex.xy) != 0) {
                    discard;
                }

这段代码是用来判断像素是否处于边缘,如果不是的话,就通过discard让这个像素不被绘制,也就是只绘制边缘,ddx和ddy是HLSL内置的函数,用于计算像素位置的梯度文章来源地址https://www.toymoban.com/news/detail-687595.html

到了这里,关于Unity_Shader入门详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity Shader 入门笔记 (一)

    前言 这个笔记系列并不会过多涉及图形学数学基础和渲染流水线的相关知识,但要求你具备相关知识,因此强烈建议你在学习和查阅此笔记前了解基础的图形学基础知识和渲染流水线相关知识。这里强烈推荐 闫令琪 老师开设的 Games101课程 :Lecture 01 Overview of Computer Graphics_哔

    2024年01月24日
    浏览(32)
  • 《Unity Shader 入门精要》笔记07

    Unity中通常使用两种方法来实现透明效果:第一种是试用 透明度测试(Alpha Test) ,这种方法其实无法得到真正的半透明效果;另一种是 透明度混合(Alpha Blending) 。 由于深度缓冲的存在,可以让不透明物体不考虑他们渲染顺序也能得到正确的排序效果。但是实现透明效果需

    2024年02月07日
    浏览(32)
  • 【Unity Shader】从入门到着魔(1)基本概念:什么是网格?材质?Shader?

    如上图,模型的三角形面就叫做网格(Mesh),网格的本质是一堆顶点数据的规则排序,在Unity和UE中由三角形表示,Maya等DCC软件(Digital Content Creation)中则通常由四边形表示(俩个三角形刚好组成一个四边形)。 在Unity中我们新建一个Cube,

    2024年02月09日
    浏览(30)
  • 1.Unity之Shader新手入门

    Unity Shader着色器的基本概念 如何使用Unity Shader着色器 示例:如何使用Unity Shader着色器创建复杂的效果 总结 什么是Unity中的Shader着色器? Shader着色器是用来控制物体外观的编程代码,它可以改变物体的颜色、纹理、光照、凹凸等,以及实现各种复杂的效果。Unity中有很多种类

    2024年02月04日
    浏览(27)
  • Unity Shader入门精要学习——透明效果

    要么完全透明,要么完全不透明。 实现简单,实质上是一种剔除机制,通过将不满足条件(通常使用小于某个阈值来判定,一般使用clip方法)的片元舍弃的方法来达到完全透明效果。这些被舍弃的片元不会再进行任何的处理,也不会对颜色缓冲产生任何影响,其余满足条件

    2024年02月17日
    浏览(34)
  • Unity Shader入门精要 第六章——Unity中的基础光照

    目录 一、标准光照模型(Phong光照模型) 1、环境光  2、自发光 3、漫反射 4、高光反射 (1)Phong模型 (2)Blinn模型 5、光照模型实现方法——逐顶点和逐像素 二、Unity Shader 漫反射光照模型的实现 1、实践:逐顶点 2、实践:逐像素 3、半兰伯特模型 4、漫反射光照模型效果展

    2024年02月04日
    浏览(40)
  • [Unity Shader入门精要]初级篇 代码拆解

    简介: 介绍了Unity Shader入门精要中初级篇包含的所有代码, 通过详细拆解代码 ,一步一步揭晓Shader的原理。 5.2.1 顶点/片元着色器的基本结构 说人话: •第一行是着色器的名字,用大括号{} 包裹后续所有的Shader代码, Shader。 •紧接着是Shader的属性,用大括号{} 包裹

    2024年02月03日
    浏览(31)
  • Unity Shader入门精要 第八章——透明效果

    目录 前言 一、渲染顺序的重要性 二、Unity Shader的渲染顺序 三、透明度测试 1、什么是透明度测试 2、实践 四、透明度混合 1、什么是透明度混合 2、实践  五、开启深度写入的半透明效果 1、实现方法  2、实践 六、ShaderLab的混合命令 1、混合等式和参数 2、混合操作  3、常见

    2024年02月04日
    浏览(28)
  • UnityShader入门学习(三)——Unity的Shader

    Tags Tags可以写在SubShader的一开始(所有的Pass用),也可以写在Pass块的内部(该Pass用) 渲染设置 同Tags一样也可以写在Pass中或者写在Pass外面(SubShader一开始) Pass介绍 Pass里面可以定义Pass名称 Pass里面的Tags还可以有额外的设置 还有CG语言所写的代码,主要是顶点片元着色器,

    2024年02月16日
    浏览(31)
  • Unity Shader 开发入门3 —— 坐标空间变换

    ​ 在 Shader 开发中存在不同的坐标空间,包括: 模型空间。 世界空间。 观察空间。 裁剪空间。 屏幕空间。 ​ 在渲染管线中,需要将坐标数据在这些空间中进行变换计算。 ​ 在设计模型时,使用模型空间。模型导入 Unity 后,最终显示在屏幕上,依次经历了如下空间的坐标

    2024年01月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包