android - 按钮、OpenGL 和渲染器 - Android

标签 android multithreading opengl-es runnable renderer

我希望有一个 OpenGL View (GLSurfaceView),它使用 RelativeLayout 中的一些按钮旁边的渲染器,以便这些按钮中的每一个都可以与渲染的 View 交互。

假设在这个 RelativeLayout 中我有一个 GLSurfaceView 和它下面的一个按钮,按下时会将 GLSurfaceView 更改为随机纯色。我了解如何在 OpenGL 中绘制,但我不了解的是如何从渲染器外部与渲染器交互,以便可以通过与 View 本身的触摸事件无关的用户输入来更改表面。

根据我的研究,我猜测我需要某种线程,并且我可能需要使用方法 queueEvent(Runnable)。虽然不确定从这里去哪里。

XML(主.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RL1"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

<android.opengl.GLSurfaceView
    android:id="@+id/GLView"
    android:layout_width="200dip"
    android:layout_height="200dip"
    android:layout_centerHorizontal="true"

     />


<Button
    android:id="@+id/Button1"
    android:layout_width="150dip"
    android:layout_height="100dip"
    android:text="Click."
    android:layout_below="@id/GLView"
    android:layout_centerHorizontal="true"
     />

Activity (Basic.java)

import android.app.Activity;
import android.opengl.*;
import android.os.Bundle;


public class Basic extends Activity {
/** Called when the activity is first created. */


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    GLSurfaceView glView = (GLSurfaceView)findViewById(R.id.GLView);
    glView.setRenderer(new BasicRenderer(this));


}
}

渲染器(OpenGLRenderer.java)

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;

public class BasicRenderer implements Renderer {

private Context mContext;
private float mWidth, mHeight;
public BasicRenderer(Context context){
    mContext=context;
}

@Override
public void onDrawFrame(GL10 gl) {
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | 
            GL10.GL_DEPTH_BUFFER_BIT);



}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    mWidth = (float)width; 
    mHeight = (float)height;

    gl.glViewport(0, 0, width, height);

    gl.glMatrixMode(GL10.GL_PROJECTION);

    gl.glLoadIdentity();

    GLU.gluPerspective(gl, 45.0f,
                               (float) width / (float) height,
                               0.1f, 100.0f);

    gl.glMatrixMode(GL10.GL_MODELVIEW);

    gl.glLoadIdentity();

}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    // Set the background color to white
    gl.glClearColor(1f, 1f, 1f, 0.5f); 

    gl.glShadeModel(GL10.GL_SMOOTH);

    gl.glClearDepthf(1.0f);

    gl.glEnable(GL10.GL_DEPTH_TEST);

    gl.glDepthFunc(GL10.GL_LEQUAL);

    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, 
                      GL10.GL_NICEST);

}

}

最佳答案

我知道这是一个老问题,但它有一些选票,所以要回答它

我用来跨线程与我的渲染器通信的技巧是将渲染器对象保持为 Activity 中的变量,然后在渲染器中排队等待绘制下一帧(下一次调用 onDraw)时执行的操作:

public class Basic extends Activity {
/** Called when the activity is first created. */

BasicRenderer myRenderer;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    myRenderer = new BasicRenderer(this);

    GLSurfaceView glView = (GLSurfaceView)findViewById(R.id.GLView);
    glView.setRenderer(myRenderer);


    myRenderer.queueDoSomethingNextTick(BasicRenderer.DO_THIS);

    findViewById(R.id.Button1).setOnTocuhListener(new OnTouchListener(){

        public void onTouch(MotionEvent event){
            myRenderer.queueDoSomethingNextTick(BasicRenderer.DO_THAT);
           // Compiler might complain about myRenderer not being final
        }


    });


}
}


public class BasicRenderer implements Renderer {

    private Context mContext;
    private float mWidth, mHeight;


    private int command;
    public static final DO_THIS = 1;
    public static final DO_THAT = 2;

public BasicRenderer(Context context){
    mContext=context;
}

@Override
public void onDrawFrame(GL10 gl) {

    if(command==DO_THIS){
        //doThis();
    } else if(command==DO_THAT){
        //doThat();
    }

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | 
        GL10.GL_DEPTH_BUFFER_BIT);

    gl.glDrawAwesomeness();


}

public void queueDoSomethingNextTick(int command){

    this.command = command;

}

}

在上面的示例中,您可能希望将命令更改为数组并循环遍历它。我实际上使用这种方法告诉我的渲染器要绘制哪些模型,或者告诉我的渲染器开始提前加载大型模型或纹理,这样当游戏轮到需要它时,它已经在内存中并且没有在绘制之前延迟加载它

关于android - 按钮、OpenGL 和渲染器 - Android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7019811/

相关文章:

android - Opengl-使用着色器,有必要吗?

android - 即使 listView 中有元素,listView.SeptEmptyView 也会始终显示

java - 为什么线程共享堆空间?

java - Java中一个对象可以创建多个线程吗

multithreading - 防止虚假分享的奇怪代码

objective-c - Xcode 'Capture OpenGL ES frame' 响应 'application not found'

android - 如何使 native C 可执行文件在 Android 中永远运行?

java - 如果没有 MainActivity,我无法使用 getAssets 方法

android - 从付费更改为免费时如何以编程方式查看用户是否已为我的应用付费

ios - 在 iOS openGL 中,如何创建类似于 kCGBlendModeDarken 的混合模式?