国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Filament】立方體貼圖(6張圖)

這篇具有很好參考價(jià)值的文章主要介紹了【Filament】立方體貼圖(6張圖)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1 前言

? 本文通過一個(gè)立方體貼圖的例子,講解三維紋理貼圖(子網(wǎng)格貼圖)的應(yīng)用,案例中使用 6 張不同的圖片給立方體貼圖,圖片如下。

【Filament】立方體貼圖(6張圖)

? 讀者如果對 Filament 不太熟悉,請回顧以下內(nèi)容。

  • Filament環(huán)境搭建
  • 繪制三角形
  • 繪制矩形
  • 繪制圓形
  • 繪制立方體
  • 紋理貼圖

2 立方體貼圖

? 本文項(xiàng)目結(jié)構(gòu)如下,完整代碼資源 → Filament立方體貼圖(6張圖)。

【Filament】立方體貼圖(6張圖)

2.1 基礎(chǔ)類

? 為方便讀者將注意力聚焦在 Filament 的輸入上,輕松配置復(fù)雜的環(huán)境依賴邏輯,筆者仿照 OpenGL ES 的寫法,抽出了 FLSurfaceView、BaseModel、Mesh、MaterialUtils 和 TextureUtils 類。FLSurfaceView 與 GLSurfaceView 的功能類似,承載了渲染環(huán)境配置;BaseModel 用于管理模型的網(wǎng)格和材質(zhì);Mesh 用于管理模型的頂點(diǎn)屬性;MaterialUtils 和 TextureUtils 中分別提供了一些材質(zhì)和紋理相關(guān)的工具。

? build.gradle

...
android {
    ...
    aaptOptions { // 在應(yīng)用程序打包過程中不壓縮的文件
        noCompress 'filamat', 'ktx'
    }
}
 
dependencies {
    implementation fileTree(dir: '../libs', include: ['*.aar'])
    ...
}

? 說明:在項(xiàng)目根目錄下的 libs 目錄中,需要放入以下 aar 文件,它們源自Filament環(huán)境搭建中編譯生成的 aar。

【Filament】立方體貼圖(6張圖)

? FLSurfaceView.java

package com.zhyan8.multitexture.filament;

import android.content.Context;
import android.graphics.Point;
import android.view.Choreographer;
import android.view.Surface;
import android.view.SurfaceView;

import com.google.android.filament.Camera;
import com.google.android.filament.Engine;
import com.google.android.filament.EntityManager;
import com.google.android.filament.Filament;
import com.google.android.filament.Renderer;
import com.google.android.filament.Scene;
import com.google.android.filament.Skybox;
import com.google.android.filament.SwapChain;
import com.google.android.filament.View;
import com.google.android.filament.Viewport;
import com.google.android.filament.android.DisplayHelper;
import com.google.android.filament.android.FilamentHelper;
import com.google.android.filament.android.UiHelper;

import java.util.ArrayList;

/*
 * Filament中待渲染的SurfaceView
 * 功能可以類比OpenGL ES中的GLSurfaceView
 * 用于創(chuàng)建Filament的渲染環(huán)境
 */
public class FLSurfaceView extends SurfaceView {
    public static int RENDERMODE_WHEN_DIRTY = 0; // 用戶請求渲染才渲染一幀
    public static int RENDERMODE_CONTINUOUSLY = 1; // 持續(xù)渲染
    protected int mRenderMode = RENDERMODE_CONTINUOUSLY; // 渲染模式
    protected Choreographer mChoreographer; // 消息控制
    protected DisplayHelper mDisplayHelper; // 管理Display(可以監(jiān)聽分辨率或刷新率的變化)
    protected UiHelper mUiHelper; // 管理SurfaceView、TextureView、SurfaceHolder
    protected Engine mEngine; // 引擎(跟蹤用戶創(chuàng)建的資源, 管理渲染線程和硬件渲染器)
    protected Renderer mRenderer; // 渲染器(用于操作系統(tǒng)窗口, 生成繪制命令, 管理幀延時(shí))
    protected Scene mScene; // 場景(管理渲染對象、燈光)
    protected View mView; // 存儲渲染數(shù)據(jù)(View是Renderer操作的對象)
    protected Camera mCamera; // 相機(jī)(視角管理)
    protected Point mDesiredSize; // 渲染分辨率
    protected float[] mSkyboxColor; // 背景顏色
    protected SwapChain mSwapChain; // 操作系統(tǒng)的本地可渲染表面(native renderable surface, 通常是一個(gè)window或view)
    protected FrameCallback mFrameCallback = new FrameCallback(); // 幀回調(diào)
    protected ArrayList<RenderCallback> mRenderCallbacks; // 每一幀渲染前的回調(diào)(一般用于處理模型變換、相機(jī)變換等)

    static {
        Filament.init();
    }

    public FLSurfaceView(Context context) {
        super(context);
        mChoreographer = Choreographer.getInstance();
        mDisplayHelper = new DisplayHelper(context);
        mRenderCallbacks = new ArrayList<>();
    }

    public void init() { // 初始化
        setupSurfaceView();
        setupFilament();
        setupView();
        setupScene();
    }

    public void setRenderMode(int renderMode) { // 設(shè)置渲染模式
        mRenderMode = renderMode;
    }

    public void addRenderCallback(RenderCallback renderCallback) { // 添加渲染回調(diào)
        if (renderCallback != null) {
            mRenderCallbacks.add(renderCallback);
        }
    }

