Android OpenGL ES 开发— 绘制四边形
Posted ywl5320
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android OpenGL ES 开发— 绘制四边形相关的知识,希望对你有一定的参考价值。
我的视频课程:《Android C++ OpenGL 教程》
上一篇博客我们以绘制三角形为例讲了OpenGL的绘制流程,并按照自己的意愿绘制出了一个红色的三角形,那么现在我们就可以开始绘制四边形了。
绘制四边形其实就是绘制2个三角形,然后拼接成一个四边形。然儿具体怎么绘制呢,OpenGL中是有一定的规则的,下面我们就来看看一些常用的绘制方式:
首先我们看看OpenGL中的glDrawArray函数,这里需要注意的是:在OpenGL中所有组合的图形的绘制方向必须一致。
要么都是顺时针,要么都是逆时针。
1、第一种绘制四边形的方式
我们绘制三角形是这样绘制的:
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
这里我们需要注意的就是第一个参数:GL_TRIANGLES,表示绘制三角形模式。然后第二个参数表示:从我们的顶点数组的哪个位置开始,然后第三个参数表示绘制几个顶点。它会依次从顶点数组0开始绘制三个点组成一个三角形,这样就把三角形绘制出来了。
然儿需要绘制四边形的话,需要2个三角形,所以我们需要6个顶点,前面三个组成一个三角形,后面三个组成另一个三角形,比如我们绘制如下三角形:
那么在GL_TRIANGLES绘制模式下,我们的2个三角形可以是(前提绘制方向一致)(v1,v2,v3)和(v2,v4,v3)也可以是其他组合方式,然后顶点数组我们就得按照顶点的顺序把坐标写进去就是:
private float[] vertexData =
//第一个三角形坐标
-1f, 0f,
0f, -1f,
0f, 1f,
//第二个三角形坐标
0f, -1f,
1f, 0f,
0f, 1f
;
这样我们的绘制方式就是从顶点数组的第0个元素开始,依次绘制6个元素就可以了:
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
OpenGL就会先绘制前面三个点组成第一个三角形,再绘制后面3个点组成第二个三角形,最终展现出来的就是一个四边形了。
2、第二种绘制四边形的方式:
前面一种绘制四边形或多边形的方式比较简单,需要绘制多少个就写出多少个三角形的坐标就行,然后依次绘制,然儿当绘制组个图形时可能会写许多重复的坐标,也会导致内存的增大。所以OpenGL中还有另一个种绘制四边形的方式,即用GL_TRIANGLE_STRIP(三角形带)的方式,其思路就是相邻2个三角形共用一条边,这样绘制四边形就不需要6个顶点了,只需要4个顶点就可以了。
我们还是以前面绘制的四边形为例,用GL_TRIANGLE_STRIP的方式来绘制四边形,我们先来看一下绘制四边形需要的其中一种顶点数组的排列方式:
private float[] vertexData =
-1f, 0f,
0f, -1f,
0f, 1f,
1f, 0f
;
然后绘制的代码如下:
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
那么这里OpenGL是怎么绘制的呢?其实OpenGL绘制的第一个三角形是:(v1,v2,v3),第二个三角形是:(v3,v2,v4),这里就需要牵扯到一个绘制的公式了,其中n表示顶点的索引值:
偶数:n-1, n-2, n
奇数:n-2, n-1, n
这个公式怎么看呢?
1、首先我们可以确定的就是(v1,v2)第一条边的坐标,而且绘制方向是逆时针;
2、然后接下来就是绘制第三个点的坐标了,那么第三个点就根据公式来,因为是绘制第三个点,所以索引(n==3)然后3是奇数,根据公式得出(3-2,3-1,3)即:(v1,v2,v3)第一个三角形,而此时v3的坐标可以是(0,1)也可以是(1,0),并且都是逆时针满足条件;
3、接下来绘制第四个顶点了,此时(n==4)是偶数,根据公式得出(4-1,4-2,4)即:(v3,v2,v4):
3.1、当v3的坐标是(0,1)的时候v4就只能是(1,0)了,那么(v3,v2,v4)是逆时针并且和第一个三角形共用一条边(v2,v3)满足条件
3.2、当v3的坐标是(1,0)时,v4坐标是(0,1),此时(v3,v2,v4)是顺时针不满足条件
4、所以这样就能确定四个点的坐标了,就如图所示,然后依次写出坐标就是(v1,v2,v3,v4),也就是我们定义的顶点数组的值。
3、主要源码
顶点着色器:
attribute vec4 av_Position;
void main()
gl_Position = av_Position;
片源着色器:
precision mediump float;
uniform vec4 af_Color;
void main()
gl_FragColor = af_Color;
Render:
package com.ywl5320.opengldemo;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class WlRender implements GLSurfaceView.Renderer
private Context context;
private final float[] vertexData =
// -1f, 0f,
// 0f, -1f,
// 0f, 1f,
//
//
// 0f, -1f,
// 1f, 0f,
// 0f, 1f
-1f, 0f,
0f, -1f,
0f, 1f,
1f, 0f
;
private FloatBuffer vertexBuffer;
private int program;
private int avPosition;
private int afColor;
public WlRender(Context context)
this.context = context;
vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(vertexData);
vertexBuffer.position(0);
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
String vertexSource = WlShaderUtil.readRawTxt(context, R.raw.vertex_shader);
String fragmentSource = WlShaderUtil.readRawTxt(context, R.raw.fragment_shader);
program = WlShaderUtil.createProgram(vertexSource, fragmentSource);
if(program > 0)
avPosition = GLES20.glGetAttribLocation(program, "av_Position");
afColor = GLES20.glGetUniformLocation(program, "af_Color");
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
GLES20.glViewport(0, 0, width, height);
@Override
public void onDrawFrame(GL10 gl)
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GLES20.glUseProgram(program);
GLES20.glUniform4f(afColor, 1f, 0f, 0f, 1f);
GLES20.glEnableVertexAttribArray(avPosition);
GLES20.glVertexAttribPointer(avPosition, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
总结:通过绘制四边形(理论上是多边形),我们知道了OpenGL的一些绘制规则,这有利于我们在以后的开发中组合出更复杂的图形,达到更酷炫的效果。好了OpenGL绘制四边形就讲到这里了!
最终效果图如下:
示例源码地址:
GitHub:Android-OpenGL-ES
以上是关于Android OpenGL ES 开发— 绘制四边形的主要内容,如果未能解决你的问题,请参考以下文章