如果从特定类的某些方法(OpenGL ES 2)添加网格,则网格不会被绘制

时间:2016-08-28 13:21:59

标签: java android opengl-es 3d opengl-es-2.0

所以,我试图制作一个基于OpenGL ES 2(Android)的简单3D引擎。首先(除了许多教程等),我逐步从developer.android.com tutorial复制粘贴的代码。一切都很好。然后我开始修改它。我改变了Mesh课程&#39;字段和构造函数,以便不预设顶点坐标,着色器代码,颜色和顶点数(所有代码都在问题的末尾)。 将GL20Renderer类中的网格字段更改为private List<Mesh> meshs = new ArrayList<Mesh>();。创建用于添加和删除网格的功能。目前在我的代码中使用的唯一添加功能如下:

public void addMesh( Mesh meshToAdd ) {
  meshs.add( meshToAdd );
}

GL20Renderer.onDrawFrame()中唯一的变化是那里的代码循环遍历网格列表并为每个网格调用Mesh.draw()方法:

for( Mesh meshToDraw : meshs ) {
  meshToDraw.draw(scratch);
}

然后我尝试从GL20Renderer.onSurfaceCreated()方法添加一个网格 - 它工作正常。从同一方法添加另一个网格 - 工作正常。 然后我尝试从GL20Activity.onCreate()方法添加网格(同时从GL20Renderer.onSurfaceCreated()中删除相同的代码):

float[] vertexCoords = { 0.0f, 0.622008459f, 0.0f, -0.5f, -0.311004243f, 0.0f, 0.5f, -0.311004243f, 0.0f };
int[] drawOrder = { 1, 2, 3 };
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
String vertexShaderCode = "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() {" + "  gl_Position = uMVPMatrix * vPosition;" + "}";
String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + "  gl_FragColor = vColor;" + "}";
renderer.addMesh( new Mesh( 3, vertexCoords, drawOrder, 1, color, vertexShaderCode, fragmentShaderCode) );

网格被添加到网格列表中但由于某种原因没有显示(它的属性与教程的网格属性相同)。如果从GL20Activity.onCreate()和Renderer.onSurfaceCreated()添加网格物体 - 它们都不会显示,但它们仍然在网格列表上。然后我将onRendererInitialized()方法添加到GL20Activity,这是从GL20Renderer.onCreate()方法的最后调用的。 onRendererInited()只是添加一个网格,并且只有在GL20Activity.onCreate()中没有添加网格时才会显示它。   问题是:如果从GL20Activity.onCreate()方法添加网格,为什么不绘制网格?我试过改变顶点&#39;坐标所以它们不是问题的原因。我还尝试向GL20Renderer.onDrawFrame()添加一些代码以确保meshToDraw.draw( scratch );代码行正常运行,并且它确实正常运行,但仍然没有绘制网格。但由于网格具有相同的顶点&#39;从GL20Activity.onRendererInitialized()和/或GL20Renderer.onSurfaceCreated()中添加的坐标和颜色被绘制,绘制网格不应该有任何问题,这是从GL20Activity.onCreate()添加的。

MainActivity.java:

package com.Reaper.VisionEngine;
import android.app.*;
import android.content.*;
import android.os.*;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState {
    super.onCreate(savedInstanceState);
    Intent intent = new Intent( this, GL20Activity.class );
    startActivity( intent );
  }
}

GL20Activity.java:

package com.Reaper.VisionEngine;
import android.app.*;
import android.os.*;
import android.widget.*;
import com.Reaper.VisionEngine.GLRenderer.*;
import com.Reaper.VisionEngine.GLSurfaceView.*;
import com.Reaper.VisionEngine.Mesh.*;
import java.io.*;

public class GL20Activity extends Activity {
  GL20SurfaceView GLView;
  GL20Renderer renderer;

  @Override
  protected void onCreate( Bundle savedInstanceState ) {
    super.onCreate(savedInstanceState);
    GLView = new GL20SurfaceView(this);
    setContentView(GLView);
    renderer = GLView.getRenderer();
    float[] vertexCoords = { 0.0f, 0.622008459f, 0.0f, -0.5f, -0.311004243f, 0.0f, 0.5f, -0.311004243f, 0.0f };
    int[] drawOrder = { 1, 2, 3 };
    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
    String vertexShaderCode = "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() {" + "  gl_Position = uMVPMatrix * vPosition;" + "}";
    String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + "  gl_FragColor = vColor;" + "}";
    renderer.addMesh( new Mesh( 3, vertexCoords, drawOrder, 1, color, vertexShaderCode, fragmentShaderCode) );
  }

GL20Renderer.java:

package com.Reaper.VisionEngine.GLRenderer;
import android.opengl.*;
import com.Reaper.VisionEngine.*;
import com.Reaper.VisionEngine.Mesh.*;
import java.util.*;
import javax.microedition.khronos.egl.*;
import javax.microedition.khronos.opengles.*;
import javax.microedition.khronos.egl.EGLConfig;

public class GL20Renderer implements GLSurfaceView.Renderer {
  private List<Mesh> meshs = new ArrayList<Mesh>();
  private final float[] mMVPMatrix = new float[16];
  private final float[] mProjectionMatrix = new float[16];
  private final float[] mViewMatrix = new float[16];
  private float[] mRotationMatrix = new float[16];
  public volatile float mAngle;
  private List<Mesh> meshQueue = new ArrayList<Mesh>();
  private GL20Activity activity;