    public void requestRender() { // 請求渲染
        mChoreographer.postFrameCallback(mFrameCallback);
    }

    public void onResume() { // 恢復(fù)
        mChoreographer.postFrameCallback(mFrameCallback);
    }

    public void onPause() { // 暫停
        mChoreographer.removeFrameCallback(mFrameCallback);
    }

    public void onDestroy() { // 銷毀Filament環(huán)境
        mChoreographer.removeFrameCallback(mFrameCallback);
        mRenderCallbacks.clear();
        mUiHelper.detach();
        mEngine.destroyRenderer(mRenderer);
        mEngine.destroyView(mView);
        mEngine.destroyScene(mScene);
        mEngine.destroyCameraComponent(mCamera.getEntity());
        EntityManager entityManager = EntityManager.get();
        entityManager.destroy(mCamera.getEntity());
        mEngine.destroy();
    }

    protected void setupScene() { // 設(shè)置Scene參數(shù)
    }

    protected void onResized(int width, int height) { // Surface尺寸變化時(shí)回調(diào)
        double zoom = 1;
        double aspect = (double) width / (double) height;
        mCamera.setProjection(Camera.Projection.ORTHO,
                -aspect * zoom, aspect * zoom, -zoom, zoom, 0, 1000);
    }

    private void setupSurfaceView() { // 設(shè)置SurfaceView
        mUiHelper = new UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK);
        mUiHelper.setRenderCallback(new SurfaceCallback());
        if (mDesiredSize != null) {
            mUiHelper.setDesiredSize(mDesiredSize.x, mDesiredSize.y);
        }
        mUiHelper.attachTo(this);
    }

    private void setupFilament() { // 設(shè)置Filament參數(shù)
        mEngine = Engine.create();
        // mEngine = (new Engine.Builder()).featureLevel(Engine.FeatureLevel.FEATURE_LEVEL_0).build();
        mRenderer = mEngine.createRenderer();
        mScene = mEngine.createScene();
        mView = mEngine.createView();
        mCamera = mEngine.createCamera(mEngine.getEntityManager().create());
    }

    private void setupView() { // 設(shè)置View參數(shù)
        float[] color = mSkyboxColor != null ? mSkyboxColor : new float[] {0, 0, 0, 1};
        Skybox skybox = (new Skybox.Builder()).color(color).build(mEngine);
        mScene.setSkybox(skybox);
        if (mEngine.getActiveFeatureLevel() == Engine.FeatureLevel.FEATURE_LEVEL_0) {
            mView.setPostProcessingEnabled(false); // FEATURE_LEVEL_0不支持post-processing
        }
        mView.setCamera(mCamera);
        mView.setScene(mScene);
    }

    /*
     * 幀回調(diào)
     */
    private class FrameCallback implements Choreographer.FrameCallback {
        @Override
        public void doFrame(long frameTimeNanos) { // 渲染每幀數(shù)據(jù)
            if (mRenderMode == RENDERMODE_CONTINUOUSLY) {
                mChoreographer.postFrameCallback(this); // 請求下一幀
            }
            mRenderCallbacks.forEach(callback -> callback.onCall());
            if (mUiHelper.isReadyToRender()) {
                if (mRenderer.beginFrame(mSwapChain, frameTimeNanos)) {
                    mRenderer.render(mView);
                    mRenderer.endFrame();
                }
            }
        }
    }

    /*
     * Surface回調(diào)
     */
    private class SurfaceCallback implements UiHelper.RendererCallback {
        @Override
        public void onNativeWindowChanged(Surface surface) { // Native窗口改變時(shí)回調(diào)
            if (mSwapChain != null) {
                mEngine.destroySwapChain(mSwapChain);
            }
            long flags = mUiHelper.getSwapChainFlags();
            if (mEngine.getActiveFeatureLevel() == Engine.FeatureLevel.FEATURE_LEVEL_0) {
                if (SwapChain.isSRGBSwapChainSupported(mEngine)) {
                    flags = flags | SwapChain.CONFIG_SRGB_COLORSPACE;
                }
            }
            mSwapChain = mEngine.createSwapChain(surface, flags);
            mDisplayHelper.attach(mRenderer, getDisplay());
        }

        @Override
        public void onDetachedFromSurface() { // 解綁Surface時(shí)回調(diào)
            mDisplayHelper.detach();
            if (mSwapChain != null) {
                mEngine.destroySwapChain(mSwapChain);
                mEngine.flushAndWait();
                mSwapChain = null;
            }
        }

        @Override
        public void onResized(int width, int height) { // Surface尺寸變化時(shí)回調(diào)
            mView.setViewport(new Viewport(0, 0, width, height));
            FilamentHelper.synchronizePendingFrames(mEngine);
            FLSurfaceView.this.onResized(width, height);
        }
    }

    /*
     * 每一幀渲染前的回調(diào)
     * 一般用于處理模型變換、相機(jī)變換等
     */
    public static interface RenderCallback {
        void onCall();
    }
}

? BaseModel.java

package com.zhyan8.multitexture.filament;

import android.content.Context;

import com.google.android.filament.Box;
import com.google.android.filament.Engine;
import com.google.android.filament.EntityManager;
import com.google.android.filament.Material;
import com.google.android.filament.MaterialInstance;
import com.google.android.filament.RenderableManager;
import com.google.android.filament.RenderableManager.PrimitiveType;
import com.google.android.filament.Texture;
import com.google.android.filament.TransformManager;

