Kelvin Chan
Kelvin Chan

Reputation: 59

ThreeJS, Ionic, AngularJS -> Cannot make SkyBox Appear

I am using ThreeJS in combination with Ionic and Angular frameworks. I have followed the Ionic tutorial to get a rotating cube, and I have created code to add a skyBox to my scene but I can't make it appear at all, and I don't know why.

My main index.html has a body:

<body ng-app="ionicApp">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r69/three.min.js"></script>
<ion-nav-bar class="bar-positive">
</ion-nav-bar>

<ion-tabs class="tabs-positive">

    <ion-tab icon="ion-home" ui-sref="home">
        <ion-nav-view name="home">

        </ion-nav-view>
    </ion-tab>

    <ion-tab icon="ion-help" ui-sref="threeJs">
        <ion-nav-view name="help">
        </ion-nav-view>
    </ion-tab>

</ion-tabs>

<ion-nav-view></ion-nav-view>

So using angular-ui-router i set the state to 'threeJs', which then shows my rotating cube. My html which is routed is as such:

<ion-view title="ThreeJS">
<ion-content padding="true" id="canvas">
    <three-js-canvas></three-js-canvas>
</ion-content>

<script type="application/x-glsl" id="sky-vertex">
varying vec2 vUV;

void main() {
    vUV = uv;
    vec4 pos = vec4(position, 1.0);
    gl_Position = projectionMatrix * modelViewMatrix * pos;
}

<script type="application/x-glsl" id="sky-fragment">
uniform sampler2D texture;
varying vec2 vUV;

void main() {
    vec4 sample = texture2D(texture, vUV);
    gl_FragColor = vec4(sample.xyz, sample.w);
}

The three-js-canvas is the custom directive I've created to handle my threeJS stuff. The code for it is as follows:

angular.module('ionicApp').directive('threeJsCanvas', function () {
    'use strict';
    console.log("hi");
    return {
        restrict: 'E',
        link: function (scope, element, attr) {
            var scene,
                camera,
                renderer,
                geometry,
                material,
                cube;

            function initCube() {
                scene = new THREE.Scene();
                camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

                renderer = new THREE.WebGLRenderer();
                renderer.setSize(window.innerWidth, window.innerHeight);
                renderer.setClearColor(0xFFFFFF, 0);
                element[0].appendChild(renderer.domElement);

                var geometryCube = new THREE.BoxGeometry(1, 1, 1),
                    materialCube = new THREE.MeshBasicMaterial({
                        color: 0x00ff00
                    });
                cube = new THREE.Mesh(geometryCube, materialCube);
                scene.add(cube);
            }

            function initSky() {
                var sphereGeometry = new THREE.SphereGeometry(3000, 60, 40),
                    uniforms = {
                        texture: {
                            type: 't',
                            value: THREE.ImageUtils.loadTexture('img/lowres.jpg')
                        }
                    },

                    sphereMaterial = new THREE.ShaderMaterial({
                        uniforms: uniforms,
                        vertexShader: document.getElementById('sky-vertex').textContent,
                        fragmentShader: document.getElementById('sky-fragment').textContent
                    });
                console.log(document.getElementById('sky-vertex').textContent);
                var skyBox = new THREE.Mesh(sphereGeometry, sphereMaterial);
                skyBox.scale.set(-1, 1, 1);
                skyBox.rotation.order = 'XYZ';
                skyBox.renderDepth = 1000.0;
                scene.add(skyBox);
            }

            function render() {
                requestAnimationFrame(render);
                cube.rotation.x += 0.1;
                cube.rotation.y += 0.1;
                camera.position.z = 5;
                renderer.render(scene, camera);
            }
            initCube();
            initSky();
            render();
        }
    };
});

When I click on my button to route to my threeJS state, I just need a nice spinning cube and a blank white background, my skyBox is nowhere do be seen. Any suggests are appreciated, thanks!

Upvotes: 0

Views: 1809

Answers (2)

Absulit
Absulit

Reputation: 1955

I've encountered this problem once in a while, because I forgot this, which is quite simple.

As stated in the Threejs docs, the PerspectiveCamera has the following parameters:

PerspectiveCamera( fov, aspect, near, far )

You are using a FAR of 1000, and then you add 3000 radius to your sphere here:

var sphereGeometry = new THREE.SphereGeometry(3000, 60, 40)

meaning that the Sphere will be out of the frustrum and it will not be visible.

So you have two choices, reduce the SphereGeometry radius, or increase the PerspectiveCamera FAR parameter to a number bigger than 3000.

Upvotes: 0

Bob Woodley
Bob Woodley

Reputation: 1284

1 - Setting a negative scale for your skybox seems very suspect.

2 - Did you try different values for the sphere size? Perhaps it is outside of the frustum.

3 - You might try setting

side = THREE.DoubleSide 

on your skybox material.

Also, why are you setting renderDepth? Shouldn't be necessary.

Here is some skybox code that definitely works:

function doSkyDome() {
    var skyGeometry = new THREE.SphereGeometry(5000,50,50);
    var texture;
    texture = THREE.ImageUtils.loadTexture('textures/sky.png');

    var skyMaterial = new THREE.MeshBasicMaterial({map: texture, side: THREE.DoubleSide });
    _skyBox = new THREE.Mesh( skyGeometry, skyMaterial );
    _skyBox.material.fog = false;
    _skyBox.position.set(0,0,0);
    _skyBox.rotation.x = Math.PI/4;
    _scene.add( _skyBox );
}

Of course, confirm that your lowres.jpg exists and is loaded.

Upvotes: 1

Related Questions