【问题标题】:Is it possible to render an Android View to an OpenGL FBO or texture?是否可以将 Android 视图渲染到 OpenGL FBO 或纹理?
【发布时间】:2012-09-19 16:56:49
【问题描述】:

是否可以将视图(例如,WebView)渲染到 FBO,以便在 OpenGL 合成中用作纹理?

【问题讨论】:

  • 继续?还是作为一次性快照交易?
  • 据我所知,没有。 AFAIK 你能做的最好的事情是将视图渲染到位图并使用 GLUtils 将其分配给纹理。
  • @harism 我无法想象这样做的帧速率会非常高。一定有比这更好的方法。

标签: android opengl-es


【解决方案1】:

我汇集了一个完整的演示项目,它以一种有效的方式实时渲染 GL 纹理的视图,可以在 this repo 中找到。以如何将 WebView 实时渲染为 GL 纹理为例。

还有一个简短的代码如下所示(取自上面 repo 中的演示项目):

public class GLWebView extends WebView {

    private ViewToGLRenderer mViewToGLRenderer;
    ...
    // drawing magic
    @Override
    public void draw( Canvas canvas ) {
        //returns canvas attached to gl texture to draw on
        Canvas glAttachedCanvas = mViewToGLRenderer.onDrawViewBegin();
        if(glAttachedCanvas != null) {
            //translate canvas to reflect view scrolling
            float xScale = glAttachedCanvas.getWidth() / (float)canvas.getWidth();
            glAttachedCanvas.scale(xScale, xScale);
            glAttachedCanvas.translate(-getScrollX(), -getScrollY());
            //draw the view to provided canvas
            super.draw(glAttachedCanvas);
        }
        // notify the canvas is updated
        mViewToGLRenderer.onDrawViewEnd();
    }

    ...
}


public class ViewToGLRenderer implements GLSurfaceView.Renderer{

    private SurfaceTexture mSurfaceTexture;
    private Surface mSurface;

    private int mGlSurfaceTexture;
    private Canvas mSurfaceCanvas;

    ...

    @Override
    public void onDrawFrame(GL10 gl){
        synchronized (this){
            // update texture
            mSurfaceTexture.updateTexImage();
        }
   }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height){
        releaseSurface();
        mGlSurfaceTexture = createTexture();
        if (mGlSurfaceTexture > 0){
            //attach the texture to a surface.
            //It's a clue class for rendering an android view to gl level
            mSurfaceTexture = new SurfaceTexture(mGlSurfaceTexture);
            mSurfaceTexture.setDefaultBufferSize(mTextureWidth, mTextureHeight);
            mSurface = new Surface(mSurfaceTexture);
        }

    }

    public Canvas onDrawViewBegin(){
        mSurfaceCanvas = null;
        if (mSurface != null) {
            try {
                mSurfaceCanvas = mSurface.lockCanvas(null);
            }catch (Exception e){
                Log.e(TAG, "error while rendering view to gl: " + e);
            }
        }
        return mSurfaceCanvas;
    }

    public void onDrawViewEnd(){
        if(mSurfaceCanvas != null) {
            mSurface.unlockCanvasAndPost(mSurfaceCanvas);
        }
        mSurfaceCanvas = null;
    }
}

演示输出截图:

【讨论】:

  • 是的,它有效。但是视图仍然需要添加到Activity中。我们可以在不将它们添加到可见布局的情况下渲染它们吗?
  • 这种方法是有问题的,因为 WebView 现在接受来自屏幕的所有触摸事件。没有用于将实际触摸事件的位置转换为虚拟触摸事件到 web 视图的 GL 表示的层。
  • @virus 有没有办法渲染整个应用程序,而不是一个 WebView?
  • @TimotejLeginus,我不这么认为,但这取决于您所说的“整个应用程序”是什么意思。您可以将任何视图呈现给 GL,并根据您的情况进行处理。此外,根据您的用例,使用 Unity、AndEngine 等引擎可能会有所帮助。
  • 实际上,我正在尝试将纹理传递给 Unity。我想知道是否有一种简单的方法可以将整个应用程序渲染为纹理。
【解决方案2】:

是的,这当然可能,我已经在这里写了一个操作方法; http://www.felixjones.co.uk/neo%20website/Android_View/

但是对于不会改变的静态元素,位图选项可能会更好。

【讨论】:

  • 我发现并非所有视图都可以绘制。 TextureView 不能这样画。你能解决吗?
  • @fadden 如果我使用 TextureView,我发现 TextureView.OnFrameAvailableListener 的 onSurfaceTextureAvailable 没有回调。为什么TextureView不能这样画?
【解决方案3】:

至少有人设法以这种方式呈现文本:

Rendering Text in OpenGL on Android

它描述了我使用 OpenGL ES 1.0 和 TrueType/OpenType 字体文件高效渲染高质量动态文本的方法。

[...]

整个过程其实很简单。我们生成位图(作为纹理),计算并存储每个字符的大小,以及它在纹理上的位置(UV 坐标)。还有一些其他更精细的细节,但我们会讲到这些。

OpenGL ES 2.0 版本:https://github.com/d3kod/Texample2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多