如何在同一布局中使用多个 GLSurfaceView 组件?

发布于 2024-10-17 10:30:36 字数 2674 浏览 7 评论 0原文

我正在为 Android 编写一个信息可视化 API,并在尝试将两个自定义 GLSurfaceView 单元放入布局中时遇到问题。此时的自定义GLSurfaceView只是对GLSurfaceView的扩展,以消除自定义方法可能导致的错误。

当我将两个组件添加到布局中并启动它运行的应用程序时。但什么也没有绘制,似乎进入了无限循环。因为渲染器内的调试消息会打印到 LogCat 中。但是,如果我只使用自定义 GLSurfaceView 组件之一,它就可以正常工作。

我读到在多个活动中使用 GLSurfaceView 存在问题,我认为同时使用其中两个组件时也存在问题。我已尝试此处发布的解决方法,但似乎无法得到它要么工作。

我将不胜感激任何帮助。我选择使用 openGL 以获得更好的性能,但如果我不能同时使用多个组件,我想我将不得不使用 Canvas。

清单如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView android:text="@string/hello" android:id="@+id/TextView01"
        android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    <com.syntronic.vtadlib.VisualizationView android:id="@+id/glview"
        android:layout_width="fill_parent" android:layout_height="300px" />


    <TextView android:text="@string/hello" android:id="@+id/TextView02"
        android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    <LinearLayout 
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <com.syntronic.vtadlib.VisualizationView android:id="@+id/glview2"
            android:layout_width="fill_parent" android:layout_height="fill_parent" />

    </LinearLayout>

</LinearLayout>

从 Activity 中,代码如下所示:

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    mSurfaceView = (VisualizationView) findViewById(R.id.glview);
    mSurfaceView2 = (VisualizationView) findViewById(R.id.glview2);

    //Enables debug flags for Errors
    //mSurfaceView.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR);   
    //mSurfaceView2.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR);  

    mSurfaceView.setRenderer(new CoordinateSystemRenderer());
    mSurfaceView2.setRenderer(new CoordinateSystemRenderer());

}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    mSurfaceView.onPause();
    mSurfaceView2.onPause();
}

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    mSurfaceView.onResume();
    mSurfaceView2.onResume();
}

我是否遗漏了一些明显的东西?或者有人可以解释为什么它不起作用?

I'm writing an Information Visualization API for Android and ran into a problem trying to place two units of a custom GLSurfaceView into a Layout. The Custom GLSurfaceView at this point is simply an extension of the GLSurfaceView to eliminate possible faults caused by custom methods.

When I have both components added in layout and start the application it runs. But nothing is drawn, seems like it enters an infinite loop. because debug messages inside the Renderers are printed into the LogCat. However, It works perfectly fine if I only use one of the custom GLSurfaceView components.

I read that there is a problem using GLSurfaceView in multiple Activities and I suppose it also applies when using two of those components at the same time. I have tried the workaround posted here but cant seem to get it to work either.

I would appreciate any help. I choose to use openGL for the better performance, but if I cant use multiple components at once I guess I'll have to use Canvas instead.

The manifest looks as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView android:text="@string/hello" android:id="@+id/TextView01"
        android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    <com.syntronic.vtadlib.VisualizationView android:id="@+id/glview"
        android:layout_width="fill_parent" android:layout_height="300px" />


    <TextView android:text="@string/hello" android:id="@+id/TextView02"
        android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    <LinearLayout 
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <com.syntronic.vtadlib.VisualizationView android:id="@+id/glview2"
            android:layout_width="fill_parent" android:layout_height="fill_parent" />

    </LinearLayout>

</LinearLayout>

From the Activity the code is like this:

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    mSurfaceView = (VisualizationView) findViewById(R.id.glview);
    mSurfaceView2 = (VisualizationView) findViewById(R.id.glview2);

    //Enables debug flags for Errors
    //mSurfaceView.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR);   
    //mSurfaceView2.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR);  

    mSurfaceView.setRenderer(new CoordinateSystemRenderer());
    mSurfaceView2.setRenderer(new CoordinateSystemRenderer());

}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    mSurfaceView.onPause();
    mSurfaceView2.onPause();
}

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    mSurfaceView.onResume();
    mSurfaceView2.onResume();
}

Am I missing something obvious? Or can someone explain why it doesn't work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

丘比特射中我 2024-10-24 10:30:36

[更新:从 Android 5.0 (Lollipop) 开始,此答案不再正确。请参阅fadden 的回答进行讨论和链接。 从 Android 2.0 开始,它也是不正确的,并且显然是即使在此之前,也只是重叠表面的问题。]

