gattass69
gattass69

Reputation: 101

Texture which maintain proportion as scene background in three.js

i have a scene where i want to add a background, i have a png image (2k resolution), but when i try it on pc it is of the right size, on mobile is a lot "disproportionated" My code is the following:

var texture = THREE.ImageUtils.loadTexture('img/texture.png');

And to add it as background is just this:

  scene = new THREE.Scene();
  scene.background = texture;

I've seen with some search that maybe i have to create a separate scene for the background, but i don't think it is the easiest solution, maybe there are a better solution for this?

(As always, sorry for my bad english)

Upvotes: 0

Views: 703

Answers (2)

Mugen87
Mugen87

Reputation: 31026

As an alternative, you can use a CSS based background:

#background {
    background-image: url('http://youring.com/test/img/texture.png');
    position: fixed;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    z-index: -1;
}

Just create your renderer like this so it's possible to see through the canvas:

renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );

DEMO: https://jsfiddle.net/f2Lommf5/5052/

Upvotes: 0

pailhead
pailhead

Reputation: 5421

You can try approaching this with THREE.ShaderMaterial

class MyBackgroundPlane extends THREE.Mesh{
    constructor(){
        super( 
            new THREE.PlaneBufferGeometry(2,2,1,1), 
            new THREE.ShaderMaterial({
                uniforms:{
                    uTexture: { value: null },
                    uAspect: { value: 1 }
                },
                vertexShader: `
                    varying vec2 vUv;
                    uniform float uAspect;

                    void main(){

                        vUv = uv; //pass coordinates to screen
                        vUv.x *= uAspect; //scale the coordinates

                        gl_Position = vec4(position.xy, 1., 1.);

                    }

                `,

                fragmentShader:`
                    varying vec2 vUv;
                    uniform sampler2D uTexture;

                    void main(){

                        gl_FragColor = texture2D( uTexture, vUv );
                    }

                `

            })
        )

        this.frustumCulled = false
    }

    setAspect( aspect ){
        this.material.uniforms.uAspect.value = aspect
    }

    setTexture( texture ){
        this.material.uniforms.uTexture.value = texture
    }
}

You kinda have to figure out what needs to happen when its portrait and when its landscape.

One approach could be to use uniform vec2 uScale; and then set the vertical and horizontal aspects differently depending on the orientation.

The same thing could be done with the scene graph by attaching a regular plane to a camera for example, and then managing it's scale.

Upvotes: 2

Related Questions