three.js - 为什么我的 "X"没有通过透明矩形显示?

标签 three.js textures transparent

此代码显示了 2 个矩形,透明矩形后面带有“X”。顶部有一个微红色的背景——“X”通过前面的矩形显示出来,就像它应该的那样。底部矩形具有默认的透明背景 - “X”不会像我希望的那样通过前面的矩形显示。也许我缺少一个“alpha..”参数? TIA。

<!doctype html>
<html>
  <head>
    <title> threejs texture transparency </title>
    <style type="text/css">
canvas { outline:1px dotted black; }
    </style>
    <script src="http://threejs.org/build/three.js"></script>
    <script type="text/javascript">
  "use strict";
  var renderer, camera, world, geometry, material, mesh;
  var js3canvas, js3w, js3h, canvas, ctx, texture;
window.onload = function() {
  "use strict";
  // the basic 3js
  js3canvas = document.getElementById("js3canvas");
  renderer = new THREE.WebGLRenderer( { canvas:js3canvas } );
  js3w = js3canvas.width;
  js3h = js3canvas.height;
  camera = new THREE.PerspectiveCamera(50, js3w/js3h, 1, 200);
  camera.position.z = 75;
  camera.lookAt(0,0,0);
  world = new THREE.Scene();
  world.background = new THREE.Color(0xaaaaaa);

  // a greenish transparent rectangle at z=+1
  geometry = new THREE.PlaneGeometry(20, 50);
  material = new THREE.MeshBasicMaterial( { color:0x55aa55, transparent:true, opacity:0.5 } );
  world.add(new THREE.Mesh(geometry, material));

  doRect("top"); // a REDDISH rectangle at z=-1 with a texture of a black "X"
  doRect("bot"); // a TRANSPARENT rectangle at z=-1 with a texture of a black "X"
  renderer.render( world, camera );
};
function doRect(topbot) { // a rectangle with a texture
  // first, the canvas for the texture
  if (topbot == "top") canvas = document.getElementById("canvas2"); // top rectangle
  else canvas = document.getElementById("canvas3"); // bot rectangle
  ctx = canvas.getContext("2d");
  if (topbot == "top") { // top only, reddish background
    ctx.fillStyle = "#aa5555"; 
    ctx.fillRect(0,0,250,50);
  } // bot is left default transparent
  ctx.strokeStyle = "#0000000"; // black lines to make "X"
  ctx.moveTo(0,0); ctx.lineTo(250,50);
  ctx.moveTo(0,50); ctx.lineTo(250,0);
  ctx.stroke();
  // second, the texture
  texture = new THREE.Texture(canvas);
  texture.minFilter = THREE.LinearFilter; // eliminates console.log msg
  texture.needsUpdate = true; // needed
  // third, the rectangle with the texture
  geometry = new THREE.PlaneGeometry(50,10);
  if (topbot == "top") { // top rectangle with "X" texture, reddish background
    geometry.translate(0,10,-1); // move up
    material = new THREE.MeshBasicMaterial( { map:texture, transparent:false } );
    // If this material is transparent(true) then the "X" doesn't show through.
  } else {               // bottom rectangle with "X" texture, default(transparent) background
    geometry.translate(0,-10,-1); // move down
    material = new THREE.MeshBasicMaterial( { map:texture, transparent:true, opacity:1.0 } );
    // This material has to be transparent to get a transparent background for the texture.
    // But then the "X" doesn't show through.
  }
  mesh = new THREE.Mesh(geometry, material); // and finally the mesh
  world.add(mesh);
}
    </script>
  </head>
  <body>
    <canvas id="js3canvas" width="600" height="600"></canvas><br />
    <canvas id="canvas2" width="250" height="50"></canvas><br />
    <canvas id="canvas3" width="250" height="50"></canvas>
  </body>
</html>

Mugen87 的编辑:
添加“side:THREE.DoubleSide,”到所有 Material ,
将这 2 条语句添加到适当的位置:

  mesh.renderOrder = 1;
  animate();

并添加此功能:

function animate() {
  renderer.render( world, camera );
  world.rotation.y += .01;
  if (world.rotation.y < 3.1416) requestAnimationFrame(animate);
}

现在底部矩形不透明? 我会看看这个。