  public void onSurfaceCreated(GL10 gl, EGLConfig glConfig) {
    GLES20.glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
  }

  public void onDrawFrame(GL10 gl) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
    float[] scratch = new float[16];
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
    for( Mesh meshToDraw : meshs ) {
      meshToDraw.draw(scratch);
    }
  }

  public void onSurfaceChanged(GL10 gl, int width, int height) {
    GLES20.glViewport(0, 0, width, height);
    float ratio = (float) width / height;
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
  }

  public static int loadShader(int type, String shaderCode){
    int shader = GLES20.glCreateShader(type);
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);
    return shader;
  }

  public void addMesh( Mesh meshToAdd ) {
    meshs.add( meshToAdd );
  }

GL20SurfaceView.java:

package com.Reaper.VisionEngine.GLSurfaceView;
import android.content.*;
import android.opengl.*;
import android.view.*;
import com.Reaper.VisionEngine.*;
import com.Reaper.VisionEngine.GLRenderer.*;

public class GL20SurfaceView extends GLSurfaceView {
  private final GL20Renderer Renderer;

  public GL20SurfaceView(Context context) {
    super(context);
    setEGLContextClientVersion(2);
    Renderer = new GL20Renderer();
    setRenderer(Renderer);
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
  }

  public boolean onTouchEvent(MotionEvent e) { // TODO: CHANGE THIS
    switch (e.getAction()) {
      case MotionEvent.ACTION_MOVE:
      requestRender();
    }
    return true;
  }

  public GL20Renderer getRenderer() {
    return Renderer;
  }
}

Mesh.java:

package com.Reaper.VisionEngine.Mesh;
import android.opengl.*;
import com.Reaper.VisionEngine.GLRenderer.*;
import java.nio.*;

public class Mesh {
  private FloatBuffer vertexBuffer;
  public final int GL20Program;
  private int PositionHandle;
  private int ColorHandle;
  private int MVPMatrixHandle;
  private int colorOverridesTexture = 0;
  private int vertexCount = 1;
  private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
  private int[] drawOrder; // TODO: Implement
  static final int COORDS_PER_VERTEX = 3;
  private float vertexCoords[];
  float color[] = new float[3];
  private String vertexShaderCode;
  private String fragmentShaderCode;
  private final String defaultVertexShaderCode = "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() }" + "  gl_Position = uMVPMatrix * vPosition;" + "}";
  private final String defaultFragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() }" + "  gl_FragColor = vColor;" + "}";

  public Mesh( int newVertexCount, float[] newVertexCoords, int[] newDrawOrder, int useColor, float[] newColor, String newVertexShaderCode, String newFragmentShaderCode ) {
    vertexCount = newVertexCount;
    vertexCoords = newVertexCoords;
    drawOrder = newDrawOrder;
    colorOverridesTexture = useColor;
    color = newColor;
    vertexShaderCode = newVertexShaderCode;
    fragmentShaderCode = newFragmentShaderCode;
    ByteBuffer bb = ByteBuffer.allocateDirect( vertexCoords.length * 4 );
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put( vertexCoords );
    vertexBuffer.position( 0 );
    int vertexShader = GL20Renderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    int fragmentShader = GL20Renderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
    GL20Program = GLES20.glCreateProgram();
    GLES20.glAttachShader(GL20Program, vertexShader);
    GLES20.glAttachShader(GL20Program, fragmentShader);
    GLES20.glLinkProgram(GL20Program);
  }

  public void draw(float[] mvpMatrix) {
    MVPMatrixHandle = GLES20.glGetUniformLocation(GL20Program, "uMVPMatrix");
    GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
    GLES20.glUseProgram(GL20Program);
    PositionHandle = GLES20.glGetAttribLocation(GL20Program, "vPosition");
    GLES20.glEnableVertexAttribArray(PositionHandle);
    GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
    ColorHandle = GLES20.glGetUniformLocation(GL20Program, "vColor");
    GLES20.glUniform4fv(ColorHandle, 1, color, 0);
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
    GLES20.glDisableVertexAttribArray(PositionHandle);
  }
}

抱歉英文不好。

1 个答案:

答案 0 :(得分:0)

我认为在GL20Activity.onCreate()阶段,EGL上下文不可用或不是最新的。因此在那里添加了网格,Mesh构造函数中的gl *命令将失败。即使将网格对象添加到列表中,也不会初始化相应的OpenGL元素,因此绘制将失败,或者不绘制任何内容。您可以通过在GL20Activity.onCreate()调用Mesh的构造函数中的gl *语句后检查OpenGL错误来验证这一点。

现在,当您在GL20Renderer.onSurfaceCreated()处执行相同操作时,(我认为这是GL20Renderer.onCreated()的意思),EGL上下文可用且有效,因此所有gl *命令都在Mesh&#中39; s构造函数将执行,因此网格的OpenGL组件存在,因此它可以正确显示。

  

由于此方法在渲染开始时调用,以及   每次EGL上下文丢失时,这种方法都是一个方便的地方   放置代码来创建需要在创建时创建的资源   渲染开始,并且需要在EGL上下文时重新创建   迷路了。纹理是您可能想要的资源示例   在这里创造。

请参阅https://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html了解详情。