Hello all.
I’m trying to create a simple multiplayer board game using THREE, and I want to be able to create a game piece with a custom texture on the top. I decided to go with a CanvasTexture
, since that’s what I know best. Below is my code with all of the constructors.
The issue is that when I create a new Piece
and add it to the scene in full ambient light (set to Math.PI), the top face (the textured one) of the block has a very different color than the other faces. For example, if the intended color is 0x555555
, all of the faces will come out as that except for the textured one, which would be 0x9c9c9c
.
import * as THREE from "three";
export class Group {
constructor(items, x = 0, y = 0, z = 0) {
let group = new THREE.Group();
for (let item of items) group.add(item);
group.position.set(x, y, z);
return group;
}
}
export class Box {
constructor(w, h, d, c, tex) {
const geometry = new THREE.BoxGeometry(w, h, d);
let materials = new Array(6).fill(new THREE.MeshStandardMaterial({ color: c }));
if (tex) materials[2] = new THREE.MeshStandardMaterial({ map: tex });
if (tex) console.log(materials[0], materials[2]); // no significant differences (just map, color and uuid)
return new THREE.Mesh( geometry, materials );
}
}
export class Block {
constructor(x, z) {
let base = new Box(1, 0.05, 1, 0x666666);
let platform = new Box(0.925, 0.05, 0.925, 0xffffff);
platform.position.y += 0.05;
return new Group([ base, platform ], x, null, z);
}
}
export class Board {
constructor(w, d) {
let group = new THREE.Group();
for (let x = -w / 2; x < w / 2; x++) {
for (let z = -d / 2; z < d / 2; z++) {
group.add(new Block(x, z));
}
}
return group;
}
}
export class Piece {
constructor(x, z, c, name, hp, ap, rp) {
let tex = new PieceTexture(name, hp, ap, rp, c, (c > 0x7FFFFF ? 0x000000 : 0xFFFFFF))
let box = new Box(0.8, 0.4, 0.8, c, tex);
let group = new Group([ box ], x, 0.275, z);
return group;
}
}
class TextureGenerator {
constructor(w, h, bg) {
this.canvas = document.createElement("canvas");
this.canvas.width = w;
this.canvas.height = h;
this.ctx = this.canvas.getContext("2d");
this.clearColor = bg;
this.clear();
}
clear() {
this.ctx.fillStyle = this.clearColor;
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
text(text, x, y, c, size = 30, font = "Arial") {
this.ctx.font = `${size}px ${font}`;
this.ctx.fillStyle = c;
this.ctx.textAlign = "center";
this.ctx.fillText(text, x, y);
}
img(src, x, y, w, h) {
this.ctx.drawImage(src, x, y, w, h);
}
getTexture() {
return new THREE.CanvasTexture(this.canvas);
}
}
class PieceTexture {
constructor(name, hp, ap, rp, bg, c) {
let gen = new TextureGenerator(512, 512, `#${bg.toString(16).padStart(6, '0')}`);
//gen.text(name, 256, 128, `#${c.toString(16).padStart(6, '0')}`, 80);
return gen.getTexture();
}
}
I’ve tried simply clearing the canvas with a white color, then setting the color
attribute of the material to be 0xffffff
, but I need to have white text on the block sometimes, which just showed up as the background color.
There are no unexpected differences between the textured material and the other 5; things like metalness
and roughness
are all the same. Additionally, I’ve tried clearing the canvas instead of drawing the background color, but that just resulted in the face being black. I’ve also already verified that the canvas itself is setting the right color.
What could be causing this color difference, and is there a way I can resolve it?