【转】Shader学习之九(CG语言基础)

CG语言基础

一、Cg语言的特性:
Cg是一种类C的语言,他沿用了大量的C语言特性,但是也有不同之处。Cg语言是脚本性语言,不能编译,调试和断点;并且Cg语言的主要用途是绘制像素颜色到屏幕上,他不能处理文字类的内容。Cg语言对单精度浮点的数据类型是非常敏感的;Cg语言因为GPU的并发特性所以导致Cg语言的所有执行过程是并发式的;
二、Cg语言的语法特性:
1.基本数据类型:
float:32位浮点数据

float _Specular = 1.0

half:16位浮点数据

half _Specular = 1.0

Int:32位整形数据

int _Specular = 1

fixed:12位浮点数据

fixed _Specular = 1.0

bool:布尔数据,用于判断if和条件操作符

if(logocolor.a == 0)
{
colors = finalColor.rgb;
} else {
colors = diffuses.rgb;
}

Sampler,纹理对象的句柄,6类:
Sampler,sampler1D,sampler2D,sampler3D,samplerCUBE和samplerRECT

sampler2D _Diffuse;

2、特殊的数据类型:
向量:一共拥有4种纬度的向量,1 - 4之间,不得低于1不得高于4;
例如:float3 a; half4 h; fixed2 m; int1 d;
向量初始化或赋值:float4 a = float4(1,2,3,4); float3 b; b = float3(0,2,3);
注意:对于向量的赋值和初始化,我们必须保证值向量的纬度一定要和变量向量的维度相等,在添值的过程中要保证所添值的数量不得多也不得少;
矩阵:矩阵的行和列都最大不得大于4维,最小不得小于1位;
例如:

float2x4 a;// 表示这是一个2行4列的矩阵; half3x3 m;// 表示是一个3 X 3的方阵;

