java 顶点着色_Shader笔记_002简单顶点/片元着色器扩展

参考<>第五章

一、如何获取其他模型数据

在001里介绍了通过POSITION获取顶点位置坐标,如果想的到更多的模型数据,比如我们想要得到模型上每个顶点的纹理坐标和法线方向

PS:我们可以通过纹理坐标来访问纹理 法线坐标一般用来计算光照

因此我们需要给顶点着色器定义一个新的参数·这个参数将不是一个简单的数据类型

而是一个结构体

Shader "Customer/SimpleShader003"{

SubShader{

Pass{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

struct a2v{

float4 vertex: POSITION;

float3 normal:NORMAL;

float4 texcoord:TEXCOORD0;

};

float4 vert(a2v v): SV_POSITION{

return mul(UNITY_MATRIX_MVP,v.vertex);

}

fixed4 frag(): SV_Target{

return fixed4(1.0,1.0,1.0,1.0);

}

ENDCG

}

}

}

在上面的代码中 声明的结构体a2v 他包含了顶点着色器需要的模型数据

在a2v的定义中,我们用到了更多的UNITY支持的语义,如

NORMAL 和TEXCOORD0,当他们作为顶点着色器的输入时都是有特定含义的

因为UNITY会根据这些语义来填充这个结构体,对于顶点着色器的输出,UNITY

支持的语义有POSITION,TANGENTM,NORMAL,TEXCOORD0,TEXCOORD1,TEXCOORD2

TEXCOORD3,COLOR等。

为了使用一个自定义的结构体,我们必须使用如下格式

struct name{

Type Name:Semantic;

Type Name:Semantic;

......

};

a表示应用 v表示顶点着色器 a2v的意义就是从应用阶段传递到顶点着色器中

那么填充到POSITION,TANGENT,NORMAL的语义里的数据酒究竟是从哪里来的呢?

在UNITY中,它们是由使用该材质的MeshRender组件提供的。

在每帧调用DRAW CALL的时候,MeshRender组件会把他负责渲染的模型的数据发送给UNITY SHADER,

我们知道,一个模型通常包含了一组三角面片。(我们不知道啊QAQ)

每个三角面片由三个顶点构成,而每个顶点又包含了一些数据,例如顶点位置、发现坐标、顶点颜色等等

通过上面的方法,我们就可以在顶点着色器中访问顶点的这些模型数据。

二、顶点、片元着色器之间如何相互通信

我们在实际开发的过程中,往往希望从顶点着色器输出一些数据,例如把模型的法线纹理坐标等传递给片元着色器

这就涉及到了顶点着色器和片元着色器之间的通信

为此我们需要新建一个结构体.修改后代码如下

Shader "Customer/SimpleShader004"{

SubShader{

Pass{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

struct a2v{

float4 vertex:POSITION;

float3 normal:NORMAL;

float4 texcoord:TEXCOORD0;

};

//使用一个结构体来定义顶点着色器的输出

struct v2f{

float4 pos :SV_POSITION;

fixed3 color:COLOR0;

};

v2f vert(a2v v):SV_POSITION{

v2f o;

o.pos = mul(UNITY_MATRIX_MVP,v.vertex);

o.color = v.normal*0.5 + fixed3(0.5,0.5,0.5);

return o;

}

fixed4 frag(v2f i):SV_Target{

return fixed4(i.color,1.0);

}

ENDCG

}

}

}

在上面的代码中,我们声明了一个新的结构体v2f

v2f中也需要指定每个变量的语义,在本例中我们定义了SV_POSITION和COLOR0,顶点着色器的输出结构中,必须包含SV_POSITION,否则无法获取

裁剪空间的顶点坐标,COLOR0则由用户自己定义,一般是用来存颜色,例如逐顶点的漫反射颜色等,类似语义还有COLOR1

至此我们完成了从顶点着色器往片元着色器传递数据,顶点着色器是逐顶点的,片元着色器是逐片元的,因此片元着色器的输入实际是把顶点着色器的输出进行插值的结果

二、如何使用属性

unityshader和材质密不可分,shader提供了一些可以设置的参数来调试材质的效果,这些参数需要写在properties语义块里面

比如我们现在有一个新的需求,需要在面板上显示一个颜色拾取器,为此需要修改上面的代码

Shader "Customer/SimpleShader004"{

Properties{

//声明一个color类型的属性

_Color("Color Tint",Color) = (1.0,1.0,1.0,1.0)

}

SubShader{

Pass{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

fixed4 _Color;

struct a2v{

float4 vertex:POSITION;

float3 normal:NORMAL;

float4 texcoord:TEXCOORD0;

};

struct v2f{

float4 pos:SV_POSITION;

float3 color:COLOR0;

};

v2f vert(a2v v) :SV_POSITION{

v2f o;

o.pos = mul(UNITY_MATRIX_MVP,v.vertex);

o.color = v.color*0.5+fixed3(0.5,0.5,0.5);

return o;

}

fixed4 frag(v2f i):SV_Target{

fixed3 = i.color;

c *=_Color.rgb;

return fixed4(c,1.0);

}

ENDCG

}

}

}

在上面的语句里我们定义了一个color,(1.0,1.0,1.0,1.0)代表的是白色

为了在CG代码里面访问他,我们还需要提前自己定义一个新变量 ,该变量名必须和属性里的变量名一致

ShaderLab中变量和CG类型中变量对应的关系如下所示

b63ce43f828134577a3a9a430486ce1d.png

有时 CG变量前会有一个 uniform 关键字

uniform fixed4 _Color; 该关键字在CG里是用来修饰变量,仅仅提供该变量初始值的是如何指定和存储的相关信息,UNITYSHADER里该关键字可以省略。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值