简体   繁体   English

在 Three.js 和 WebGL 中渲染 2D SVG 时遇到问题

[英]Trouble rendering a 2D SVG in Three.js & WebGL

I have a ThreeJS Scene (below, or here on CodePen ) with some objects in it - one is a Mesh object of a cat, one is a cube, and now, I'm trying to render a 2D SVG illustration I made.我有一个 ThreeJS 场景(在下面,或在 CodePen 上),其中有一些对象 - 一个是猫的 Mesh 对象,一个是立方体,现在,我正在尝试渲染我制作的 2D SVG 插图 I want to put the SVG illustration in the scene in between the cat image and the cube, displayed the same way the cat image appears (upright, and 2D).我想将场景中的 SVG 插图放在猫图像和立方体之间,以与猫图像相同的方式显示(直立和 2D)。

It has taken me days to figure out how to render my own SVG, I find the documentation and examples on ThreeJs.org for SVGRenderer and SVGLoader extremely cumbersome and hard to pick apply to my own image (I'm a novice).我花了几天时间才弄清楚如何渲染我自己的 SVG,我发现 ThreeJs.org 上的 SVGRenderer 和 SVGLoader 文档和示例非常繁琐,很难选择适用于我自己的图像(我是新手)。 The closest I've come to rendering my SVG is using the code from this SO thread that uses a LegacySVG Loader.我来渲染我的SVG最接近的是使用从代码是使用SO线程LegacySVG装载机。 Problem is, I'm completely lost on how to render this code onto a canvas versus a DOM, and it appears this LegacySVG Loader was a solution to a bug which makes it extremely hard to find resources.问题是,我完全不知道如何将这段代码呈现到画布上而不是 DOM 上,而且这个 LegacySVG Loader 似乎是解决一个错误的解决方案,该错误使得很难找到资源。

So, essentially, I have rendered an SVG in an individual CodePen using the above resources and now I am lost on how to render it onto the same scene as my cube and cat image.所以,基本上,我已经使用上述资源在单个 CodePen 中渲染了一个 SVG,现在我迷失了如何将它渲染到与我的立方体和猫图像相同的场景中。 Is it possible to use LegacySVG to render onto a canvas?是否可以使用 LegacySVG 渲染到画布上? Or, is there a simpler way to get my SVG onto the same canvas as the other objects?或者,是否有一种更简单的方法可以将我的 SVG 与其他对象放在同一个画布上?

 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>

There are a few things you need to keep in mind.有几件事你需要记住。

  1. SVGRenderer does not render the same things as WebGLRenderer . SVGRenderer不呈现与WebGLRenderer相同的东西。

    a.一种。 SVGRenderer takes items inside an <svg> element and applies transformations to its internal <path> , <circle> , <rect> , etc, elements. SVGRenderer<svg>元素中获取项目并将转换应用于其内部的<path><circle><rect>等元素。 You can see the svg_sandbox example .您可以查看svg_sandbox 示例 All SVG elements are 2D, but can give the impression of being 3D when rotated.所有 SVG 元素都是 2D 的,但在旋转时可以给人以 3D 的印象。

    b.WebGLRenderer draws onto a <canvas> element, and can render all kinds of true 3D geometry. WebGLRenderer绘制在<canvas>元素上,可以渲染各种真实的 3D 几何图形。 If you want to draw an SVG in WebGL, you'll need to first convert the SVG file into a geometry that WebGL can understand by using THREE.SVGLoader .如果您想在 WebGL 中绘制 SVG,您需要首先使用THREE.SVGLoader将 SVG 文件转换为 WebGL 可以理解的THREE.SVGLoader You can see how that's done in the webgl_loader_svg example , (the source code is available by clicking on the <> button on the bottom right).您可以在webgl_loader_svg 示例中看到这是如何完成的(单击右下角的<>按钮可以获得源代码)。

  2. You cannot have <svg> elements co-existing in the same 3D space as WebGL elements in the <canvas> . <svg>元素不能与<canvas>中的 WebGL 元素共存于同一 3D 空间中。 If you want to add cubes and planes with cat images to the same space, I recommend you use the WebGLRenderer approach.如果您想将带有猫图像的立方体和平面添加到同一空间,我建议您使用 WebGLRenderer 方法。

  3. I noticed in your code snippet that you're using files from many different sources, and all kinds of Three.js revisions.我在你的代码片段中注意到你使用了许多不同来源的文件,以及各种 Three.js 修订版。 Some files are r102.1 , some are r68 , and some are the latest, which is r113 .有些文件是r102.1 ,有些是r68 ,有些是最新的,也就是r113 You should stick to one revision to avoid conflicts when trying to get older files to work with newer ones.在尝试让旧文件与新文件一起工作时,您应该坚持一个修订以避免冲突。 For example:例如:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM