我有一个渲染脚本,它处理在输出中提供给分配的图像。我想在我的 OpenGL 程序中将此分配用作纹理,但我不知道如何从分配中获取纹理 ID。
另一方面,我知道我可以使用图形渲染脚本,但由于它已被弃用,我想必须有其他方法来实现相同的结果。
我有一个渲染脚本,它处理在输出中提供给分配的图像。我想在我的 OpenGL 程序中将此分配用作纹理,但我不知道如何从分配中获取纹理 ID。
另一方面,我知道我可以使用图形渲染脚本,但由于它已被弃用,我想必须有其他方法来实现相同的结果。
创建分配时指定 USAGE_IO_OUTPUT。假设您在脚本中生成纹理数据,您还将添加 USAGE_SCRIPT。然后你可以打电话
Allocation.setSurface(GLSurface)
将分配链接到纹理。每次你想用你需要调用的脚本的内容来更新纹理。
分配.ioSend()
这将在不制作额外副本的情况下移动数据。
您已经根据将分配转换为纹理来表达问题,但更容易想到创建纹理然后授予该纹理的分配所有权。这样,您将在将纹理 ID 传递给分配之前知道它。当心:分配有能力从根本上改变纹理的属性。
创建 GL 纹理
使用其 ID创建SurfaceTexture
使用使用情况创建分配Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT
将 SurfaceTexture 传递给分配setSurface()
将数据放入分配
调用ioSend()
分配以更新纹理
尽可能频繁地重复步骤 5 和 6,以更新纹理
我离 GL 专家还很远,所以第 2 步坦率地说是猜想。下面是对 HelloCompute 示例的改编,我在其中替换
displayout
为TextureView,这是一个可以为我轻松创建纹理和 SurfaceTexture 的视图。从那时起,我按照上面的步骤。
package com.example.android.rs.hellocompute;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.Type;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.TextureView;
import android.widget.ImageView;
public class HelloCompute extends Activity {
private Bitmap mBitmapIn;
private RenderScript mRS;
private ScriptC_mono mScript;
private Allocation mSurfaceAllocation;
private Allocation mCanvasAllocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mBitmapIn = loadBitmap(R.drawable.data);
int x = mBitmapIn.getWidth();
int y = mBitmapIn.getHeight();
ImageView in = (ImageView) findViewById(R.id.displayin);
in.setImageBitmap(mBitmapIn);
mRS = RenderScript.create(this);
mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono);
mCanvasAllocation = Allocation.createTyped(mRS,
new Type.Builder(mRS, Element.RGBA_8888(mRS))
.setX(x).setY(y).create(),
Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
mSurfaceAllocation = Allocation.createTyped(mRS,
new Type.Builder(mRS, Element.RGBA_8888(mRS))
.setX(x).setY(y).create(),
Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);
TextureView mTextureView = (TextureView) findViewById(R.id.displayout);
mTextureView.setSurfaceTextureListener(
new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture s,
int w, int h) {
if(s != null) mSurfaceAllocation.setSurface(new Surface(s));
mScript.forEach_root(mCanvasAllocation, mSurfaceAllocation);
mSurfaceAllocation.ioSend();
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture s) {
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture s,
int w, int h) {
if(s != null) mSurfaceAllocation.setSurface(new Surface(s));
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture s) {
mSurfaceAllocation.setSurface(null);
return true;
}
});
try {
Surface surface = mCanvasAllocation.getSurface();
Canvas canvas = surface.lockCanvas(new Rect(0,0,100,100));
canvas.drawBitmap(mBitmapIn, 0, 0, new Paint());
surface.unlockCanvasAndPost(canvas);
mCanvasAllocation.ioReceive();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (OutOfResourcesException e) {
e.printStackTrace();
}
}
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
return BitmapFactory.decodeResource(getResources(), resource, options);
}
}