花开莲现,花落莲成

107 阅读2分钟

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);