在各种游戏中,想必大家一定和我一样总是惊叹于游戏画面的各种炫酷的特效。

作为游戏开发中单独列出的一个职业TA(Technology Art),他们会利用GLSL或者HLSL等着色器语言绘制出一幅幅美丽的画面。

于是作为小白,从零开始学习ShaderLab,记录一下学习历程。

 

  ShaderLab从入门到放弃过很多次,总是想搞清楚一个shader完整的语法结构和每一行声明的意义。

 事实上,作为小白,如果不想总是碰壁然后放弃,也许先从修改开始比较合适。


1.创建第一个Shader

我们在Unity 工程文件中新建一个Unlit Shader文件,默认的Shader文件是一个具备基本功能的shader。


Shader "Unlit/DrawCircle"
//定义了着色器的名称为 “Unlit/DrawCircle”,表示这是一个不受光照影响的着色器。
{
    //着色器属性列表,定义了着色器材质上可以自定义的属性
    Properties
    {
        //主纹理
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        //指定了渲染类型为不透明物体。
        Tags { "RenderType"="Opaque" }
        //指定了细节层级为 100
        LOD 100
        //在 SubShader 中定义了一个 Pass。
        Pass
        {
            //在 Pass 中,通过 CGPROGRAM 和 ENDCG 标记将着色器代码包裹起来,表示代码块开始和结束。
            CGPROGRAM
            //定义了顶点着色器函数的入口
            #pragma vertex vert
            //定义了片元着色器函数的入口
            #pragma fragment frag
            // 启用雾效
            #pragma multi_compile_fog
            #include "UnityCG.cginc"
            //定义了输入顶点数据的数据结构,包括顶点坐标和纹理坐标。
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            //定义了传递给片元着色器的数据结构,包括纹理坐标、雾效坐标、裁剪空间位置和世界空间位置。
            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };
            sampler2D _MainTex;
            float4 _MainTex_ST;
            //顶点着色器函数的定义,将输入顶点数据转换为屏幕空间坐标,并传递给片元着色器。
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
            //片元着色器函数的定义,接收顶点着色器传递的数据,并计算最终的像素颜色。
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

2.做出一些修改。比如说绘制一个自定义颜色的圆

首先应该公开定义一个颜色变量,所有在着色器列表属性中公开的属性都应该遵循①在Properties中定义   ②在Pass中声明

比如在这里我们声明一个颜色Color1

    //着色器属性列表,定义了着色器材质上可以自定义的属性
Properties
{
//主纹理
_MainTex ("Texture", 2D) = "white" {}
_Color1("Color1",Color)=(1,1,1,1)
}

  

            sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color1;

  

其次绘制圆,要定下来圆心,比如把圆心放在面的中心点。

那么我需要知道每个像素点的坐标,我们可以在传递给片元着色器的数据结构中加入一个自定义的字段worldPos,就是每个像素点的坐标

            //定义了传递给片元着色器的数据结构,包括纹理坐标、雾效坐标、裁剪空间位置和世界空间位置。
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float3 worldPos :TEXCOORD1;
};

  其次在顶点着色器函数中增加一段逻辑,将输入的顶点数据转化为屏幕坐标,并传递给片元着色器

            //顶点着色器函数的定义,将输入顶点数据转换为屏幕空间坐标,并传递给片元着色器。
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
// o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.uv = mul(unity_ObjectToWorld, v.vertex).xyz;;
o.worldPos=v.vertex;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}

  最后我们调整片元着色器函数的逻辑,接受顶点着色器传递的数据,并计算最终像素颜色

            //片元着色器函数的定义,接收顶点着色器传递的数据,并计算最终的像素颜色。
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv); //定义一个变量存储:当前像素点距离中心点的位置
float dist=distance(i.worldPos,float3(0,0,0));
//如果像素点距离中心点大于0.3小于0.32,将自定义的颜色赋值在这区间的像素内;
//否则丢弃当前像素点
if(dist>0.3&&dist<0.32){
col*=_Color1;
}
else{
discard;
}
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}

  

附上最后的效果:

以及完整的Shader代码

Shader "Unlit/DrawCircle123"
//定义了着色器的名称为 “Unlit/DrawCircle”,表示这是一个不受光照影响的着色器。
{ //着色器属性列表,定义了着色器材质上可以自定义的属性
Properties
{
//主纹理
_MainTex ("Texture", 2D) = "white" {}
_Color1("Color1",Color)=(1,1,1,1)
}
SubShader
{
//指定了渲染类型为不透明物体。
Tags { "RenderType"="Opaque" } //指定了细节层级为 100
LOD 100 //在 SubShader 中定义了一个 Pass。 Pass
{
//在 Pass 中,通过 CGPROGRAM 和 ENDCG 标记将着色器代码包裹起来,表示代码块开始和结束。
CGPROGRAM
//定义了顶点着色器函数的入口
#pragma vertex vert //定义了片元着色器函数的入口
#pragma fragment frag // 启用雾效
#pragma multi_compile_fog #include "UnityCG.cginc" //定义了输入顶点数据的数据结构,包括顶点坐标和纹理坐标。
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
}; //定义了传递给片元着色器的数据结构,包括纹理坐标、雾效坐标、裁剪空间位置和世界空间位置。
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float3 worldPos :TEXCOORD1;
}; sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color1;
//顶点着色器函数的定义,将输入顶点数据转换为屏幕空间坐标,并传递给片元着色器。
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
// o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.uv = mul(unity_ObjectToWorld, v.vertex).xyz;;
o.worldPos=v.vertex;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
//片元着色器函数的定义,接收顶点着色器传递的数据,并计算最终的像素颜色。
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv); //定义一个变量存储:当前像素点距离中心点的位置
float dist=distance(i.worldPos,float3(0,0,0.5));
//如果像素点距离中心点大于0.3小于0.32,将自定义的颜色赋值在这区间的像素内;
//否则丢弃当前像素点
if(dist>0.3&&dist<0.32){
col*=_Color1;
}
else{
discard;
}
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}

