Google Filament学习-从Android官方项目分析2

前一节分析了一部分官方项目,包括如何引入Filament库、如何使用Filament库和Filament的渲染过程三个部分。
Filament分析-从Android官方项目分析1

接下来接续分析Android中使用Filament。

一、初始化

//编舞者
        choreographer = Choreographer.getInstance()
//利用UiHelper初始化渲染窗口
        setupSurfaceView()
//初始化Filament,包括engine/renderer/view/scene/camera
        setupFilament()
//初始化view(filament的view,不是android的view)
        setupView()
//初始化scene
        setupScene()

初始化scene。

//加载渲染材质
        loadMaterial()
//设置渲染材质
        setupMaterial()
//初始化mesh
        createMesh()
//生成材质类,
    private fun loadMaterial() {
        readUncompressedAsset("materials/lit.filamat").let {
            material = Material.Builder().payload(it, it.remaining()).build(engine)
        }
    }

//由材质类生成材质实例
    private fun setupMaterial() {
        materialInstance = material.createInstance()
        materialInstance.setParameter("baseColor", Colors.RgbType.SRGB, 1.0f, 0.85f, 0.57f)
        materialInstance.setParameter("roughness", 0.3f)
    }

在readUncompressedAsset()方法中,将生成的材质文件lit.filamat转换为ByteBuffer,传递给native层,native层又调用了NioUtils.h里的方法,将ByteBuffer转换为byte[],而转换方式又调用了java层的NioUtils类提供的方法。

设置材质时,提供了几个参数:

materialInstance = material.createInstance()
materialInstance.setParameter("baseColor", Colors.RgbType.SRGB, 1.0f, 0.85f, 0.57f)
materialInstance.setParameter("roughness", 0.3f)

其中baseColor和roughness是在lit.mat里设定的。

    // List of parameters exposed by this material
    parameters : [
        // The color must be passed in linear space, not sRGB
        {
            type : float3,
            name : baseColor
        },
        {
            type : float,
            name : roughness
        },
        {
            type : samplerExternal,
            name : videoTexture
        },
        {
            type : mat4,
            name : textureTransform
        }
    ],

关于材质之后会单独分析。

二、Mesh

分析创建网格化的代码:

    private fun createMesh() {
        val floatSize = 4
        val shortSize = 2
        // A vertex is a position + a tangent frame:
        // 3 floats for XYZ position, 4 floats for normal+tangents (quaternion)
        val vertexSize = 3 * floatSize + 4 * floatSize
        ....
}

filament的顶点由2个部分组成,位置和正切值(法线+正切组成的四元数)。
位置:x/y/z 三个float
正切:四元数,4个float

为此,建立了一个顶点类Vertex,并增加了ByteBuffer的临时方法,存放顶点数据。

        // Define a vertex and a function to put a vertex in a ByteBuffer
        @Suppress("ArrayInDataClass")
        data class Vertex(val x: Float, val y: Float, val z: Float, val tangents: FloatArray)

        fun ByteBuffer.put(v: Vertex): ByteBuffer {
            putFloat(v.x)
            putFloat(v.y)
            putFloat(v.z)
            v.tangents.forEach { putFloat(it) }
            return this
        }

为什么用法线+正切组成的四元数存储顶点呢?
这是用于切线空间Tangent Space用的,可以参考一下文章:
切线空间
法线纹理

接下来有多个api调用,包括VertexBuffer、IndexBuffer,都是渲染引擎里的概念,可以参考OpenGL里的概念。
除了渲染材质RenderableManager外,还用上了光照LightManager、转换TransformManager。

TransformManager is used to add transform components to entities.
LightManager allows to create a light source in the scene, such as a sun or street lights.

你可能感兴趣的:(Google Filament学习-从Android官方项目分析2)