查看: 1428|回复: 0
打印 上一主题 下一主题

[经验分享] Vertex Magic —— 访问顶点颜色

[复制链接]

100

主题

3

听众

7683

积分

高级设计师

Rank: 6Rank: 6

纳金币
2378
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2015-2-19 19:26:34 |只看该作者 |倒序浏览

[color=ize:24px]写在前面



啦啦啦~我又回来看书啦。文章开始说一些题外话。因为写博客和在群里比较活跃(为什么QQ给我的称谓是“吐槽”。。。我这么乖。。。),最近有一些朋友给我发邮件或者私信,很多人都给了我鼓励,我很开心,也有人给了我很好的学习建议,这些经历让我觉得坚持写博客是正确的一条路~也谢谢所有鼓励、支持和关注我的人!我会坚持下去的。



好啦,言归正传~这篇开始,我决定开始一个新的章节——Vertex Magic。顾名思义,就是学习顶点相关的内容。自从看了下面Unity Gems里面的一张图,我对整个Surface Shader的工作流程有了更好的理解,在此再重温一下。







可以看出来共有四个阶段我们可以参与。我们之前学习的大多是在上图的第二和第三个阶段,也就是编写surf和LightingXXX函数来影响表面着色和光照函数的。在卡通风格的Shader中,我们也对最后一个更改像素颜色的机会——finalcolor命令有了一个初步的尝试。而现在,我们将用一章的时间来学习如何利用第一个阶段——顶点函数来影响像素颜色。



顶点函数是在每个顶点被传送到GPU之前被调用一次。它的作用是从模型坐标系中得到三维坐标,然后再转换到其渲染到屏幕时在屏幕坐标系中的二维位置。因此,通过顶点函数,我们可以修改顶点的位置、颜色和UV坐标。一旦我们完成了对顶点的修改后,就会进入到surf函数的执行。与顶点函数是逐顶点执行的方式不同,surf函数则是逐像素执行的。



通过顶点函数,我们可以创造像海上的波浪、旗帜飘动的动态效果,或者使用Shader来给顶点着色。这一篇,我们来学习如何在一个Surface Shader中创建一个最简单的顶点函数!




[color=ize:24px]准备工作



在深入学习顶点函数之前,我们得首先了解如何通过顶点函数得到和存储顶点相关信息。




首先,我们要准备一个已经给顶点着色过的模型,以便我们可以在顶点函数中查看顶点颜色。为了方便,我们使用本书自带资源(见文章开头)中第七章的模型资源——VertexColorObject.fbx。我们把VertexColorObject.fbx导入Unity,并拖入到一个新的场景中。最后添加一个平行光。

新建一个Shader和Material,可以分别命名为SimpleVertexColor,并将Shader赋给Material,再将Material赋给模型。

你的场景应该看起来是这样的:













[color=ize:24px]实现



下面,我们开始编写Shader。




在Properties块中添加新的Properties:

Properties

{

_MainTint(“Global Color Tint”, Color) = (1,1,1,1)

}


接下来,告诉Unity我们将使用自己的顶点函数:

CGPROGRAM

#pragma surface surf Lambert vertex:vert


为Properties中新添加的属性添加对应的引用:

float4 _MainTint;


下面是很重要的Input结构。我们添加了一个新的变量vertColor以便surf函数可以访问vert函数中传递的数据:

struct Input

{

float2 uv_MainTex;

float4 vertColor;

};


下面是一个非常简单的vert函数。我们访问模型的顶点颜色,再存储到Input结构体中:

void vert(inout appdata_full v, out Input o)

{

o.vertColor = v.color;

}


最后,我们使用从Input中得到的数据填充SurfaceOutput结构体的Albedo参数:

void surf (Input IN, inout SurfaceOutput o)

{

o.Albedo = IN.vertColor.rgb * _MainTint.rgb;

}


完整代码如下:



Shader “Custom/SimpleVertexColor” {

Properties

{

_MainTint(“Global Color Tint”, Color) = (1,1,1,1)

}


SubShader

{

Tags { “RenderType”=”Opaque” }

LOD 200


CGPROGRAM

#pragma surface surf Lambert vertex:vert


float4 _MainTint;


struct Input

{

float2 uv_MainTex;

float4 vertColor;

};


void vert(inout appdata_full v, out Input o)

{

o.vertColor = v.color;

}


void surf (Input IN, inout SurfaceOutput o)

{

o.Albedo = IN.vertColor.rgb * _MainTint.rgb;

}

ENDCG

}

FallBack “Diffuse”

}

效果如下:




















解释







通过顶点函数,我们可以修改顶点的位置、颜色、UV坐标等值。在本节中我们使用了一个从maya导入的已给顶点着色的模型,但我们可以发现,在使用默认材质的情况下这些颜色在Unity中是不显示的。我们需要编写Shader,提取这些颜色再在模型上显示出来。





我们首先通过在#pragma声明中添加vertex:vert语句。这实际上告诉Unity,嘿,不要用你自己内置的顶点函数访问模型顶点信息啦,去我写的Shader里找一个名叫vert的家伙,用它去处理信息!如果Unity没有找到,它就会报一个编译错误。





vert函数里,除了我们熟悉的Input结构体,还有一个很特别的参数——appdata_full 。这个参数也是Unity内置的一个变量,它包含了模型顶点的所有信息,包括位置、切线、法线、两个纹理坐标和颜色信息。其他的还有appdata_base和appdata_tan,具体可以看见官网。





你还可以发现,vertColor是一个float4类型的变量,这意味着我们还可以访问它的透明通道。像下面这样:


void surf (Input IN, inout SurfaceOutput o)

{

o.Albedo = IN.vertColor.rgb * _MainTint.rgb;

o.Alpha = IN.vertColor.a;

}


分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-14 20:52 , Processed in 1.317964 second(s), 28 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部