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';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
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(),
vector: new THREE.Vector2(),
color: new THREE.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 = null
this.scene = null
this.camera = null
this.renderer = null
this.controller = null
this.stats = null
this.mixer = null
this.model = null
},
methods: {
init() {
this.container = document.getElementById('container')
this.setScene()
this.setCamera()
this.setRenderer()
this.addHelper()
this.setController()
this.setPMREMGenerator()
this.setLight()
this.setGltfLoader()
},
setScene() {
this.scene = new THREE.Scene()
this.sceneOrtho = new THREE.Scene();
},
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))
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;
},
setRenderer() {
this.renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true,
})
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
this.renderer.autoClear = false;
this.container.appendChild(this.renderer.domElement);
},
setController() {
this.controller = new OrbitControls(this.camera, document.getElementById('selection'));
this.controller.enablePan = false;
this.controller.enableDamping = true;
this.controller.dampingFactor = 0.04;
},
addHelper() {
let helper = new THREE.CameraHelper(this.camera);
let axisHelper = new THREE.AxesHelper(150);
this.scene.add(axisHelper)
let gridHelper = new THREE.GridHelper(100, 30, 0x2C2C2C, 0x888888);
},
setPMREMGenerator() {
const pmremGenerator = new THREE.PMREMGenerator(this.renderer);
this.scene.environment = pmremGenerator.fromScene(new RoomEnvironment(this.renderer), 0.04).texture;
},
setLight() {
const ambientLight = new THREE.AmbientLight(0x404040, 4);
const directionalLight = new THREE.DirectionalLight(0xffffff, 100);
const test = new THREE.PointLight("#ffffff", 10, 2);
const testHelperMap = new THREE.PointLightHelper(test);
},
addStatus() {
this.stats = new Stats();
this.container.appendChild(this.stats.dom);
},
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)
this.texture = new THREE.FramebufferTexture(textureSize, textureSize);
const spriteMaterial = new THREE.SpriteMaterial({ map: this.texture });
this.sprite = new THREE.Sprite(spriteMaterial);
this.sprite.scale.set(textureSize, textureSize, 1);
this.sceneOrtho.add(this.sprite)
this.updateSpritePosition()
this.updateColors(colorAttribute);
},
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);
},
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;
},
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)
const 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()
},
animate() {
requestAnimationFrame(this.animate);
this.controller.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);
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>