您不能将 2 个 SurfaceViews(SV) 放入一个 Activity 中。
为了理解为什么你应该知道 SV 是如何工作的。

当您创建它并将其放置在活动上时,它实际上不会放置在活动中(或其顶部),而是会在当前活动后面创建,并在该活动中创建“透明”视图。

在 Android 4.0 (API 14) 中,有一个名为 TextureView 的新视图
无法在旧平台上创建类似 View 的内容。

[UPDATE: This answer is no longer correct, as of Android 5.0 (Lollipop). See fadden's answer for a discussion, and links. It was also incorrect as of Android 2.0, and apparently was only an issue for OVERLAPPING surfaces even before then.]

You cannot place 2 SurfaceViews(SV) into one Activity.
For understand why you should know how SVs works.

When you create it and place on activity it doesnt actually will be placed in activity (or top of it), instead it will be created behind of current activity with "transparent" view created in that activity.

In Android 4.0 (API 14) there are new View called TextureView
There are no way to create something like that View on older platforms.

攀登最高峰 2024-10-24 10:30:36

CooperativeSystemRenderer 的实现是什么?

我今天遇到了同样的要求并尝试过,它实际上有效,这意味着您可以将 2 个 GLSurfaceView 放入同一个活动中。

需要注意的是,

  1. GLRender中,当onSurfaceChanged被调用时,你必须调整你的视口大小,
  2. 如果GLSurfaceView为2,渲染线程将为2 ,所以会出现同步问题。这取决于您的 onDrawFrame 实现。

SDK GLSurfaceViewActivity 中有一个使用 Android API 的快速测试演示

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.apis.graphics;

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

import android.opengl.GLSurfaceView;

/**
 * Render a pair of tumbling cubes.
 */

public class CubeRenderer implements GLSurfaceView.Renderer
{
    boolean isReverse = false;

    public CubeRenderer(boolean useTranslucentBackground, boolean isReverse)
    {
        mTranslucentBackground = useTranslucentBackground;
        mCube = new Cube();
        this.isReverse = isReverse;
    }

    public CubeRenderer(boolean useTranslucentBackground)
    {
        this(useTranslucentBackground, false);
    }

    public void onDrawFrame(GL10 gl)
    {
        /*
         * Usually, the first thing one might want to do is to clear the screen. The most efficient way of doing this is
         * to use glClear().
         */

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

        /*
         * Now we're ready to draw some 3D objects
         */

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -3.0f);
        gl.glRotatef(mAngle, 0, 1, 0);
        gl.glRotatef(mAngle * 0.25f, 1, 0, 0);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

        mCube.draw(gl);

        gl.glRotatef(mAngle * 2.0f, 0, 1, 1);
        gl.glTranslatef(0.5f, 0.5f, 0.5f);

        mCube.draw(gl);

        if (isReverse)
        {
            mAngle -= 1.2f;
        }
        else
        {
            mAngle += 1.2f;
        }
    }

    public void onSurfaceChanged(GL10 gl, int width, int height)
    {
        System.out.println("Joey's Log width : " + width + " height : " + height);
        gl.glViewport(0, 0, width, height);

        /*
         * Set our projection matrix. This doesn't have to be done each time we draw, but usually a new projection needs
         * to be set when the viewport is resized.
         */

        float ratio = (float) width / height;
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config)
    {
        /*
         * By default, OpenGL enables features that improve quality but reduce performance. One might want to tweak that
         * especially on software renderer.
         */
        gl.glDisable(GL10.GL_DITHER);

        /*
         * Some one-time OpenGL initialization can be made here probably based on features of this particular context
         */
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

        if (mTranslucentBackground)
        {
            gl.glClearColor(0, 0, 0, 0);
        }
        else
        {
            gl.glClearColor(1, 1, 1, 1);
        }
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glEnable(GL10.GL_DEPTH_TEST);
    }

    private boolean mTranslucentBackground;

    private Cube mCube;

    private float mAngle;
}


------------------------------------------------------------------------------------------
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.apis.graphics;

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

import android.opengl.GLSurfaceView;

/**
 * Render a pair of tumbling cubes.
 */

public class CubeRenderer implements GLSurfaceView.Renderer {
    boolean isReverse = false;
    public CubeRenderer(boolean useTranslucentBackground,boolean isReverse) {
        mTranslucentBackground = useTranslucentBackground;
        mCube = new Cube();
        this.isReverse = isReverse;
    }

    public CubeRenderer(boolean useTranslucentBackground)
    {
        this(useTranslucentBackground, false);
    }