矩阵赋值和初始化 float2x2 rtX = {sin@, 0, 0, cos@};// 注意,矩阵在赋值的时候一定要人为的分开行与行之间的关系,但是程序只认识顺序的赋值;
注意:CG中向量,矩阵和数组是完全不同的,向量和矩阵是内置的数据类型,而数组则是一种数据结构,不是内置数据类型。
3、数组:
因为Cg是显卡操作语言,他没有相应的内存,所以对于Cg语言来讲就不可能存在空间申请,那么Cg的数组就必须在定义的时候指定大小,除非数组出现在函数的行参当中,我们可以不指定数组大小;
一维数组: 类型(数据类型,向量,矩阵类型) 数组名[数组的个数];
二维数组: 类型(数据类型,向量,矩阵类型) 数组名[数组的行数][数组的列数];
数组的赋值:float a[2] = {1, 2}; float a[2][2] = PW_1,2}, {3, 4;
一维数组的赋值一定要和矩阵分开,他们不是同一种关系;
数组可以获取长度;

float2 b[2];
int arrayLen = b.length; // 结果2
float m[3][4];
arrayLen = m.length;// 结果是3;
arrayLen = m[1].length;// 结果是4;

4、结构体:
结构体是一种自定义数据类型,他可以把所有的数据类型进行集合式的包装,起到了数据封装的作用;
结构体中可以定义任意类型的变量,变量在定义的时候可以同时初始化。与高级语言不通,Cg没有修饰词,所以struct中的所有变量和函数都是公共的;

struct appdata_full
{ float normal:NORMAL; };

5.CG表达式与控制语句
关系操作符:<,>,<=,>=,!=,==,

if(logocolor.a == 0)

逻辑操作符:&&,||,!
数学操作符:+,—,*,/,%
移位操作符:>>
Swizzle操作符:float a=1.0,float4 b = a.xxxx;这种用法我们有时候会用到
控制流语句:if ,if-else while ,for,break
6、点操作符:
点操作符只能针对Cg的:向量和结构体;
向量点操作:
对于向量他可以按照坐标顺序和色彩顺序访问向量中的每个元素: xyzw, rgba;
注意:他和向量的维度有关,绝对不能超过向量的维度进行访问;

float2 a = float2(1,2); float3 b = a.xyx; float4 m = a.yyyy; float3 m1 = a.xyz;// 这是错误的!因为超出了维度的访问范围;

结构的点操作:

v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

和普通编译语言是一样的;
7、行参修饰词:
in: 表示当前行参是只能输入的;
out:表示当前行参用来输出数据的;
inout: 表示可以进行输入和输出;
8、离散数据图元信息:
这些离散的图元信息是引擎向着色器下达的数据通知内容,比如纹理贴图这样的大数据;
离散图元变量的关键字 : uniform;
特性:
(1)只读性,只要标有uniform标签的变量,这个变量我们就不能初始化也不能修改其内容;
(2)使用范围特性,只能存在于入口函数的行参上或者是全局的变量身上;
(3)他只能支持引擎向着色器传入的数据,不能向外提交数据;
9、语义:
为了表达当前变量是指定的数据范围,我们提出语义的概念。语义可以作为输入也可以作为输出。语义的定义只能存在于入口函数的行参和返回值上。
常用的语义:
POSITION : 表示当前这个变量表示的是坐标,我们需要使用float4向量来作为变量的类型;
COLOR: 表示当前这个变量是颜色表示,我们需要使用float4/ half4 / fixed4 来表示颜色信息;
NORMAL: 表示当前这个变量是法线坐标,因为法线描述的是一个点的特性,所以他没有坐标系关系,那么我们就可以使用float3向量;
TEXCOORD0 – TEXCOORD7: 这样的语义可以表示任意的数据类型,但是我们经常使用 TEXCOORD0来表示贴图UV坐标用float4向量;
TANGENT:表示顶点角的正切值,用float3传递;
语义的输入性和输出性,需要和行参中的修饰词结合表示,in 表示当前语义是输入,out 表示当前语义是输出型的,inout表示支持输入和输出;
语义的写法:
(1) 作为行参来实现: [in|out|inout] <数据类型> <行参名> [: <语义词>]
(2) 作为返回值来实现: <返回值类型不能是void> <入口函数名>([行参列表]) [: <语义词>] {}
(3) 作为结构体来实现:

float3 worldLightDir:TEXCOORD1;

(4) 作为全局非静态实现:<数据类型> <行参名> [: <语义词>];
10、Cg语言的入口函数:
因为Cg语言是一种特殊的显卡语言,他需要同时处理显卡的两个工作部分,一个是点的位置描述,另外一个是点的颜色值描述。所以Cg语言有两个入口函数,他们分别是:顶点程序、片段/片装源/像素程序;
其它的函数我们称为内部函数。
注意:Cg的入口函数没有特定的函数面,我们都是后期自己制定出来的,所以如果我们想让某个函数成为入口函数就一定要通知引擎这个函数的名字;
入口函数的特性:
(1)顶点入口函数:顶点入口函数是唯一可以和引擎沟通的函数,所以语义数据的传入都需要在顶点入口函数中完成。顶点入口函数必须履行向光栅硬件传递变换后的坐标,所以顶点入口函数必须有一个返回型的语义,而且必须是POSITION类型的语义。同时他可以向我们片段入口函数传递响应的数据。
(2)片段入口函数:片段程序的主要责任是给当前这个像素点设定颜色的,所以我们需要在片段程序中返回一个颜色语义,类型必须是COLOR,而且只能向外输出COLOR,因为他是最后一道程序,所以其他的语义抛出是无任何意义的。入口函数中传回来 POSITION, NORMAL, TANGENT等语义,片段程序不能读也不能写,对于COLOR0 – COLOR1 和 TEXCOORD0 – TEXCOORD7这样的语义片段程序可以读写;
三、Unity3D引擎中ShaderLab语言与Cg的结合
因为Cg属于可编程着色器程序,所以在SubShader必须用Pass过程块;
在着色器中,我们需要两个特定的命令夹住Cg语言,这样ShaderLab才认识你的Cg代码:
CGPROGRAM



ENDCG
因为Cg语言的入口函数没有特定,所以我们需要通知ShaderLab哪两个入口函数是我们的顶点和片段的入口函数。我们需要借助以下命令:
// 顶点入口函数的设定

pragma vertex 入口函数名

// 片段入口函数的设定

pragma fragment 入口函数名

注意:可编程着色器只要写了入口函数就一定要按照同样的名字来实现入口函数;
Cg语言也支持对于第三方的代码调用,如果需要调用第三方的代码,我们需要使用: #include “需要包含的代码文件.cginc” 这样的关键字;
对于Unity引擎,他为我们提供了两个cginc文件,方便了我们与引擎的沟通;
UnityCG.cginc :当前文件提供了Unity引擎中大部分的位置坐标和方向的内容;
Lighting.cginc:当前文件提供了Unity引擎中灯光的操作;
当我们Cg需要使用我们ShaderLab语言的属性时,我们必须借助 uniform这个关键字。需要注意,uniform变量的名字必须和我们属性的名字一模一样;
对于Cg语言来说,如果我们直接定义uniform变量,而不在我们的ShaderLab属性列表中定义,那么我们的Unity引擎同样也可以向这个变量传递数据。但是这个变量在我们的Inspector面中无法显示出来;
1.从应用程序传递到GPU的数据,分为图元信息数据(在GPU处理的基本数据如顶点位置信息等)和其他的离散数据(在GPU运行流程中不会发生变化,如材质对光的反射、折射信息),这两种输入数据如何区分?
Cg 语言提供了一组语义词,用以表明参数是由顶点的哪些数据初始化的,Uniform 修辞一个参数,表示该参数的值由外部应用程序初始化并传入

  1. 从应用程序传递到GPU中的图元信息如何区分类型,即,顶点程序怎么知道一个数据是位置数据,而不是法向量数据?
    语义词,表示输入图元的数据含义(是位置信息,还是法向量信息),也表明这些图元数据存放的硬件资源(寄存器或者纹理缓冲区)。顶点着色程序和片段着色程序中 Varying inputs 类型的输入,必须和一个语义词相绑定
    3.顶点着色程序与片段着色程序之间的数据传递如何进行?
    根据输入语义,图形处理器从某个寄存器取数据;然后再将处理好的数据,根据输出语义,放到指定的寄存器,语义,是两个处理阶段(顶点程序、片段程序)之间的输入\ 输出数据和寄存器之间的桥梁,同时语义通常也表示数据的含义,POSITION 一般表示参数种存放的数据是顶点位置
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 1 前言 一直想沿着图像处理这条线建立一套完整的理论知识体系,同时积累实际应用经验。因此有了从使用AVFounda...
    RichardJieChen阅读 5,641评论 5 12
  • 在OpenGL中,大量的数据在着色器中传递,数据通过Buffer和Texture两种形式组织。 1 缓存(Buff...
    RichardJieChen阅读 7,944评论 1 10
  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,422评论 3 44
  • <转>我也忘了转自哪里,抱歉,感谢原作者 什么是Shader Shader(着色器)是一段能够针对3D对象进行操作...
    星易乾川阅读 5,574评论 1 16
  • 感恩今天是农历的立冬,从今天起要进入冬季了,但是今天的气温却异常的温暖,感恩大自然的馈赠。 感恩先生的精进,这几天...
    武丹yoyo阅读 178评论 0 3