頂點(diǎn)緩存區(qū)在第六章已經(jīng)說過,這里整理一個(gè)案例体谒。還是最簡(jiǎn)單的代碼杯聚,繪制一個(gè)三角形。這案例繼承附錄5中的基類抒痒。
不使用頂點(diǎn)緩存區(qū)
/**
* 三角形
*/
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
};
//頂點(diǎn)個(gè)數(shù)
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
//頂點(diǎn)之間的偏移量
private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)
//設(shè)置顏色械媒,依次為紅綠藍(lán)和透明通道
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);
//程序加入到環(huán)境里面
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);
//準(zhǔn)備三角形的坐標(biāo)數(shù)據(jù)
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;
}
//設(shè)置繪制三角形的顏色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//繪制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁止頂點(diǎn)數(shù)組的句柄
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
使用頂點(diǎn)緩存區(qū)
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
};
//頂點(diǎn)個(gè)數(shù)
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
//頂點(diǎn)之間的偏移量
private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個(gè)頂點(diǎn)四個(gè)字節(jié)
//設(shè)置顏色,依次為紅綠藍(lán)和透明通道
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);
//程序加入到環(huán)境里面
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);
//準(zhǔn)備三角形的坐標(biāo)數(shù)據(jù)
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;
}
//設(shè)置繪制三角形的顏色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//繪制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁止頂點(diǎn)數(shù)組的句柄
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
int vboId = 0;
private void createVBO() {
//1. 創(chuàng)建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設(shè)置頂點(diǎn)數(shù)據(jù)的值
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. 設(shè)置頂點(diǎn)數(shù)據(jù)
GLES20.glVertexAttribPointer(
mPositionHandle,
COORDS_PER_VERTEX,
GLES20.GL_FLOAT,
false,
vertexStride,
0);
//3. 解綁VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
}
區(qū)別在哪里评汰,只有兩個(gè)地方,第一個(gè)創(chuàng)建緩存區(qū)放入數(shù)據(jù)痢虹,第二個(gè)是使用緩存區(qū)被去。
private void createVBO() {
//1. 創(chuàng)建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設(shè)置頂點(diǎn)數(shù)據(jù)的值
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);
}
第二個(gè)是使用
private void useVboDraw() {
//1. 綁定VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
//2. 設(shè)置頂點(diǎn)數(shù)據(jù)
GLES20.glVertexAttribPointer(
mPositionHandle,
COORDS_PER_VERTEX,
GLES20.GL_FLOAT,
false,
vertexStride,
0);
//3. 解綁VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
創(chuàng)建部分,不需要做任何修改脆丁, 只需要加入創(chuàng)建代碼即可构眯,使用部分岔冀,需要?jiǎng)h除之前頂點(diǎn)的指定方式,換成這個(gè)調(diào)用方法即可坯墨。