|
@@ -2,6 +2,9 @@
|
|
|
<div>
|
|
|
<input type="file" ref="loadModel" id="load-model" style="display: none"/>
|
|
|
<input type="file" ref="loadBackground" id="load-background" style="display: none"/>
|
|
|
+ <div id="mask">
|
|
|
+ <img id="cover"/>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -14,10 +17,8 @@
|
|
|
|
|
|
import { EffectComposer } from '../examples/jsm/postprocessing/EffectComposer.js';
|
|
|
import { RenderPass } from '../examples/jsm/postprocessing/RenderPass.js';
|
|
|
- import { SSAOPass } from '../examples/jsm/postprocessing/SSAOPass2.js';
|
|
|
import { SSRPass } from '../examples/jsm/postprocessing/SSRPass_Blending.js';
|
|
|
import { TAARenderPass2 } from '../examples/jsm/postprocessing/TAARenderPass2.js';
|
|
|
- import { UnrealBloomPass } from '../examples/jsm/postprocessing/UnrealBloomPass2.js';
|
|
|
import { BloomPass } from '../examples/jsm/postprocessing/BloomPass2.js';
|
|
|
import { ShaderPass } from '../examples/jsm/postprocessing/ShaderPass.js'
|
|
|
|
|
@@ -40,8 +41,9 @@
|
|
|
import { EXRLoader } from '../examples/jsm/loaders/EXRLoader.js';
|
|
|
import { DRACOLoader } from '../examples/jsm/loaders/DRACOLoader.js';
|
|
|
import { RGBELoader } from '../examples/jsm/loaders/RGBELoader.js';
|
|
|
- import {OBJLoader} from '../examples/jsm/loaders/OBJLoader.js'
|
|
|
- import {MTLLoader} from '../examples/jsm/loaders/MTLLoader.js'
|
|
|
+ import { KTX2Loader } from '../examples/jsm/loaders/KTX2Loader.js';
|
|
|
+ import { OBJLoader } from '../examples/jsm/loaders/OBJLoader.js';
|
|
|
+ import { MTLLoader } from '../examples/jsm/loaders/MTLLoader.js';
|
|
|
|
|
|
|
|
|
import { OrbitControls } from '../examples/jsm/controls/OrbitControls.js'
|
|
@@ -49,6 +51,7 @@
|
|
|
|
|
|
import { ProgressiveShadows } from '../examples/jsm/postprocessing/ProgressiveShadows.js';
|
|
|
import { TransformControls } from '../examples/jsm/controls/TransformControls.js';
|
|
|
+ import { MeshoptDecoder } from '../examples/jsm/libs/meshopt_decoder.module.js';
|
|
|
|
|
|
import $ from 'jquery'
|
|
|
import gsap from 'gsap'
|
|
@@ -57,17 +60,23 @@
|
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
|
import {ref, onMounted } from 'vue'
|
|
|
|
|
|
+ import NProgress from 'nprogress'
|
|
|
+ import 'nprogress/nprogress.css'
|
|
|
+
|
|
|
|
|
|
const router = useRouter()
|
|
|
const route = useRoute()
|
|
|
|
|
|
const baseURL = '/renderer' //'http://120.24.144.164:10003'
|
|
|
- let container, stats;
|
|
|
- let num;
|
|
|
+ const sourceURL = 'https://4dkk.4dage.com/renderer/'
|
|
|
+
|
|
|
+ let container, mask, stats;
|
|
|
+ let num, renderRes;
|
|
|
let metadata;
|
|
|
let modelFile, backgroundFile, coverFile;
|
|
|
let gui;
|
|
|
- let camera, scene, renderer;
|
|
|
+ let camera, scene;
|
|
|
+ const renderer = new WebGLRenderer()
|
|
|
let composer;
|
|
|
let group = new THREE.Group();
|
|
|
let controls;
|
|
@@ -82,7 +91,6 @@
|
|
|
let renderPass;
|
|
|
let ssrPass;
|
|
|
let hbaoPass;
|
|
|
- let ssaoPass;
|
|
|
let BCSPass;
|
|
|
let colorBalancePass;
|
|
|
let sharpenPass;
|
|
@@ -98,13 +106,24 @@
|
|
|
const loadModel = ref(null)
|
|
|
const loadBackground = ref(null)
|
|
|
|
|
|
+ const loadingManager = new THREE.LoadingManager()
|
|
|
+
|
|
|
+ let gltfLoader = new GLTFLoader(loadingManager);
|
|
|
+ let ktx2Loader = new KTX2Loader(loadingManager);
|
|
|
+ ktx2Loader.setTranscoderPath('../assets/libs/basis/');
|
|
|
+ ktx2Loader.detectSupport(renderer)
|
|
|
|
|
|
- let gltfLoader = new GLTFLoader();
|
|
|
+
|
|
|
const exrLoader = new EXRLoader();
|
|
|
const rgbeLoader = new RGBELoader();
|
|
|
let dracoLoader = new DRACOLoader();
|
|
|
- dracoLoader.setDecoderPath('../examples/jsm/libs/draco');
|
|
|
+ dracoLoader.setDecoderPath('../assets/libs/draco/');
|
|
|
+
|
|
|
+ gltfLoader.setKTX2Loader(ktx2Loader);
|
|
|
gltfLoader.setDRACOLoader(dracoLoader);
|
|
|
+ gltfLoader.setMeshoptDecoder(MeshoptDecoder)
|
|
|
+
|
|
|
+
|
|
|
const toneMappingOptions = {
|
|
|
Linear: THREE.LinearToneMapping,
|
|
|
Reinhard: THREE.ReinhardToneMapping,
|
|
@@ -420,7 +439,8 @@
|
|
|
y: 0,
|
|
|
z: 0,
|
|
|
},
|
|
|
- }
|
|
|
+ },
|
|
|
+ lock: false
|
|
|
}
|
|
|
let params;
|
|
|
const upload1 = () => {
|
|
@@ -457,7 +477,7 @@
|
|
|
lights.push(dL)
|
|
|
})
|
|
|
}
|
|
|
- function updateCamera(time = 1, position = params.camera.position, quaternion = params.camera.quaternion, target = params.camera.target) {
|
|
|
+ function updateCamera(time = 2, position = params.camera.position, quaternion = params.camera.quaternion, target = params.camera.target) {
|
|
|
gsap.to(camera.position, {
|
|
|
duration: time,
|
|
|
ease: "circ.out",
|
|
@@ -480,26 +500,6 @@
|
|
|
y: target.y,
|
|
|
z: target.z,
|
|
|
})
|
|
|
-
|
|
|
- // gsap.to(camera.position, {
|
|
|
- // duration: 1,
|
|
|
- // x: activeModel.position.x,
|
|
|
- // y: activeModel.position.y,
|
|
|
- // z: activeModel.position.z,
|
|
|
- // })
|
|
|
- // gsap.to(camera.quaternion, {
|
|
|
- // duration: 1,
|
|
|
- // x: activeModel.quaternion.x,
|
|
|
- // y: activeModel.quaternion.y,
|
|
|
- // z: activeModel.quaternion.z,
|
|
|
- // w: activeModel.quaternion.x,
|
|
|
- // })
|
|
|
- // gsap.to(controls.target, {
|
|
|
- // duration: 1,
|
|
|
- // x: activeModel.target.x,
|
|
|
- // y: activeModel.target.y,
|
|
|
- // z: activeModel.target.z,
|
|
|
- // })
|
|
|
}
|
|
|
function getCameraData() {
|
|
|
|
|
@@ -534,7 +534,7 @@
|
|
|
camera.aspect = screenShotSize.width / screenShotSize.height
|
|
|
renderer.setSize(screenShotSize.width, screenShotSize.height)
|
|
|
composer.setSize(screenShotSize.width, screenShotSize.height)
|
|
|
- composer.setPixelRatio(2)
|
|
|
+ composer.setPixelRatio(renderRes * 2)
|
|
|
setTimeout(() => {
|
|
|
cameraMove()
|
|
|
}, 50)
|
|
@@ -545,13 +545,13 @@
|
|
|
link.download = saveAsFileName
|
|
|
link.click();
|
|
|
// reset
|
|
|
- composer.setPixelRatio(1)
|
|
|
+ composer.setPixelRatio(renderRes)
|
|
|
canvas.width = width
|
|
|
canvas.height = height
|
|
|
camera.aspect = aspect
|
|
|
renderer.setSize(width, height)
|
|
|
composer.setSize(width, height)
|
|
|
- }, 1000)
|
|
|
+ }, 2000)
|
|
|
|
|
|
// canvas.width = width
|
|
|
// canvas.height = height
|
|
@@ -572,6 +572,7 @@
|
|
|
|
|
|
function initGui() {
|
|
|
// Init gui
|
|
|
+ if(gui) return
|
|
|
gui = new GUI();
|
|
|
|
|
|
//file
|
|
@@ -636,7 +637,7 @@
|
|
|
addGround(true)
|
|
|
}
|
|
|
|
|
|
- folderScene.add(group.rotation, 'y').min(0).max(10)
|
|
|
+ // folderScene.add(group.rotation, 'y').min(0).max(10)
|
|
|
|
|
|
// camera
|
|
|
const shotSize = {
|
|
@@ -651,6 +652,7 @@
|
|
|
const folderCamera = gui.addFolder('摄像机');
|
|
|
folderCamera.add(params.camera, 'fov').min(10).max(90).step(0.1).onChange(() => {
|
|
|
camera.fov = params.camera.fov;
|
|
|
+ cameraMove()
|
|
|
})
|
|
|
const cameraFun = {
|
|
|
saveCameraPos: getCameraData,
|
|
@@ -1022,18 +1024,57 @@
|
|
|
|
|
|
// folderTaa.add(fxaaPass,'enabled').name('fxaa')
|
|
|
folderTaa.close();
|
|
|
- }
|
|
|
+ }
|
|
|
+
|
|
|
+ function initLoadingManager() {
|
|
|
+ loadingManager.onStart = () => {
|
|
|
+ NProgress.start()
|
|
|
+ }
|
|
|
+
|
|
|
+ loadingManager.onProgress = (itemUrl, itemsLoaded, itemsTotal) => {
|
|
|
+ if(itemsLoaded === 1) {
|
|
|
+ NProgress.inc(0.5)
|
|
|
+ } else {
|
|
|
+ NProgress.inc()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ loadingManager.onLoad = () => {
|
|
|
+ initGui();
|
|
|
+ updateCamera(2, params.camera.position, params.camera.quaternion, params.camera.target)
|
|
|
+ gsap.to('#cover', {
|
|
|
+ duration: 1,
|
|
|
+ opacity: 0,
|
|
|
+ })
|
|
|
+ gsap.to('#mask', {
|
|
|
+ duration: 1,
|
|
|
+ opacity: 0,
|
|
|
+ onComplete: () => {
|
|
|
+ mask.style.display = 'none'
|
|
|
+ }
|
|
|
+ })
|
|
|
+ NProgress.done()
|
|
|
+ }
|
|
|
+
|
|
|
+ loadingManager.onError = () => {
|
|
|
+ console.log('load error')
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
function initScene() {
|
|
|
- const width = window.innerWidth * window.devicePixelRatio;
|
|
|
- const height = window.innerHeight * window.devicePixelRatio;
|
|
|
+ const width = window.innerWidth;
|
|
|
+ const height = window.innerHeight;
|
|
|
container = document.createElement('div');
|
|
|
+ mask = document.getElementById('mask');
|
|
|
+
|
|
|
+ // container = document.getElementById('container')
|
|
|
+ // let canvas = document.getElementById('canvas')
|
|
|
document.body.appendChild(container);
|
|
|
scene = new THREE.Scene();
|
|
|
// const texturePass = new TexturePass();
|
|
|
let envUrl = '../assets/textures/rainforest.exr'
|
|
|
envUrl = params.scene.envPath ? params.scene.envPath : envUrl;
|
|
|
- console.log(envUrl)
|
|
|
+ // console.log(envUrl)
|
|
|
|
|
|
exrLoader.load(envUrl, (exr) => {
|
|
|
exr.mapping = THREE.EquirectangularReflectionMapping;
|
|
@@ -1044,27 +1085,27 @@
|
|
|
scene.backgroundBlurriness = params.scene.backgroundBlurriness;
|
|
|
})
|
|
|
|
|
|
- renderer = new WebGLRenderer({antialias: false});
|
|
|
+ // renderer = new WebGLRenderer({antialias: false});
|
|
|
renderer.shadowMap.enabled = true
|
|
|
renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
|
|
renderer.useLegacyLights = true
|
|
|
renderer.toneMapping = THREE.ACESFilmicToneMapping
|
|
|
|
|
|
renderer.toneMappingExposure = params.toneMapping.toneMappingExposure
|
|
|
- renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
- console.log(window.devicePixelRatio)
|
|
|
+ renderer.setSize(width, height);
|
|
|
+ console.log(width, height, renderRes);
|
|
|
document.body.appendChild(renderer.domElement);
|
|
|
renderer.domElement.addEventListener( 'mousedown', onMouseDown );
|
|
|
renderer.domElement.addEventListener( 'mouseup', onMouseUp );
|
|
|
- // renderer.setPixelRatio(2)
|
|
|
+ renderer.setPixelRatio(renderRes);
|
|
|
|
|
|
backgroundPlane = new THREE.Mesh(new THREE.PlaneGeometry(1000, 1000), new THREE.MeshBasicMaterial({color: params.backColor.color}))
|
|
|
- backgroundPlane.position.z = -100
|
|
|
- backgroundPlane.visible = params.backColor.enabled
|
|
|
+ backgroundPlane.position.z = -100;
|
|
|
+ backgroundPlane.visible = params.backColor.enabled;
|
|
|
camera = new THREE.PerspectiveCamera(params.camera.fov, window.innerWidth / window.innerHeight, 0.1, 150);
|
|
|
- camera.add(backgroundPlane)
|
|
|
+ camera.add(backgroundPlane);
|
|
|
camera.position.set( 100, 2, 100 );
|
|
|
- scene.add(camera)
|
|
|
+ scene.add(camera);
|
|
|
|
|
|
controls = new OrbitControls(camera, renderer.domElement)
|
|
|
controls.enableDamping = true;
|
|
@@ -1083,13 +1124,7 @@
|
|
|
controls.enabled = true
|
|
|
})
|
|
|
scene.add(transformControls)
|
|
|
- if(params.scene.modelPath) {
|
|
|
- gltfLoader.load(params.scene.modelPath, (gltf) => {
|
|
|
- loadGLTF(gltf);
|
|
|
- })
|
|
|
- }
|
|
|
- // switchModels(0);
|
|
|
- scene.add(group);
|
|
|
+
|
|
|
|
|
|
stats = new Stats();
|
|
|
container.appendChild(stats.dom);
|
|
@@ -1097,7 +1132,7 @@
|
|
|
|
|
|
|
|
|
composer = new EffectComposer(renderer);
|
|
|
-
|
|
|
+ composer.setPixelRatio(renderRes)
|
|
|
// colorPass = new ColorPass();
|
|
|
// colorPass.enabled = params.backColor.enabled;
|
|
|
// colorPass.color.set(params.backColor.color);
|
|
@@ -1169,16 +1204,13 @@
|
|
|
sharpenPass.uniforms.strength.value = params.sharpen.strength;
|
|
|
composer.addPass(sharpenPass);
|
|
|
|
|
|
- bloomPass = new BloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
|
|
|
+ bloomPass = new BloomPass( width, height );
|
|
|
composer.addPass( bloomPass );
|
|
|
bloomPass.enabled = params.bloom.enabled;
|
|
|
bloomPass.threshold = params.bloom.threshold;
|
|
|
bloomPass.strength = params.bloom.strength;
|
|
|
bloomPass.radius = params.bloom.radius;
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
rgbShiftPass = new ShaderPass(RGBShiftShader);
|
|
|
rgbShiftPass.enabled = params.rgbShift.enabled;
|
|
|
rgbShiftPass.uniforms.amount.value = params.rgbShift.amount;
|
|
@@ -1194,24 +1226,48 @@
|
|
|
const outputPass = new OutputPass();
|
|
|
composer.addPass( outputPass );
|
|
|
|
|
|
+ if(params.scene.modelPath) {
|
|
|
+ gltfLoader.load(params.scene.modelPath, (gltf) => {
|
|
|
+ loadGLTF(gltf);
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ gsap.to('#cover', {
|
|
|
+ duration: 1,
|
|
|
+ opacity: 0,
|
|
|
+ })
|
|
|
+ gsap.to('#mask', {
|
|
|
+ duration: 1,
|
|
|
+ opacity: 0,
|
|
|
+ onComplete: () => {
|
|
|
+ mask.style.display = 'none'
|
|
|
+ }
|
|
|
+ })
|
|
|
+ initGui();
|
|
|
+ }
|
|
|
+ scene.add(group);
|
|
|
+
|
|
|
controls.addEventListener('change', () => {
|
|
|
- ssrPass.cameraMoving = true
|
|
|
+ cameraMove()
|
|
|
})
|
|
|
camera.addEventListener('change', () => {
|
|
|
- ssrPass.cameraMoving = true
|
|
|
-
|
|
|
+ cameraMove()
|
|
|
})
|
|
|
window.addEventListener('resize', () => {
|
|
|
onWindowResize()
|
|
|
- ssrPass.cameraMoving = true
|
|
|
-
|
|
|
+ cameraMove()
|
|
|
});
|
|
|
}
|
|
|
|
|
|
function onWindowResize() {
|
|
|
|
|
|
- const width = window.innerWidth;
|
|
|
- const height = window.innerHeight;
|
|
|
+ // const width = window.innerWidth;
|
|
|
+ // const height = window.innerHeight;
|
|
|
+ // const devicePixelRatio = window.devicePixelRatio;
|
|
|
+ const width = document.documentElement.clientWidth;
|
|
|
+ const height = document.documentElement.clientHeight;
|
|
|
+ console.log(width, height)
|
|
|
+ // console.log('window.inner:', width, height)
|
|
|
+ // console.log('document:', document.documentElement.clientWidth, document.documentElement.clientHeight)
|
|
|
|
|
|
camera.aspect = width / height;
|
|
|
camera.updateProjectionMatrix();
|
|
@@ -1235,10 +1291,8 @@
|
|
|
controls.update();
|
|
|
if(ssrPass.cameraMoving === false){
|
|
|
taaPass.accumulate = true;
|
|
|
- // composer.setPixelRatio(2)
|
|
|
} else {
|
|
|
taaPass.accumulate = false;
|
|
|
- // composer.setPixelRatio(1)
|
|
|
}
|
|
|
composer.render();
|
|
|
// renderer.render(scene, camera);
|
|
@@ -1286,7 +1340,7 @@
|
|
|
shadowGroundFolder.add(shadowGround.scale, 'x').onChange(() => {
|
|
|
shadowGround.scale.y = shadowGround.scale.x
|
|
|
params.scene.shadowGround.size = shadowGround.scale.x
|
|
|
- }).min(1).max(5)
|
|
|
+ }).min(1).max(5).name('scale')
|
|
|
|
|
|
} else {
|
|
|
shadowGround.visible = true
|
|
@@ -1321,10 +1375,9 @@
|
|
|
boundingBox.setFromObject(model);
|
|
|
boundingBox.getCenter(center)
|
|
|
boundingBox.getSize(size);
|
|
|
- console.log(size, center)
|
|
|
+ // console.log(size, center)
|
|
|
group.add(model)
|
|
|
if(params.scene.useShadows) useShadows(true)
|
|
|
- updateCamera(1, params.camera.position, params.camera.quaternion, params.camera.target)
|
|
|
}
|
|
|
function loadEXR(exr) {
|
|
|
// console.log(exr)
|
|
@@ -1471,9 +1524,9 @@
|
|
|
camera.aspect = 16/9
|
|
|
renderer.setSize(960, 540)
|
|
|
composer.setSize(960, 540)
|
|
|
- composer.setPixelRatio(2)
|
|
|
+ // composer.setPixelRatio(2)
|
|
|
setTimeout(() => {
|
|
|
- cameraMove()
|
|
|
+ cameraMove()
|
|
|
}, 50)
|
|
|
setTimeout(async () => {
|
|
|
composer.render()
|
|
@@ -1484,7 +1537,7 @@
|
|
|
coverFile = file
|
|
|
console.log(coverFile)
|
|
|
// reset
|
|
|
- composer.setPixelRatio(1)
|
|
|
+ // composer.setPixelRatio(1)
|
|
|
canvas.width = width
|
|
|
canvas.height = height
|
|
|
camera.aspect = aspect
|
|
@@ -1495,18 +1548,50 @@
|
|
|
alert('文件上传失败')
|
|
|
// return
|
|
|
}
|
|
|
- }, 1000)
|
|
|
+ }, 2000)
|
|
|
+ }
|
|
|
+ function startLoad() {
|
|
|
+ let cover = document.getElementById('cover')
|
|
|
+ let url = sourceURL + num + "/cover.png"
|
|
|
+
|
|
|
+ checkImgExists(url)
|
|
|
+ .then(() => {
|
|
|
+ cover.src = url;
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ mask.style.display = 'none'
|
|
|
+ initGui()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ function checkImgExists(url) {
|
|
|
+ return new Promise(function(resolve, reject) {
|
|
|
+ let img = new Image();
|
|
|
+ img.src = url;
|
|
|
+ img.onload = function(res) {
|
|
|
+ resolve(res)
|
|
|
+ }
|
|
|
+ img.onerror = function(err) {
|
|
|
+ reject(err)
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
async function getNum() {
|
|
|
// num = decodeURI(window.location.search)
|
|
|
num = route.params.num
|
|
|
// num = num.split('num=')[1]
|
|
|
+ if(/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)) {
|
|
|
+ renderRes = window.devicePixelRatio * 0.5
|
|
|
+ } else {
|
|
|
+ renderRes = window.devicePixelRatio
|
|
|
+ }
|
|
|
+
|
|
|
if(!num) {
|
|
|
router.push('home')
|
|
|
} else {
|
|
|
console.log(num)
|
|
|
await getParams()
|
|
|
+ startLoad()
|
|
|
}
|
|
|
}
|
|
|
async function getParams() {
|
|
@@ -1523,8 +1608,8 @@
|
|
|
}
|
|
|
updateParams()
|
|
|
console.log(params)
|
|
|
+ initLoadingManager();
|
|
|
initScene();
|
|
|
- initGui();
|
|
|
animate();
|
|
|
} else {
|
|
|
alert('场景初始化错误')
|
|
@@ -1694,7 +1779,8 @@
|
|
|
if(!params.dof.bladeCount) {
|
|
|
params.dof.bladeCount = 6
|
|
|
}
|
|
|
- // params.lock = true
|
|
|
+
|
|
|
+ params.lock = false
|
|
|
|
|
|
// params.colorBalance = {
|
|
|
// enabled: true,
|
|
@@ -1739,5 +1825,24 @@
|
|
|
margin: 0;
|
|
|
padding: 0;
|
|
|
background-color: #252525;
|
|
|
+ overflow: hidden;
|
|
|
}
|
|
|
+ #mask{
|
|
|
+ background-color: rgba(0,0,0,1);
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ position: absolute;
|
|
|
+ z-index: 100;
|
|
|
+ /* display: none; */
|
|
|
+ }
|
|
|
+ #cover{
|
|
|
+ /* height: 100%; */
|
|
|
+ width: 100%;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ opacity: 0.5;
|
|
|
+ filter: blur(20px);
|
|
|
+ -webkit-filter: blur(20px);
|
|
|
+ pointer-events:none;
|
|
|
+ }
|
|
|
</style>
|