上一篇已经画出来了一个红色三角形。
上一篇是一个平面的三角形,看起来好像是2D的其实已经显示在3D世界中了因为没有使用到Z轴,所以在3D世界中显示一个平面,比较简单。
下面我来教你们加入一个Z轴显示一个金字塔
。
步骤
想显示一个图像,你先必须知道一个图像的大概结构,例如我们想建一个金字塔,得知道金字塔大概模样
根据上图的金字塔,我们可以知道一个金字塔是由4个三角形,和一个正方形组成
根据我们上一篇案例,我们知道显示一个三角形需要定义3个顶点位置并且存入到顶点数组。金字塔由4个三角形
和一个正方形
组成,我们可以把它分解成许多的三角形
正方形可以分解成两个三角形
现在知道金字塔一共需要 3个顶点
x六个三角形
=18个顶点
现在我们来用坐标表示这6个三角形
的顶点位置
先把上一篇三角形的顶点数组
删除
//初始化
@Override
public void SurfaceCreated(Rendering rendering)
{
//设置背景颜色为白色
rendering.setColor(new ColorRGBA(1,1,1,1));
//顶点数组
float vertex[]={
};
mesh=new Mesh();
//设置网格的顶点数组数据
mesh.setVertex(vertex);
//初始化着色器
shader=new ColorShader();
//设置颜色
shader.setColor(new ColorRGBA(1,0,0,1));
//初始化几何体
geometry=new Geometry(mesh);
//给几何体设置一个着色器
geometry.setShader(shader);
//获取视图类
ViewPort viewport=rendering.getViewport();
//设置摄像机参数
viewport.setCameraPosition(0,0,-5);
viewport.setCameraLook(0,0,0);
viewport.setCameraUp(0,1,0);
}
现在开始定义金字塔6个三角形顶点的位置
这里需要一些想象力,在脑中建立一个金字塔模型
我们先定义金字塔下面的正方形
,正方形由两个直角三角形
组成。
先定义下面正方形的第一个直角三角形
//顶点数组
float vertex[]={
//金字塔下面的正方形
//第一个直角三角形
-0.5f,0,-0.5f,
-0.5f,0,0.5f,
0.5f,0,0.5f
};
因为金字塔
正方形
Y轴都是一样的,我们这里不需要用Y轴
所以设置为0。
运行看看效果
为什么看不见?
因为我们摄像头的位置的Y轴是0,并且观测点Y轴也为0,加上三角形定义的Y轴位置也是0,所以导致他们平行看不见任何东西。
解决方法
把摄像头位置的Y轴上调,让摄像头从高位置低头看三角形。我这里让他往上移了4个坐标
//获取视图类
ViewPort viewport=rendering.getViewport();
//设置摄像机参数
viewport.setCameraPosition(0,4,-5);
viewport.setCameraLook(0,0,0);
viewport.setCameraUp(0,1,0);
定义第二个直角三角形组成一个正方形
//顶点数组
float vertex[]={
//金字塔下面的正方形
//由两个直角三角形组成
//第一个直角三角形
-0.5f,0,-0.5f,
-0.5f,0,0.5f,
0.5f,0,0.5f,
//第二个直角三角形
0.5f,0,-0.5f,
-0.5f,0,-0.5f,
0.5f,0,0.5f
};
然后再把把前面,后面,左边,右边的三角形坐标分别写入。
//顶点数组
float vertex[]={
//金字塔下面的正方形
//由两个直角三角形组成
//第一个直角三角形
-0.5f,0,-0.5f,
-0.5f,0,0.5f,
0.5f,0,0.5f,
//第二个直角三角形
0.5f,0,-0.5f,
-0.5f,0,-0.5f,
0.5f,0,0.5f,
//前面三角形
-0.5f,0,0.5f,
0.5f,0,0.5f,
0,1,0f,
//后面三角形 只需要复制
//前面三角形
//然后把z轴改为相反数
-0.5f,0,-0.5f,
0.5f,0,-0.5f,
0,1,0f,
//右边三角形
0.5f,0,0.5f,
0.5f,0,-0.5f,
0,1,0,
//左边三角形
//复制右然后x改为相反数
-0.5f,0,0.5f,
-0.5f,0,-0.5f,
0,1,0,
};
这里的数据可能比较难理解,建议读者自行试试慢慢构建一个几何体,只需要明白这些原理就行,复杂模型可以用模型文件导入
现在我把摄像机y轴改为0,运行项目看看?
这里3D效果不明显,但是它确确实实是个3D图形,但是由于都是红色导致看起来像2D。
我来写一个自定义着色器ColorsShader
给每个顶点上个颜色,让立体感更强
自定义着色器,这里读者如果不懂,没关系,后面读者学会自定义着色器之后这里自然就懂了
着色器全部代码
public class ColorsShader extends BaseShader
{
//给不同的顶点上不同颜色
private float[] colors;
@Override
protected void setShader(RenderingData data, Geometry geometry, ShaderTool shader)
{
shader.setAttribFloat("colors",4,colors);
}
@Override
public String getVertexShader()
{
String str=
"in vec4 colors;"
+"out vec4 mColors;"
+"vec4 VS(ShaderData data){"
+" mColors=colors;"
+"return data.viewPortMatrix*data.modelPosition;"
+"}";
return str;
}
@Override
public String getFragShader()
{
String str=
"in vec4 mColors; "
+"vec4 FS(ShaderData data){"
+" return mColors;"
+"}";
return str;
}
public void setColors(float[] colors)
{
this.colors = colors;
}
public float[] getColors()
{
return colors;
}
}
写一个随机颜色给每个顶点设置成不同的颜色,
float colors[]=new float[vertex.length/3*4];
for(int i=0;i<colors.length/4;i++){
colors[i*4]=(float)Math.random();//红色
colors[i*4+1]=(float)Math.random();//绿色
colors[i*4+2]=(float)Math.random();//蓝色
colors[i*4+3]=1;//透明度
}
//初始化着色器
shader=new ColorsShader();
//设置颜色
shader.setColors(colors);
项目代码
public class MainActivity extends Activity implements DrawRenderer
{
//渲染控件类
private GameView gameview;
//网格
private Mesh mesh;
//几何体
private Geometry geometry;
//带颜色的着色器
private ColorsShader shader;
//旋转角度
private float angle;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
gameview=new GameView(this);
gameview.setDrawRenderer(this);
setContentView(gameview);
}
//初始化
@Override
public void SurfaceCreated(Rendering rendering)
{
//设置背景颜色为白色
rendering.setColor(new ColorRGBA(1,1,1,1));
//顶点数组
float vertex[]={
//金字塔下面的正方形
//由两个直角三角形组成
//第一个直角三角形
-0.5f,0,-0.5f,
-0.5f,0,0.5f,
0.5f,0,0.5f,
//第二个直角三角形
0.5f,0,-0.5f,
-0.5f,0,-0.5f,
0.5f,0,0.5f,
//前面三角形
-0.5f,0,0.5f,
0.5f,0,0.5f,
0,1,0f,
//后面三角形 只需要复制
//前面三角形
//然后把z轴改为相反数
-0.5f,0,-0.5f,
0.5f,0,-0.5f,
0,1,0f,
//右边三角形
0.5f,0,0.5f,
0.5f,0,-0.5f,
0,1,0,
//左边三角形
//复制右然后x改为相反数
-0.5f,0,0.5f,
-0.5f,0,-0.5f,
0,1,0,
};
float colors[]=new float[vertex.length/3*4];
for(int i=0;i<colors.length/4;i++){
colors[i*4]=(float)Math.random();//红色
colors[i*4+1]=(float)Math.random();//绿色
colors[i*4+2]=(float)Math.random();//蓝色
colors[i*4+3]=1;//透明度
}
mesh=new Mesh();
//设置网格的顶点数组数据
mesh.setVertex(vertex);
//初始化着色器
shader=new ColorsShader();
//设置颜色
shader.setColors(colors);
//初始化几何体
geometry=new Geometry(mesh);
//给几何体设置一个着色器
geometry.setShader(shader);
//获取视图类
ViewPort viewport=rendering.getViewport();
//设置摄像机参数
viewport.setCameraPosition(0,0,-5);
viewport.setCameraLook(0,0,0);
viewport.setCameraUp(0,1,0);
}
//绘画函数
@Override
public void draw(Rendering rendering)
{
//重制几何体位置矩阵
geometry.genMatrix();
//设置几何体位置
geometry.translate(0,0,0);
//绕Y轴旋转angle度
angle+=0.5f;
geometry.rotate(angle,0,1,0);
//把几何体加入到渲染列表
rendering.addGeometry(geometry);
}
//改变宽高调用
@Override
public void SurfaceChanged(Rendering rendering, int width, int heigth)
{
}
}