three场景基础~
一.web3d.ts文件
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { CSS2DRenderer } from 'three/addons/renderers/CSS2DRenderer.js';
/* 墨 */
let width = window.innerWidth;
let height = window.innerHeight;
let css2Renderer = new CSS2DRenderer();
css2Renderer.domElement.style.position = 'absolute';
css2Renderer.domElement.style.top = '0px';
css2Renderer.domElement.style.pointerEvents = 'none';
css2Renderer.setSize(width, height);
/* 一. 创建3D场景对象Scene */
let scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xcccccc, 0.0015 );
/* 二.相机 */
/* 1.透视投影相机视锥体 */
let camera = new THREE.PerspectiveCamera(50, width / height, 1, 5000);
/* 2.相机位置 */
camera.position.set(0, 50, 300)
/* 3.观察目标 */
camera.lookAt(0, 0, 0)
/* 三.WebGL渲染器 */
/* 1.创建渲染器 */
let renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
logarithmicDepthBuffer: true
})
/* 2.定义尺寸 (颜色/透明度) 设备像素*/
renderer.setSize(width, height)
renderer.setClearColor(0x00ff00,0.1);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
/* 3.渲染 场景及相机 */
// 模型表面产生条纹影响渲染效果,可以改变.shadowMap.type默认值优化
renderer.shadowMap.type = THREE.VSMShadowMap;
renderer.render(scene, camera)
/* 墨 */
/* 平行光 */
const directionalLight = new THREE.DirectionalLight(0xffffff, 3);
directionalLight.position.set(100, 60, 50);
const ambient = new THREE.AmbientLight(0xffffff, 3);
/* 相机控件 */
const controls = new OrbitControls(camera, renderer.domElement)
controls.minPolarAngle = 0;
controls.maxPolarAngle = Math.PI / 2;
controls.enableDamping = true;
controls.dampingFactor = 0.1
/* 窗口响应 */
window.onresize = () => {
let width = window.innerWidth;
let height = window.innerHeight;
css2Renderer.setSize(width, height);
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
/* 四.渲染循环 */
let render = () => {
console.log('render');
TWEEN.update()
/* 若有composer 无需 renderer */
renderer.render(scene, camera);
css2Renderer.render(scene, camera);
requestAnimationFrame(render);
}
render()
let sceneArr = [ model, directionalLight, ambient, ]
scene.add(...sceneArr)
export {
scene, camera, renderer, controls, model,
css2Renderer, gsap, width, height,
}
2.outPass.ts文件
***** 1.注意: composer 后处理顺序需写好;
import * as THREE from 'three'
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { OutlinePass } from 'three/addons/postprocessing/OutlinePass.js';
import { GammaCorrectionShader } from 'three/addons/shaders/GammaCorrectionShader.js';
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
import { SMAAPass } from 'three/addons/postprocessing/SMAAPass.js';
import { camera,model,renderer,scene } from '../webthree/web3d';
const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
const gammaPass = new ShaderPass(GammaCorrectionShader);
let pixelRatio = renderer.getPixelRatio();
let smaaPass = new SMAAPass(window.innerWidth * pixelRatio, window.innerWidth * pixelRatio);
const v2 = new THREE.Vector2(window.innerWidth, window.innerWidth);
const outlinePass = new OutlinePass(v2, scene, camera);
composer.addPass(renderPass);
composer.addPass(outlinePass);
composer.addPass(gammaPass);
composer.addPass(smaaPass);
let outpassFn = (dam:any='大门02')=>{
addEventListener('click', function (event) {
const px = event.offsetX;
const py = event.offsetY;
//屏幕坐标转标准设备坐标
const x = (px / window.innerWidth) * 2 - 1;
const y = -(py / window.innerHeight) * 2 + 1;
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
let passmod = model.getObjectByName(dam);
const intersects = raycaster.intersectObjects([passmod]);
console.log("射线器返回的对象", intersects);
if (intersects.length > 0) {
outlinePass.visibleEdgeColor.set(0xffffff);
outlinePass.edgeThickness = 10;
outlinePass.edgeStrength = 15;
outlinePass.selectedObjects = [passmod];
}else outlinePass.selectedObjects = [];
/* let cunchu = model.getObjectByName(dam);
let intersects = raycaster.intersectObjects(cunchu.children);
for (let i = 0; i < cunchu.children.length; i++) {
let group = cunchu.children[i];
group.traverse(function (obj:any) {
if (obj.isMesh) {
obj.ancestors = group;
}
})
}
if (intersects.length > 0) {
outlinePass.selectedObjects = [intersects[0].object.ancestors];
}else outlinePass.selectedObjects = []; */
})
}
/* 拾取描边 */
outpassFn('主体楼01',)
export default outpassFn;
export {composer,renderPass,gammaPass,smaaPass,outlinePass};
App.vue
<script setup lang="ts">
onMounted(() => {
/* 四.渲染循环 */
let render = () => {
composer.render();
requestAnimationFrame(render);
}
render()
</script>
更新
/* 抗锯齿 */
import { SSAARenderPass } from 'three/addons/postprocessing/SSAARenderPass.js';
const ssaaRenderPass = new SSAARenderPass(scene, camera);
ssaaRenderPass.sampleLevel = 2;
ssaaRenderPass.unbiased = true;
/* 注意:后处理顺序问题 */
composer.addPass(renderPass);
composer.addPass(ssaaRenderPass);
// composer.addPass(smaaPass);
composer.addPass(outlinePass);
composer.addPass(gammaPass);