import com.zhyan8.multitexture.filament.Mesh.SubMesh;
import com.zhyan8.multitexture.filament.utils.MaterialUtils;
import com.zhyan8.multitexture.filament.utils.TextureUtils;

/*
 * 模型基類
 * 管理模型的網(wǎng)格、材質(zhì)、渲染id
 */
public class BaseModel {
    private static String TAG = "BaseModel";
    protected Context mContext; // 上下文
    protected Engine mEngine; // Filament引擎
    protected TransformManager mTransformManager; // 模型變換管理器
    protected Mesh mMesh; // 模型網(wǎng)格
    protected SubMesh[] mSubMeshes; // 子網(wǎng)格
    protected Material[] mMaterials; // 模型材質(zhì)
    protected MaterialInstance[] mMaterialInstances; // 模型材質(zhì)實(shí)例
    protected Texture[] mTextures; // 紋理
    protected int mRenderable; // 渲染id
    protected int mTransformComponent; // 模型變換組件的id
    protected Box mBox; // 渲染區(qū)域
    protected FLSurfaceView.RenderCallback mRenderCallback; // 每一幀渲染前的回調(diào)(一般用于處理模型變換、相機(jī)變換等)

    public BaseModel(Context context, Engine engine) {
        mContext = context;
        mEngine = engine;
        mTransformManager = mEngine.getTransformManager();
    }

    public int getRenderable() { // 獲取渲染id
        return mRenderable;
    }

    public FLSurfaceView.RenderCallback getRenderCallback() { // 獲取渲染回調(diào)
        return mRenderCallback;
    }

    public void destroy() { // 銷毀模型
        mEngine.destroyEntity(mRenderable);
        if (mMesh != null) {
            mMesh.destroy();
        }
        if (mTextures != null) {
            for (int i = 0; i < mTextures.length; i++) {
                mEngine.destroyTexture(mTextures[i]);
            }
        }
        if (mMaterialInstances != null) {
            for (int i = 0; i < mMaterialInstances.length; i++) {
                mEngine.destroyMaterialInstance(mMaterialInstances[i]);
            }
        }
        if (mMaterials != null) {
            for (int i = 0; i < mMaterials.length; i++) {
                mEngine.destroyMaterial(mMaterials[i]);
            }
        }
        EntityManager entityManager = EntityManager.get();
        entityManager.destroy(mRenderable);
    }

    protected int getRenderable(PrimitiveType primitiveType, int vertexCount) { // 獲取渲染id
        int renderable = EntityManager.get().create();
        if (mSubMeshes == null) {
            mSubMeshes = new SubMesh[] {new SubMesh(0, 0, vertexCount - 1, vertexCount)};
        }
        RenderableManager.Builder builder = new RenderableManager.Builder(mSubMeshes.length).boundingBox(mBox);
        for (int i = 0; i < mSubMeshes.length; i++) {
            builder.geometry(i, primitiveType, mMesh.getVertexBuffer(), mMesh.getIndexBuffer(),
                            mSubMeshes[i].offset, mSubMeshes[i].minIndex, mSubMeshes[i].maxIndex, mSubMeshes[i].indexCount)
                    .material(i, mMaterialInstances[i]);
        }
        builder.build(mEngine, renderable);
        return renderable;
    }

    protected Material[] loadMaterials(String materialPath) { // 加載材質(zhì)
        Material material = MaterialUtils.loadMaterial(mContext, mEngine, materialPath);
        if (material != null) {
            return new Material[] {material};
        }
        return null;
    }

    protected Material[] loadMaterials(String[] materialPaths) { // 加載材質(zhì)
        Material[] materials = new Material[materialPaths.length];
        for (int i = 0; i < materials.length; i++) {
            materials[i] = MaterialUtils.loadMaterial(mContext, mEngine, materialPaths[i]);
        }
        return materials;
    }

    protected MaterialInstance[] getMaterialInstance(Material[] materials) { // 獲取材質(zhì)實(shí)例
        MaterialInstance[] materialInstances = new MaterialInstance[materials.length];
        for (int i = 0; i < materials.length; i++) {
            materialInstances[i] = materials[i].createInstance();
        }
        return materialInstances;
    }

    protected MaterialInstance[] getMaterialInstance(Material material, int count) { // 獲取材質(zhì)實(shí)例
        MaterialInstance[] materialInstances = new MaterialInstance[count];
        for (int i = 0; i < count; i++) {
            materialInstances[i] = material.createInstance();
        }
        return materialInstances;
    }

    protected Texture[] loadTextures(String texturePath) { // 加載紋理
        Texture texture = TextureUtils.getTexture(mContext, mEngine, texturePath);
        if (texture != null) {
            return new Texture[] {texture};
        }
        return null;
    }

    protected Texture[] loadTextures(String[] texturePaths) { // 加載紋理
        Texture[] textures = new Texture[texturePaths.length];
        for (int i = 0; i < textures.length; i++) {
            textures[i] = TextureUtils.getTexture(mContext, mEngine, texturePaths[i]);
        }
        return textures;
    }
}

? Mesh.java

package com.zhyan8.multitexture.filament;

import com.google.android.filament.Engine;
import com.google.android.filament.IndexBuffer;
import com.google.android.filament.VertexBuffer;
import com.google.android.filament.VertexBuffer.AttributeType;
import com.google.android.filament.VertexBuffer.VertexAttribute;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/*
 * 網(wǎng)格
 * 用于管理模型的頂點(diǎn)屬性和頂點(diǎn)索引
 */