最佳答案

你看到的是深度排序问题。两个透明对象(绿色平面网格和透明 X)都放置在 3D 空间中的相同位置。因此,它们根据场景图中的顺序进行渲染。为了获得正确的结果,您必须确保绿色平面最后渲染。您可以通过定义 Object3D.renderOrder 来影响渲染器的默认排序。 .

var renderer, camera, world, geometry, material, mesh;
var js3canvas, js3w, js3h, canvas, ctx, texture;

// the basic 3js
js3canvas = document.getElementById("js3canvas");
renderer = new THREE.WebGLRenderer( { canvas:js3canvas } );
js3w = js3canvas.width;
js3h = js3canvas.height;
camera = new THREE.PerspectiveCamera(50, js3w/js3h, 1, 200);
camera.position.z = 75;
camera.lookAt(0,0,0);
world = new THREE.Scene();
world.background = new THREE.Color(0xaaaaaa);

// a greenish transparent rectangle at z=+1
geometry = new THREE.PlaneGeometry(20, 50);
material = new THREE.MeshBasicMaterial( { color:0x55aa55, transparent:true, opacity:0.5 } );
var mesh = new THREE.Mesh(geometry, material);
mesh.renderOrder = 1;
world.add(mesh);

doRect("top"); // a REDDISH rectangle at z=-1 with a texture of a black "X"
doRect("bot"); // a TRANSPARENT rectangle at z=-1 with a texture of a black "X"

renderer.render( world, camera );

function doRect(topbot) { // a rectangle with a texture
  // first, the canvas for the texture
  if (topbot == "top") canvas = document.getElementById("canvas2"); // top rectangle
  else canvas = document.getElementById("canvas3"); // bot rectangle
  ctx = canvas.getContext("2d");
  if (topbot == "top") { // top only, reddish background
    ctx.fillStyle = "#aa5555"; 
    ctx.fillRect(0,0,250,50);
  } // bot is left default transparent
  ctx.strokeStyle = "#0000000"; // black lines to make "X"
  ctx.moveTo(0,0); ctx.lineTo(250,50);
  ctx.moveTo(0,50); ctx.lineTo(250,0);
  ctx.stroke();
  // second, the texture
  texture = new THREE.Texture(canvas);
  texture.minFilter = THREE.LinearFilter; // eliminates console.log msg
  texture.needsUpdate = true; // needed
  // third, the rectangle with the texture
  geometry = new THREE.PlaneGeometry(50,10);
  if (topbot == "top") { // top rectangle with "X" texture, reddish background
    geometry.translate(0,10,-1); // move up
    material = new THREE.MeshBasicMaterial( { map:texture } );
    // If this material is transparent(true) then the "X" doesn't show through.
  } else {               // bottom rectangle with "X" texture, default(transparent) background
    geometry.translate(0,-10,-1); // move down
    material = new THREE.MeshBasicMaterial( { map:texture, transparent:true, opacity:1.0 } );
    // This material has to be transparent to get a transparent background for the texture.
    // But then the "X" doesn't show through.
  }
  mesh = new THREE.Mesh(geometry, material); // and finally the mesh
  world.add(mesh);
}
body {
	  margin: 0;
}
canvas { 
	outline: 1px dotted black; 
	}
<script src="https://rawcdn.githack.com/mrdoob/three.js/r113/build/three.js"></script>

<canvas id="js3canvas" width="600" height="600"></canvas><br />
<canvas id="canvas2" width="250" height="50"></canvas><br />
<canvas id="canvas3" width="250" height="50"></canvas>

关于three.js - 为什么我的 "X"没有通过透明矩形显示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60251312/

相关文章:

javascript - 围绕场景旋转相机

javascript - 三.TextureLoader加载不上图片文件

textures - 共享 ID3D11Buffer 和 ID3D12Resource

c++ - OpenGL 多纹理加载错误

c# - winform 上的透明背景?

python - 使 tkinter 中 'Text' 小部件的背景透明

javascript - 如何从 Three.js Canvas 中保存图像?

javascript - 从 2018 年开始在 WebGL 中加载着色器?

directx - 在 DirectX 11 和 DirectX 10 之间共享纹理

Android OpenGL ES 透明背景