OpenGL ES在运行时创建对象(OpenGLES - Create objects at runtime)

我是OpenGL的新手,从dev.android.com的小教程开始。 示例代码包含Square几何的Square类。该对象将在onSurfaceCreated()方法中创建,并使用onDrawFrame()绘制每一帧。 这是Square(构造函数和draw-method)的示例代码:

public Square() { // initialize vertex byte buffer for shape coordinates ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); bb.order(ByteOrder.nativeOrder()); vertexBuffer = bb.asFloatBuffer(); vertexBuffer.put(squareCoords); vertexBuffer.position(0); // initialize byte buffer for the draw list ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2); dlb.order(ByteOrder.nativeOrder()); drawListBuffer = dlb.asShortBuffer(); drawListBuffer.put(drawOrder); drawListBuffer.position(0); // prepare shaders and OpenGL program int vertexShader = MyGLRenderer.loadShader( GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = MyGLRenderer.loadShader( GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program GLES20.glLinkProgram(mProgram); // create OpenGL program executables } public void draw(float[] mvpMatrix) { // Add program to OpenGL environment GLES20.glUseProgram(mProgram); // get handle to vertex shader's vPosition member mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(mPositionHandle); // Prepare the triangle coordinate data GLES20.glVertexAttribPointer( mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); // get handle to fragment shader's vColor member mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // Set color for drawing the triangle GLES20.glUniform4fv(mColorHandle, 1, color, 0); // get handle to shape's transformation matrix mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); MyGLRenderer.checkGlError("glGetUniformLocation"); // Apply the projection and view transformation GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); MyGLRenderer.checkGlError("glUniformMatrix4fv"); // Draw the square GLES20.glDrawElements( GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer); // Disable vertex array GLES20.glDisableVertexAttribArray(mPositionHandle); }

我现在的问题是:如何在触摸事件之后创建不在onSurfaceCreated()的对象?

我尝试定义一个Square变量但不在onSurfaceCreated()初始化它,然后在绘制之前检查对象是否为null。 触摸后我打电话给

mSquare = new Square();

我知道它不是实现这个的好方法,但我只想尝试一下是否有效。 我会创建一个可绘制元素列表并在onDrawFrame()方法中运行它,从列表对象中调用每个draw()。 但由于这种方法导致Proram崩溃,我不知道该怎么做

I'm new to OpenGL and started with the small tutorial from dev.android.com. The sample code includes this Square class for a square geometry. The object will be created in the onSurfaceCreated() method and drawn every frame using onDrawFrame(). Here is the example code of the Square (constructor and draw-method):

public Square() { // initialize vertex byte buffer for shape coordinates ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); bb.order(ByteOrder.nativeOrder()); vertexBuffer = bb.asFloatBuffer(); vertexBuffer.put(squareCoords); vertexBuffer.position(0); // initialize byte buffer for the draw list ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2); dlb.order(ByteOrder.nativeOrder()); drawListBuffer = dlb.asShortBuffer(); drawListBuffer.put(drawOrder); drawListBuffer.position(0); // prepare shaders and OpenGL program int vertexShader = MyGLRenderer.loadShader( GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = MyGLRenderer.loadShader( GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program GLES20.glLinkProgram(mProgram); // create OpenGL program executables } public void draw(float[] mvpMatrix) { // Add program to OpenGL environment GLES20.glUseProgram(mProgram); // get handle to vertex shader's vPosition member mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(mPositionHandle); // Prepare the triangle coordinate data GLES20.glVertexAttribPointer( mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); // get handle to fragment shader's vColor member mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // Set color for drawing the triangle GLES20.glUniform4fv(mColorHandle, 1, color, 0); // get handle to shape's transformation matrix mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); MyGLRenderer.checkGlError("glGetUniformLocation"); // Apply the projection and view transformation GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); MyGLRenderer.checkGlError("glUniformMatrix4fv"); // Draw the square GLES20.glDrawElements( GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer); // Disable vertex array GLES20.glDisableVertexAttribArray(mPositionHandle); }

My question is now: how can I create the object not at onSurfaceCreated() but after a touch event?

I tried to define a Square variable but not initialize it at onSurfaceCreated(), then check if the object is null before drawing it. After the touch I called:

mSquare = new Square();

I know it's not a good way of implementing this, but I just wanted to try if it works. I would have created a list of drawable elements and run through it in the onDrawFrame() method, calling every draw() from the list objects. But since this method causes the program to crash, I don't know how to go on.

最满意答案

您只能在OpenGL上下文中调用OpenGL。

存在此上下文的方法有3种:

1) onSurfaceCreated - 当创建/重新创建onSurfaceCreated时 - 您应该在此处加载资源

2) onSurfaceChanged - 创建后和表面调整大小 - 你应该在这里指定依赖于大小的变量

3) onDrawFrame - 这里执行渲染。 在这里,您应该执行所有绘图命令

如果您尝试在上下文之外执行OpenGL调用 - 很可能代码将无法正确执行

You can only make calls to OpenGL within an OpenGL context.

There are 3 methods in which this context exists:

1) onSurfaceCreated - when context is created/recreated - you should load resources here

2) onSurfaceChanged - after creation and on a surface resize - you should assign size-dependent variables here

3) onDrawFrame - here rendering is executed - here you should execute all drawing commands

If you try to execute OpenGL calls outside of the context, most likely the code will fail to execute correctly.

更多推荐