顶点缓存区在第六章已经说过,这里整理一个案例。还是最简单的代码,绘制一个三角形。这案例继承附录5中的基类。
不使用顶点缓存区
/**
* 三角形
*/
public class Triangle extends BaseGameScreen {
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
static final int COORDS_PER_VERTEX = 3;
private FloatBuffer vertexBuffer;
static float triangleCoords[] = {
0.5f, 0.5f, 0.0f, // top
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f // bottom right
};
//顶点个数
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
//顶点之间的偏移量
private final int vertexStride = COORDS_PER_VERTEX * 4; // 每个顶点四个字节
//设置颜色,依次为红绿蓝和透明通道
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
private int mPositionHandle;
private int mColorHandle;
float d = 0.01F;
public Triangle(){
}
public void create(){
ByteBuffer bb = ByteBuffer.allocateDirect(
triangleCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(triangleCoords);
vertexBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram,vertexShader);
GLES20.glAttachShader(mProgram,fragmentShader);
GLES20.glLinkProgram(mProgram);
//程序加入到环境里面
GLES20.glUseProgram(mProgram);
// 检查是否有效
GLES20.glValidateProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
}
@Override
public void surfaceChange(int width, int height) {
GLES20.glViewport(0,0,width,height);
}
@Override
public void dispose() {
}
@Override
public void render() {
//获取位置句柄 属性句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//准备三角形的坐标数据
GLES20.glVertexAttribPointer(
mPositionHandle,
COORDS_PER_VERTEX,
GLES20.GL_FLOAT,
false,
vertexStride,
vertexBuffer);
//获取片元着色器的vColor成员的句柄
color[1] = color[1]-d;
if (color[1]<=0||color[1]>=1){
d=-d;
}
//设置绘制三角形的颜色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//绘制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁止顶点数组的句柄
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
使用顶点缓存区
package com.example.myapplication.learn.shape;
import android.opengl.GLES20;
import com.example.myapplication.MainActivity;
import com.example.myapplication.learn.shape.base.BaseGameScreen;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
/**
* 三角形
*/
public class TriangleBuffer extends BaseGameScreen {
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
static final int COORDS_PER_VERTEX = 3;
private FloatBuffer vertexBuffer;
static float triangleCoords[] = {
0.5f, 0.5f, 0.0f, // top
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f // bottom right
};
//顶点个数
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
//顶点之间的偏移量
private final int vertexStride = COORDS_PER_VERTEX * 4; // 每个顶点四个字节
//设置颜色,依次为红绿蓝和透明通道
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
private int mPositionHandle;
private int mColorHandle;
float d = 0.01F;
public TriangleBuffer(MainActivity activity){
}
public void create(){
ByteBuffer bb = ByteBuffer.allocateDirect(
triangleCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(triangleCoords);
vertexBuffer.position(0);
createVBO();
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram,vertexShader);
GLES20.glAttachShader(mProgram,fragmentShader);
GLES20.glLinkProgram(mProgram);
//程序加入到环境里面
GLES20.glUseProgram(mProgram);
// 检查是否有效
GLES20.glValidateProgram(mProgram);
//得到活跃的unifor
int arr[] = new int[1];
int arr1[] = new int[1];
int arr2[] = new int[1];
int arr3[] = new int[1];
byte arr4[] = new byte[10];
GLES20.glGetProgramiv(mProgram,GLES20.GL_ACTIVE_UNIFORMS,arr,0);
GLES20.glGetActiveUniform(
mProgram,
1,
1,
arr1,
1,
arr2,
1,
arr3,
1,
arr4,
0
);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
}
@Override
public void surfaceChange(int width, int height) {
GLES20.glViewport(0,0,width,height);
}
@Override
public void dispose() {
}
@Override
public void render() {
//获取位置句柄 属性句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//准备三角形的坐标数据
useVboDraw();
// GLES20.glVertexAttribPointer(
// mPositionHandle,
// COORDS_PER_VERTEX,
// GLES20.GL_FLOAT,
// false,
// vertexStride,
// vertexBuffer);
//获取片元着色器的vColor成员的句柄
color[1] = color[1]-d;
if (color[1]<=0||color[1]>=1){
d=-d;
}
//设置绘制三角形的颜色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//绘制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁止顶点数组的句柄
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
int vboId = 0;
private void createVBO() {
//1. 创建VBO
int[] vbos = new int[1];
GLES20.glGenBuffers(vbos.length, vbos, 0);
vboId = vbos[0];
//2. 绑定VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//3. 分配VBO需要的缓存大小
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
triangleCoords.length * 4 +
triangleCoords.length * 4,
null, GLES20.GL_STATIC_DRAW);
//4. 为VBO设置顶点数据的值
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER,
0,
triangleCoords.length * 4,
vertexBuffer);
// GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, textureData.length * 4, textureBuffer);
//5. 解绑VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
private void useVboDraw() {
//1. 绑定VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//2. 设置顶点数据
GLES20.glVertexAttribPointer(
mPositionHandle,
COORDS_PER_VERTEX,
GLES20.GL_FLOAT,
false,
vertexStride,
0);
//3. 解绑VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
}
区别在哪里,只有两个地方,第一个创建缓存区放入数据,第二个是使用缓存区。
private void createVBO() {
//1. 创建VBO
int[] vbos = new int[1];
GLES20.glGenBuffers(vbos.length, vbos, 0);
vboId = vbos[0];
//2. 绑定VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//3. 分配VBO需要的缓存大小
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
triangleCoords.length * 4 +
triangleCoords.length * 4,
null, GLES20.GL_STATIC_DRAW);
//4. 为VBO设置顶点数据的值
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER,
0,
triangleCoords.length * 4,
vertexBuffer);
// GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, textureData.length * 4, textureBuffer);
//5. 解绑VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
第二个是使用
private void useVboDraw() {
//1. 绑定VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//2. 设置顶点数据
GLES20.glVertexAttribPointer(
mPositionHandle,
COORDS_PER_VERTEX,
GLES20.GL_FLOAT,
false,
vertexStride,
0);
//3. 解绑VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
创建部分,不需要做任何修改, 只需要加入创建代码即可,使用部分,需要删除之前顶点的指定方式,换成这个调用方法即可。
网友评论