Unity Shader学习日记 part5 CG基础
在了解完Shader的基本结构之后,我们再来看看编写着色器的语言。
Shader编写语言有CG,HLSL两种,我们主要学习CG的写法。
数据类型
CG的基础变量类型
uint a=12;//无符号32位整形
int b=12;//32位整形float f=1.2f;//32位浮点型
half h=1.2h;//16位浮点型
fixed fix=1.2;//12位浮点型bool b=true;
string str="123";纹理对象句柄(理解为一个纹理就行)
sampler sam;sampler1D 用于一维纹理,通常用于对一维纹理进行采用,如从左到右的渐变色
sampler2D 用于二维纹理,最常见的纹理类型之一,用于处理二维图像纹理,比如贴图
sampler3D 用于三维纹理,通常用于体积纹理,如体积渲染
samplerCUBE 用于立方体纹理,通常用于处理环境映射登需要立方体贴图的情况
samplerRECT 用于处理矩形纹理,通常用于一些非标准的纹理映射需求他们都是用来处理纹理(Texture)数据的数据类型
注意区别在意纹理的类型和维度
可以看到,基本上和C#差不多,除此之外多了纹理对象句柄的类型。
CG的复合变量类型
复合类型也和C#差不多,数组,结构体
基础复合数据类型
数组:和C#差不多
int c[4]={1,2,3,4};
// a.length;int d[2][3]={{1,2,3},{4,5,6}};
//d.length 行
//d[0].length 列//结构体
//没有访问修饰
//申明结束加分号
//一般在函数外部申明
注意结构体的写法

