简体   繁体   中英

Trying to add GLSurfaceView to a layout programmatically

Ok, Just some background... I have a fully functioning game that uses the canvas to draw, and I'm in the process of trying to learn and convert the drawing over to OpenGL ES 1.0. (to keep compatibility.)

What I've been trying to do, Is figure out a way to incorporate the GLSurfaceView and Renderer into the program so that I can switch the drawing over piece by piece. (There are a lot of sprites and I have needs to update often, so I don't want it to take me a month to release the next update.)

It has been suggested that I Use the GLSurfaceView on top of the current SurfaceView, and i'm getting there but I've hit a snag.

I'm basically using the LunarLander example and trying to add on a simple OpenGL renderer that draws a texture on a square and renders it. The goal would be to draw the square on top of the canvas.

Here is the relevant code in the Activity:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);



        setContentView(R.layout.lunar_layout);


        LinearLayout detailListView = (LinearLayout) findViewById(R.id.dets); // Find the layout where you want to add button

    Button button = new Button(this);
    button.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));
    detailListView.addView(button);//add view to add



    mGLSV = new BasicGLSurfaceView(this);
    mGLSV.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));
    detailListView.addView(mGLSV);

    //clipped

The lunar_layout file looks like this:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"

    android:layout_width="match_parent"
    android:layout_height="match_parent">



    <com.example.android.lunarlander.LunarView
        android:id="@+id/lunar"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

    <LinearLayout
       android:id="@+id/dets"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentLeft="true"
       android:layout_alignParentTop="true"
       android:layout_marginLeft="0dp"
       android:layout_marginTop="50dp"
       android:orientation="vertical" >

         <com.google.ads.AdView
             android:id="@+id/adView"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             ads:adSize="BANNER"
             ads:adUnitId="a14ecf8f2d9ef49"
             ads:loadAdOnCreate="true" >
         </com.google.ads.AdView>

    </LinearLayout>



     <RelativeLayout   
         android:id="@+id/relLayout"
         android:layout_width="match_parent"
         android:layout_height="match_parent" >

         <TextView
             android:id="@+id/text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
             android:gravity="center_horizontal"
             android:text="@string/lunar_layout_text_text"
             android:textColor="#88ffffff"
             android:textSize="24sp"
             android:visibility="visible" />

      </RelativeLayout>

</FrameLayout>

Pretty Simple, I'm trying to use that LinearLayout to add things on top of the Surface View. Notice I also add a scratch Button, just to check the concept works. What I end up with is the canvas, and the button showing up correctly, but no sign of the GLSurfaceView. What am I doing wrong?

I'd suggest you have your BasicGLSurfaceView already added to your framelayout in XML, and use findViewById(R.id.basicGLSurfaceView1) to get a hold of it, rather than trying to create it programatically:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.android.lunarlander.BasicGLSurfaceView 
        android:id="@+id/glSurfaceView1" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent">
    </com.example.android.lunarlander.BasicGLSurfaceView>

    <com.example.android.lunarlander.LunarView
      android:id="@+id/lunar"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

    <LinearLayout
       android:id="@+id/dets"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentLeft="true"
       android:layout_alignParentTop="true"
       android:layout_marginLeft="0dp"
       android:layout_marginTop="50dp"
       android:orientation="vertical" >

         <com.google.ads.AdView
             android:id="@+id/adView"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             ads:adSize="BANNER"
             ads:adUnitId="a14ecf8f2d9ef49"
             ads:loadAdOnCreate="true" >
         </com.google.ads.AdView>

    </LinearLayout>



     <RelativeLayout   
         android:id="@+id/relLayout"
         android:layout_width="match_parent"
         android:layout_height="match_parent" >

         <TextView
             android:id="@+id/text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
             android:gravity="center_horizontal"
             android:text="@string/lunar_layout_text_text"
             android:textColor="#88ffffff"
             android:textSize="24sp"
             android:visibility="visible" />

      </RelativeLayout>

</FrameLayout>

You need to tell the GLSurfaceView to start rendering. You have to call (or even override) GLSurfaceView.start() in your GLSurfaceView. Alternatively, setRenderer is public, so if you call mGLSV.setRenderer(myRenderer); in your Activity where myRenderer is an instance of MyRenderer implements GLSurfaceView.Renderer then it should automatically start the rendering without you having to touch start()

EDIT: Actually, start() is called when the view is laid out (ie when you setContentView() or add it to whatever layout you set as content view), not when setRenderer is called

It sounds back-to-front but implementing Renderer is for if you just want to render something in the standard android/opengl-es way, whilst extending GLSurfaceView is if you actually want to get under the hood and edit the way android renders. In fact, I would recommend not extending GLSurfaceView at all but doing as much as possible in your GLSurfaceView.Renderer. I have programmed my entire 3D game without extending GLSurfaceView. My code looks like this:

public class stackoverflowTest extends Activity {

MyGLSurfaceView glSurface;
MyRenderer myRenderer;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    myRenderer = new MyRenderer();

    //Get hold of our GLSurfaceView
    glSurface = (MyGLSurfaceView) findViewById(R.id.graphics_glsurfaceview1);
    // optional
    glSurface.setEGLConfigChooser(true);

    glSurface.setRenderer(myRenderer);
    //Set the renderer. setRenderer will call start() and start the GL thread, which then calls onSurfaceCreated, onDraw etc in the Renderer



}

    @Override
public void onPause(){
    super.onPause();
     glSurface.onPause();
}

@Override
public void onResume() {
       super.onResume();
       glSurface.onResume();
    }
}

}

Renderer:

public class MyRenderer implements Renderer {

@Override
public void onDrawFrame(GL10 gl) {
    // openGL drawing code goes here


}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {

    // etc


}

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


}

}

GLSurfaceView:

public class MyGLSurfaceView extends GLSurfaceView {

public MyGLSurfaceView(Context context) {
    super(context);

}

public MyGLSurfaceView(Context context, AttributeSet attribs) {
    super(context, attribs);

}

@Override
public void onPause(){
    super.onPause();
}

@Override
public void onResume(){
    super.onResume();
}

}

If you can stand upgrading to android 2.1 (opengl-es 1.1) you can use point-sprites rather than rendering textured quads or whatever

Figured it out myself. Even though SurfaceView is a subclass of View, the way SurfaceView displays through the window is kinda funny, Basically The canvas actually goes through the surfaceview but is behind it in Z order. Because of this Multiple surface views have to be ordered using surfaceview.setZOrderOnTop(true);

Now I just have to worry about making the GLSurfaceView Transparent.

Taken from min3d, this should work on making the GLSurfaceView transparent

_glSurfaceView.setEGLConfigChooser(8,8,8,8, 16, 0); 
_glSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM