three SVGRenderer SVG渲染器

344 阅读3分钟

SVGRenderer 是 Three.js 中一个专门用于将 3D 场景渲染为 SVG(可缩放矢量图形)格式的渲染器。与 WebGLRenderer 使用 GPU 渲染 3D 图形不同,SVGRenderer 使用 CPU 生成 SVG 输出,适合用于生成静态的 2D 图像、矢量图形或可视化效果,不适用于实时交互或动画。

SVGRenderer 有七个方法

<template>
    <div id="parkingLot" ref="parkingLot">
    </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import * as THREE from 'three';
import hdrImg from "@public/hdr/bgImage.hdr"
import imgPng from "@public/rg.png"
import person from "@public/person.jpg"
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { SVGRenderer, SVGObject } from 'three/addons/renderers/SVGRenderer.js';
const parkingLot = ref();

onMounted(async () => {
    const DOMEl = parkingLot.value;
    // 获取 DOMEl 的宽度和高度,以设置渲染器的大小。
    const width = DOMEl.clientWidth;
    const height = DOMEl.clientHeight;

    const renderer = new SVGRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setQuality( 'low' );
    DOMEl.appendChild( renderer.domElement );
    const scene = new THREE.Scene();
    renderer.setClearColor(0x000000);
    const camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );
    camera.position.set( 0, 80, 0 );
    camera.lookAt( 0, 0, 0 );
    // 禁用颜色管理
    THREE.ColorManagement.enabled = false;
    // 加载并显示二维码的几何体
    const loader = new THREE.BufferGeometryLoader();
    loader.load('https://raw.githubusercontent.com/mrdoob/three.js/refs/heads/master/examples/models/json/QRCode_buffergeometry.json', function (geometry) {
        // 使用加载的几何体创建一个新的 Mesh
        mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({ vertexColors: true }));
        mesh.scale.x = mesh.scale.y = mesh.scale.z = 2; // 设置缩放
        scene.add(mesh); // 将该 Mesh 添加到场景中
    });
    // 创建两个立方体并添加到场景中
    const boxGeometry = new THREE.BoxGeometry(100, 100, 100);
    // 第一个立方体:蓝色,半透明
    let mesh = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({ color: 0x0000ff, opacity: 0.5, transparent: true }));
    mesh.position.x = 500;
    mesh.rotation.x = Math.random();
    mesh.rotation.y = Math.random();
    mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
    scene.add(mesh);
    // 第二个立方体:随机颜色
    mesh = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff }));
    mesh.position.x = 500;
    mesh.position.y = 500;
    mesh.rotation.x = Math.random();
    mesh.rotation.y = Math.random();
    mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
    scene.add(mesh);
    // 创建一个平面并添加到场景中
    mesh = new THREE.Mesh(new THREE.PlaneGeometry(100, 100), new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff, side: THREE.DoubleSide }));
    mesh.position.y = -500;
    mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
    scene.add(mesh);
    // 创建一个圆柱体并添加到场景中
    mesh = new THREE.Mesh(new THREE.CylinderGeometry(20, 100, 200, 10), new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff }));
    mesh.position.x = -500;
    mesh.rotation.x = -Math.PI / 2;
    mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
    scene.add(mesh);
    // 创建一个多边形场地并添加到场景中
    const geometry = new THREE.BufferGeometry();
    const material = new THREE.MeshBasicMaterial({ vertexColors: true, side: THREE.DoubleSide });
    const v = new THREE.Vector3();
    const v0 = new THREE.Vector3();
    const v1 = new THREE.Vector3();
    const v2 = new THREE.Vector3();
    const color = new THREE.Color();
    const vertices = [];
    const colors = [];
    for (let i = 0; i < 100; i++) {
        // 随机生成三角形的三个顶点
        v.set(Math.random() * 1000 - 500, Math.random() * 1000 - 500, Math.random() * 1000 - 500);
        v0.set(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50);
        v1.set(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50);
        v2.set(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50);
        v0.add(v);
        v1.add(v);
        v2.add(v);
        color.setHex(Math.random() * 0xffffff);
        // 创建一个三角形的顶点并设置颜色
        vertices.push(v0.x, v0.y, v0.z);
        vertices.push(v1.x, v1.y, v1.z);
        vertices.push(v2.x, v2.y, v2.z);
        colors.push(color.r, color.g, color.b);
        colors.push(color.r, color.g, color.b);
        colors.push(color.r, color.g, color.b);
    }
    geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
    const group = new THREE.Mesh(geometry, material);
    group.scale.set(2, 2, 2);
    scene.add(group);
    // 创建多个精灵并添加到场景中
    for (let i = 0; i < 50; i++) {
        const material = new THREE.SpriteMaterial({ color: Math.random() * 0xffffff });
        const sprite = new THREE.Sprite(material);
        sprite.position.x = Math.random() * 1000 - 500;
        sprite.position.y = Math.random() * 1000 - 500;
        sprite.position.z = Math.random() * 1000 - 500;
        sprite.scale.set(64, 64, 1); // 设置精灵的缩放
        scene.add(sprite);
    }
    // 使用自定义 SVG 图形创建对象并添加到场景中
    const node = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    node.setAttribute('stroke', 'black');
    node.setAttribute('fill', 'red');
    node.setAttribute('r', '40');
    for (let i = 0; i < 50; i++) {
        const object = new SVGObject(node.cloneNode());
        object.position.x = Math.random() * 1000 - 500;
        object.position.y = Math.random() * 1000 - 500;
        object.position.z = Math.random() * 1000 - 500;
        scene.add(object);
    }
    // 从文件加载 SVG 并将其转换为对象添加到场景中
    const fileLoader = new THREE.FileLoader();
    fileLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/refs/heads/master/examples/models/svg/hexagon.svg', function (svg) {
        const node = document.createElementNS('http://www.w3.org/2000/svg', 'g');
        const parser = new DOMParser();
        const doc = parser.parseFromString(svg, 'image/svg+xml');
        node.appendChild(doc.documentElement);
        const object = new SVGObject(node);
        object.position.x = 500;
        scene.add(object);
    });
    // 创建光源并添加到场景中
    const ambient = new THREE.AmbientLight(0x80ffff);
    scene.add(ambient);
    const directional = new THREE.DirectionalLight(0xffff00);
    directional.position.set(-1, 0.5, 0);
    scene.add(directional);
    // 创建 OrbitControls 实例,用于控制摄像机
    const controls = new OrbitControls(camera, renderer.domElement);
    // 设置控制器的目标点为原点
    controls.target.set(0, 0, 0);
    // 动画函数
    function animate() {
        requestAnimationFrame(animate);
        group.rotation.x += 0.01; // 使多边形场地不断旋转
        controls.update(); // 更新 OrbitControls
        renderer.render(scene, camera); // 渲染场景
    }
    animate();
});

</script>
<style lang="scss" scoped="scoped">

    #parkingLot {
        width: 940px;
        height: 940px;
        border: 1px solid #ccc;
        margin: 30px auto;
    }

</style>

方法

  • clear () : undefined 告诉渲染器来清除其绘图表面。
  • getSize () : Object 返回一个包含有渲染器宽和高的对象。
  • render ( scene : Scene, camera : Camera ) : undefined 使用camera来渲染一个scene。
  • setClearColor ( color : Color, alpha : number ) : undefined 设置clearColor(空白颜色)以及clearAlpha(空白Alpha)。
  • setPrecision ( precision : Number ) : undefined 设置用于创建路径的数据的精度。
  • setQuality () : undefined 设置渲染质量。可能的值有low和high(默认值)。
  • setSize ( width : Number, height : Number ) : undefined 改变渲染器尺寸为(width, height)。