1、引言
这一篇我们我们来了解下流程控制语句,在CG语言中支持条件语句和循环语句。
- if…else 条件语句
- while 循环
- do … while 循环
- for 循环
需要注意的是早期版本Cg不支持switch…case语句,但是保留了这些关键字!但是经过验证我这里是支持的,大家自行验证自己的情况!
2、示例
下面我们来通过一个例子来了解各个语句的用法!我们这里同样是新建一个场景,创建一个材质球和一个立方体,然后创建一个shader命名为NewSurfaceShaderTest2,把材质球应用到这个立方体上,选择前面的新建的shader。
2.1、验证switch…case条件语句
语法:
switch(条件变量)
{
case 条件1:
[语句块]
break;
case 条件2:
[语句块]
break;
...
default:
[语句块]
break;
}
示例如下:
Shader "lxt610/NewSurfaceShaderTest2" {
SubShader
{
Pass
{
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
void vert(in float2 objPos:POSITION,out float4 pos:POSITION,out float4 col:COLOR0)
{
pos = float4(objPos,0,1);
col = pos;
}
void frag(inout float4 col:COLOR0)
{
col = float4(1,1,0,1);
//关于switch case验证
int i = 3;
switch(i)
{
case 0:
col = float4(1,0,0,1);//红色
break;
case 1:
col = float4(0,1,0,1);//绿色
break;
case 2:
col = float4(0,0,1,1);//蓝色
break;
case 3:
col = float4(1,0,0.5,1);
break;
case 4:
col = float4(1,0.5,1,1);
break;
default:
col = float4(1,1,1,1);//白色
break;
}
}
ENDCG
}
}
}
这里修改i的值使其进入相应的条件,发现颜色发生了相应的变化并没有进入default条件中,这说明现在的Cg支持了这个语句!或者说至少我这里是支持的,我这里使用的是unity2017.4.27f1,shader model 3.0是支持的!大家可以看看自己的情况!
2.2、if…else条件语句
if…else条件语句的语法为:
if(条件语句)
{
//语句块1
}
elseif(条件语句)
{
//语句块2
}
...
else
{
//语句块
}
示例如下:
Shader "lxt610/NewSurfaceShaderTest2" {
SubShader
{
Pass
{
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
void vert(in float2 objPos:POSITION,out float4 col:COLOR0,out float4 pos:POSITION)
{
pos = float4(objPos,0,1);
if(pos.x < 0)
{
col = float4(1,0,0,1);//红色
}
else
{
col = float4(0,1,0,1);//绿色
}
//col = pos;
}
void frag(inout float4 col:COLOR0)
{
}
ENDCG
}
}
}
回到unity中编译通过我们我们发现,左边变成了红色,右边成了绿色,中间是一个过渡区域。这是因为在摄像机的剪裁空间cvv中坐标范围是(-1,1),而物体的模型坐标处于(-0.5,0.5)之间(左下角(-0.5,-0.5),右上角(0.5,0.5)),所以物体的左边就变成了红色,右边就成了绿色。而中间的部分我们发现是一个缓慢的融合过程区域!这是由于顶点的颜色处理过后,还有大量的像素没有处理这时在光栅化阶段就是片元函数处理的过程中做了一个差值的运算。
此时我们修改功能,代码和效果如下:
Shader "lxt610/NewSurfaceShaderTest2" {
SubShader
{
Pass
{
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
void vert(in float2 objPos:POSITION,out float4 col:COLOR0,out float4 pos:POSITION)
{
pos = float4(objPos,0,1);
if(pos.x < 0 && pos.y < 0)
{
col = float4(1,0,0,1);//红色
}
else if(pos.x < 0)
{
col = float4(0,1,0,1);//绿色
}
else if(pos.y > 0)
{
col = float4(1,1,0,1);//黄色
}
else
{
col = float4(0,0,1,1);//蓝色
}
//col = pos;
}
void frag(inout float4 col:COLOR0)
{
}
ENDCG
}
}
}
我们也可以嵌套多个条件语句,执行更复杂的操作,这里就不再演示了!
2.3、while循环语句
while语句的语法格式:
while(条件语句)//满足条件执行,否则退出循坏(先判断,再执行))
{
语句块;
}
下面是一个示例,代码和效果如下:
Shader "lxt610/NewSurfaceShaderTest2" {
SubShader
{
Pass
{
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
void vert(in float2 objPos:POSITION,out float4 col:COLOR0,out float4 pos:POSITION)
{
pos = float4(objPos,0,1);
if(pos.x < 0 && pos.y < 0)
{
col = float4(1,0,0,1);//红色
}
else if(pos.x < 0)
{
col = float4(0,1,0,1);//绿色
}
else if(pos.y > 0)
{
col = float4(1,1,0,1);//黄色
}
else
{
col = float4(0,0,1,1);//蓝色
}
//col = pos;
}
void frag(inout float4 col:COLOR0)
{
int i = 0;
while(i < 10)
{
i++;
}
if(i == 10)
col = float4(0,0,0,1);
}
ENDCG
}
}
}
这里为了方便演示我们只是循环了十次,由于没有控制台输出这里为了方便观察,结束循环后颜色设为黑色(float4(0,0,0,1))!这说明循环执行了10次!
2.4、do…while循环语句
while语句的语法格式:
{
语句块;
}
while(条件语句);//满足条件执行,否则退出循坏(先执行一次,再判断)
下面是一个示例,代码和效果如下:
Shader "lxt610/NewSurfaceShaderTest2" {
SubShader
{
Pass
{
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
void vert(in float2 objPos:POSITION,out float4 col:COLOR0,out float4 pos:POSITION)
{
pos = float4(objPos,0,1);
if(pos.x < 0 && pos.y < 0)
{
col = float4(1,0,0,1);//红色
}
else if(pos.x < 0)
{
col = float4(0,1,0,1);//绿色
}
else if(pos.y > 0)
{
col = float4(1,1,0,1);//黄色
}
else
{
col = float4(0,0,1,1);//蓝色
}
//col = pos;
}
void frag(inout float4 col:COLOR0)
{
int i = 0;
while(i < 10)
{
i++;
}
if(i == 10)
col = float4(0,0,0,1);
i = 0;
do{
i++;
}
while(i < 10);
if(i == 10)
col = float4(1,1,1,1);
}
ENDCG
}
}
}
这里为了方便演示我们只是循环了十次,由于没有控制台输出这里为了方便观察,结束循环后颜色设为白色(float4(1,1,1,1))!这说明循环执行了10次退出,然后设为了白色!
2.5、for循环
for循环的语法:
for(int i = 0; i < 10; i++)(初始值,条件1,语句2)
{
语句块;
}
下面是一个示例,代码和效果如下:
Shader "lxt610/NewSurfaceShaderTest2" {
SubShader
{
Pass
{
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
void vert(in float2 objPos:POSITION,out float4 col:COLOR0,out float4 pos:POSITION)
{
pos = float4(objPos,0,1);
if(pos.x < 0 && pos.y < 0)
{
col = float4(1,0,0,1);//红色
}
else if(pos.x < 0)
{
col = float4(0,1,0,1);//绿色
}
else if(pos.y > 0)
{
col = float4(1,1,0,1);//黄色
}
else
{
col = float4(0,0,1,1);//蓝色
}
//col = pos;
}
void frag(inout float4 col:COLOR0)
{
for(int i = 0; i < 10; i++)
{
}
if(i == 10)
col = float4(0.5,0.5,0,1);
}
ENDCG
}
}
}
观察发现变为暗黄色,说明执行了条件语句中的内容,说明了能够正常跳出循环!
值得注意的是for循环的次数有些版本是有限制的,超过了1024就会报运行异常,有的则不会根据实际情况测试!
3、结束语
The End
好了,今天的分享就到这里,如有不足之处,还望大家及时指正,随时欢迎探讨交流!!!
喜欢的朋友们,请帮顶、点赞、评论!您的肯定是我写作的不竭动力!