Three.js: Black background on obj with PNG textures.

Created on 7 Sep 2017  Â·  14Comments  Â·  Source: mrdoob/three.js

Description of the problem

Hello!

I have problem with transparent UV map in threejs. When I set texture in blender and I click "render" everything it's ok

but when I load model in threejs by JSONloader the black background load under PNG texture instead blender's material color.

How can I delete this black background in threejs and use blender material color?

Here is my code:

var scene, camera, renderer;
  var guiControls, controls, stats, axis, lightHelper;
  var sceneBackground;
  var spotLight;
  var cube, ground, toursKnot, text;
  var groundMaterial, boxMaterial, torMaterial, textMaterial;
  var groundGeometry, boxGeometry, torGeometry, textGeometry;
  var SCREEN_WIDTH, SCREEN_HEIGHT;


  var loader = new THREE.JSONLoader();
  loader.load('models/CupME9.json', addModel);

  function addModel(geometry, materials){
    var material = new THREE.MeshFaceMaterial(materials);
    model = new THREE.Mesh(geometry, material);
    model.scale.set(1,1,1);
    model.position.set(5,2,0);
    model.castShadow = true;
    scene.add(model);
  }


  function init(){
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, .1, 500);
    renderer = new THREE.WebGLRenderer({antialias:true });



    sceneBackground = renderer.setClearColor(0xdddddd);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    renderer.shadowMapSoft = true;


  //Controls
    controls = new THREE.OrbitControls(camera,renderer.domElement);
    controls.addEventListener('change', render);

  //add helpers
    axis = new THREE.AxisHelper(10);
    scene.add(axis);


  //grid

    color = new THREE.Color("rgb(255,0,0)");
    lineColor = new THREE.Color(0x000000);
    grid = new THREE.GridHelper(50,20,color,lineColor);
    scene.add(grid);

  //camera
    camera.position.set(15,12,10);
    camera.lookAt(scene.position);

    guiControls = new function(){
      this.rotationX = 0.0;
      this.rotationY = 0.0;
      this.rotationZ = 0.0;

      this.lightX = 10;
      this.lightY = 10;
      this.lightZ = 15;
      this.intensity = 1;
      this.distance = 0;
      this.angle = 1.570;
      this.exponent = 0;
      this.shadowCameraNear = 1;
      this.shadowCameraFar = 100;
      this.shadowCameraFov = 50;
      this.shadowCameraVisible = true;
      this.shadowMapWidth = 1024;
      this.shadowMapHeigh = 1024;
      this.shadowBias = 0;
      this.shadowDarkness = 0.5;
      this.target = 'cube';
    }

  //lights
    var ambient = new THREE.AmbientLight(0x404040);
    scene.add(ambient);

    spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(10,10,15);
    spotLight.castShadow = true;
    spotLight.shadow.camera.left = -500;
    spotLight.shadow.camera.right = 500;
    spotLight.shadow.camera.top = 500;
    spotLight.shadow.camera.bottom = -500;
    spotLight.intensity = guiControls.intensity;
    spotLight.distance = guiControls.distance;
    spotLight.shadow.bias = guiControls.shadowBias;
    spotLight.shadow.camera.fov = guiControls.shadowCameraFov;
    spotLight.shadow.camera.near = guiControls.shadowCameraNear;
    spotLight.shadow.camera.far = guiControls.shadowCameraFar;
    spotLight.shadow.camera.visible = guiControls.shadowCameraVisible;
    spotLight.shadow.mapSize.width = guiControls.shadowMapWidth; // default is 512
    spotLight.shadow.mapSize.height = guiControls.shadowMapHeigh;
    spotLight.name = 'Spot light';

    lightHelper = new THREE.CameraHelper( spotLight.shadow.camera )
    scene.add(lightHelper);
    scene.add(spotLight);

  //Plane
    groundGeometry = new THREE.BoxGeometry(40,0,40);
    groundMaterial = new THREE.MeshPhongMaterial({
      color: 0xa0adaf,
      shininess: 150,
      specular: 0xffffff,
      flatShading : true
    });
    ground = new THREE.Mesh(groundGeometry, groundMaterial);
    ground.castShadow = false;
    ground.receiveShadow = true;
    scene.add(ground);



    var datGUI = new dat.GUI();

    datGUI.add(guiControls, 'rotationX', 0, 1);
    datGUI.add(guiControls, 'rotationY', 0, 1);
    datGUI.add(guiControls, 'rotationZ', 0, 1);
    datGUI.add(guiControls, 'lightX',-60,180);
    datGUI.add(guiControls, 'lightY',0,180);
    datGUI.add(guiControls, 'lightZ',-60,180);

    datGUI.add(guiControls, 'target', ['cube', 'torusKnot','text']).onChange(function(){
        if (guiControls.target == 'cube'){
            spotLight.target =  cube;
        }
        else if (guiControls.target == 'torusKnot'){
            spotLight.target =  toursKnot;
        }
        else if (guiControls.target == 'text'){
            spotLight.target =  text;
        }
    });

    datGUI.add(guiControls, 'intensity', 0.01, 5).onChange(function(value){
      spotLight.intensity = value;
    });

    datGUI.add(guiControls, 'distance', 0, 1000).onChange(function(value){
      spotLight.distance = value;
    });

    datGUI.add(guiControls, 'angle', 0.001, 1.570).onChange(function(value){
      spotLight.angle = value;
    });

    datGUI.add(guiControls, 'exponent', 0, 50).onChange(function(value){
      spotLight.exponent = value;
    });

    datGUI.add(guiControls, 'shadowCameraNear', 0 , 100).name("Near").onChange(function(value){
      spotLight.shadow.camera.near = value;
      spotLight.shadow.camera.updateProjectionMatrix();
      lightHelper.update();
    });

    datGUI.add(guiControls, 'shadowCameraFar', 0 , 100).name("Far").onChange(function(value){
      spotLight.shadow.camera.far = value;
      spotLight.shadow.camera.updateProjectionMatrix();
      lightHelper.update();
    });

    datGUI.add(guiControls, 'shadowCameraFov', 0 , 100).name("Fov").onChange(function(value){
      spotLight.shadow.camera.fov = value;
      spotLight.shadow.camera.updateProjectionMatrix();
      lightHelper.update();
    });

    datGUI.add(guiControls, 'shadowCameraVisible').onChange(function(value){
      spotLight.shadow.camera.visible = value;
      spotLight.shadow.camera.updateProjectionMatrix();
      //lightHelper.update();
    });
    //datGUI.close();

    datGUI.add(guiControls, 'shadowBias', 0 , 1).onChange(function(value){
      spotLight.shadow.bias = value;
      spotLight.shadow.camera.updateProjectionMatrix();
      lightHelper.update();
    });

    /*datGUI.add(guiControls, 'shadowDarkness', 0 , 1).onChange(function(value){
      spotLight.shadow.camera.darkness = value;
      spotLight.shadow.camera.updateProjectionMatrix();
    });*/
    $("#webGL-container").append(renderer.domElement);

    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.left = '0px';
    stats.domElement.style.top = '0px';

    $("#webGL-container").append(stats.domElement);


  }




  function render(){

    spotLight.position.x = guiControls.lightX;
    spotLight.position.y = guiControls.lightY;
    spotLight.position.z = guiControls.lightZ;

  }



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

  init();
  animate();


  $(window).resize(function(){
    SCREEN_WIDTH = window.innerWidth;
    SCREEN_HEIGHT = window.innerHeight;
    camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
    camera.updateProjectionMatrix();
    renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);

  });