CG的特殊变量类型
学了这么多知识点,其中矩阵和向量占了很大一部分,同样,CG中也为我们提供了矩阵的变量以及向量相关的变量。
这些变量的类型都是基于基本数据类型的,无非就是在基本数据类型的后面加一些数字之类的
//向量:CG语言内置的数据类型
//内置的向量类型是基于基础数据类型申明的,最大不超过4维,可以是任意数值类型
//数据类型n=数据类型(a1,...,an);fixed2 f2=fixed2(1.3,1.5);
fixed3 f3=fixed3(2,3,4);//矩阵(行列不大于4不小于1)
//数据类型 'n'x'm'={n1m1,n1m2...}
int2x3 mytest={1,2,3,3,4,6};
int4x4 test1={1,2,3,4,5,6,7,8,4,5,6,7,1,2,2,3};
其他类型的向量和矩阵我就不举例了,类似一下,大差不差。
了解了这些之后,我们再来看看一些类型的特殊用法
Bool的特殊用法
之前我们提到特殊变量类型是基于基本类型的,所以,bool类型同样能够用在特殊类型中
//bool类型同样可以用于向量的申明
//它可以用于储存一些逻辑判断结果
//比如
//float3 fa=float3(0.5,0.0,1.0);
//float3 fb=float3(0.6,-0.1,0.9;
//bool3 bc=a<b;
//结果为 boool3(true,false,false)
学习了数据类型之后,我们思考,矩阵和向量使用如此的频繁,那我我们怎么去获取这些变量中的分量值呢?这就需要Swizzle操作符
Swizzle操作符
Swizzle使用点号(.)来表示,使用就和我们去使用类的成员一样。
但是,Swizzle操作符的作用远不止这一点,我们来看看
//如:向量.xyzw,向量.rgba来获取其中的值
//使用:1。用来提取分量,2.用来重新排列分量 3.创建新的分量1.用来提取分量
fixed4 f4=fixed4(1,2,3,4);
fixed f=f4.w;
f=f4.r;2.用来重新排列分量
f4=f4.wyzx;
f4=f4.gbar;3.创建新的分量
//fixed3 f3=f4.xyz;
//fixed2 f2=f4.rg;
fixed4 f4_1=fixed4(f2,1,2);//低维创建高维,补充元素即可
我们发现,矩阵中的数据其实就是基本数据类型,那我们能不能用向量来表示呢?
向量和矩阵的特殊用法
其实向量和矩阵是可以相互使用的,就像这样
//向量和矩阵的更多用法
//1.利用向量声明矩阵
fixed4x4 f44={fixed4(1,2,3,4),fixed4(2,3,4,5),fixed4(4,5,6,7),fixed4(5,6,7,8)};
//2.获取矩阵中的元素
f=f44[0][0];//一行一列
//3.利用向量获取矩阵的某一行
f4_1=f44[0];
//4.高维转低维
fixed3x3 f33=f44;//自动取值
fixed3 f5=f;
注意的是,如果使用低维转高维,需要将欠缺的维度补齐
那么,我们再来了解了解运算表达式吧
语法相关
基本运算和流程控制
比较运算符(和C#一样的)条件运算符(三元运算符,用法和C#一样)逻辑运算符(和C#一样,不过CG中不存在“短路”)短路:在比较的过程中,如果一边满足则不会继续比较属性运算符(和C#一样,不过%取余只能整数取余)流程控制(和C#一样)条件分支(if,switch)循环(for,while,do while)注意:虽然用法和C#一样,但是在使用的时候更多考虑性能的消耗1.尽量少的使用循环,必要情况可以减少次数和复杂度2.可以利用GPU并行性来代替循环3.尽量避免复杂的条件分支
这一部分和C#没什么区别,唯一需要注意的是逻辑运算符短路的问题。
函数相关
这一部分也和C#一样,我就不多说了
函数相关函数的申明和用法几乎和C#中一模一样无返回值结构void name(in 参数类型 参数名,out 参数类型 参数名){函数体}name:函数名,CG中一般小写in:表示输入参数,外部传递过来的值,内部不会做更改,只会用来计算,允许有多个out:表示输出参数,由内部向外传递,函数内部必须进行初始化或者修改,允许有多个in,out可以不写,这样就可以避免in,out的特性,不过为了可读性和可维护性,建议写上void test_01(in fixed inf,out fixed outf){outf=inf+10;}
至此,CG的基本内容就结束了,接下来我们看看CG的编写
CG编写
在此之前我们先来看看CG的结构
可以看到顶点片元着色器的结构和表面光照着色器的结构是不同的,不过他们都是使用CG代码段的方式来编写,所以我们在编写CG代码时同样要将代码放在CGPROGRAM和ENDCG之间。
在CG中最重要的就是顶点回调函数以及片元回调函数了,这也是渲染代码存放的位置
顶点/片元函数
//顶点着色器回调函数//编译指令#pragma vertex myVert//处理顶点相关#pragma fragment myFra//处理颜色相关//POSITION,SV_POSITION,语义,用来表面参数的含义//POSITION:把模型的顶点坐标填充到输入的参数v中//SV_POSITION:输出的内容是裁剪空间中的顶点坐标float4 myVert(float4 v:POSITION):SV_POSITION{//mul是CG提供的内部函数,矩阵和向量的乘法//UNITY_MATRIX_MVP,代表一个变换矩阵,是UNITY的内置模型,观察,投影矩阵的集合//return mul(UNITY_MATRIX_MVP,v);return UnityObjectToClipPos(v*2);//和上一个等价,新的写法}//片源着色器回调函数//SV_Target:告诉着色器,把输出的颜色存储到一个渲染目标中,这里输出到默认的帧缓存中fixed4 myFra():SV_Target{return fixed4(1,0,0,1);}
可以看到最主要的部分就是申明编译指令

这个步骤决定了函数的名字以及调用。除此之外,我们可以看到,在函数的后面或者参数中还有一些代码,这一部分叫语义,它定义了参数的含义,就像POSITION:把模型的顶点坐标填充到输入的参数v中,这部分后面再说。
![]()
那么如何在函数中使用我们定义的变量呢?
非常简单,只需要申明一个同名变量即可,不过需要注意类型的对应
函数中使用自定义的变量
ShaderLab的属性和CG变量类型的对应ShaderLab CG类型Color,Vector float4,half4,fixed4Range,Float,Int float,half,fixed2D sampler2DCube samplerCube3D sampler3D2DArray sampler2DArray使用是在CG中声明对应类型的同名变量即可
语义
在上面我们基本了解了语义的基本用法。我们再来看看。
语义:修饰输入和输出参数,让shader知道从哪里读取数据,并且把数据输出到哪里
语义是什么不重要,重要的是我们需要了解的语义有哪些
应用阶段-->顶点着色器
常用语义应用阶段-->顶点着色器一般在顶点着色器回调函数的传入中使用POSITION:模型空间的顶点位置,通常为float4类型NORMAL:顶点法线,通常为float3类型TANGENT:顶点切线,通常为float4类型TEXCOORDn:例如:TEXCOOORD0,TEXCOORD1....该顶点的纹理坐标,通常为float2或者float4类型n 表示第n+1组纹理坐标,TEXCOOORD0 第一组纹理坐标纹理坐标:UV坐标,表示这个顶点在对于纹理图像上的位置COLOR:顶点颜色,通常为fixed4或者float4类型
顶点着色器-->片元着色器
顶点着色器-->片元着色器一般在顶点着色器的返回值中使用SV_POSITION:(必须)裁剪空间中的顶点坐标COLOR0:通常用来输出第一组的顶点颜色COLOR1通常用来输出第二组颜色TEXCOORD0--TEXCOORD7通常用于输出纹理坐标
片元着色器输出
片元着色器输出一般在片元着色器的返回值中使用SV_Target:输出的值会存档渲染目标中如果顶点着色器和片元着色器需要更多的参数,可以通过定义结构体的方式,对参数进行封装传递
东西非常多,可以再使用中慢慢熟悉
我们想一下,这么多东西,那么再我们使用的时候必然会相当的麻烦,所以CG也内置了很多的函数,我们来看看
CG内置函数
数学相关
//1.三角函数相关sincos(floatx,out s,out c) 同时计算x的sin和cos值并返回sin(x) 正弦函数cos(x) 余弦函数tan(x) 正切函数sinh(x) 双曲正弦函数cosh(x) 双曲余弦函数tanh(x) 双曲正切函数asin(x) 反正弦函数,输入参数[-1,1],返回[-pai/2,pai/2]区间的角度值acos(x) 反余弦函数,输入参数[-1,1],返回[0,pai]区间的角度值atan(x) 反正切函数,输入参数[-1,1],返回[-pai/2,pai/2]区间的角度值atan2(x) 计算y/x的反正切值,和atan功能一样,只是输入参数不同 atan(x)=atan2(x,1)
//2.向量,矩阵相关cross(A,B) 叉乘(传入必须为三维向量)dot(A,B) 点乘(三维向量)mul(M,N) 计算两个矩阵相乘 mul(M,V) 计算矩阵和向量的相乘mul(v,m) 计算向量和矩阵的相乘transpose(M) M为矩阵,计算M的转置矩阵determinant(m) 计算矩阵的行列式因子
//3.数值相关abs(x)ceil(x) 向上取整floor(x) 向下取整clamp(x,a,b)等等//4.其他lit(NdotL,NdotH,m) N表示法向量,L表示入射光向量,H表示半角向量,m表示高光系数这个函数计算环境光,散射光,镜面光的 贡献,返回4维向量x表示环境光贡献,y表示散射光贡献,z表示镜面光贡献,w始终为1noise(x) 噪声函数,返回值始终在0-1之间,对于相同的输入,始终返回相同值,不是真正的随机噪声
几何相关
//几何相关length(v) 向量模长normalize(v) 归一化向量 distance(p1,p2) 两个点的距离reflect(I,N) 计算反射光的方向向量,I为入射光,N为顶点法向量。I是指向顶点的,I和N必须归一化的三维向量refract(I,N,eta) 计算折射向量,I为入射,N为顶点法向量,eta为折射系数。I是指向顶点的,I和N必须归一化的三维向量
纹理相关
//纹理相关返回值均为fixed4类型的颜色值1.二维纹理tex2D(sampler2D tex,flota2 s) 二维纹理查询等等2.立方体纹理3.其他纹理
CG内置文件
CG内置文件unity中的常用内置1.UnityCG.cginc2.Lighting.cginc3.UnityShaderVariables.cginc4.HLSLSupport.cginc等等
这些内置文件为我们提供了很多的方法,需要使用时通过#include 的方式引用即可。
来看看这些文件中常用的东西吧
//常用内容方法(UnityCG.cginc)1.float3 WorldSpaceViewDir(float4 v)输入模型空间的顶点位置,返回世界空间中从该点到摄像机的观察方向2.float3 ObjSpaceViewDir(float4 v)输入模型空间的顶点位置,返回模型空间中该点到摄像机的观察方向3.float3 WorldSpaceLightDir(float4 v)仅用于向前渲染,输入一个模型空间的顶点位置,返回世界空间中从该店到光源的光照方向(没有归一化)4.float3 ObjSpaceLightDir(float4 v)仅用于向前渲染,输入一个模型空间的顶点位置,返回模型空间中从该店到光源的光照方向(没有归一化)5.float3 UnityObjectToWorldNormal(float3 norm)把法线方向从模型空间转到世界空间中6.float3 UnityObjectToWorldDir(float3 dir)把方向矢量从模型空间转到世界空间中7.float3 UnityWorldToObjectDir(float3 dir)把方向矢量从世界空间转到模型空间中结构体(UnityCG.cginc)1.appdata_base(顶点着色器输入)顶点位置,顶点法线,第一组纹理坐标2.appdata_tan(顶点着色器输入)顶点位置,顶点法线,顶点切线,第一组纹理坐标3.appdata_img(顶点着色器输入)顶点位置,第一组纹理坐标4.appdata_full(顶点着色器输入)顶点位置,顶点法线,顶点切线,四组(或者更多)纹理坐标5.appdata_img(顶点着色器输输出)裁剪空间中的位置,纹理坐标等等变换宏矩阵等等
东西有很多,我只举例部分,感兴趣的可以到HSLS的官网查看,这部分CG与HSLS差不多。
内部函数 - Win32 apps | Microsoft Learn
具体的用法会在之后的编写中用到,这里留个印象即可。
那么到这里,CG的基础就完结啦,后面部分我们会学习到基本的光照模型,到时候我们在通过使用的方式来认识他们。
相关文章:
Unity Shader学习日记 part5 CG基础
在了解完Shader的基本结构之后,我们再来看看编写着色器的语言。 Shader编写语言有CG,HLSL两种,我们主要学习CG的写法。 数据类型 CG的基础变量类型 uint a12;//无符号32位整形 int b12;//32位整形float f1.2f;//32位浮点型 half h1.2h;//…...
第7章:Python TDD测试Franc对象乘法功能
写在前面 这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许…...
两级式三相光伏并网逆变器Matlab/Simulink仿真模型
忘记更新最经典的光伏并网仿真模型了,作为包含经典的MPPT和并网恒功率因素的双闭环控制模型,也是很多相关专业学生的入门研究内容,光伏并网模型三相的和单相都有。 其中三相光伏并网逆变器有大功率和小功率的两种,之前早在硕士期…...
redis性能优化参考——筑梦之路
基准性能测试 redis响应延迟耗时多长判定为慢? 比如机器硬件配置比较差,响应延迟10毫秒,就认为是慢,机器硬件配置比较高,响应延迟0.5毫秒,就认为是慢。这个没有固定的标准,只有了解了你的 Red…...
Ubuntu 22.04 TLS 忘记root密码,重启修改的解决办法
1.想办法进入这个界面,我这里是BIOS引导的是按Esc按一下就行,UEFI的貌似是按Shift不得而知,没操作过。下移到Advanced options for Ubuntu,按enter 2.根据使用的内核版本,选择带「recovery mode」字样的内核版本&#…...
HTML<bdo>标签
例子 指定文本方向: <bdo dir"rtl"> This text will go right-to-left. </bdo> <!DOCTYPE html> <html> <body> <h1>The bdo element</h1> <p>This paragraph will go left-to-right.</p> …...
STM32+W5500+以太网应用开发+003_TCP服务器添加OLED(u8g2)显示状态
STM32W5500以太网应用开发003_TCP服务器添加OLED(u8g2)显示状态 实验效果3-TCP服务器OLED1 拷贝显示驱动代码1.1 拷贝源代码1.2 将源代码添加到工程1.3 修改代码优化等级1.4 添加头文件路径1.5 修改STM32CubeMX工程 2 修改源代码2.1 添加头文件2.2 main函…...
【机器学习实战中阶】使用SARIMAX,ARIMA预测比特币价格,时间序列预测
数据集说明 比特币价格预测(轻量级CSV)关于数据集 致谢 这些数据来自CoinMarketCap,并且可以免费使用该数据。 https://coinmarketcap.com/ 数据集:链接: 价格预测器 源代码与数据集 算法说明 SARIMAX(Seasonal AutoRegressive …...
各语言镜像配置汇总
镜像配置汇总 Nodejs [ npm ]Python [ pip ] Nodejs [ npm ] // # 记录日期:2025-01-20// 查询当前使用的镜像 npm get registry// 设置淘宝镜像 npm config set registry https://registry.npmmirror.com/// 恢复为官方镜像 npm config set registry https://regi…...
细说STM32F407单片机电源低功耗StopMode模式及应用示例
目录 一、停止模式基础知识 1、进入停止模式 2、停止模式的状态 3、退出停止模式 4、SysTick定时器的影响 二、停止模式应用示例 1、示例功能和CubeMX项目配置 (1)时钟 (2)RTC (3)ADC1 …...
PHP语言的循环实现
PHP语言的循环实现详解 在当今的编程世界中,循环是一种不可或缺的基本构造,它使得我们能够重复执行某些操作,极大地提高了代码的复用性和可读性。在PHP语言中,循环的种类以及使用方式繁多,本文将全面探讨PHP中的循环实…...
求两个矩阵的乘积
求两个矩阵的乘积 分数 15 全屏浏览 切换布局 作者 C课程组-hwr-zy 单位 浙江大学 输入三个正整数m,l,n(0<m,n,l<10),再输入两个的矩阵a(mxl)和b(lxn)。要求把a和…...
警惕IDEA 2024版重大Bug问题:LomBok失效、Gradle冲突、Spring Boot启动错误
一直以来我认为工具类的软件是越新越好,因为工具代表着一定的先进性;但是IDEA 2024好好的给我上了一课,比如lombok 不起作用、比如Spring Boot 3.4.x 启动报错、再比如MyBatis log plus冲突、再比如Gradle插件冲突. 一、Lombok 失效问题 请不…...
Go语言的正则表达式
Go语言的正则表达式:深度解析与应用实例 引言 正则表达式(Regular Expression,简称 regex)是一种用于匹配字符串的强大工具,广泛应用于文本处理、数据验证、解析和提取等场景。Go语言作为一种现代编程语言࿰…...
通过ssh连接debian
使用方法 ssh usernameipaddress [inputpasswd]root用户默认无法由ssh连接, 可以通过修改配置 sudo vim /etc/ssh/sshd_config去掉PermitRootLogin前的‘#’,并修改为 PermitRootLogin yes 重启sshd服务 sudo systemctl restart sshd参考 https://linuxconfig.or…...
计算机创造的奇迹——C语言
一.简介 C语言是一种较早的程序设计语言,诞生于1972年的贝尔实验室。1972 年,Dennis Ritchie 设计了C语言,它继承了B语言的许多思想,并加入了数据类型的概念及其他特性。 尽管C 语言是与 UNIX 操作系统一起被开发出来的ÿ…...
磁盘阵列服务器和普通服务器的区别
磁盘阵列服务器(RAID Server)和普通服务器在多个方面存在显著区别。以下是它们的主要区别: 1. 存储架构 磁盘阵列服务器 RAID 技术:使用 RAID(冗余独立磁盘阵列)技术,将多个硬盘组合成一个逻…...
搭建一个人脸识别pipeline
文章目录 概要入门所需设置你的开发环境人脸识别的工作原理数据加载和预处理建立你的人脸识别模型评估你的模型总结概要 人脸识别已发展成为一项关键技术,现已嵌入从安全系统到社交媒体平台等各个领域。在本文中,我们将逐步指导您在短短 30 分钟内使用 Python 和机器学习创建…...
Docker 之mysql从头开始——Docker下mysql安装、启动、配置、进入容器执行(查询)sql
一、Docker 之mysql安装配置 步骤一:拉取镜像 1. 查看是否包含已安装的mysql。 docker images | grep mysql 2. 如上图所示,我们有mysql镜像,所以不必对mysql镜像进行拉取,如若没有上图中的惊喜,使用如下命令进行拉取…...
LeetCodeHOT100:60. n个骰子的点数、4. 寻找两个正序数组的中位数
LeetCodeHOT100: 剑指 Offer 60. n个骰子的点数4. 寻找两个正序数组的中位数96. 不同的二叉搜索树 剑指 Offer 60. n个骰子的点数 题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
对象回调初步研究
_OBJECT_TYPE结构分析 在介绍什么是对象回调前,首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例,用_OBJECT_TYPE这个结构来解析它,0x80处就是今天要介绍的回调链表,但是先不着急,先把目光…...
RabbitMQ 各类交换机
为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息:将消息…...
