2013-01-07 45 views
0

我目前有一个功能,应该在运行时创建一个3d行星球体,但我似乎无法让我的功能渲染多次,如果我运行它不止一次它只是完全忽略了除了最后一次调用函数的页面,我知道我做了一个可怕的工作来编写它,它是用来作为概念的证明,但我不想去优化任何东西,如果我无法弄清楚为什么我无法在同一页面上获得3个不同的效果图。three.js多个效果图

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); 
} 

任何人都可以解释为什么我不能在一个页面上多次使用这个函数吗?

当我在任何页面上多次运行该函数时,我只看到1个3D对象,其他应该渲染对象的地方没有出现,认为我有3个部分,每个部分都意味着呈现不同的行星,如果我用不同的参数运行这个函数3次,最后一次运行函数是唯一显示的函数,另外两个地方不显示任何内容,只是一个空白点。

此外,我已检查,如果我删除第三个,第二个显示,但不是第一个,所以它不是一个问题与参数不正确,我相信这是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种不同的效果,他们不是在同一场景中,或者我会作出他们都一个场景,它们被认为是网站中的不同块,这仅仅是一个例子,并不是函数需要工作的唯一途径,但函数确实需要把每个星球当作自己的场景,我们不能把他们一起在一个场景中。

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

+0

_“如果我在页面上多次运行它,它只是完全忽略了最后一次调用函数”_ Huh?那是什么意思?什么功能?你如何运行“不止一次”?你期望看到什么?你看到了什么呢? –

+0

@AlexWayne当我在任何页面上多次运行该函数时,我只会看到1个3D对象,其他应该渲染对象的地方不会出现,认为我有3个部分,每个部分都表示呈现不同的行星,如果我用不同的参数运行这个函数3次,上次运行函数是唯一显示的函数,另外两个地方不显示任何东西,只是一个空白点。 –

+0

@AlexWayne此外,我已检查,如果我删除第三个,第二个显示,但不是第一个,所以它不是一个问题,参数不正确,我相信这是一个问题与three.js不想要创建一个以上的渲染器实例。 –

回答

2

所以我想通了,我自己的问题,显然是因为我使用全局变量和函数内没有局部变量。我所要做的就是改变

$this = this; 

var $this = this; 

,并且修复了所有我的问题......有时候我觉得像这样一个白痴。

1

你可能要考虑更换:对于

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

部分:

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

的主要原因是​​不浪费的渲染力,当浏览器窗口中是不可见的。

+0

如果画布不可见,它是否也会浪费渲染能力? (IE:它是在不同的选项卡上,我将选项卡更改为不同的选项卡,因此画布不再可见?)我使用setTimeout的原因是因为我打算添加检查选项卡当前是否可见)。 –

+0

@CoryEvans我不知道所有的浏览器是否以相同的方式工作,但在谷歌浏览器中,当切换标签时它会停止更新。在我的笔记本电脑上,当我渲染沉重的3D场景时,温度控制风扇转速达到最高。当我切换标签时,风扇旋转下来。 = o) – Aycox

+0

不是“窗口选项卡”我的意思是如果我设置父容器显示:无,将requestAnimationFrame停止运行? –