簡體   English   中英

three.js:重用紋理?

[英]three.js: reusing a texture?

在我的程序中,我有多個實例化幾何的地方,每個地方都有關於如何對其幾何進行網格化的偏好(是否是雙面的?是否是Lambert或基本材料?)。 但是,它們都使用相同的紋理。 我只想加載一次此通用紋理。 這給了我一個設計問題:

使用TextureLoader.load()加載紋理時,我只能使用一次紋理,即在傳遞給load函數的回調函數內部。 這意味着我必須在加載紋理之前收集所有幾何實例以及它們的每個首選項,以便在加載開始時可以將其全部(通過閉包)提供給回調函數。

我在想是否有解決此問題的規范方法? 我猜想其他Three.js用戶可能也遇到過類似情況。 我知道如何使用Promise解決這個問題:load函數將返回一個表示紋理的Promise。 然后可以將此紋理傳遞到每個需要對幾何進行網格化的位置。 該解決方案很方便,因為我不必收集大量的幾何數據就可以稍后將其傳遞。

但是,是否存在類似的方便或幾乎一樣方便的解決方案,仍留在回調語義領域?

我最終走了Promise路線:將TextureLoader.load()調用包裝在名為Promise Javascript內置內置返回承諾的構造函數中:

var loadTexture_promise = ( texture_path, texture_loader ) => {
    var texture_promise;

    if (       loadTexture_promise.texturePromises_cache[texture_path] !== undefined ) {
        return loadTexture_promise.texturePromises_cache[texture_path]
    }

    texture_promise = new Promise(
        function( resolve, reject )
        {
            texture_loader.load(
                texture_path,
                function (texture) {
                    // Success callback of TextureLoader
                    // We're done, so tell the promise it is complete
                    resolve(texture);
                },
                function (XmlHttpRequest_instance) {
                    // Progress callback of TextureLoader
                },
                function (unknown_parameter) {
                    // Failure callback of TextureLoader
                    // Reject the promise with the failure
                    reject(new Error('Could not load texture ' + texture_path));
                }
            );
        }
    );

    // add texture_promise to cache:
    loadTexture_promise.texturePromises_cache[texture_path] = texture_promise;

    return texture_promise;
};
// establish cache object on the loadTexture_promise function:
loadTexture_promise.texturePromises_cache = [];

然后,我有了一個lambertMesher函數,我的幾何圖形供應商可以調用該函數:

function lambertMesher ( aGeometry, aTexture_promise, doubleSided, debug ) {
    var aMesh_promise = aTexture_promise.then(
        ( resolved_texture ) =>
        {
            var material, mesh;

            if ( debug ) {
                console.log("resolved_texture: ", resolved_texture);
                console.log("aGeometry: ", aGeometry);
            }

            resolved_texture.minFilter = THREE.NearestFilter;

            if (doubleSided) {
                material = new THREE.MeshLambertMaterial( { map: resolved_texture, side: THREE.DoubleSide } );
            } else {
                material = new THREE.MeshLambertMaterial( { map: resolved_texture, emissive: 0xffffff } );
            }

            mesh = new THREE.Mesh(aGeometry, material);
            if ( debug ) {
                console.log("mesh: ", mesh);
            }
            return mesh

        },
        ( reason_of_textureLoading_failure ) =>
        {
            console.log( "meshing failed. Also: " + reason_of_textureLoading_failure )
        }
    );

    return aMesh_promise
}

最后,這就是我所說的lambertMesher

var myPlateGeom = new THREE.PlateGeometry( myPlatePolygonSet, true );
var myPlateMesh_promise = utils_meshers.lambertMesher( myPlateGeom, myRobinieTexture_promise, true, false );

然后,最后,最后,我將網格物體添加到場景中,如下所示:

myPlateMesh_promise.then(
    (myPlateMesh) => { myScene.add( myPlateMesh ) },
    (reason)     =>   console.log( "failed to add myPlateMesh. Also: " + reason )
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM