本文主要是介绍webgl_framebuffer_texture,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
ThreeJS 官方案例学习(webgl_framebuffer_texture)
1.效果图
2.源码
<template><div><div id="container"></div><div id="selection"><div></div></div></div>
</template>
<script>
import * as THREE from 'three';
// 导入控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// 引入房间环境,创建一个室内环境
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
// 导入性能监视器
import Stats from 'three/examples/jsm/libs/stats.module.js';
// 导入gltf载入库、模型加载器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
// 引入模型解压器
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
//GUI界面
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import gsap from 'gsap';
import * as GeometryUtils from 'three/examples/jsm/utils/GeometryUtils.js';
const dpr = window.devicePixelRatio;const textureSize = 128 * dpr;
export default {data() {return {container: null, //界面需要渲染的容器scene: null, // 场景对象camera: null, //相机对象(透视相机)renderer: null, //渲染器对象controller: null, // 相机控件对象stats: null,// 性能监听器mixer: null,//动画混合器clock: new THREE.Clock(),// 创建一个clock对象,用于跟踪时间vector: new THREE.Vector2(),//用于计算复制部分帧数据的起始位置color: new THREE.Color(),//Color颜色对象,方便后续使用offset: 0,//颜色偏移度line: null,//线模型sprite: null,//点精灵材质texture: null,//帧缓冲纹理cameraOrtho: null,//正交相机sceneOrtho: null,//};},mounted() {this.init()this.animate() //如果引入了模型并存在动画,可在模型引入成功后加载动画window.addEventListener("resize", this.onWindowSize)},beforeUnmount() {console.log('beforeUnmount===============');// 组件销毁时置空,视具体情况自定义销毁,以下实例不完整this.container = nullthis.scene = nullthis.camera = nullthis.renderer = nullthis.controller = nullthis.stats = nullthis.mixer = nullthis.model = null//导入的模型},methods: {/*** @description 初始化*/init() {this.container = document.getElementById('container')this.setScene()this.setCamera()this.setRenderer()this.addHelper()this.setController()this.setPMREMGenerator()this.setLight()this.setGltfLoader()// this.addStatus()},/*** @description 创建场景*/setScene() {// 创建场景对象Scenethis.scene = new THREE.Scene()// 设置场景背景// this.scene.background = new THREE.Color(0xbfe3dd);this.sceneOrtho = new THREE.Scene();},/*** @description 创建相机*/setCamera() {// 第二参数就是 长度和宽度比 默认采用浏览器 返回以像素为单位的窗口的内部宽度和高度this.camera = new THREE.PerspectiveCamera(70, this.container.clientWidth / this.container.clientHeight, 1, 1000)// 设置相机位置this.camera.position.set(0, 0, 20)// 设置摄像头宽高比例this.camera.aspect = this.container.clientWidth / this.container.clientHeight;// 设置摄像头投影矩阵this.camera.updateProjectionMatrix();// 设置相机视线方向this.camera.lookAt(new THREE.Vector3(0, 0, 0))// 0, 0, 0 this.scene.position// 将相机加入场景this.scene.add(this.camera)// 添加正交相机this.cameraOrtho = new THREE.OrthographicCamera(- this.container.clientWidth / 2, this.container.clientWidth / 2, this.container.clientHeight / 2, - this.container.clientHeight / 2, 1, 10);this.cameraOrtho.position.z = 10;},/*** @description 创建渲染器*/setRenderer() {// 初始化渲染器this.renderer = new THREE.WebGLRenderer({antialias: true,// 设置抗锯齿logarithmicDepthBuffer: true, // 是否使用对数深度缓存})// 设置渲染器宽高this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);// 设置渲染器的像素比// this.renderer.setPixelRatio(window.devicePixelRatio);// 是否需要对对象排序// this.renderer.sortObjects = false;// 渲染器是否在渲染每一帧之前自动清除其输出this.renderer.autoClear = false;// 将渲染器添加到页面this.container.appendChild(this.renderer.domElement);},/*** @description 添加创建控制器*/setController() {// 为什么要绑定 selection 对象(可能selection的css层级最高,需要绑定它才能移动模型)this.controller = new OrbitControls(this.camera, document.getElementById('selection'));// 绑定这个也可以运行 this.renderer.domElement,但是要降低 selection 的层级,但是降低了就看不到白色边框了,需要另外除了白色边框// this.controller = new OrbitControls(this.camera, this.renderer.domElement);// 控制缩放范围// this.controller.minDistance = 1;// this.controller.maxDistance = 5;//是否开启右键拖拽this.controller.enablePan = false;// 阻尼(惯性)this.controller.enableDamping = true; //启用阻尼(惯性)this.controller.dampingFactor = 0.04; //阻尼惯性有多大},/*** @description 创建辅助坐标轴*/addHelper() {// 模拟相机视锥体的辅助对象let helper = new THREE.CameraHelper(this.camera);// this.scene.add(helper);//创建辅助坐标轴、轴辅助 (每一个轴的长度)let axisHelper = new THREE.AxesHelper(150); // 红线是X轴,绿线是Y轴,蓝线是Z轴this.scene.add(axisHelper)// 坐标格辅助对象let gridHelper = new THREE.GridHelper(100, 30, 0x2C2C2C, 0x888888);// this.scene.add(gridHelper);},/*** @description 给场景添加环境光效果*/setPMREMGenerator() {// 预过滤的Mipmapped辐射环境贴图const pmremGenerator = new THREE.PMREMGenerator(this.renderer);this.scene.environment = pmremGenerator.fromScene(new RoomEnvironment(this.renderer), 0.04).texture;},/*** @description 设置光源*/setLight() {// 环境光const ambientLight = new THREE.AmbientLight(0x404040, 4);// this.scene.add(ambientLight);// 平行光const directionalLight = new THREE.DirectionalLight(0xffffff, 100);// this.scene.add(directionalLight);// 点光源 - 照模型const test = new THREE.PointLight("#ffffff", 10, 2);// test.position.set(0, 0, 0);// this.scene.add(test);//点光源 - 辅助对象const testHelperMap = new THREE.PointLightHelper(test);// this.scene.add(testHelperMap);},/*** @description 创建性能监听器*/addStatus() {// 创建一个性能监听器this.stats = new Stats();// 将性能监听器添加到容器中this.container.appendChild(this.stats.dom);},/*** @description 添加创建模型*/setGltfLoader() {// 添加线模型const points = GeometryUtils.gosper(8)const geometry = new THREE.BufferGeometry()const positionAttribute = new THREE.Float32BufferAttribute(points, 3)geometry.setAttribute('position', positionAttribute)geometry.center()const colorAttribute = new THREE.BufferAttribute(new Float32Array(positionAttribute.array.length), 3)colorAttribute.setUsage(THREE.DynamicDrawUsage);geometry.setAttribute('color', colorAttribute);const material = new THREE.LineBasicMaterial({ vertexColors: true });// 使用点设置的颜色,使用点设置的颜色this.line = new THREE.Line(geometry, material)this.line.scale.setScalar(0.05)this.scene.add(this.line)//实例化一个framebuffer纹理this.texture = new THREE.FramebufferTexture(textureSize, textureSize);//(这个类只能与 WebGLRenderer.copyFramebufferToTexture() 结合使用)const spriteMaterial = new THREE.SpriteMaterial({ map: this.texture });//创建Sprite平面this.sprite = new THREE.Sprite(spriteMaterial);this.sprite.scale.set(textureSize, textureSize, 1);this.sceneOrtho.add(this.sprite)this.updateSpritePosition()this.updateColors(colorAttribute);},/*** @description 更新Sprite位置*/updateSpritePosition() {const halfWidth = this.container.clientWidth / 2;const halfHeight = this.container.clientHeight / 2;const halfImageWidth = textureSize / 2;const halfImageHeight = textureSize / 2;this.sprite.position.set(- halfWidth + halfImageWidth, halfHeight - halfImageHeight, 1);},/*** @description 模型颜色更新*/updateColors(colorAttribute) {const l = colorAttribute.count;for (let i = 0; i < l; i++) {const h = ((this.offset + i) % l) / l;this.color.setHSL(h, 1, 0.5);colorAttribute.setX(i, this.color.r);colorAttribute.setY(i, this.color.g);colorAttribute.setZ(i, this.color.b);}colorAttribute.needsUpdate = true;// 颜色循环速度(偏离量)this.offset -= 10;},/*** @description 监听屏幕的大小改变,修改渲染器的宽高,相机的比例*/// 窗口变化onWindowSize() {// 更新摄像头this.camera.aspect = this.container.clientWidth / this.container.clientHeight;// 更新摄像机的投影矩阵this.camera.updateProjectionMatrix();//更新渲染器this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);// 设置渲染器的像素比this.renderer.setPixelRatio(window.devicePixelRatio)// 更新cameraOrthoconst width = this.container.clientWidth;const height = this.container.clientHeight;this.cameraOrtho.left = - width / 2;this.cameraOrtho.right = width / 2;this.cameraOrtho.top = height / 2;this.cameraOrtho.bottom = - height / 2;this.cameraOrtho.updateProjectionMatrix();this.updateSpritePosition()},/*** @description 动画执行函数*/animate() {// 引擎自动更新渲染器requestAnimationFrame(this.animate);//update()函数内会执行camera.lookAt(x, y, z)this.controller.update();// 更新性能监听器// this.stats.update();// 模型颜色更新const colorAttribute = this.line.geometry.getAttribute('color');this.updateColors(colorAttribute);//场景渲染this.renderer.clear();// 重新渲染场景this.renderer.render(this.scene, this.camera);// 计算复制部分帧数据的起始位置this.vector.x = (this.container.clientWidth * dpr / 2) - (textureSize / 2);this.vector.y = (this.container.clientHeight * dpr / 2) - (textureSize / 2);//复制渲染帧的一部分到framebuffer纹理this.renderer.copyFramebufferToTexture(this.vector, this.texture);this.renderer.clearDepth();this.renderer.render(this.sceneOrtho, this.cameraOrtho);},},
};
</script>
<style>
#container {position: absolute;width: 100%;height: 100%;
}#selection {position: fixed;display: flex;flex-direction: column;justify-content: center;align-items: center;height: 100%;width: 100%;top: 0;z-index: 999;
}#selection>div {height: 128px;width: 128px;border: 1px solid white;
}
</style>r {position: absolute;width: 100%;height: 100%;
}#selection {position: fixed;display: flex;flex-direction: column;justify-content: center;align-items: center;height: 100%;width: 100%;top: 0;z-index: 999;
}#selection>div {height: 128px;width: 128px;border: 1px solid white;
}
</style>
这篇关于webgl_framebuffer_texture的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!