第一个程序-绘制三角形(一)

本文介绍了如何在Android应用中使用Filament渲染引擎绘制三角形。首先,通过Android Studio添加Filament依赖,接着讲解了初始化引擎环境、创建Surface的重要性。分析了SurfaceView和TextureView在构建Surface中的角色,以及Filament如何通过SwapChain与Surface关联。最后提到了在Filament中渲染前必须创建的关键对象,为后续的渲染配置做准备。
部署运行你感兴趣的模型镜像

    上篇在文章 Filament简介 中对Filament总体做了简单的介绍,了解到Filament是一个小巧但很

高效的渲染引擎。像其它程序学习初期的HelloWorld一样,本章我们开始介绍如何使用Filament

绘制一个简单的三角形。

    在开始绘制三角形之前,Filament中有几个重要概念我们做一个简单的说明:

Engine可以理解为Filament的程序入口点,主要用来跟踪用户创建的所有资源,管理渲染线程和硬件渲染。
Renderer可以理解为操作系统的窗口
SwapChain可以理解为操作系统的可以绘制的画布
View        用来保存可以绘制对象及其相关信息,一个View跟一个Scene相关联
Scene可以理解为容器,包含光照和可绘制实体信息
Camera相机信息包含投影矩阵信息及其曝光值参数

    在开始绘制之前,我们首先要做的就是准备环境,在 Android 平台我们开发APP,主要使用

Android Studio 作为IDE,我们要做的就是将需要的依赖库文件添加到编译文件中:

dependencies {
    implementation 'com.google.android.filament:filament-android:1.27.1'
    implementation 'com.google.android.filament:filament-utils-android:1.27.1'
    implementation 'com.google.android.filament:gltfio-android:1.27.1'
    implementation 'com.google.android.filament:filamat-android:1.27.1'
}

    上面引用的依赖有版本信息,Filament目前在不断更新,目前(2023-01-31)最新的版本为

v1.31.2。添加了依赖之后,我们就可以在 Android Studio 工程中进行开发。在 Android 平台上

使用 Filament 首先要做的事情就是调用:

Filament.init()

    其作用就是初始化引擎环境,主要是加载so库,我们来看一下这里面的具体实现:

public class Filament {
    static {
        Platform.get();
        System.loadLibrary("filament-jni");
    }

    private Filament() {
    }

    @SuppressWarnings("unused")
    public static void init() {
    }
}

   上面代码主要做了两件事情:

    1、初始化平台 Platform.get, 在 Android 平台主要是构建 AndroidPlatform 对象

    2、加载库文件 filament-jni.so

    以上工作准备完毕之后,就可以着手绘制工作。

    绘制工作首先要做的工作就是准备画布。如果使用OpenGL绘制图形,在不同的平

台上需要不同的画布,在Windows平台上需要Window,在Android平台则需要 Surface。那么在

Android平台上如何提供这个Surface画布呢?

    Android 平台 提供了两个控件可以提供Surface画布:

1、SurfaceView

2、TextureView

我们首先分析一下,这两个控件是如何构建 Android 平台 Surface 的。

1、通过 SurfaceView 构建 Surface

      我们看一下 Android 平台 源码中 SurfaceView的主要相关代码:

public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback {

   private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
        private static final String LOG_TAG = "SurfaceHolder";


        @Override
        public Surface getSurface() {
            return mSurface;
        }

    };

    /**
     * Return the SurfaceHolder providing access and control over this
     * SurfaceView's underlying surface.
     *
     * @return SurfaceHolder The holder of the surface.
     */
    public SurfaceHolder getHolder() {
        return mSurfaceHolder;
    }
}

    上述我们只列出了与Surface相关的主要代码,可以看到,可以先获取到 SurfaceHolder,然后

通过 SurfaceHolder 的成员方法 getSurface 获取到 Surface对象。

2、通过 TextureView 构建 Surface

      同样的,我们看下 TextureView 的源码:

public class TextureView extends View {

    /**
     * Returns the {@link SurfaceTexture} used by this view. This method
     * may return null if the view is not attached to a window or if the surface
     * texture has not been initialized yet.
     *
     * @see #isAvailable()
     */
    public @Nullable SurfaceTexture getSurfaceTexture() {
        return mSurface;
    }
}

   通过 TextureView 的 getSurfaceTexture() 方法获取 SurfaceTexture对象,而后可以通过

