1

我正在开发一个简单的安卓游戏。我想通过多线程优化我的引擎。我正在使用 OpenGL ES,Android 2.2

现在 UpdateGame() 和 RenderScene() 在单线程中运行并在 onDrawFrame(GL10 gl) 中执行

我有一个具有 Position、Rotation、Scale 和 Color 成员的 RenderObject 类。所有 RenderObjects 都是在我开始游戏时创建的,并存储在 RenderObject 数组中。

在 UpdateGame() 函数中,我通过 RenderObject 数组中的 RenderObjects 并更新新的位置、旋转、缩放和颜色。

在 RenderScene() 函数中,我通过 RenderObject 数组中的 RenderObjects 并使用新的 Position、Rotation、Scale 和 Color 渲染它们。

这在单线程中工作正常。

于是我尝试为 UpdateGame() 创建一个线程。

所以我的想法是:

更新线程:......渲染线程:

更新第 0 帧

更新第 1 帧.............渲染第 0 帧....更新和渲染并行工作

更新第 2 帧.............渲染第 1 帧

更新第 3 帧................渲染第 2 帧

但首先我修改了 RenderObject 类,使其具有 RenderPosition、RenderRotation、RenderScale 和 RenderColor 成员。

这些成员在渲染前一帧之前被复制。这样并行更新线程就可以修改新的位置、旋转、比例、颜色。

Runnable pRunnable;
Thread pThread;
public int renderframe = 0;
piblic int updateframe = 0;

public void onSurfaceCreated(GL10 gl, EGLConfig config) 
{
    // I create a new thread in this function        
    pRunnable = new Runnable(){
         public void run(){
             while(true)
             {
                 while( renderframe < updateframe )
                 {
                     // WAITING for render to finish so that data does not get corrupterd
                 }
                 // 
                 // I update RenderObject Position, Rotation, Scale, Color members here
                 UpdateGame();
                 updateframe++;
             }  
         }
    };

    pThread = new Thread(pRunnable);
    pThread.start();
}

public void onDrawFrame(GL10 gl) 
{
    while( renderframe == updateframe )
    {
         // Wait for update to finish
    }

    for(int a=0;a<MAX_RENDER_OBJECTS;a++)
    {
        RenderObject ro = aRenderObjects[a];
        // I do this in a function
        ro.RenderPosition[0] = ro.Position[0];
        ro.RenderPosition[1] = ro.Position[1];
        ro.RenderPosition[2] = ro.Position[2];
        ro.RenderPosition[3] = ro.Position[3];
        // I do the same for Rotation, Scale, Color

    }

    renderframe++;

    // When rendering scene I use RenderPosition, RenderRotation members when calling OpenGL API
    RenderScene(); 

}

但是当我运行我的游戏时。图形不正确。看起来好像数据不同步。

关于如何在 Update 和 Render 线程之间适当地同步 RenderObject 数据的任何建议。

谢谢你。

4

1 回答 1

0

这种风格通常看起来效率低下(自旋等待循环会阻止两个线程同时工作)并且很危险(我不知道 Android 是如何实现的,但 Java 内存模型并不能保证来自一个线程的数据对另一个线程可见无需通过同步块)。

我的建议是:主线程是渲染线程(GL 上下文是线程本地的,所以你不能从另一个线程使用它(尽管你可以在另一个线程上创建另一个上下文来执行一些数据共享)),然后产生更新线程。然后主线程继续循环,在每次迭代时等待互斥体。更新线程更新游戏逻辑,并创建一个新对象来表示必须绘制的所有内容(例如绘制命令列表)。然后将该对象放入队列并唤醒主线程(使用 notify())。然后主线程获取绘图数据并进行绘制。

如果更新循环比渲染循环快得多,您可能希望忽略较旧的数据集,但是这个总体思路应该可以帮助您入门。

于 2012-07-28T13:28:26.237 回答