mjanisz1
mjanisz1

Reputation: 1516

Shaders performance with threeJS

I want to get as best performance as possible with rendering simple textured shapes. The problem is with phong model it requires extra lighting (which involves calculations) + the colors are not like the one desired and needs some tweeking.

To simplify the case I've decided to use a simple flat shader, but some problems occur:

    <script id="vertShader" type="shader">
        varying vec2 vUv;
        void main() {
              vUv = uv;
              gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
        }
    </script>
    <script id="fragShader" type="shader">
        varying vec2 vUv;
        uniform sampler2D material;
        void main() {
            gl_FragColor = texture2D(material, vUv);
        }
    </script>

Under certain camera angles some of the shelves dissapear (you can notice the darker places, and see through them), which does not occur using the phong material:

Screenshot using the flat shader - some shelves become transparent

It happens with the shadow texture put inside each shelf. It's a textured cube with a shadow texture put inside each space (don't ask me why, this is just a task I got:))

I don't know what may be causing this. Maybe the loading? Im using the standard obj loader and adding textures. Obj loader sets the material to phong and im switching it to custom shader like this:

    var objLoader = new THREE.OBJLoader( manager );
    objLoader.load( obj, function ( model ) {

        elements[name] = model;
        console.log('loaded ', name);
        var img = THREE.ImageUtils.loadTexture(mat);
        elements[name].traverse( function ( child ) {
            if ( child instanceof THREE.Mesh ) {
                child.material = new THREE.ShaderMaterial( {
                    uniforms: {
                        color: {type: 'f', value: 0.0},
                        material: {type: 't', value: img}
                    },
                    fragmentShader: document.getElementById('fragShader').text,
                    vertexShader: document.getElementById('vertShader').text,
                } );
            }
        });

any suggestions would be helpful

Upvotes: 1

Views: 1047

Answers (1)

marcel
marcel

Reputation: 3155

Every surface is drawn in one direction (clockwise or counter-clockwise). if you are showing a surface from the other side, it will "dissapear". I think this is the problem of your own shader. -> you should render them from both sides (-> worse performance) or calculate, from which side it should render.

To optimize the performance slightly you should use a standard material from THREE. You can use them without writing your own shader.

something like:

child.material = new THREE.MeshBasicMaterial({
    side: THREE.DoubleSide,
    color: 0x000000
    // ...
});

i created a skybox-material with textures in an own project:

function getSkyboxMaterial() {
    var faceMaterials = getSkyboxFaces();
    var skyboxMaterial = new THREE.MeshFaceMaterial(faceMaterials);
    return skyboxMaterial;
}

function getSkyboxFaces() {
    var NUMBER_OF_FACES = 6, faces = [], texture, faceMaterial, texturePath, i;

    for (i = 0; i < NUMBER_OF_FACES; i++) {
        texturePath = IMAGE_PREFIX + DIRECTIONS[i] + IMAGE_SUFFIX;
        texture = loadFlippedTexture( texturePath );
        faceMaterial = getFaceMaterial( texture );
        faces.push( faceMaterial );
    }
    return faces;
}

function loadFlippedTexture(texturePath) {
    var texture = loadTexture(texturePath);
    flipTexture(texture); // This is necessary, because the skybox-textures are mirrored.
    return texture;
}

function loadTexture(path) {
    return THREE.ImageUtils.loadTexture(path);
}

function flipTexture(texture) {
    texture.repeat.set(-1, 1);
    texture.offset.set(1, 0);
    return texture;
}

function getFaceMaterial(texture) {
    var faceMaterial = new THREE.MeshBasicMaterial({
        map: texture,
        side: THREE.DoubleSide
    });
    return faceMaterial;
}

Upvotes: 1

Related Questions