javascript - ThreeJS透明PNG纹理黑色
问题描述
我试图理解 ThreeJS 面临的一个问题。我在页面上有一个简单的立方体,我有一个白色问号的 PNG,图像的其余部分是透明的。当我将纹理添加到立方体时;
cubeGeometry = new THREE.BoxGeometry( 5, 5, 5 );
cubeMaterial = new THREE.MeshStandardMaterial( { color: this.cubeColor, flatShading: true, map:new THREE.TextureLoader().load( require("./question-mark.png") ) } );
cubeMesh = new THREE.Mesh( cubeGeometry, cubeMaterial );
无论我做什么,PNG 中的透明像素都会显示为黑色。更奇怪的是 PNG 的白色像素出现 this.cubeColor 的颜色 - 设置为橙色。
我希望立方体颜色为橙色,PNG 的透明像素采用该颜色,PNG 中的白色像素保持白色。
任何人阐明一些光?
我所看到的
质地
解决方案
您可以像这样应用 2 种或更多材料
const geometry = new THREE.BoxBufferGeometry(boxWidth, boxHeight, boxDepth);
// prepare geometry to use 2 materials
geometry.clearGroups();
geometry.addGroup( 0, Infinity, 0 );
geometry.addGroup( 0, Infinity, 1 );
const loader = new THREE.TextureLoader();
// create 2 materials
const material0 = new THREE.MeshBasicMaterial({
color: 'orange',
});
const material1 = new THREE.MeshBasicMaterial({
map: loader.load('https://i.imgur.com/iFom4eT.png'),
transparent: true,
});
// apply 2 materials to geometry
const materials = [material0, material1];
const cube = new THREE.Mesh(geometry, materials);
示例,注意它使用BoxBufferGeometry
notBoxGeometry
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2;
const scene = new THREE.Scene();
scene.background = new THREE.Color('purple');
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxBufferGeometry(boxWidth, boxHeight, boxDepth);
// prepare geometry to use 2 materials
geometry.clearGroups();
geometry.addGroup( 0, Infinity, 0 );
geometry.addGroup( 0, Infinity, 1 );
const loader = new THREE.TextureLoader();
// create 2 materials
const material0 = new THREE.MeshBasicMaterial({
color: 'orange',
});
const material1 = new THREE.MeshBasicMaterial({
map: loader.load('https://i.imgur.com/hrzoDMj.png'),
transparent: true,
});
// apply 2 materials to geometry
const materials = [material0, material1];
const cube = new THREE.Mesh(geometry, materials);
scene.add(cube);
function render(time) {
time *= 0.001; // convert time to seconds
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
cube.rotation.x = time;
cube.rotation.y = time;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
main();
body { margin: 0; }
#c { width: 100vw; height: 100vh; display: block; }
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r110/build/three.min.js"></script>
<canvas id="c"></canvas>
请注意,如果您将颜色和纹理(贴图)放在单一材质中,则 2 种颜色(1)您指定的颜色和(2)纹理中的颜色将相互相乘。所以,只要纹理有零,RGBA = 0,0,0,0 那么结果就是 0,0,0,0,因为任何乘以零都是零。这就是为什么你得到你最初得到的结果,问号外面是透明的,里面是橙色的。
知道这一点后,您可以使用白色问号并通过在使用纹理的材料上设置颜色来更改其颜色。
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2;
const scene = new THREE.Scene();
scene.background = new THREE.Color('purple');
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxBufferGeometry(boxWidth, boxHeight, boxDepth);
// prepare geometry to use 2 materials
geometry.clearGroups();
geometry.addGroup( 0, Infinity, 0 );
geometry.addGroup( 0, Infinity, 1 );
const loader = new THREE.TextureLoader();
// create 2 materials
const material0 = new THREE.MeshBasicMaterial({
color: 'orange',
});
const material1 = new THREE.MeshBasicMaterial({
map: loader.load('https://i.imgur.com/hrzoDMj.png'),
transparent: true,
});
// apply 2 materials to geometry
const materials = [material0, material1];
const cube = new THREE.Mesh(geometry, materials);
scene.add(cube);
function render(time) {
time *= 0.001; // convert time to seconds
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
material1.color.setHSL(time, 1, 0.5);
cube.rotation.x = time;
cube.rotation.y = time;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
main();
body { margin: 0; }
#c { width: 100vw; height: 100vh; display: block; }
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r110/build/three.min.js"></script>
<canvas id="c"></canvas>
推荐阅读
- spring-boot - Spring 安全性:HttpSecurity 与 WebSecurity
- python - Pyspark/Python 方法
- c# - 使用 Grid.Left 作为 DoubleAnimation 中 Rectangle 的 TargetProperty 的异常
- json - Django、MySQL 和 JSONField 的过滤问题
- binary-search - 二分查找算法平均实际查找次数
- pivot - 交易视图图表松树编辑器中指标的自动缩放禁用
- javascript - Ionic React Uncaught TypeError:赋值给常量变量
- linux - Unity 游戏服务器未在 Linux 上运行
- r - R - 处理 spatstat 包中的 shapefile 问题将空间线数据帧转换为 psp
- r - 从分钟到每日值返回 NA