0

現在、実行時に 3D 惑星球体を作成する関数がありますが、関数を複数回レンダリングすることができないようです。ページで複数回実行すると、すべてが完全に無視されますが、関数への最後の呼び出し、私はこれをコーディングする恐ろしい仕事をしたことを知っています。これは概念実証として使用することを意図していますが、3 を取得できない理由がわからない場合は、何かを最適化したくありません。同じページで異なるレンダリング。

function makePlanet(planetContainer, texture){
        $this = this;

    $this.camera; 
    $this.scene;
    $this.sceneAtmosphere;
    $this.renderer;
    $this.primitive; 
    $this.material;
    $this.stats;

    $this.loop = function() {
        var angle = (Math.PI/180*0.1);

        cosRY = Math.cos(angle);
        sinRY = Math.sin(angle);

        var tempz = $this.camera.position.z;
        var tempx = $this.camera.position.x; 

        $this.camera.position.x = (tempx*cosRY)+(tempz*sinRY);
        $this.camera.position.z = (tempx*-sinRY)+(tempz*cosRY);

        $this.renderer.clear();
        $this.renderer.render( $this.scene, $this.camera );
        $this.renderer.render( $this.sceneAtmosphere, $this.camera );

        setTimeout(function(){
            $this.loop();
        }, 1000 / 60);
    }

        $this.Shaders = {

        'earth' : {

            uniforms: {

                "texture": { type: "t", value: 0, texture: null }

            },

            vertex_shader: [

                "varying vec3 vNormal;",
                "varying vec2 vUv;",

                "void main() {",

                    "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",

                    "vNormal = normalize( normalMatrix * normal );",
                    "vUv = uv;",

                "}"

            ].join("\n"),

            fragment_shader: [

                "uniform sampler2D texture;",

                "varying vec3 vNormal;",
                "varying vec2 vUv;",

                "void main() {",

                    "vec3 diffuse = texture2D( texture, vUv ).xyz;",
                    "float intensity = 1.10 - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) );",
                    "vec3 atmosphere = vec3( 0.75, 0.75, 2.0 ) * pow( intensity, 3.0 );",

                    "gl_FragColor = vec4( diffuse + atmosphere, 1.0 );",

                "}"

            ].join("\n")

        },

        'atmosphere' : {

            uniforms: {},

            vertex_shader: [

                "varying vec3 vNormal;",

                "void main() {",

                    "vNormal = normalize( normalMatrix * normal );",
                    "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",

                "}"

            ].join("\n"),

            fragment_shader: [

                "varying vec3 vNormal;",

                "void main() {",
                    // First float seems to affect opacity, and the last float affects size/strenth of the gradient
                    "float intensity = pow( 0.4 - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) ), 5.0 );",
                    // This seems to just be a simple colour value
                    "gl_FragColor = vec4( 0.5, 1.0, 1.0, 0.8 ) * intensity;",

                "}"

            ].join("\n")

        }

    };

    $this.camera = new THREE.Camera(30, $(planetContainer).width() / $(planetContainer).height(), 1, 100000);
    $this.camera.position.z = 1000;

    $this.scene = new THREE.Scene();
    $this.sceneAtmosphere = new THREE.Scene();

    $this.texture = ImageUtils.loadTexture('img/planets/textures/'+texture, {}, function() {
        $this.renderer.render($this.scene);
    });
    $this.texture.needsUpdate = true;

    $this.material = new THREE.MeshBasicMaterial( { map: $this.texture });
    $this.geom = new Sphere( 200, 50, 50);

    $this.primitive = new THREE.Mesh($this.geom, $this.material );

    $this.scene.addObject( $this.primitive );

// Atmosphere
    $this.shader = $this.Shaders[ 'atmosphere' ];
    $this.uniforms = Uniforms.clone( $this.shader.uniforms );

    $this.material = new THREE.MeshShaderMaterial( {

        uniforms: $this.uniforms,
        vertex_shader: $this.shader.vertex_shader,
        fragment_shader: $this.shader.fragment_shader

    } );

    $this.primitive = new THREE.Mesh( $this.geom, $this.material );
    $this.primitive.scale.x = $this.primitive.scale.y = $this.primitive.scale.z = 1.12;
    $this.primitive.flipSided = true;
    $this.sceneAtmosphere.addObject( $this.primitive );


    $this.renderer = new THREE.WebGLRenderer();
    $this.renderer.autoClear = false;
    $this.renderer.setClearColorHex( 0x000000, 1.0 );
    $this.renderer.setSize($(planetContainer).width(), $(planetContainer).height());

    $(planetContainer).append($this.renderer.domElement);

    setTimeout(function(){
        $this.loop();
    }, 1000 / 60);
}

ページでこの機能を複数回使用できない理由を誰か説明できますか?

任意のページで関数を複数回実行すると、3D オブジェクトが 1 つしか表示されず、オブジェクトをレンダリングするはずだった他の場所が表示されません。実行すると、それぞれが異なる惑星をレンダリングするための 3 つのセクションがあると思いますこの関数を異なる引数で 3 回実行しました。最後に関数を実行したときだけが表示され、他の 2 つの場所には何も表示されず、空の場所だけが表示されます。

また、確認したところ、3 番目のものを削除すると、2 番目のものは表示されますが、最初のものは表示されないため、パラメーターが正しくないという問題ではなく、three.js がさらに作成したくないという問題だと思いますレンダラーの複数のインスタンス。

使用例

$(document).ready(function(){
    var goldilocks = new makePlanet('.goldilocksplanet .planetRender','planet_Jinx1200.png');
    var ocean = new makePlanet('.oceanplanet .planetRender','planet_serendip_1600.jpg');
    var sulfur = new makePlanet('.sulfurplanet .planetRender','planet_Telos1200.png');
});

以下は、3 つの異なるレンダリングを含む Web ページのサンプルです。それらは同じシーンにはありません。または、1 つのシーンですべてを作成したはずです。これらは、Web サイト内の異なるブロックと見なされます。これは単なる例であり、関数が機能する必要がある唯一の方法ではありませんが、関数は各惑星を独自のシーンとして扱う必要があります。それらすべてを 1 つのシーンにまとめることはできません。

http://i.stack.imgur.com/tooOA.jpg

4

2 に答える 2

2

どうやらそれは、関数内でローカル変数ではなくグローバル変数を使用していたためだったようです。私がしなければならなかったのは、変更することだけでした

$this = this;

var $this = this;

そしてそれは私の問題をすべて解決しました...時々私はそのようなばかのように感じます.

于 2013-01-08T04:44:44.097 に答える
1

次のものを置き換えることを検討してください。

    setTimeout(function(){
            $this.loop();
        }, 1000 / 60);

の一部:

    function animate() {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
    }

主な理由はrequestAnimationFrame、ブラウザウィンドウが表示されていないときにレンダリング能力を無駄にしないことです。

于 2013-01-08T21:56:43.140 に答える