我有一个 ThreeJS 场景(如下,或 here on CodePen ),其中有一些对象 - 一个是猫的网格对象,一个是立方体,现在,我正在尝试渲染 a 2D SVG illustration我做了。我想将场景中的 SVG 插图放在猫图像和立方体之间,以与猫图像相同的方式显示(直立和 2D)。
我花了几天时间才弄清楚如何渲染我自己的 SVG,我发现 ThreeJs.org 上关于 SVGRenderer 和 SVGLoader 的文档和示例非常繁琐,很难选择适用于我自己的图像(我是新手) 。我最接近渲染 SVG 的是使用 this 中的代码SO 线程使用 LegacySVG装载机。问题是,我完全不知道如何将此代码渲染到 Canvas 上而不是 DOM 上,而且这个 LegacySVG Loader 似乎是一个错误的解决方案,该错误使得查找资源变得极其困难。
所以,本质上,我在an individual CodePen中渲染了一个SVG。使用上述资源,现在我不知道如何将其渲染到与我的立方体和猫图像相同的场景上。是否可以使用 LegacySVG 渲染到 Canvas 上?或者,是否有更简单的方法将我的 SVG 与其他对象放在同一 Canvas 上?
let renderer;
let camera;
//let controls;
let scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(54, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({
antialias: true,
canvas: document.getElementById("viewport")
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(new THREE.Color(0xfefefe));
// document.body.appendChild(renderer.domElement);
camera.position.x = 1;
camera.position.y = 1;
camera.position.z = 15;
let light = new THREE.AmbientLight(0xFFFFFF);
scene.add(light);
let gridHelper = new THREE.GridHelper(10, 10);
scene.add(gridHelper);
// example code
const geometry1 = new THREE.BoxGeometry(1, 1, 1);
const material1 = new THREE.MeshStandardMaterial({
color: 0xff0000
});
const topBox = new THREE.Mesh(geometry1, material1);
scene.add(topBox);
var loader = new THREE.TextureLoader();
// Load an image file into a custom material
var material = new THREE.MeshLambertMaterial({
map: loader.load('https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2850&q=80')
});
// create a plane geometry for the image with a width of 10
// and a height that preserves the image's aspect ratio
var geometry = new THREE.PlaneGeometry(2, 1.5);
// combine our image geometry and material into a mesh
var mesh = new THREE.Mesh(geometry, material);
// set the position of the image mesh in the x,y,z dimensions
mesh.position.set(0,0,5);
// add the image to the scene
scene.add(mesh);
let animate = function() {
requestAnimationFrame(animate);
//controls.update();
renderer.render(scene, camera);
};
//////////////////
animate();
function updateCamera(ev) {
camera.position.z = 15 - window.scrollY / 250.0;
}
window.addEventListener("scroll", updateCamera);
body {
overflow-x: hidden;
overflow-y: scroll;
padding: 0;
margin: 0;
}
canvas {
position: fixed;
height: 100vh;
}
#threeD {
position: fixed;
margin: 0;
padding: 0;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.page-wrapper {
padding: 0px;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 4000vh;
}
#container {
height: 500vh;
position: fixed;
}
<html>
<script src="https://raw.githubusercontent.com/mrdoob/three.js/master/src/loaders/LoadingManager.js"></script>
<script src="https://unpkg.com/three@0.102.1/build/three.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/r68/examples/js/loaders/SVGLoader.js"></script>
<script src="https://raw.githubusercontent.com/mrdoob/three.js/master/examples/js/renderers/SVGRenderer.js"></script>
<link rel="stylesheet" type="text/css" href="index1.css" />
<body>
<canvas id="viewport"></canvas>
<div class="page-wrapper" >
<h1> scroll! </h1>
</div>
</body>
<script src="index1.js"></script>
</html>
最佳答案
有几件事您需要牢记。
SVGRenderer不会呈现与 WebGLRenderer 相同的内容。
a. SVGRenderer 获取
<svg>
内的项目元素并将转换应用于其内部<path>
,<circle>
,<rect>
等元素。你可以看到svg_sandbox example 。所有 SVG 元素都是 2D,但旋转时可以给人 3D 的印象。b. WebGLRenderer 绘制到
<canvas>
元素,并且可以渲染各种真实的3D几何图形。如果您想在 WebGL 中绘制 SVG,则需要首先使用THREE.SVGLoader
将 SVG 文件转换为 WebGL 可以理解的几何图形。 。您可以在 webgl_loader_svg example 中查看这是如何完成的。 ,(点击右下角的<>
按钮即可获取源代码)。您不能拥有
<svg>
元素与<canvas>
中的 WebGL 元素共存于同一 3D 空间中。如果您想将带有猫图像的立方体和平面添加到同一空间,我建议您使用WebGLRenderer方法。我在您的代码片段中注意到您正在使用来自许多不同来源的文件以及各种 Three.js 修订版。一些文件是
r102.1
,有些是r68
,还有一些是最新的,即r113
。您应该坚持使用一种修订版,以避免在尝试使旧文件与新文件一起使用时发生冲突。例如:
关于javascript - 在 Three.js 和 WebGL 中渲染 2D SVG 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60203864/