谈谈Processing 3D世界 三
2016-08-08 17:48
232 查看
有了前两节的知识,接下来咱们该做什么呢?丰富多边形?控制摄影机?这些先不急,我们不妨先来了解下纹理
(Texture)。有了这玩意,能极大的丰富我们绘制的对象。
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朝向什么方向,最后都能旋转成上图这样。
当我们指定好绘制多边形使用的纹理后,我们把纹理标准化到一个0到1的坐标系空间中。横轴称为U轴,纵
轴成为V轴。我们将每个顶点映射到这个平面空间中,从而指定了这个多边形使用了贴图的那一片区域。
textureMode()
textureMode(IMAGE) -使用图片自身像素尺寸作为坐标(默认)
textureMode(NORMAL) -使用标准化坐标
因此,贴图(也就是用于载入纹理的图片)最好是1:1的正方形。其次因为数据位的原因,贴图的尺寸最好是
128*128, 256*256, 512*512这样的2的n次幂。另外,贴图的尺寸不要太大,牛逼一些的游戏使用的也
不过是2k贴图(也就是2048*2048)。当然了,这里是我大Processing,没有那么严谨也是容许的。
---------------------------------这里是华丽的分割线 ---------------------------------
我们有两种处理的方法:
1.我们可以吧这个cube展成一个平面就像下图这样:
如此我们在一张贴图的空间内就可以描述所有顶点的UV坐标。这也就是我们常说的对模型网格展UV的工作了。
2.鉴于cube简单的构造,倘若我们把贴图平贴在cube的每一面上也是一种不错的方法。游戏
-《我的世界》
便是这种做法。这样我们也只需要一张贴图便可以完成工作。
这里我们采用第二中方法。这里先给出贴图。
PImage tex;
tex = loadImage("t1.jpg"); //你可以随意替换自己喜欢的贴图
tex.resize(256, 0); //我们这里不需要那么的贴图,重设成256的
textureMode(NORMAL); //纹理使用标准化UV坐标
有东西拯救我们。
PVector[][]uv;
uv =new PVector[12][3]; // 12个面,每个面3个顶点,为每个顶点描述UV
//top
uv[0][0] = new PVector(0, 1); // face0
uv[0][1] = new PVector(0, 0); //注意UV是浮点数
uv[0][2] = new PVector(1, 0);
uv[1][0] = new PVector(0, 1); // face1
uv[1][1] = new PVector(1, 0);
uv[1][2] = new PVector(1, 1);
...
// bottom
...
//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);
}
如此应该可以看见咱们的图块出现在屏幕中了,有没开始觉得有一点兴奋?
这里是完整的代码,不太清楚的同学可以查看。
------------------------------------- 这里是华丽的分割线 -------------------------------
textureWrap()
-设置纹理环绕模式
是的这个函数负责设置纹理环绕的方式。Processing慈悲的准备了两种:
CLAMP - 纹理坐标绘制0到1之间,超出的部分会重复纹理坐标的边缘,就像是边缘被拉伸。(默认的)
REPEAT - 重复纹理图像,比如吧坐标设置成4,这会使纹理重复4次。
咱们可以吧之前cube的案例拿来试试效果,首先咱们换一张好体现效果的贴图。
接下来把uv改造一下:
float max = 1.0;
// top
uv[0][0] = new PVector(0, max); // face0
uv[0][1] = new PVector(0, 0);
uv[0][2] = new PVector(max, 0);
uv[1][0] = new PVector(0, max); // face1
uv[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);时,纹理会被重复:
在制作地面的时候,纹理重复就十分好用。想想魔兽世界那广鞣的土地,一个劲的重复着单调的纹理!
完整代码看这里。
(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朝向什么方向,最后都能旋转成上图这样。
当我们指定好绘制多边形使用的纹理后,我们把纹理标准化到一个0到1的坐标系空间中。横轴称为U轴,纵
轴成为V轴。我们将每个顶点映射到这个平面空间中,从而指定了这个多边形使用了贴图的那一片区域。
textureMode()
- 用来设定纹理是否标准化
textureMode(IMAGE) -使用图片自身像素尺寸作为坐标(默认)
textureMode(NORMAL) -使用标准化坐标
因此,贴图(也就是用于载入纹理的图片)最好是1:1的正方形。其次因为数据位的原因,贴图的尺寸最好是
128*128, 256*256, 512*512这样的2的n次幂。另外,贴图的尺寸不要太大,牛逼一些的游戏使用的也
不过是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
//top
uv[0][0] = new PVector(0, 1); // face0
uv[0][1] = new PVector(0, 0); //注意UV是浮点数
uv[0][2] = new PVector(1, 0);
uv[1][0] = new PVector(0, 1); // face1
uv[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;
// top
uv[0][0] = new PVector(0, max); // face0
uv[0][1] = new PVector(0, 0);
uv[0][2] = new PVector(max, 0);
uv[1][0] = new PVector(0, max); // face1
uv[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);时,纹理会被重复:
在制作地面的时候,纹理重复就十分好用。想想魔兽世界那广鞣的土地,一个劲的重复着单调的纹理!
完整代码看这里。
相关文章推荐
- 谈谈Processing 3D世界 六
- 谈谈Processing 3D世界 四(补充)
- 谈谈Processing 3D世界 四
- 谈谈Processing 3D世界 五
- 谈谈Processing 3D世界 六 (续二)
- 谈谈Processing 3D世界 一
- 谈谈Processing 3D世界 二
- 谈谈Processing 3D世界 六 (续)
- 在3D世界中创建不同的相机模式——创建一个模糊(Blur),(发光)Glow Post-Processing Effect
- XNA那些事(五) 3D世界中的平移与旋转
- Win32 OpenGL编程(6) 踏入3D世界
- 【Qt OpenGL教程】10:加载3D世界,并在其中漫游
- [3D] - (开源)1997年世界编程大赛第一名作品
- Away3D学习笔记2--3D世界的坐标系
- OpenGL教程之漫游3D世界
- (一)图像坐标:我想和世界坐标谈谈(A) 【计算机视觉学习笔记--双目视觉几何框架系列】
- Study 3D《6、世界坐标到相机坐标的变换》
- 在3D世界中创建不同的相机模式——创建一个相机:Position,Target和View Frustum
- 在3D世界中创建不同的相机模式——使用四叉树隐藏不在视野中的部分网格
- 处理顶点——在3D世界添加水面