谈谈Processing 3D世界 三

来源:互联网 发布:尼尔森数据分析报告ppt 编辑:程序博客网 时间:2024/04/29 04:51

有了前两节的知识,接下来咱们该做什么呢?丰富多边形?控制摄影机?这些先不急,我们不妨先来了解下纹理

(Texture)。有了这玩意,能极大的丰富我们绘制的对象。

纹理(Texture)

我们先来看看有关纹理的函数,很简单只有3

texture()        -载入纹理

textureMode()    -设置纹理坐标模式

textureWrap()    -设置纹理环绕模式


逐个来分析一下: 


texture() - 载入纹理


这个函数必须在beginShape()endShape()这对基友之间使用,它将一副图像载入到纹理中,并应用

到顶点。

 

范例:

size(100, 100,P3D);noStroke();PImage img =loadImage("laDefense.jpg");beginShape();texture(img);vertex(10, 20,0, 0);vertex(80, 5,100, 0);vertex(95, 90,100, 100);vertex(40, 95,0, 100);endShape();


 

这时候vertex()中的后两位参数不在描述坐标,而是顶点的UV

vertex(x,y, u, v);    - 2d

vertex(x,y, z, u, v); - 3d

 

何为顶点的UV?看下图:




*注意,2D坐标系只有相对方向。所以无论UV朝向什么方向,最后都能旋转成上图这样。

当我们指定好绘制多边形使用的纹理后,我们把纹理标准化到一个01的坐标系空间中。横轴称为U轴,纵

轴成为V轴。我们将每个顶点映射到这个平面空间中,从而指定了这个多边形使用了贴图的那一片区域。

 

textureMode() - 用来设定纹理是否标准化

 

textureMode(IMAGE)  -使用图片自身像素尺寸作为坐标(默认)

textureMode(NORMAL) -使用标准化坐标

 

因此,贴图(也就是用于载入纹理的图片)最好是1:1的正方形。其次因为数据位的原因,贴图的尺寸最好是

128*128, 256*256, 512*512这样的2n次幂。另外,贴图的尺寸不要太大,牛逼一些的游戏使用的也

不过是2k贴图(也就是2048*2048)。当然了,这里是我大Processing,没有那么严谨也是容许的。

 

---------------------------------这里是华丽的分割线 ---------------------------------


绘制带纹理的cube


回顾一下第二节的知识,我们要如何处理cube才能使其拥有纹理呢?

我们有两种处理的方法:

1.我们可以吧这个cube展成一个平面就像下图这样:


如此我们在一张贴图的空间内就可以描述所有顶点的UV坐标。这也就是我们常说的对模型网格展UV的工作了。


2.鉴于cube简单的构造,倘若我们把贴图平贴在cube的每一面上也是一种不错的方法。游戏 -《我的世界》

便是这种做法。这样我们也只需要一张贴图便可以完成工作。

 

这里我们采用第二中方法。这里先给出贴图。

 

step 1导入贴图

 

PImage tex;tex = loadImage("t1.jpg"); //你可以随意替换自己喜欢的贴图tex.resize(256, 0);        //我们这里不需要那么的贴图,重设成256的textureMode(NORMAL);       //纹理使用标准化UV坐标

step2设置顶点UV


我们需要对每一个顶点设置UV,算算我们有36个顶点。因此目前有一点苦力活需要干,但很快,将会

有东西拯救我们。

 

PVector[][]uv;uv =new PVector[12][3]; // 12个面,每个面3个顶点,为每个顶点描述UV//topuv[0][0]  = new PVector(0, 1); // face0uv[0][1]  = new PVector(0, 0); //注意UV是浮点数uv[0][2]  = new PVector(1, 0);uv[1][0]  = new PVector(0, 1); // face1uv[1][1]  = new PVector(1, 0);uv[1][2]  = new PVector(1, 1);...// bottom...

 

step 3更新绘图过程

 

//fill(255, 127, 39);有了纹理我们不再需要填充颜色了。for (int i = 0; i < face.length; i++) {  beginShape();  texture(tex); //这里装载并启用纹理  //    x                    , y                    , z                    , u         , v  vertex(ver[int(face[i].x)].x,ver[int(face[i].x)].y, ver[int(face[i].x)].z, uv[i][0].x, uv[i][0].y);  vertex(ver[int(face[i].y)].x,ver[int(face[i].y)].y, ver[int(face[i].y)].z, uv[i][1].x, uv[i][1].y);  vertex(ver[int(face[i].z)].x,ver[int(face[i].z)].y, ver[int(face[i].z)].z, uv[i][2].x, uv[i][2].y);  endShape(TRIANGLES);}

如此应该可以看见咱们的图块出现在屏幕中了,有没开始觉得有一点兴奋?

 


 

 

这里是完整的代码,不太清楚的同学可以查看。


------------------------------------- 这里是华丽的分割线 -------------------------------


纹理环绕

让我们进入最后一个知识点,纹理环绕方式(Texture Weapping)。


textureWrap()    -设置纹理环绕模式


是的这个函数负责设置纹理环绕的方式。Processing慈悲的准备了两种:

CLAMP  - 纹理坐标绘制0到1之间,超出的部分会重复纹理坐标的边缘,就像是边缘被拉伸。(默认的)

REPEAT - 重复纹理图像,比如吧坐标设置成4,这会使纹理重复4次。


咱们可以吧之前cube的案例拿来试试效果,首先咱们换一张好体现效果的贴图。


接下来把uv改造一下:

float max = 1.0;// topuv[0][0]  = new PVector(0,   max); // face0uv[0][1]  = new PVector(0,   0);uv[0][2]  = new PVector(max, 0);uv[1][0]  = new PVector(0,   max); // face1uv[1][1]  = new PVector(max, 0);uv[1][2]  = new PVector(max, max);...


然后设置纹理属性:

// 载入贴图tex = loadImage("t3.jpg");tex.resize(int(256/max), 0);// 设置纹理属性textureMode(NORMAL);textureWrap(REPEAT);

现在我们来试试结果。

当max = 1.0;时应该是这样:



当max = 2.0; textureWrap(CLAMP);时,纹理边缘会被拉伸:




旁白:瞬间好像明白了星际穿越中外星人的五维空间是咋做的了?


当max = 2.0; textureWrap(REPEAT);时,纹理会被重复:




在制作地面的时候,纹理重复就十分好用。想想魔兽世界那广鞣的土地,一个劲的重复着单调的纹理!


完整代码看这里。

0 0
原创粉丝点击