public class Mesh {
    private Engine mEngine; // Filament引擎
    private VertexBuffer mVertexBuffer; // 頂點(diǎn)屬性緩存
    private IndexBuffer mIndexBuffer; // 頂點(diǎn)索引緩存

    public Mesh(Engine engine) {
        mEngine = engine;
    }

    public Mesh(Engine engine, float[] vertices, short[] indices) {
        mEngine = engine;
        setVertices(vertices);
        setIndices(indices);
    }

    public Mesh(Engine engine, VertexPosCol[] vertices, short[] indices) {
        mEngine = engine;
        setVertices(vertices);
        setIndices(indices);
    }

    public Mesh(Engine engine, VertexPosUV[] vertices, short[] indices) {
        mEngine = engine;
        setVertices(vertices);
        setIndices(indices);
    }

    public void setVertices(float[] vertices) { // 設(shè)置頂點(diǎn)屬性
        mVertexBuffer = getVertexBuffer(vertices);
    }

    public void setVertices(VertexPosCol[] vertices) { // 設(shè)置頂點(diǎn)屬性
        mVertexBuffer = getVertexBuffer(vertices);
    }

    public void setVertices(VertexPosUV[] vertices) { // 設(shè)置頂點(diǎn)屬性
        mVertexBuffer = getVertexBuffer(vertices);
    }

    public void setIndices(short[] indices) { // 設(shè)置頂點(diǎn)索引
        mIndexBuffer = getIndexBuffer(indices);
    }

    public VertexBuffer getVertexBuffer() { // 獲取頂點(diǎn)屬性緩存
        return mVertexBuffer;
    }

    public IndexBuffer getIndexBuffer() { // 獲取頂點(diǎn)索引緩存
        return mIndexBuffer;
    }

    public void destroy() {
        mEngine.destroyVertexBuffer(mVertexBuffer);
        mEngine.destroyIndexBuffer(mIndexBuffer);
    }

    private VertexBuffer getVertexBuffer(float[] values) { // 獲取頂點(diǎn)屬性緩存
        ByteBuffer vertexData = getByteBuffer(values);
        int vertexCount = values.length / 3;
        int vertexSize = Float.BYTES * 3;
        VertexBuffer vertexBuffer = new VertexBuffer.Builder()
                .bufferCount(1)
                .vertexCount(vertexCount)
                .attribute(VertexBuffer.VertexAttribute.POSITION, 0, VertexBuffer.AttributeType.FLOAT3, 0, vertexSize)
                .build(mEngine);
        vertexBuffer.setBufferAt(mEngine, 0, vertexData);
        return vertexBuffer;
    }