Shader学习笔记 (一) :利用shader在一个面绘制出圆的更多相关文章

  1. Shader学习笔记

    Shader学习笔记 例子: Shader "SrfShader1"{ //定义显示在Inspector中的变量,并从Inspector中获取值 Properties{ _Colo ...

  2. 【HLSL学习笔记】WPF Shader Effect Library算法解读之[DirectionalBlur]

    原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[DirectionalBlur] 方位模糊是一个按照指定角度循环位移并叠加纹理,最后平均颜色值并输出的一种特效. ...

  3. 【HLSL学习笔记】WPF Shader Effect Library算法解读之[Embossed]

    原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[Embossed] Embossed(浮雕效果)          浮雕效果主要有两个参数:Amount和Wid ...

  4. 【HLSL学习笔记】WPF Shader Effect Library算法解读之[BandedSwirl]

    原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[BandedSwirl] 因工作原因,需要在Silverlight中使用Pixel Shader技术,这对于我来 ...

  5. 学习笔记:利用GDI+生成简单的验证码图片

    学习笔记:利用GDI+生成简单的验证码图片 /// <summary> /// 单击图片时切换图片 /// </summary> /// <param name=&quo ...

  6. 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据

    机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...

  7. Spring MVC 学习笔记2 - 利用Spring Tool Suite创建一个web 项目

    Spring MVC 学习笔记2 - 利用Spring Tool Suite创建一个web 项目 Spring Tool Suite 是一个带有全套的Spring相关支持功能的Eclipse插件包. ...

  8. Unity Shader学习笔记-1

    本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的github 如果有什么说的不正确的请批评指正 目录 渲染流水线 流程图 Shader作用 屏幕映射 三角形遍历 两大 ...

  9. Unity3D学习笔记3——Unity Shader的初步使用

    目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. 渲染 ...

  10. Unity3D Shader 学习笔记(一):初识Shader

    第一节:图形处理器简史 GPU发展简史 GPU英文全称Graphic Procssing Unit. T&L变换和光照流水线 可编程GPU GPU的优点和缺点 第二节:Unity Shader ...

随机推荐

  1. Linux中的进程页表

    是什么 进程页表是用于管理进程虚拟地址空间和物理内存之间映射关系的数据结构.它记录了进程中每个虚拟页对应的物理页的信息. 什么作用 进程使用进程页表的方式是通过虚拟地址访问内存.当进程访问一个虚拟地址 ...

  2. ValueError: Max value is 14 解决方案

    方案一(有时会失效): 将EXCEL文件中的格式全部清除即可.最好是复制,然后只粘贴值. 方案二(指定引擎): data = pd.read_excel(path, engine="open ...

  3. js面向对象编程,你需要知道这些

    javascript中对象由key和value组成,key是标识符,value可以为任意类型 创建对象的方式 1.通过构造函数 var obj = new Object() obj.name = 'a ...

  4. 操作系统实验——利用Linux的消息队列通信机制实现两个线程间的通信

    目录 一. 题目描述 二.实验思路 三.代码及实验结果 四.遇到问题及解决方法 五.参考文献 一. 题目描述 编写程序创建三个线程:sender1线程.sender2线程和receive线程,三个线程 ...

  5. 论文解读(WDGRL)《Wasserstein Distance Guided Representation Learning for Domain Adaptation》

    Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:Wasserstein Distance Guided Representation Learning f ...

  6. ThreadLocal:线程中的全局变量

    最近接了一个新需求,业务场景上需要在原有基础上新增2个字段,接口新增参数意味着很多类和方法的逻辑都需要改变,需要先判断是否属于该业务场景,再做对应的逻辑.原本的打算是在入口处新增变量,在操作数据的时候 ...

  7. 我的新书《Flink大数据分析实战》出版啦

  8. 数据库安装postgresql

    数据库安装postgresql 目录 数据库安装postgresql 1.数据库源替换下载 2.初始化数据库并启动安装 3.登录数据库设置密码 4.常用命令 一.常用命令 二.用户 三.权限 四.模式 ...

  9. Solution -「CF 959E」Mahmoud and Ehab and the xor-MST

    Description Link. 一完全图有 \(n\) 个节点 \(0,...,n-1\),其中边 \((i,j)\) 的权值为 \(i\oplus j\),其中 \(\oplus\) 为位异或操 ...

  10. Springboot简单功能示例-3 实现基本登录验证

    springboot-sample 介绍 springboot简单示例 跳转到发行版 查看发行版说明 软件架构(当前发行版使用) springboot hutool-all 非常好的常用java工具库 ...