    public void onDrawFrame(GL10 gl) {
        /*
         * Usually, the first thing one might want to do is to clear
         * the screen. The most efficient way of doing this is to use
         * glClear().
         */

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

        /*
         * Now we're ready to draw some 3D objects
         */

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -3.0f);
        gl.glRotatef(mAngle,        0, 1, 0);
        gl.glRotatef(mAngle*0.25f,  1, 0, 0);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

        mCube.draw(gl);

        gl.glRotatef(mAngle*2.0f, 0, 1, 1);
        gl.glTranslatef(0.5f, 0.5f, 0.5f);

        mCube.draw(gl);

        if (isReverse)
        {
            mAngle -= 1.2f;
        }
        else
        {
            mAngle += 1.2f;
        }
    }

    public void onSurfaceChanged(GL10 gl, int width, int height) {
        System.out.println("Joey's Log width : " + width + " height : " + height);
         gl.glViewport(0, 0, width, height);

         /*
          * Set our projection matrix. This doesn't have to be done
          * each time we draw, but usually a new projection needs to
          * be set when the viewport is resized.
          */

         float ratio = (float) width / height;
         gl.glMatrixMode(GL10.GL_PROJECTION);
         gl.glLoadIdentity();
         gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        /*
         * By default, OpenGL enables features that improve quality
         * but reduce performance. One might want to tweak that
         * especially on software renderer.
         */
        gl.glDisable(GL10.GL_DITHER);

        /*
         * Some one-time OpenGL initialization can be made here
         * probably based on features of this particular context
         */
         gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
                 GL10.GL_FASTEST);

         if (mTranslucentBackground) {
             gl.glClearColor(0,0,0,0);
         } else {
             gl.glClearColor(1,1,1,1);
         }
         gl.glEnable(GL10.GL_CULL_FACE);
         gl.glShadeModel(GL10.GL_SMOOTH);
         gl.glEnable(GL10.GL_DEPTH_TEST);
    }
    private boolean mTranslucentBackground;
    private Cube mCube;
    private float mAngle;
}

What's the implementation for CoordinateSystemRenderer?

I met the same requirement today and tried, it actually works that means, you can put 2 GLSurfaceView into same activity.

Something need to be noticed,

  1. In GLRender, when onSurfaceChanged is invoked, you must resize your viewport
  2. With 2 GLSurfaceView, the render thread will be 2, so synchronize issue will be occurred. It depends on your implementation of onDrawFrame.

There is a quick test to use Android API demo in SDK GLSurfaceViewActivity

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.apis.graphics;

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

import android.opengl.GLSurfaceView;

/**
 * Render a pair of tumbling cubes.
 */

public class CubeRenderer implements GLSurfaceView.Renderer
{
    boolean isReverse = false;

    public CubeRenderer(boolean useTranslucentBackground, boolean isReverse)
    {
        mTranslucentBackground = useTranslucentBackground;
        mCube = new Cube();
        this.isReverse = isReverse;
    }

    public CubeRenderer(boolean useTranslucentBackground)
    {
        this(useTranslucentBackground, false);
    }

    public void onDrawFrame(GL10 gl)
    {
        /*
         * Usually, the first thing one might want to do is to clear the screen. The most efficient way of doing this is
         * to use glClear().
         */

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

        /*
         * Now we're ready to draw some 3D objects
         */

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -3.0f);
        gl.glRotatef(mAngle, 0, 1, 0);
        gl.glRotatef(mAngle * 0.25f, 1, 0, 0);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

        mCube.draw(gl);

        gl.glRotatef(mAngle * 2.0f, 0, 1, 1);
        gl.glTranslatef(0.5f, 0.5f, 0.5f);

        mCube.draw(gl);

        if (isReverse)
        {
            mAngle -= 1.2f;
        }
        else
        {
            mAngle += 1.2f;
        }
    }

    public void onSurfaceChanged(GL10 gl, int width, int height)
    {
        System.out.println("Joey's Log width : " + width + " height : " + height);
        gl.glViewport(0, 0, width, height);

        /*
         * Set our projection matrix. This doesn't have to be done each time we draw, but usually a new projection needs
         * to be set when the viewport is resized.
         */

        float ratio = (float) width / height;
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config)
    {
        /*
         * By default, OpenGL enables features that improve quality but reduce performance. One might want to tweak that
         * especially on software renderer.
         */
        gl.glDisable(GL10.GL_DITHER);

        /*
         * Some one-time OpenGL initialization can be made here probably based on features of this particular context
         */
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

        if (mTranslucentBackground)
        {
            gl.glClearColor(0, 0, 0, 0);
        }
        else
        {
            gl.glClearColor(1, 1, 1, 1);
        }
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glEnable(GL10.GL_DEPTH_TEST);
    }

    private boolean mTranslucentBackground;

    private Cube mCube;

    private float mAngle;
}