    private VertexBuffer getVertexBuffer(VertexPosCol[] values) { // 獲取頂點(diǎn)屬性緩存
        ByteBuffer vertexData = getByteBuffer(values);
        int vertexCount = values.length;
        int vertexSize = VertexPosCol.BYTES;
        VertexBuffer vertexBuffer = new VertexBuffer.Builder()
                .bufferCount(1)
                .vertexCount(vertexCount)
                .attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT3, 0, vertexSize)
                .attribute(VertexAttribute.COLOR,    0, AttributeType.UBYTE4, 3 * Float.BYTES, vertexSize)
                .normalized(VertexBuffer.VertexAttribute.COLOR)
                .build(mEngine);
        vertexBuffer.setBufferAt(mEngine, 0, vertexData);
        return vertexBuffer;
    }

    private VertexBuffer getVertexBuffer(VertexPosUV[] values) { // 獲取頂點(diǎn)屬性緩存
        ByteBuffer vertexData = getByteBuffer(values);
        int vertexCount = values.length;
        int vertexSize = VertexPosUV.BYTES;
        VertexBuffer vertexBuffer = new VertexBuffer.Builder()
                .bufferCount(1)
                .vertexCount(vertexCount)
                .attribute(VertexBuffer.VertexAttribute.POSITION, 0, VertexBuffer.AttributeType.FLOAT3, 0, vertexSize)
                .attribute(VertexBuffer.VertexAttribute.UV0,    0, VertexBuffer.AttributeType.FLOAT2, 3 * Float.BYTES, vertexSize)
                .build(mEngine);
        vertexBuffer.setBufferAt(mEngine, 0, vertexData);
        return vertexBuffer;
    }

    private IndexBuffer getIndexBuffer(short[] values) { // 獲取頂點(diǎn)索引緩存
        ByteBuffer indexData = getByteBuffer(values);
        int indexCount = values.length;
        IndexBuffer indexBuffer = new IndexBuffer.Builder()
                .indexCount(indexCount)
                .bufferType(IndexBuffer.Builder.IndexType.USHORT)
                .build(mEngine);
        indexBuffer.setBuffer(mEngine, indexData);
        return indexBuffer;
    }

    private ByteBuffer getByteBuffer(float[] values) { // float數(shù)組轉(zhuǎn)換為ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(values.length * Float.BYTES);
        byteBuffer.order(ByteOrder.nativeOrder());
        for (int i = 0; i < values.length; i++) {
            byteBuffer.putFloat(values[i]);
        }
        byteBuffer.flip();
        return byteBuffer;
    }

    private ByteBuffer getByteBuffer(short[] values) { // short數(shù)組轉(zhuǎn)換為ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(values.length * Short.BYTES);
        byteBuffer.order(ByteOrder.nativeOrder());
        for (int i = 0; i < values.length; i++) {
            byteBuffer.putShort(values[i]);
        }
        byteBuffer.flip();
        return byteBuffer;
    }

    private ByteBuffer getByteBuffer(VertexPosCol[] values) { // VertexPosCol數(shù)組轉(zhuǎn)換為ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(values.length * VertexPosCol.BYTES);
        byteBuffer.order(ByteOrder.nativeOrder());
        for (int i = 0; i < values.length; i++) {
            values[i].put(byteBuffer);
        }
        byteBuffer.flip();
        return byteBuffer;
    }

    private ByteBuffer getByteBuffer(VertexPosUV[] values) { // VertexPosUV數(shù)組轉(zhuǎn)換為ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(values.length * VertexPosUV.BYTES);
        byteBuffer.order(ByteOrder.nativeOrder());
        for (int i = 0; i < values.length; i++) {
            values[i].put(byteBuffer);
        }
        byteBuffer.flip();
        return byteBuffer;
    }

    /*
     * 子網(wǎng)格
     */
    public static class SubMesh {
        public int offset;
        public int minIndex;
        public int maxIndex;
        public int indexCount;

        public SubMesh() {}

        public SubMesh(int offset, int minIndex, int maxIndex, int indexCount) {
            this.offset = offset;
            this.minIndex = minIndex;
            this.maxIndex = maxIndex;
            this.indexCount = indexCount;
        }
    }

    /*
     * 頂點(diǎn)數(shù)據(jù)(位置+顏色)
     * 包含頂點(diǎn)位置和顏色
     */
    public static class VertexPosCol {
        public static int BYTES = 16;
        public float x;
        public float y;
        public float z;
        public int color;

        public VertexPosCol() {}

        public VertexPosCol(float x, float y, float z, int color) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.color = color;
        }

        public ByteBuffer put(ByteBuffer buffer) { // VertexPosCol轉(zhuǎn)換為ByteBuffer
            buffer.putFloat(x);
            buffer.putFloat(y);
            buffer.putFloat(z);
            buffer.putInt(color);
            return buffer;
        }
    }

    /*
     * 頂點(diǎn)數(shù)據(jù)(位置+紋理坐標(biāo))
     * 包含頂點(diǎn)位置和紋理坐標(biāo)
     */
    public static class VertexPosUV {
        public static int BYTES = 20;
        public float x;
        public float y;
        public float z;
        public float u;
        public float v;

        public VertexPosUV() {}

        public VertexPosUV(float x, float y, float z, float u, float v) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.u = u;
            this.v = v;
        }

        public ByteBuffer put(ByteBuffer buffer) { // VertexPosUV轉(zhuǎn)換為ByteBuffer
            buffer.putFloat(x);
            buffer.putFloat(y);
            buffer.putFloat(z);
            buffer.putFloat(u);
            buffer.putFloat(v);
            return buffer;
        }
    }
}

? MaterialUtils.java

package com.zhyan8.multitexture.filament.utils;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.google.android.filament.Engine;
import com.google.android.filament.Material;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

/*
 * 材質(zhì)工具類
 */
public class MaterialUtils {
    private static String TAG = "MaterialUtils";

    public static Material loadMaterial(Context context, Engine engine, String materialPath) { // 加載材質(zhì)
        Buffer buffer = readUncompressedAsset(context, materialPath);
        if (buffer != null) {
            Material material = (new Material.Builder()).payload(buffer, buffer.remaining()).build(engine);
            material.compile(
                    Material.CompilerPriorityQueue.HIGH,
                    Material.UserVariantFilterBit.ALL,
                    new Handler(Looper.getMainLooper()),
                    () -> Log.i(TAG, "Material " + material.getName() + " compiled."));
            engine.flush();
            return material;
        }
        return null;
    }

