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

作为游戏开发中单独列出的一个职业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. vue+element 判断table表格输入不能为空

    点击确定的时候,判断表格其中某行某值不能为空 1.HTML <div class="app-container"> <el-form ref="form ...

  2. Spring-配置文件(引入其他配置文件,分模块开发)

    引入其他配置文件 实际开发,Spring的配置文件内容非常多,这就导致了Spring配置很复杂且体积很大,所以可以将配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载 & ...

  3. C语言链表实现(郝斌数链表学习笔记)

    #include "stdafx.h" #include<stdio.h> #include<stdlib.h> typedef struct Node { ...

  4. Java服务刚启动时,一小波接口超时排查全过程

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明. 简介 我们组有一个流量较大的Java服务,每次发代码时,服务都会有一小波接口超时,之前简单分析过,发现这些超时的 ...

  5. Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream

    伪 分布模式下启动spark报错 从spark1.4以后,所有spark的编译都是没有将hadoop的classpath编译进去的,所以必须在spark-env.sh中指定hadoop中的所有jar包 ...

  6. Linux 概念:u-boot

    U-Boot介绍 参考:https://baike.baidu.com/item/U-Boot/10377075 参考:https://u-boot.readthedocs.io/en/latest/ ...

  7. debian11编译安装freeswitch

    前言 环境: 系统版本:debian 11 x86_64 FreeSWITCH版本:1.10.6 安装步骤 安装依赖(安装之前最好换apt软件源为国内的) apt install -y gnupg2 ...

  8. VMware虚拟机的安装与配置

    一.VMware简介 VMware Workstation Pro 是业界标准的桌面 Hypervisor,用于在 Linux 或 Windows PC 上运行虚拟机. Workstation 16 ...

  9. Java 日志系列:JUL 使用和原理分析

    目录 一. 简介 二.使用 三.日志级别 四.Logger 继承关系 五.配置文件 六.原理解析 一. 简介 JUL 全称 Java util Logging 是 java 原生的日志框架,使用时不需 ...

  10. MIT6.s081/6.828 lectrue4:page tables 以及 Lab3 心得

    不管是计算机组成还是操作系统,虚拟内存都是其中的重要内容,所以这一节我会结合 CSAPP 第九章:虚拟内存 来一起复习(顺便一说,CSAPP 这一节的 lab 是要求设计一个内存分配器,也是很有意思的 ...