分享
 
 
 

着色器和效果——2.5 样例应用程序:卡通渲染(上)

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

2.5 样例应用程序:卡通渲染(上)

阅读此文表明您已同意文末的声明

作为第二个顶点着色器的例子,让我们编写两个顶点着色器,它们以卡通风格绘画的方式对网格着色(shade)和画轮廓(outline)。图17.2展示了这一点:

图 2.2:(a)使用卡通着色法着色的对象(注意着色间的尖锐过渡)。(b)增强卡通效果,轮廓边(silhouette edge)被勾出。(c)使用标准散射光照着色的对象

注意:卡通渲染是一种特定类型的非写实渲染(non-photorealistic rendering),有时被称作风格化渲染(stylistic rendering)。

虽然卡通渲染不适用于所有游戏,例如激烈的第一人称射击游戏,但是它仍然可以增强一些希望表现卡通感觉类型游戏的气氛。此外,卡通渲染相当易于实现,并让我们得以漂亮的演示顶点着色器。

我们将卡通渲染分割为两步:

1. 卡通绘图典型的很少有在两种着色间强烈过渡的着色强度(luminance)级别;我们称此为卡通着色(cartoon shading)。在图2.2(a)中,我们看到只用了三种着色强度(亮、中、暗)对网格进行着色,而且其间的过渡是不连贯的——不像图2.2(c),其明暗过渡是平滑的。

2. 卡通绘图也典型的有其轮廓边被勾出,如图2.2(b)所示。

这两个步骤都需要其各自的顶点着色器。

2.5.1 卡通着色

要实现卡通着色,我们采用Lander在2000年3月发表在Game Developer Magazine的文章“Shades of Disney: Opaquing a 3D World”中所描述的方法。它像这样工作:我们创建一个带强度级别的灰度纹理,它包含我们需要的不同的着色强度。图2.3显示了我们在样例程序中使用的这个纹理。

图 2.3:用来保存着色强度的着色纹理。注意观察不连续的着色间过渡和纹理着色强度必须从左到右增加。

然后在顶点着色器中,我们执行标准散射点积运算(standard diffuse calculation dot product)来确定顶点法线N和光线向量L之间角度的余弦,用以确定顶点接收到多少光线:

s=L·N

如果s<0,就表示光线向量和顶点法线之间的角度大于90度,也就表示该表面接收不到光线。因此,如果s<0,我们就让s=0。所以s ∈ [0, 1]。

现在,在通常的散射光照模型中,我们使用s来标记颜色向量,这样顶点颜色就根据接收到的光照的量变暗:

diffuseColor = s(r, g, b, a)

但是,这将会导致从亮到暗之间着色的平滑过渡。这是与我们期望的卡通着色相反的。我们想要一个(对卡通渲染在两至四种着色间工作良好的)在一些不同着色间的不连续的过渡。

反其道而行之,不使用s来标记颜色向量,我们准备使用s作为早先提到的强度纹理的u纹理坐标——如图2.3。

注意:标量(scalar)s必定是一个有效的纹理坐标,因为s ∈ [0, 1],这是通常纹理坐标的区间。

按这种方式,顶点不会被平滑着色,而是不连续的。例如,强度纹理可能被分成3种着色,如图2.4所示:

图 2.4:那么,s ∈ [0, 0.33]的值使用shader0着色,s ∈ [ 0.33,0.66]的值使用shader1着色,s ∈ [0.66,1]的值使用shader2着色。当然,从这些着色的一种到另一种的过渡是不连续的,这就赋予了我们期望的效果。

注意:我们还为卡通着色关闭了纹理过滤,因为这种过滤会试图使着色过渡变平滑。这对于我们要求的不连续过渡是多余的。

2.5.2 卡通着色的顶点着色器代码

我们现在呈现卡通着色的顶点着色器。这个着色器的主要任务只是根据s=L·N计算并设置纹理坐标。注意观察输出结构,我们已经增加了一个数据成员来存储已被计算过的纹理坐标。同时还需注意,我们仍然输出顶点颜色,虽然我们不修改它,不过当颜色被与强度纹理组合起来的时候,它呈现为被着色的。

// File: toon.txt

// Desc: Vertex shader that lights geometry so it appears to be

// drawn in a cartoon style.

//

// Globals

//

extern matrix WorldViewMatrix;

extern matrix WorldViewProjMatrix;

extern vector Color;

extern vector LightDirection;

static vector Black = {0.0f, 0.0f, 0.0f, 0.0f};

//

// Structures

//

struct VS_INPUT

{

vector position : POSITION;

vector normal : NORMAL;

};

struct VS_OUTPUT

{

vector position : POSITION;

float2 uvCoords : TEXCOORD;

vector diffuse : COLOR;

};

//

// Main

//

VS_OUTPUT Main(VS_INPUT input)

{

// zero out each member in output

VS_OUTPUT output = (VS_OUTPUT)0;

// transform vertex position to homogenous clip space

output.position = mul(input.position, WorldViewProjMatrix);

//

// Transform lights and normals to view space. Set w

// components to zero since we're transforming vectors.

// Assume there are no scalings in the world

// matrix as well.

//

LightDirection.w = 0.0f;

input.normal.w = 0.0f;

LightDirection = mul(LightDirection, WorldViewMatrix);

input.normal = mul(input.normal, WorldViewMatrix);

//

// Compute the 1D texture coordinate for toon rendering.

//

float u = dot(LightDirection, input.normal);

//

// Clamp to zero if u is negative because u

// negative implies the angle between the light

// and normal is greater than 90 degrees. And

// if that is true then the surface receives

// no light.

//

if(u < 0.0f)

u = 0.0f;

//

// Set other tex coord to middle.

//

float v = 0.5f;

output.uvCoords.x = u;

output.uvCoords.y = v;

// save color

output.diffuse = Color;

return output;

}

两点注解:

n 我们假设世界矩阵没有执行任何缩放。因为如果它执行,它就会弄乱乘以它的顶点的长度和方向。

n 我们总是设置v纹理坐标为纹理的中点。这意味着我们仅使用纹理中一条单一的线,那就是说我们可以使用1D强度纹理来代替2D的那个纹理。不管怎样,1D和2D纹理都能工作。本例中,我们使用了2D纹理而不是1D纹理,这是没有什么特别的原因的。

[声明]:本文译自Frank Luna的《Introduction to 3D Game Programming with DirectX 9.0》,限于译者水平,文中难免错漏之处,欢迎各位网友批评指正;本文仅用于学习交流与参考用途,不得用于任何形式的商业用途;如需转载需事先征得作者本人和译者的同意,保持文章的完整性,并注明作者、译者和出处,作者保留对译文的所有权利。对于违反以上条款造成的后果,译者对此不负任何责任。我的MSN是Raymond_King123@hotmail.com,欢迎热爱3D图形和游戏,并有一定图形编程经验的朋友与我进行交流。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有