    private static Buffer readUncompressedAsset(Context context, String assetPath) { // 加載資源
        ByteBuffer dist = null;
        try {
            AssetFileDescriptor fd = context.getAssets().openFd(assetPath);
            try(FileInputStream fis = fd.createInputStream()) {
                dist = ByteBuffer.allocate((int) fd.getLength());
                try (ReadableByteChannel src = Channels.newChannel(fis)) {
                    src.read(dist);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (dist != null) {
            return dist.rewind();
        }
        return null;
    }
}

? TextureUtils.java

package com.zhyan8.multitexture.filament.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.util.Log;

import com.google.android.filament.Engine;
import com.google.android.filament.Texture;
import com.google.android.filament.android.TextureHelper;

import java.io.IOException;
import java.io.InputStream;

/*
 * 紋理工具類
 */
public class TextureUtils {
    private static String TAG = "TextureUtils";

    public static Texture getTexture(Context context, Engine engine, String texturePath) { // 獲取Texture
        Bitmap bitmap = loadBitmapFromAsset(context, texturePath);
        if (bitmap != null) {
            return generateTexture(engine, bitmap);
        }
        return null;
    }

    public static Texture getTexture(Context context, Engine engine, int resourceId) { // 獲取Texture
        Bitmap bitmap = loadBitmapFromDrawable(context, resourceId);
        if (bitmap != null) {
            return generateTexture(engine, bitmap);
        }
        return null;
    }

    private static Texture generateTexture(Engine engine, Bitmap bitmap) { // 生成Texture
        Texture texture = new Texture.Builder()
                .width(bitmap.getWidth())
                .height(bitmap.getHeight())
                .sampler(Texture.Sampler.SAMPLER_2D)
                .format(Texture.InternalFormat.SRGB8_A8)
                .levels(0xff)
                .build(engine);
        TextureHelper.setBitmap(engine, texture, 0, bitmap, new Handler(), () ->
                Log.i(TAG, "getTexture, Bitmap is released.")
        );
        texture.generateMipmaps(engine);
        return texture;
    }

    private static Bitmap loadBitmapFromAsset(Context context, String assetPath) { // 從asset中加載bitmap
        Bitmap bitmap = null;
        try (InputStream inputStream = context.getAssets().open(assetPath)) {
            bitmap = BitmapFactory.decodeStream(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    private static Bitmap loadBitmapFromDrawable(Context context, int resourceId) { // 從drawable中加載bitmap
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPremultiplied = true;
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
        return bitmap;
    }
}

2.2 業(yè)務(wù)類

? MainActivity.java

package com.zhyan8.multitexture;

import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;

import com.zhyan8.multitexture.filament.FLSurfaceView;

public class MainActivity extends AppCompatActivity {
    private FLSurfaceView mFLSurfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mFLSurfaceView = new MyFLSurfaceView(this);
        setContentView(mFLSurfaceView);
        mFLSurfaceView.init();
        mFLSurfaceView.setRenderMode(FLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }

    @Override
    public void onResume() {
        super.onResume();
        mFLSurfaceView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mFLSurfaceView.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mFLSurfaceView.onDestroy();
    }
}

? MyFLSurfaceView.java

package com.zhyan8.multitexture;

import android.content.Context;

import com.google.android.filament.Camera;
import com.zhyan8.multitexture.filament.BaseModel;
import com.zhyan8.multitexture.filament.FLSurfaceView;

public class MyFLSurfaceView extends FLSurfaceView {
    private BaseModel mMyModel;
    public MyFLSurfaceView(Context context) {
        super(context);
    }

    public void init() {
        mSkyboxColor = new float[] {0.35f, 0.35f, 0.35f, 1};
        super.init();
    }

    @Override
    public void onDestroy() {
        mMyModel.destroy();
        super.onDestroy();
    }

    @Override
    protected void setupScene() { // 設(shè)置Scene參數(shù)
        mMyModel = new Cube(getContext(), mEngine);
        mScene.addEntity(mMyModel.getRenderable());
        addRenderCallback(mMyModel.getRenderCallback());
    }

    @Override
    protected void onResized(int width, int height) {
        double zoom = 0.25;
        double aspect = (double) width / (double) height;
        mCamera.setProjection(Camera.Projection.PERSPECTIVE,
                -aspect * zoom, aspect * zoom, -zoom, zoom, 0.3, 100);
        float[] eye = new float[] {1, 1, 1.5f};
        float[] center = new float[] {0, 0, 0};
        float[] up = new float[] {0, 1, 0};
        mCamera.lookAt(eye[0], eye[1], eye[2],center[0], center[1], center[2], up[0], up[1], up[2]);
    }
}

? Cube.java

package com.zhyan8.multitexture;

import android.content.Context;
import android.opengl.Matrix;

import com.google.android.filament.Box;
import com.google.android.filament.Engine;
import com.google.android.filament.RenderableManager.PrimitiveType;
import com.google.android.filament.TextureSampler;
import com.zhyan8.multitexture.filament.BaseModel;
import com.zhyan8.multitexture.filament.Mesh;
import com.zhyan8.multitexture.filament.Mesh.SubMesh;
import com.zhyan8.multitexture.filament.Mesh.VertexPosUV;

public class Cube extends BaseModel {
    private String materialPaths = "materials/square.filamat";
    private String[] texturePaths = new String[] {
            "textures/a1.jpg", "textures/a2.jpg", "textures/a3.jpg",
            "textures/a4.jpg", "textures/a6.jpg", "textures/a5.jpg"
    };
    private VertexPosUV[] mVertices; // 頂點(diǎn)坐標(biāo)
    private short[] mIndices; // 頂點(diǎn)索引
    private float[] mModelMatrix; // 模型變換矩陣
    private float[] mRotateAxis; // 旋轉(zhuǎn)軸
    private float mRotateAgree = 0; // 旋轉(zhuǎn)角度

    public Cube(Context context, Engine engine) {
        super(context, engine);
        init();
    }

    private void init() {
        mBox = new Box(0.0f, 0.0f, 0.0f, 2.0f, 2.0f, 2.0f);
        mVertices = getVertices(0.5f);
        mIndices = getIndices();
        mMesh = new Mesh(mEngine, mVertices, mIndices);
        mSubMeshes = getSubMesh();
        mTextures = loadTextures(texturePaths);
        mMaterials = loadMaterials(materialPaths);
        mMaterialInstances = getMaterialInstance(mMaterials[0], mTextures.length);
        TextureSampler textureSampler = new TextureSampler();
        for (int i = 0; i < mMaterialInstances.length; i++) {
            mMaterialInstances[i].setParameter("mainTex", mTextures[i], textureSampler);
        }
        mRenderable = getRenderable(PrimitiveType.TRIANGLES, mIndices.length);
        mTransformComponent = mTransformManager.getInstance(mRenderable);
        mRenderCallback = () -> renderCallback();
        mModelMatrix = new float[16];
        mRotateAxis = new float[] { 0.5f, 1f, 1f };
    }

    private void renderCallback() {
        mRotateAgree = (mRotateAgree + 1) % 360;
        mRotateAxis[0] = mRotateAgree / 180f - 1;
        mRotateAxis[1] = (float) Math.sin(mRotateAgree / 180f * Math.PI * 0.7f);
        mRotateAxis[2] = (float) Math.cos(mRotateAgree / 180f * Math.PI * 0.5f);
        Matrix.setRotateM(mModelMatrix, 0, mRotateAgree, mRotateAxis[0], mRotateAxis[1], mRotateAxis[2]);
        mTransformManager.setTransform(mTransformComponent, mModelMatrix);
    }

    private VertexPosUV[] getVertices(float r) {
        VertexPosUV[] vertices = new VertexPosUV[] {
                // 前面
                new VertexPosUV(r, r, r, 0f, 1f), // 0
                new VertexPosUV(-r, r, r, 1f, 1f), // 1
                new VertexPosUV(-r, -r, r, 1f, 0f), // 2
                new VertexPosUV(r, -r, r, 0f, 0f), // 3
                // 后面
                new VertexPosUV(r, r, -r, 0f, 1f), // 4
                new VertexPosUV(-r, r, -r, 1f, 1f), // 5
                new VertexPosUV(-r, -r, -r, 1f, 0f), // 6
                new VertexPosUV(r, -r, -r, 0f, 0f), // 7
                // 上面
                new VertexPosUV(r, r, r, 0f, 1f), // 8
                new VertexPosUV(r, r, -r, 1f, 1f), // 9
                new VertexPosUV(-r, r, -r, 1f, 0f), // 10
                new VertexPosUV(-r, r, r, 0f, 0f), // 11
                // 下面
                new VertexPosUV(r, -r, r, 0f, 1f), // 12
                new VertexPosUV(r, -r, -r, 1f, 1f), // 13
                new VertexPosUV(-r, -r, -r, 1f, 0f), // 14
                new VertexPosUV(-r, -r, r, 0f, 0f), // 15
                // 右面
                new VertexPosUV(r, r, r, 0f, 1f), // 16
                new VertexPosUV(r, r, -r, 1f, 1f), // 17
                new VertexPosUV(r, -r, -r, 1f, 0f), // 18
                new VertexPosUV(r, -r, r, 0f, 0f), // 19
                // 左面
                new VertexPosUV(-r, r, r, 0f, 1f), // 20
                new VertexPosUV(-r, r, -r, 1f, 1f), // 21
                new VertexPosUV(-r, -r, -r, 1f, 0f), // 22
                new VertexPosUV(-r, -r, r, 0f, 0f) // 23
        };
        return vertices;
    }

    private short[] getIndices() {
        short[] indices = new short[] {
                0, 1, 2, 0, 2, 3, // 前面
                4, 6, 5, 4, 7, 6, // 上面
                8, 9, 10, 8, 10, 11, // 右面
                12, 14, 13, 12, 15, 14, // 后面
                16, 18, 17, 16, 19, 18, // 下面
                20, 21, 22, 20, 22, 23 // 左面
        };
        return indices;
    }

    private SubMesh[] getSubMesh() {
        int subMeshCount = 6;
        int vertexCount = 6;
        SubMesh[] subMeshes = new SubMesh[subMeshCount];
        for (int i = 0; i < subMeshCount; i++) {
            int offset = i * vertexCount;
            int minIndex = offset;
            int maxIndex = minIndex + vertexCount - 1;
            subMeshes[i] = new SubMesh(offset, minIndex, maxIndex, vertexCount);
        }
        return subMeshes;
    }
}

? square.mat

material {
    name : square,

    shadingModel : unlit, // 禁用所有l(wèi)ighting
    // 自定義變量參數(shù)
    parameters : [
        {
            type : sampler2d,
            name : mainTex
        }
    ],
    // 頂點(diǎn)著色器入?yún)aterialVertexInputs中需要的頂點(diǎn)屬性
    requires : [
        uv0
    ]
}

fragment {
    void material(inout MaterialInputs material) {
        prepareMaterial(material); // 在方法返回前必須回調(diào)該函數(shù)
        material.baseColor = texture(materialParams_mainTex, getUV0());
    }
}

? transform.bat

@echo off
setlocal enabledelayedexpansion
set "srcFolder=../src/main/materials"
set "distFolder=../src/main/assets/materials"

for %%f in ("%srcFolder%\*.mat") do (
	set "matfile=%%~nf"
	matc -p mobile -a opengl -o "!matfile!.filamat" "%%f"
    move "!matfile!.filamat" "%distFolder%\!matfile!.filamat"
)

echo Processing complete.
pause

? 說明:需要將 matc.exe 文件與 transform.bat 文件放在同一個(gè)目錄下面,matc.exe 源自Filament環(huán)境搭建中編譯生成的 exe 文件。雙擊 transform.bat 文件,會自動(dòng)將 /src/main/materials/ 下面的所有 mat 文件全部轉(zhuǎn)換為 filamat 文件,并移到 /src/main/assets/materials/ 目錄下面。

? 運(yùn)行效果如下。

【Filament】立方體貼圖(6張圖)

? 說明:本文轉(zhuǎn)自【Filament】立方體貼圖(6張圖)。文章來源地址http://www.zghlxwxcb.cn/news/detail-837746.html

到了這里,關(guān)于【Filament】立方體貼圖(6張圖)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Opengl學(xué)習(xí)-立方體貼圖踩坑記錄

    2023/10/25 星期三 昨晚寫到了凌晨1點(diǎn),今早終于查出了問題,寫一篇隨筆記錄一下 綁定到特定紋理單元,沿用 TEXTURE_2D 方式: (更正)Cubemap可以使用Mipmap,但 GL_TEXTURE_MAG_FILTER 不可設(shè)置為帶MIPMAP類型,否則將引發(fā) GL_INVALID_ENUM = 1280 錯(cuò)誤 可以主動(dòng)加載多個(gè)Mipmap level,在 glTexIm

    2024年02月08日
    瀏覽(19)
  • 【libGDX】立方體手動(dòng)旋轉(zhuǎn)

    【libGDX】立方體手動(dòng)旋轉(zhuǎn)

    ? 本文主要介紹使用 libGDX 繪制立方體,并實(shí)現(xiàn)手動(dòng)觸摸事件控制立方體旋轉(zhuǎn)。 ? 為方便控制觸摸旋轉(zhuǎn),并提高渲染性能,我們通過改變相機(jī)的位置和姿態(tài)實(shí)現(xiàn)立方體旋轉(zhuǎn)效果。 ? 讀者如果對 libGDX 不太熟悉,請回顧以下內(nèi)容。 使用Mesh繪制三角形 使用Mesh繪制矩形 使用M

    2024年03月09日
    瀏覽(32)
  • 【css】動(dòng)畫:立方體相冊

    【css】動(dòng)畫:立方體相冊

    2024年02月11日
    瀏覽(23)
  • VCG 網(wǎng)格簡化之移動(dòng)立方體

    我們先來回顧一下原始的移動(dòng)立方體算法,該算法的基本思想是通過找出所有與等值面相交的體素,在這些基礎(chǔ)上再分別找出每個(gè)體素與等值面相交的交面,最終將這些交面連在一起即是我們所求的曲面。其大致過程如下所述: (1)首先將點(diǎn)云在空間上進(jìn)行體素劃分,并對

    2024年01月22日
    瀏覽(18)
  • 項(xiàng)目管理之干系人立方體分析

    項(xiàng)目管理之干系人立方體分析

    權(quán)力利益方格、權(quán)力影響方格,或作用影響方格 :基于干系人的職權(quán)級別(權(quán)力)、對項(xiàng)目成果的關(guān)心程度(利益)、對項(xiàng)目成果的影響能力(影響),或改變項(xiàng)目計(jì)劃或執(zhí)行的能力,每一種方格都可用于對干系人進(jìn)行分類。對于小型項(xiàng)目、干系人與項(xiàng)目的關(guān)系很簡單的項(xiàng)目,或干系

    2024年02月06日
    瀏覽(17)
  • 計(jì)算機(jī)圖形學(xué) | 實(shí)驗(yàn)六:旋轉(zhuǎn)立方體

    計(jì)算機(jī)圖形學(xué) | 實(shí)驗(yàn)六:旋轉(zhuǎn)立方體

    華中科技大學(xué)《計(jì)算機(jī)圖形學(xué)》課程 MOOC地址:計(jì)算機(jī)圖形學(xué)(HUST) 在正式搭建環(huán)境之前,我們先來介紹一下讀完下面的部分你會了解些什么。 繪制出旋轉(zhuǎn)立方體需要的新知識 認(rèn)識一些 OpenGL的新功能 接下來,我們來介紹一下繪制旋轉(zhuǎn)立方體。繪制效果如下: Z-緩存(Z-Buff

    2024年02月06日
    瀏覽(86)
  • css3實(shí)現(xiàn)3D立方體旋轉(zhuǎn)特效源碼

    css3實(shí)現(xiàn)3D立方體旋轉(zhuǎn)特效源碼

    CSS3自動(dòng)旋轉(zhuǎn)正方體3D特效是一款基于css3 keyframes屬性制作的圖片相冊自動(dòng)旋轉(zhuǎn)立方體特效 css3實(shí)現(xiàn)3D立方體旋轉(zhuǎn)特效代碼

    2024年04月09日
    瀏覽(33)
  • 使用html+css制作一個(gè)發(fā)光立方體特效

    使用html+css制作一個(gè)發(fā)光立方體特效

    使用html+css制作一個(gè)發(fā)光立方體特效

    2024年03月14日
    瀏覽(34)
  • Qt3D繪制旋轉(zhuǎn)立方體

    Qt3D繪制旋轉(zhuǎn)立方體

    近期用了款叫DesktopSpace,也想實(shí)現(xiàn)一下這款軟件實(shí)現(xiàn)的效果 具體實(shí)現(xiàn)步驟: 使用Qt3D繪制個(gè)旋轉(zhuǎn)的立方體(一) 使用快捷鍵控制立方體顯示面(二) 創(chuàng)建6個(gè)人虛擬桌面,截取不同虛擬桌面,顯示在不同的面上 (三) 在立方體上播放視頻 首先用Qt3D繪制一下桌面截圖旋轉(zhuǎn)的效

    2024年02月06日
    瀏覽(21)
  • Python展示 RGB立方體的二維切面視圖

    Python展示 RGB立方體的二維切面視圖

    生成 RGB 立方體的三個(gè)中間切面視圖,分別對應(yīng)于紅色、綠色和藍(lán)色通道。這些切面展示了在固定一個(gè)顏色通道值的情況下,其他兩個(gè)顏色通道是如何變化的。雖然這不能顯示出 RGB 立方體的全部復(fù)雜性,但它提供了一個(gè)很好的視覺表示,幫助理解 RGB 顏色空間的工作原理。

    2024年01月16日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包