Three.js version
  • [ ] Dev
  • [ x] r87
  • [ ] ...
Browser
  • [x] All of them
  • [ ] Chrome
  • [ ] Firefox
  • [ ] Internet Explorer
OS
  • [x] All of them
  • [ ] Windows
  • [ ] macOS
  • [ ] Linux
  • [ ] Android
  • [ ] iOS
Hardware Requirements (graphics card, VR Device, ...)
Help (please use the forum)

Most helpful comment

this is not fixed yet ritgh?

There will be no fix since nothing is broken. As you can see here, the transparent part of a PNG is black per default (since no color is defined for transparent texels). You can change this behavior by setting Material.transparent to true so three.js can perform alpha blending with the respective background pixels. Another approach is to set Material.alphaTest to a value like 0.5. In this case the material is not marked as transparent but transparent texels are discared in the fragment shader in order to produce an alpha cutout.

All 14 comments

Help question posted on stackoverflow.

Does Blender support decals? That is what this looks like.

If so, how does the exporter handle them?

/ping @Mugen87 Maybe you know something about this?

@MarcinBorkowski03 Can you please share the .blend file and the corresponding JSON export?

Sure guys. Thanks for your help, here's my model in blender
blenderModel.zip

I ran into the same problem with a model in 3DS Max recently - this is the workaround I used.

