所以我一直试图整合一个Opengl ES 2.0应用程序。我的测试设备是Moto G手机。 我正在设置一个例程来加载大型地形网格。 我的方法是Terrain类。在这个类中,存储在2D数组中的单独地形图块在组合时构成整个地形网格。每个图块都是64x64顶点,并作为VBO在GPU上推送。我的计划是尽可能在GPU上获得尽可能多的磁贴,然后使用LOD算法处理绘制性能。 然而,就目前而言,我能够加载40x40的瓷砖,但除此之外,我遇到了崩溃。没有错误,没有。我一直在检查每个GL呼叫的错误,但没有找到任何东西。我对这一切都比较陌生,我对于为什么会这样做的两点想法是:
1)我只是在重载GPU。这里有什么限制,我该如何测试它们? 2)我在加载这些VBO的UI线程中花费了太多时间并且发生了崩溃......
任何人都可以填写这些限制以及可能引发崩溃的内容吗?
这是我的Terrain类,它创建了一个Tile对象的2D数组:
package com.example.terraintiletest;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class Terrain {
Tile[][] mTiles; //A 2D array of all tiles representing this terrain Mesh.
public int tileNRows; //How many rows of tileNSize tiles
public int tileNCols; //How many cols of tileNSize tiles
public int tileNSize; //Size of each tile in verteces. They are square.
/* The constructor here simply creates a 2D array of Tiles given a tileSize and how many tiles wide by how many tiles high */
Terrain(int tileSize, int tileRows, int tileCols){
this.tileNRows = tileRows;
this.tileNCols = tileCols;
this.tileNSize = tileSize;
int tilescreated = 0;
int row,col,x,y;
float xOff=0,yOff=0;
int positions_ctr = 0,colour_ctr=0;
int posLen = tileSize*tileSize*3;
int colLen = tileSize*tileSize*4;
int indLen = ((tileSize-1) * ((tileSize*2) +2))-2;
int posBytes = tileSize*tileSize*3*4;
int colBytes = tileSize*tileSize*4*4;
int indBytes = (((tileSize-1) * ((tileSize*2) +2))-2) * 2;
float[] poss = new float[posLen];
float[] cols = new float[colLen];
short[][] index = new short[tileSize][tileSize];
short[] IDA = new short[indLen];
/* Buffer for glbufferdata */
ByteBuffer bPos = ByteBuffer.allocateDirect(posBytes).order(ByteOrder.nativeOrder());
FloatBuffer fPos = bPos.asFloatBuffer();
ByteBuffer bCol = ByteBuffer.allocateDirect(colBytes).order(ByteOrder.nativeOrder());
FloatBuffer fCol = bCol.asFloatBuffer();
ByteBuffer bInd = ByteBuffer.allocateDirect(indBytes).order(ByteOrder.nativeOrder());
ShortBuffer sInd = bInd.asShortBuffer();
/* Build an Indece Buffer for triangle strips */
int ct = 0;
for(y=0;y<tileSize;y++){
for(x=0;x<tileSize;x++){
index[y][x] = (short)ct;
ct++;
}
}
ct = 0;
for(y=0;y<tileSize-1;y++){
for(x=0;x<tileSize;x++){
IDA[ct] = index[y+1][x];
ct++;
IDA[ct] = index[y][x];
ct++;
if(x==tileSize-1 && y != tileSize -2) {
IDA[ct] = index[y][x];
ct++;
IDA[ct] = index[y+2][0];
ct++;
}
}
}
sInd.clear();
sInd.put(IDA);
sInd.position(0);
this.mTiles = new Tile[tileRows][tileCols];
/* Create positions and colors for all tiles */
try{
// iterate through tiles
for(y=0;y<tileRows;y++){
for(x=0;x<tileCols;x++){
//iterate through tile contents
for(row=0;row<tileSize;row++){
for(col=0;col<tileSize;col++){
poss[positions_ctr] = xOff+col;
poss[positions_ctr+1] = yOff+row;
poss[positions_ctr+2] = 0.0f;
cols[colour_ctr] = 1.0f;
cols[colour_ctr+1] = 0.0f;
cols[colour_ctr+2] = 0.0f;
cols[colour_ctr+3] = 1.0f;
//System.out.println("tile["+x+"]["+y+"]: "+poss[positions_ctr]+","+poss[positions_ctr+1]+","+poss[positions_ctr+2]+","+cols[colour_ctr]+","+cols[colour_ctr+1]+","+cols[colour_ctr+2]+","+cols[colour_ctr+2]);
positions_ctr+=3;
colour_ctr+=4;
}
}
fPos.clear();
fCol.clear();
fPos.put(poss);
fCol.put(cols);
fPos.position(0);
fCol.position(0);
//Init a Tile VBO
this.mTiles[y][x] = new Tile(fPos, fCol, sInd, posLen, colLen, indLen);
tilescreated++;
xOff+=tileSize;
positions_ctr=0;
colour_ctr=0;
}
xOff=0;
yOff+=tileSize;
}
} catch (OutOfMemoryError err) {
System.out.println("OUT OF MEMORY!");
System.exit(1);
}
bPos.limit(0);
bCol.limit(0);
bInd.limit(0);
fPos.limit(0);
fCol.limit(0);
sInd.limit(0);
fPos = null;
fCol = null;
sInd = null;
bPos = null;
bCol = null;
bInd = null;
index = null;
IDA = null;
System.gc();
System.out.println("Tiles Created:"+tilescreated);
}
}
这是我的Tile课程:
package com.example.terraintiletest;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import android.opengl.GLES20;
public class Tile {
private final int vbo[];
private final int ibo[];
private final int COLOURS = 0;
private final int POSITIONS = 1;
private final int FINE = 0;
int mProgram = 0;
int mPositionHandle = 0;
int mColorHandle = 0;
int mMVPMatrixHandle = 0;
int vertexShaderHandle = 0;
int fragmentShaderHandle = 0;
int indeceSize;
final String vertexShaderCode =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.
+ "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in.
+ "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in.
+ "varying vec4 v_Color; \n" // This will be passed into the fragment shader.
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
+ " v_Color = a_Color; \n" // Pass the color through to the fragment shader.
// It will be interpolated across the triangle.
+ " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position.
+ " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in
+ "} \n"; // normalized screen coordinates.
final String fragmentShaderCode =
"precision mediump float; \n" // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
+ "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = v_Color; \n" // Pass the color directly through the pipeline.
+ "} \n";
public Tile(FloatBuffer Zbuf, FloatBuffer Cbuf, ShortBuffer Ibuf,int azLength,int acLength,int siLength) {
int x;
for(x=0;x<Zbuf.capacity();x++){
//System.out.println("Position "+Zbuf.get(x));
}
for(x=0;x<Cbuf.capacity();x++){
//System.out.println("Colour "+Cbuf.get(x));
}
for(x=0;x<Ibuf.capacity();x++){
//System.out.println("Index "+Ibuf.get(x));
}
// Load in the vertex shader.
vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(vertexShaderHandle, vertexShaderCode);
// Compile the shader.
GLES20.glCompileShader(vertexShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(vertexShaderHandle);
vertexShaderHandle = 0;
}
}
if (vertexShaderHandle == 0)
{
throw new RuntimeException("Error creating vertex shader.");
}
// Load in the fragment shader shader.
fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(fragmentShaderHandle, fragmentShaderCode);
// Compile the shader.
GLES20.glCompileShader(fragmentShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(fragmentShaderHandle);
fragmentShaderHandle = 0;
}
}
if (fragmentShaderHandle == 0)
{
throw new RuntimeException("Error creating fragment shader.");
}
// Create a program object and store the handle to it.
mProgram = GLES20.glCreateProgram();
if (mProgram != 0)
{
// Bind the vertex shader to the program.
GLES20.glAttachShader(mProgram, vertexShaderHandle);
// Bind the fragment shader to the program.
GLES20.glAttachShader(mProgram, fragmentShaderHandle);
GLES20.glBindAttribLocation(mProgram, 0, "a_Position");
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindAttribLocation(mProgram, 1, "a_Color");
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glLinkProgram(mProgram);
// Get the link status.
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(mProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0)
{
GLES20.glDeleteProgram(mProgram);
mProgram = 0;
}
}
if (mProgram == 0)
{
throw new RuntimeException("Error creating program.");
}
// Set program handles. These will later be used to pass in values to the program.
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
mColorHandle = GLES20.glGetAttribLocation(mProgram, "a_Color");
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
//VBO create
vbo = new int[2];
ibo = new int[1];
GLES20.glGenBuffers(2,vbo,0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glGenBuffers(1,ibo,0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
//Positions
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[POSITIONS] );
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, azLength * FH_Utilities.FLOAT_SIZE,
Zbuf, GLES20.GL_STATIC_DRAW);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
//Colours
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[COLOURS] );
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, acLength * FH_Utilities.FLOAT_SIZE,
Cbuf, GLES20.GL_STATIC_DRAW);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
//Indeces
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[FINE]);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, siLength * FH_Utilities.SHORT_SIZE, Ibuf, GLES20.GL_STATIC_DRAW);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
indeceSize = Ibuf.capacity();
}
public void draw(float[] mvpMatrix) {
if(mPositionHandle<0 || mMVPMatrixHandle<0 || mColorHandle<0 || mProgram<0) {
System.out.println("ERROR - A Handle has failed");
System.out.println("mPositionHandle "+mPositionHandle);
System.out.println("mMVPMatrixHandle "+mMVPMatrixHandle);
System.out.println("mColorHandle "+mColorHandle);
System.out.println("mProgram "+mProgram);
System.exit(1);
}
GLES20.glUseProgram(mProgram);
final int mPositionDataSize = 3;
final int mColorDataSize = 4;
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
// Pass in the position information
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[POSITIONS]);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glEnableVertexAttribArray(mPositionHandle);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize,
GLES20.GL_FLOAT, false, 0, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[COLOURS]);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glEnableVertexAttribArray(mColorHandle);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize,
GLES20.GL_FLOAT, false, 0, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[FINE]);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indeceSize, GLES20.GL_UNSIGNED_SHORT, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
//Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
//Disable vertex array
GLES20.glDisableVertexAttribArray(mColorHandle);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
}
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
Logcat ERROR输出:
10-17 10:58:33.851: E/AuthorizationBluetoothService(11845): Proximity feature is not enabled.
10-17 10:58:33.878: E/AuthorizationBluetoothService(11845): Proximity feature is not enabled.
10-17 10:58:38.040: E/MDMCTBK(269): MdmCutbackHndler,Could not open ''
10-17 10:58:38.067: E/MDMCTBK(269): MdmCutbackHndler,Could not open ''
10-17 10:58:42.103: E/AuthorizationBluetoothService(12984): Proximity feature is not enabled.
10-17 10:58:42.130: E/AuthorizationBluetoothService(12984): Proximity feature is not enabled.
10-17 10:58:47.113: E/dalvikvm(12909): Could not find class 'android.app.Notification$Action$Builder', referenced from method android.support.v4.app.L.a
10-17 10:58:47.135: E/PartnerBookmarksReader(12909): ATTENTION: not using partner bookmarks as none were provided
10-17 10:58:47.673: E/GoogleApiIcingClientImpl(12909): NoSuchMethodException while trying to construct DocumentContents
10-17 10:59:23.604: E/AuthorizationBluetoothService(12984): Proximity feature is not enabled.
10-17 10:59:33.840: A/ProcessStats(995): Starting service ServiceState{4320e1c0 com.motorola.ccc.devicemanagement.DeviceManagementNotifierService pkg=com.motorola.ccc.devicemanagement proc=4320e1c0} without owner
10-17 10:59:33.849: A/ProcessStats(995): Starting service ServiceState{43317ea0 com.motorola.ccc.checkin.CheckinService pkg=com.motorola.ccc.checkin proc=43317ea0} without owner
10-17 10:59:33.854: A/ProcessStats(995): Starting service ServiceState{432d64c0 com.motorola.blur.service.blur.BlurServiceMother pkg=com.motorola.ccc.cce proc=432d64c0} without owner
10-17 10:59:33.858: A/ProcessStats(995): Starting service ServiceState{431d4538 com.motorola.ccc.ota.env.OtaService pkg=com.motorola.ccc.ota proc=431d4538} without owner
10-17 10:59:33.862: A/ProcessStats(995): Starting service ServiceState{4317ed80 com.google.android.location.fused.NlpLocationReceiverService pkg=com.google.android.gms proc=4317ed80} without owner
10-17 10:59:33.867: A/ProcessStats(995): Starting service ServiceState{430f6950 com.google.android.location.geocode.GeocodeService pkg=com.google.android.gms proc=430f6950} without owner
10-17 10:59:33.870: A/ProcessStats(995): Starting service ServiceState{431be468 com.google.android.location.fused.service.FusedProviderService pkg=com.google.android.gms proc=431be468} without owner
10-17 10:59:33.874: A/ProcessStats(995): Starting service ServiceState{4317dce0 com.google.android.location.geofencer.service.GeofenceProviderService pkg=com.google.android.gms proc=4317dce0} without owner
10-17 10:59:33.878: A/ProcessStats(995): Starting service ServiceState{42ed1ce0 com.google.android.location.reporting.service.DispatchingService pkg=com.google.android.gms proc=42ed1ce0} without owner
10-17 10:59:33.882: A/ProcessStats(995): Starting service ServiceState{43104248 com.google.android.location.internal.server.GoogleLocationService pkg=com.google.android.gms proc=43104248} without owner
10-17 10:59:33.886: A/ProcessStats(995): Starting service ServiceState{430f9868 com.google.android.location.network.NetworkLocationService pkg=com.google.android.gms proc=430f9868} without owner
10-17 10:59:33.891: A/ProcessStats(995): Starting service ServiceState{43188228 com.google.android.location.internal.GoogleLocationManagerService pkg=com.google.android.gms proc=43188228} without owner
10-17 10:59:33.895: A/ProcessStats(995): Starting service ServiceState{42b2c7c0 com.google.android.backup.BackupTransportService pkg=com.google.android.backuptransport proc=42b2c7c0} without owner
10-17 10:59:33.900: A/ProcessStats(995): Starting service ServiceState{436e4208 com.android.email.service.AttachmentDownloadService pkg=com.android.email proc=436e4208} without owner
10-17 10:59:43.622: E/AuthorizationBluetoothService(12984): Proximity feature is not enabled.
10-17 10:59:43.697: E/GCoreFlp(13341): Bound FusedProviderService with LocationManager
10-17 11:00:58.035: E/MDMCTBK(269): MdmCutbackHndler,Could not open ''
10-17 11:00:58.090: E/MDMCTBK(269): MdmCutbackHndler,Could not open ''
10-17 11:01:24.382: E/ActivityThread(13467): Failed to find provider info for com.motorola.blur.setupprovider
10-17 11:01:24.488: E/ActivityThread(13467): Failed to find provider info for com.motorola.blur.setupprovider
10-17 11:01:24.643: E/OtaApp(13467): [error] > CusSM.wifiDiscoverySanityCheck failed: wifi discover time is not set nothing to process
10-17 11:01:24.680: A/ProcessStats(995): Starting service ServiceState{436e4208 com.android.email.service.AttachmentDownloadService pkg=com.android.email proc=436e4208} without owner
10-17 11:01:25.102: E/MMApiProvisionService(13467): handleResponse(): no settings sent by the server:
10-17 11:02:18.030: E/MDMCTBK(269): MdmCutbackHndler,Could not open ''
10-17 11:02:18.054: E/MDMCTBK(269): MdmCutbackHndler,Could not open ''
10-17 11:03:25.164: E/global frequency(13467): no tags to log