所以,我试图制作一个基于OpenGL ES 2(Android)的简单3D引擎。首先(除了许多教程等),我逐步从developer.android.com tutorial复制粘贴的代码。一切都很好。然后我开始修改它。我改变了Mesh课程'字段和构造函数,以便不预设顶点坐标,着色器代码,颜色和顶点数(所有代码都在问题的末尾)。
将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);
}
}
抱歉英文不好。
答案 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了解详情。