------------------------------------------------------------------------------------------
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.apis.graphics;

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

import android.opengl.GLSurfaceView;

/**
 * Render a pair of tumbling cubes.
 */

public class CubeRenderer implements GLSurfaceView.Renderer {
    boolean isReverse = false;
    public CubeRenderer(boolean useTranslucentBackground,boolean isReverse) {
        mTranslucentBackground = useTranslucentBackground;
        mCube = new Cube();
        this.isReverse = isReverse;
    }

    public CubeRenderer(boolean useTranslucentBackground)
    {
        this(useTranslucentBackground, false);
    }

    public void onDrawFrame(GL10 gl) {
        /*
         * Usually, the first thing one might want to do is to clear
         * the screen. The most efficient way of doing this is to use
         * glClear().
         */

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

        /*
         * Now we're ready to draw some 3D objects
         */

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -3.0f);
        gl.glRotatef(mAngle,        0, 1, 0);
        gl.glRotatef(mAngle*0.25f,  1, 0, 0);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

        mCube.draw(gl);

        gl.glRotatef(mAngle*2.0f, 0, 1, 1);
        gl.glTranslatef(0.5f, 0.5f, 0.5f);

        mCube.draw(gl);

        if (isReverse)
        {
            mAngle -= 1.2f;
        }
        else
        {
            mAngle += 1.2f;
        }
    }

    public void onSurfaceChanged(GL10 gl, int width, int height) {
        System.out.println("Joey's Log width : " + width + " height : " + height);
         gl.glViewport(0, 0, width, height);

         /*
          * Set our projection matrix. This doesn't have to be done
          * each time we draw, but usually a new projection needs to
          * be set when the viewport is resized.
          */

         float ratio = (float) width / height;
         gl.glMatrixMode(GL10.GL_PROJECTION);
         gl.glLoadIdentity();
         gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        /*
         * By default, OpenGL enables features that improve quality
         * but reduce performance. One might want to tweak that
         * especially on software renderer.
         */
        gl.glDisable(GL10.GL_DITHER);

        /*
         * Some one-time OpenGL initialization can be made here
         * probably based on features of this particular context
         */
         gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
                 GL10.GL_FASTEST);

         if (mTranslucentBackground) {
             gl.glClearColor(0,0,0,0);
         } else {
             gl.glClearColor(1,1,1,1);
         }
         gl.glEnable(GL10.GL_CULL_FACE);
         gl.glShadeModel(GL10.GL_SMOOTH);
         gl.glEnable(GL10.GL_DEPTH_TEST);
    }
    private boolean mTranslucentBackground;
    private Cube mCube;
    private float mAngle;
}
初见终念 2024-10-24 10:30:36

GLSurfaceView 背后有很多事情要做,包括管理 GLContext,我很确定你无法让它工作,即使你成功了,以后可能会遇到更多意想不到的问题。所以我真的相信这不是正确的应用程序架构。

There is a lot going behind the GLSurfaceView including managing GLContext, I'm pretty sure you won't be able to make it work, even if you succeed you might get into more unexpected issues later on. So I really believe it is not the right application architecture.

哑剧 2024-10-24 10:30:36

您可能想使用全屏 GLSurfaceView 研究在屏幕的“正确”区域中覆盖/底层模型。您可能想要组合某种布局框架来简化此操作,或者可能在全屏 GLSurfaceView 上使用多个视口。还没有在 OpenGL ES 中尝试过这些,但通常这些方法中的任何一个都将用于在桌面系统上的单个应用程序中渲染相同甚至许多不同模型的多个视图,而不是使用多个 GLContext(如果是这样的话)这里发生在幕后)。

You may may want to investigate overlaying/under-laying your models in the 'correct' area of the screen using a full screen GLSurfaceView. You may want to put together some sort of layout framework to make this simpler, or perhaps using multiple Viewports on the full screen GLSurfaceView. Haven't tried these in OpenGL ES, but generally either of these methods would be the used to render multiple views of the same or even many different models in a single application on a desktop system rather than using multiple GLContexts (if that is what is going on behind the scenes here).

つ低調成傷 2024-10-24 10:30:36

这是一种替代方法。从此处的 Android 文档下载示例: http://developer.android.com/shareables/训练/OpenGLES.zip
在此 zip 文件中,您将看到 2 个项目。打开项目:HelloOpenGLES20,并将“MyGLRenderer”类替换为下面列出的我的类,然后运行该项目。

