我正在 Android 上使用 OpenGL ES 2.0 制作 2D 游戏,以此作为学习很多东西的借口。我画了很多线来制作一个网格,但是设置一切都需要时间,我想在设置稍后绘制的对象时渲染一个加载屏幕。
在尝试解决这个问题时,我遇到了一个我无法理解的问题,所以我的问题是为什么我会看到这种行为。
编码:
这是其实例将代表每一行的类:
这只是我在网上找到的一个稍作修改的示例。对 Thread.sleep 的调用只是为了增加创建它所需的时间,以便我可以显示我面临的问题。
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
public class LineExample {
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"void main() {" +
" gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);" +
"}";
private int mProgram;
private FloatBuffer vertexBuffer;
private ByteBuffer bb;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 2;
private final int vertexStride = COORDS_PER_VERTEX * 4; // bytes per vertex
private float lineCoords[] = new float[2*COORDS_PER_VERTEX];
private int vertexCount = lineCoords.length / COORDS_PER_VERTEX;
public LineExample(float[] lineCoords) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.lineCoords = lineCoords;
// initialize vertex byte buffer for shape coordinates
bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
lineCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(lineCoords);
vertexBuffer.position(0);
// prepare shaders and OpenGL program
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = 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() {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
int 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);
// Draw
GLES20.glDrawArrays(GLES20.GL_LINES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
private 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;
}
}
这是渲染器:
public class MyRenderer2 implements Renderer {
LineExample currentLineToRender = null;
@Override
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
if (currentLineToRender!=null){
currentLineToRender.draw();
}
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//initializeLines();
initializeLinesSameThread();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
private void initializeLines(){
float[] waitingLineVerts = {-0.5f,0.0f , 0.5f,0.0f};
currentLineToRender = new LineExample(waitingLineVerts);
new Thread(){
public void run() {
float[] doneLineVerts = {0.0f,-0.5f , 0.0f,0.5f};
currentLineToRender = new LineExample(doneLineVerts);
}
}.start();
}
private void initializeLinesSameThread(){
float[] waitingLineVerts = {-0.5f,0.0f , 0.5f,0.0f};
currentLineToRender = new LineExample(waitingLineVerts);
float[] doneLineVerts = {0.0f,-0.5f , 0.0f,0.5f};
currentLineToRender = new LineExample(doneLineVerts);
}
}
目标是在 5 秒内看到一条水平线(类似于加载屏幕),然后看到一条垂直线(类似于实际游戏网格)。但是,使用此代码,我会得到一个黑屏约 10 秒,然后绘制第二条线。
我认为线程正忙于初始化代码,所以它没有绘制第一行,所以为了让它到达onDrawFrame方法并绘制第一行,我决定在另一个线程上调用第二行的初始化(通过在onSurfaceCreated上调用initializeLines()而不是initializeLinesSameThread()),但这样做,我只看到第一行,而我永远看不到第二行。
我的猜测是,当调用 line 的 draw 方法时,渲染器线程无法访问其他线程中完成的某些事情。
我的问题是为什么会这样?
(如果你能给我一个关于如何实现我想做的事情的建议,我将不胜感激)