SurfaceTexture 构建 Surface 对象:

public class Surface implements Parcelable {

    public Surface(SurfaceTexture surfaceTexture) {
        if (surfaceTexture == null) {
            throw new IllegalArgumentException("surfaceTexture must not be null");
        }
        mIsSingleBuffered = surfaceTexture.isSingleBuffered();
        synchronized (mLock) {
            mName = surfaceTexture.toString();
            setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
        }
    }

}

    如上,在 Android 源码中, Surface 提供了以 SurfaceTexture 为参数的构造方法。

    现在我们知道如何利用 Android 平台的基础控件获取到画布,但 Filament 渲染引擎提供的

画布为 SwapChain ,那么 Filament 是如何将二者联系起来的?


    /**
     * Creates an opaque {@link SwapChain} from the given OS native window handle.
     *
     * @param surface on Android, <b>must be</b> an instance of {@link android.view.Surface}
     *
     * @return a newly created {@link SwapChain} object
     *
     * @exception IllegalStateException can be thrown if the SwapChain couldn't be created
     */
    @NonNull
    public SwapChain createSwapChain(@NonNull Object surface) {
        return createSwapChain(surface, SwapChain.CONFIG_DEFAULT);
    }

    Filament 的 Engine 类提供了成员方法 createSwapChain 将 Surface 和 SwapChain 联系了起

来。在 Filament 中 通过 UiHelper 将 Android 中控件与 SwapChain 联系起来。

public class UiHelper {
    /**
     * Interface used to know when the native surface is created, destroyed or resized.
     *
     * @see #setRenderCallback(RendererCallback)
     */
    public interface RendererCallback {
        /**
         * Called when the underlying native window has changed.
         */
        void onNativeWindowChanged(Surface surface);

        /**
         * Called when the surface is going away. After this call <code>isReadyToRender()</code>
         * returns false. You MUST have stopped drawing when returning.
         * This is called from detach() or if the surface disappears on its own.
         */
        void onDetachedFromSurface();

        /**
         * Called when the underlying native window has been resized.
         */
        void onResized(int width, int height);
    }

}

 UiHelper 中提供了一个接口 RenderCallback,需要用户实现该接口,主要用于创建SwapChain

    class SurfaceCallback implements UiHelper.RendererCallback {

        @Override
        public void onNativeWindowChanged(Surface surface) {
            mSwapChain = mEngine.createSwapChain(surface);
        }

        @Override
        public void onDetachedFromSurface() {
            mEngine.destroySwapChain(mSwapChain);
        }

        @Override
        public void onResized(int width, int height) {

        }
    }

     实现了该接口之后,将 SurfaceView 和 UiHelper 联系起来:

UiHelper uiHelper = new UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK);
uiHelper.setRenderCallback(new SurfaceCallback());
uiHelper.attachTo(mSurfaceView);

    到这里我们梳理一下,我们通过 Android 的控件 SurfaceView 与 Filament 的 UiHelper 联系起

来,用于提供画布。也就是说,我们目前将画布准备好了。

    下面我们就要学习该如何使用 Filament 进行渲染三角形。开始渲染之前,Filament 要求我们

必须创建几个我们在本章开篇提到的几个对象:

Engine engine = Engine.create();
Renderer renderer = engine.createRenderer();
Scene scene = engine.createScene();
View view = engine.createView();
Camera camera = engine.createCamera(engine.getEntityManager().create());

    Filament 的渲染工作离不开上面几个对象,后面就需要对各个对象进行配置,最后调用下面

的语句进行具体的渲染:

        if (renderer.beginFrame(mSwapChain, frameTimeNanos)) {
            renderer.render(view);
            renderer.endFrame();
        }

    其中mSwapChain 是我们前面利用 Surface 创建的对象, frameTimeNanos 是 Android 平台

的时间戳, 可通过 System.nanoTime() 获取当前时间戳。view 对象是我们前面创建的,当然

现在我们还没有对view进行配置,即使调用了以上代码也无发渲染出任何内容,我们在

下一章分析讲解具体如何配置这几个对象。

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后知后觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值