package com.example.android.opengl;

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

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

public class MyGLRenderer implements GLSurfaceView.Renderer {

    private static final String TAG = "MyGLRenderer";
    private Triangle[] mTriangle = new Triangle[2];
    private final float[] mMVPMatrix = new float[16];
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];
    private final float[] mRotationMatrix = new float[16];

    private float mAngle;

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

        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        mTriangle[0] = new Triangle();
        mTriangle[1] = new Triangle();

    }

    @Override
    public void onDrawFrame(GL10 unused) {

        final float[] scratch = new float[16];

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

        for(int i = 0; i < 2; i++) {

            if(i % 2 == 0) {

                Matrix.setRotateM(mRotationMatrix, 0, mAngle / 2f, 0, 0, 1.0f);

            }
            else {

                Matrix.setRotateM(mRotationMatrix, 0, mAngle / 4f, 0, 0, 1.0f);

            }

            Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

            mTriangle[i].draw(scratch);

        }//End for(int i = 0; i < 2; i++)

    }//End public void onDrawFrame(GL10 unused)

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

        GLES20.glViewport(0, 0, width, height);
        float ratio = (float) width / height;
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);

    }

    public static int loadShader(int type, String shaderCode){

        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        return shader;

    }

    public static void checkGlError(String glOperation) {

        int error;

        while((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {

            Log.e(TAG, glOperation + ": glError " + error);
            throw new RuntimeException(glOperation + ": glError " + error);

        }

    }

    public float getAngle() {
        return mAngle;
    }


    public void setAngle(float angle) {
        mAngle = angle;
    }

}

据我了解,OpenGLES 设计为仅使用一个视图,但可能具有多个渲染目标。尽管我必须管理,但我不确定您尝试做的事情是否错误。我自己对 OpenGLES 来说还是个新手。我在 bitbucket 中有一个 OpenGL 开源库。您也许可以从中得到一些想法:https://bitbucket.org/warwick/hacergestov2,这是一个手势库。

Here's an alternative way of doing it. Download the sample from the Android docs here: http://developer.android.com/shareables/training/OpenGLES.zip
In this zip file you will see 2 projects. Open the project: HelloOpenGLES20 and replace the 'MyGLRenderer' Class with my one listed below and run the project.

package com.example.android.opengl;

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

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

public class MyGLRenderer implements GLSurfaceView.Renderer {

    private static final String TAG = "MyGLRenderer";
    private Triangle[] mTriangle = new Triangle[2];
    private final float[] mMVPMatrix = new float[16];
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];
    private final float[] mRotationMatrix = new float[16];

    private float mAngle;

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

        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        mTriangle[0] = new Triangle();
        mTriangle[1] = new Triangle();

    }

    @Override
    public void onDrawFrame(GL10 unused) {

        final float[] scratch = new float[16];

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

        for(int i = 0; i < 2; i++) {

            if(i % 2 == 0) {

                Matrix.setRotateM(mRotationMatrix, 0, mAngle / 2f, 0, 0, 1.0f);

            }
            else {

                Matrix.setRotateM(mRotationMatrix, 0, mAngle / 4f, 0, 0, 1.0f);

            }

            Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

            mTriangle[i].draw(scratch);

        }//End for(int i = 0; i < 2; i++)

    }//End public void onDrawFrame(GL10 unused)

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

        GLES20.glViewport(0, 0, width, height);
        float ratio = (float) width / height;
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);

    }

    public static int loadShader(int type, String shaderCode){

        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        return shader;

    }

    public static void checkGlError(String glOperation) {

        int error;

        while((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {

            Log.e(TAG, glOperation + ": glError " + error);
            throw new RuntimeException(glOperation + ": glError " + error);

        }

    }

    public float getAngle() {
        return mAngle;
    }


    public void setAngle(float angle) {
        mAngle = angle;
    }

}

From what I understand, OpenGLES is designed to use only One view but with potentially multiple Render targets. Though I must admin I'm not sure that what your trying to do is wrong or not. I'm a bit of a newb to OpenGLES myself. I have an OpenGL open source library in bitbucket. You may be able to get some ideas from it: https://bitbucket.org/warwick/hacergestov2, it's a gesture library.

梦里泪两行 2024-10-24 10:30:36

您可以在一个活动中让多个 GLSurfaceView 处于活动状态并可见。每个视图都有自己的 GL 上下文。

You can have multiple GLSurfaceViews active and visible in an Activity. Each view gets its own GL context.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文