Use UV unwrapping to map your model (I've never done this in blender, docs are here though, and the process should be pretty similar to Max).

Map the polygons where you want the texture to show as normal - that is, get the model to the point where the texture looks the way it currently does in your screenshot.
Then map all of the rest of the polygons to a small patch of the background colour of the texture.

This is probably best practice anyway, since otherwise it's hard to make the colour of the rest of your model blend with the background colour of your texture

@MarcinBorkowski03 Can you also share the .blend file, please? I can only find in your zip file the JSON export data and the texture.

@looeee Thank you for your workaround but I need to make the whole black surface transparent beacuse I'm trying to create creator when customer can upload his PNG photo and change the model texture.

@Mugen87 I'm so sorry, sure here is .blend model. CupBlenderModel.zip

this is not fixed yet ritgh? I have the same problem

this is not fixed yet ritgh?

There will be no fix since nothing is broken. As you can see here, the transparent part of a PNG is black per default (since no color is defined for transparent texels). You can change this behavior by setting Material.transparent to true so three.js can perform alpha blending with the respective background pixels. Another approach is to set Material.alphaTest to a value like 0.5. In this case the material is not marked as transparent but transparent texels are discared in the fragment shader in order to produce an alpha cutout.

Thanks , if the transparent part of a PNG is black per default , how can i
make this default another color?
The alphaTest = 0.5 is not working for me

Michael Herzog notifications@github.com escreveu no dia sexta, 29/03/2019
à(s) 21:02:

this is not fixed yet ritgh?

There will be no fix since nothing is broken. As you can see at here
https://jsfiddle.net/16u8dmqv/1/, the transparent part of a PNG is
black per default (since no color is defined for transparent texels). You
can change this behavior by setting Material.transparent to true so
three.js can perform alpha blending with the respective background
pixels. Another approach is to set Material.alphaTest to a value like 0.5.
In this case the material is not marked as transparent but transparent
texels are discared in the fragment shader in order to produce an alpha
cutout.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/mrdoob/three.js/issues/12148#issuecomment-478148568,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AZR4Uge8JeuwVucMKjtehesWdmOBWCm7ks5vbn97gaJpZM4PPkh8
.

Please redirect your questions to stackoverflow or the forum.

Just a quick note -- Material.transparent is a better solution than Material.alphaTest since the latter will cause hard edges and won't handle partially transparent PNGs well. You really want full alpha blending. https://en.wikipedia.org/wiki/Alpha_compositing

You really want full alpha blending.

@garyo I think this really depends on the scenario. When rendering vegetation for example, using alpha cutouts is the better option and also more performant since you avoid any blending overhead.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexprut picture alexprut  Â·  3Comments

filharvey picture filharvey  Â·  3Comments

konijn picture konijn  Â·  3Comments

zsitro picture zsitro  Â·  3Comments

yqrashawn picture yqrashawn  Â·  3Comments