ThreeJS-离屏渲染(三十五)

离屏渲染: 个人理解,渲染两个场景A、B,假如A是主场景,B是离屏场景,首先离屏场景先借助主场景将视图渲染缓存,

代码位置:

      //离屏渲染
      render.setClearColor(0x53868B);
      render.setRenderTarget(target);
      render.render(scene2, camera2);

然后再切回主场景,将B场景中看到的视角以贴图纹理的形式渲染到主场景物体上

代码位置:

    const meshMaterial = new THREE.MeshBasicMaterial({
        color: 0x8B8878,
        map: target.texture
    })

 render.setClearColor(0x6A5ACD);
      render.setRenderTarget(null);
      render.render(scene, camera);

逻辑:

主场景是一个平面,离屏场景是一个正方体,现在控制器控制离屏场景照相机,将离屏场景照相机视角渲染到主场景平面上,所以我们下面看到的效果图,不是主场景照相机在动产生的效果,而是离屏照相机变动产生的效果

关键代码:

    //创建轨道控制器,可以拖动,控制的是摄像头
    const controls = new OrbitControls(camera2, render.domElement);
    //设置控制阻尼,让控制器有更真实的效果
    controls.enableDamping = true;

完整代码:

<template>
  <div id="three_div"></div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { Reflector } from "three/examples/jsm/objects/Reflector";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import gsap from "gsap";

export default {
  name: "HOME",
  components: {
    // vueQr,
    // glHome,
  },
  data() {
    return {};
  },
  mounted() {
 
    //1.离屏场景
    const scene2 = new THREE.Scene()
    const camera2 = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      20000
    );
    camera2.position.set(0, 0, 10);
    scene2.add(camera2);
    const meshGeometry2 = new THREE.BoxBufferGeometry(1, 1, 1);
    const meshMaterial2 = new THREE.MeshBasicMaterial({
        color: 0x8B7765,
        transparent: true,
        opacity: 0.4
    })
    const mesh2 = new THREE.Mesh(meshGeometry2, meshMaterial2);
    scene2.add(mesh2);
    const target = new THREE.WebGLRenderTarget(500, 500);
    

    
    //主场景
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      20000
    );
    camera.position.set(0, 0, 10);
    scene.add(camera);
    const meshGeometry = new THREE.PlaneBufferGeometry(29,15);
    const meshMaterial = new THREE.MeshBasicMaterial({
        color: 0x8B8878,
        map: target.texture
    })
    const mesh = new THREE.Mesh(meshGeometry, meshMaterial);
    scene.add(mesh);
    //初始化渲染器
    const render = new THREE.WebGLRenderer({
      //设置抗锯齿,防失真
      antialis: true,
      //对数深度缓冲区,防止模型闪烁
      logarithmicdepthbuffer: true,
    });
    /*设置场景渲染编码threejs将贴图的编码都默认设置为THREE.LinearEncoding,
     *导致图片色彩失真(色彩不像正常那么鲜艳,会灰蒙蒙的),所以务必将场景中的所有贴图的编码都调整为THREE.sRGBEncoding
     */
    render.outputEncoding = THREE.sRGBEncoding;
    //设置渲染器的尺寸
    render.setSize(window.innerWidth, window.innerHeight);
    //清除默认设置颜色
    render.setClearColor("#000");
    //设置曝光类型(电影类型、文本类型、游戏类型),电影类型
    render.toneMapping = THREE.ACESFilmicToneMapping;
    //曝光强度
    render.toneMappingExposure = 0.5;
    //开启物理灯光,使灯光效果更佳真实Correct(准确)
    render.physicallyCorrectLights = true;

    //创建轨道控制器,可以拖动,控制的是摄像头
    const controls = new OrbitControls(camera2, render.domElement);
    //设置控制阻尼,让控制器有更真实的效果
    controls.enableDamping = true;
    //自动转起来
    // controls.autoRotate = true;
    //将webgl渲染的canvas内容添加到body上
    document.getElementById("three_div").appendChild(render.domElement);

    //渲染下一帧的时候就会调用回调函数
    let renderFun = () => {
      //更新阻尼数据
      controls.update();
      //离屏渲染
      render.setClearColor(0x53868B);
      render.setRenderTarget(target);
      render.render(scene2, camera2);
      //需要重新绘制canvas画布.主场景
      render.setClearColor(0x6A5ACD);
      render.setRenderTarget(null);
      render.render(scene, camera);
      //监听屏幕刷新(60HZ,120HZ),每次刷新触发一次requestAnimationFrame回调函数
      //但是requestAnimationFrame的回调函数注册生命只有一次,因此需要循环注册,才能达到一直调用的效果
      window.requestAnimationFrame(renderFun);
    };
    // window.requestAnimationFrame(renderFun);
    renderFun();

    //画布全屏
    window.addEventListener("dblclick", () => {
      if (document.fullscreenElement) {
        document.exitFullscreen();
      } else {
        //document.documentElement.requestFullscreen();
        render.domElement.requestFullscreen();
      }
    });

    //监听画面变化,更新渲染画面,(自适应的大小)
    window.addEventListener("resize", () => {
      //更新摄像机的宽高比
      camera.aspect = window.innerWidth / window.innerHeight;
      //更新摄像机的投影矩阵
      camera.updateProjectionMatrix();
      //更新渲染器宽度和高度
      render.setSize(window.innerWidth, window.innerHeight);
      //设置渲染器的像素比
      render.setPixelRatio(window.devicePixelRatio);
    });
  },
  methods: {},
};
</script>

<style scoped lang="scss">
* {
  margin: 0;
  padding: 0;
}

.home-content {
  position: fixed;
  top: 0;
  right: 20px;
}

.select-item-color {
  width: 50px;
  height: 50px;
  border: 1px solid #ccc;
  margin: 10px;
  display: inline-block;
  cursor: pointer;
  border-radius: 10px;
}
.select {
  display: flex;
}
</style>

效果图:

猜你喜欢

转载自blog.csdn.net/sunboylife/article/details/130177563
今日推荐