Jack Franzen
Jack Franzen

Reputation: 778

Unusual antialias while using basic texture material in three.js

In the following code I am setting up a very basic scene with an orthographic camera and a canvas mapped as a texture to a plane geometry.

I put some white text on to a transparent canvas, and if I use canvas.toDataURL(), the effect isn't present.

However, when I apply the canvas contents to a material as a texture and render it within a super-standard 2d scene, a black line outlines my text, probably the result of weird antialias stuff happening. In this example, the renderer clear color, material, and text are all pure white.

Here is a screenshot: screenshot

var camera = new THREE.OrthographicCamera(window.innerWidth / - 2,
                                          window.innerWidth / 2, 
                                          window.innerHeight / 2, 
                                          window.innerHeight / - 2, 0, 10);

var scene = new THREE.Scene();

canvas = document.createElement('canvas');
canvas.width = 300;
canvas.height = 300;

var context = canvas.getContext('2d');

context.fillStyle = "white";
context.font = "bold 72px Arial";
context.fillText("Zibri", 50, 100);        

var texture = new THREE.Texture(canvas);
var geometry = new THREE.PlaneGeometry(canvas.width, canvas.height);

texture.needsUpdate = true;

var material = new THREE.MeshBasicMaterial({ color: 0xffffff, map: texture, transparent: true });
var mesh = new THREE.Mesh(geometry, material);

scene.add(mesh);

renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor(0xffffff)

document.body.appendChild( renderer.domElement );

camera.lookAt(scene.position);
renderer.render(scene, camera);

Upvotes: 5

Views: 4258

Answers (1)

netpraxis
netpraxis

Reputation: 156

I've also been struggling with this problem, WestLangley's solution came part way to fixing the issue but left the rendered text with very poorly antialiased edges. After extensive research, I've come up with a solution that I'm happy with which I've outline here.

Before drawing the text, fill the canvas with the same colour as the text but with alpha set to 0.01

context.fillStyle = 'rgba(255,255,255,0.01)';
context.fillRect(0,0,canvas.width,canvas.height);

and then use the material's alphaTest property to discard pixels of this opacity:

var material = new THREE.MeshBasicMaterial({
    color: 0xffffff,
    map: texture,
    transparent: true,
    alphaTest:0.01
});

finally, set the texture map's premultiplyAlpha value to false:

texture.map.premultiplyAlpha = false;
texture.map.needsUpdate = true;

Upvotes: 6

Related Questions