diff --git a/assets/glsl/BuildingFragment.glsl b/assets/glsl/BuildingFragment.glsl new file mode 100644 index 0000000..afff170 --- /dev/null +++ b/assets/glsl/BuildingFragment.glsl @@ -0,0 +1,33 @@ +// https://gamedevelopment.tutsplus.com/tutorials/a-beginners-guide-to-coding-graphics-shaders--cms-23313 +uniform vec3 topColor; +uniform vec3 groundColor; +uniform vec3 bottomColor; +varying vec3 vWorldPosition; +void main() { + float h = vWorldPosition.y; + if(h > 0.0) + { + gl_FragColor = vec4(topColor,1.0); + } + else + { + // gl_FragColor = vec4(bottomColor,1.0); + // h = h * -1.0; + // float hh = abs(normalize( vWorldPosition ).y); + gl_FragColor = vec4( + mix( + groundColor, + bottomColor, + min(abs(h)/100.0,1.0) + // min(h/150.0 , 2.0) + // max( + // pow( + // max( hh , 0.0), + // exponent + // ), + // 0.0 + // ) + ), 1.0 + ); + } +} diff --git a/src/App.vue b/src/App.vue index 8c8f3d5..64f03b2 100644 --- a/src/App.vue +++ b/src/App.vue @@ -91,7 +91,9 @@ export default { // const envcolor = 0xffffff let renderer = new THREE.WebGLRenderer({ alpha: false, antialias: true }) renderer.setClearColor(0x000000, 0) - renderer.shadowMap.enabled = true + // renderer.shadowMap.enabled = true + // // to antialias the shadow + // renderer.shadowMap.type = THREE.PCFSoftShadowMap // scene obj is well overwrited but background color not visible let scene = new THREE.Scene() @@ -99,6 +101,8 @@ export default { // scene.fog = new THREE.Fog(new THREE.Color(0xffffff), 50, 200) // console.log('myScene', scene) + // scene.add(new THREE.AxesHelper(500)) + // SKYDOME // https://github.com/mrdoob/three.js/blob/master/examples/webgl_lights_hemisphere.html // https://gamedevelopment.tutsplus.com/tutorials/a-beginners-guide-to-coding-graphics-shaders--cms-23313 @@ -113,7 +117,7 @@ export default { 'waterexponent': { value: 0.6 } } // SphereBufferGeometry(radius : Float, widthSegments : Integer, heightSegments : Integer, phiStart : Float, phiLength : Float, thetaStart : Float, thetaLength : Float) - var bgGeo = new THREE.SphereBufferGeometry(900, 32, 15, 0, 2 * Math.PI, 0, 0.5 * Math.PI) + var bgGeo = new THREE.SphereBufferGeometry(700, 32, 15, 0, 2 * Math.PI, 0, 0.5 * Math.PI) var skyMat = new THREE.ShaderMaterial({ uniforms: uniforms, vertexShader: BgVertex, @@ -135,33 +139,40 @@ export default { // SEA // lights + var ambient = new THREE.AmbientLight(0xfcfcf9, 0.5) + scene.add(ambient) + var sun = new THREE.PointLight(0xfcfcf9, 2) + // var sun = new THREE.DirectionalLight(0xfcfcf9, 2) sun.position.set(-150, 150, 110) - sun.castShadows = true + // sun.castShadow = true + // sun.shadow.bias = -0.0001 + // sun.shadow.mapSize.width = 1024 * 4 + // sun.shadow.mapSize.height = 1024 * 4 // sun.target.position.set(0, 0, 0) scene.add(sun) // scene.add(sun.target) - var sun2 = new THREE.PointLight(0xfcfcf9, 0.6) - sun2.position.set(150, 150, 110) - sun2.castShadows = true - // sun2.target.position.set(0, 0, 0) - scene.add(sun2) - // scene.add(sun2.target) - - var sun3 = new THREE.PointLight(0xfcfcf9, 0.6) - sun3.position.set(0, 150, -110) - sun3.castShadows = true - // sun3.target.position.set(0, 0, 0) - scene.add(sun3) - // scene.add(sun2.target) - - var sun4 = new THREE.PointLight(0xfcfcf9, 0.6) - sun4.position.set(0, -150, -110) - sun4.castShadows = true - // sun4.target.position.set(0, 0, 0) - scene.add(sun4) - // scene.add(sun2.target) + // var sun2 = new THREE.PointLight(0xfcfcf9, 0.6) + // sun2.position.set(150, 150, 110) + // // sun2.castShadow = true + // // sun2.target.position.set(0, 0, 0) + // scene.add(sun2) + // // scene.add(sun2.target) + // + // var sun3 = new THREE.PointLight(0xfcfcf9, 0.6) + // sun3.position.set(0, 150, -110) + // // sun3.castShadow = true + // // sun3.target.position.set(0, 0, 0) + // scene.add(sun3) + // // scene.add(sun2.target) + // + // var sun4 = new THREE.PointLight(0xfcfcf9, 0.6) + // sun4.position.set(0, -150, -110) + // // sun4.castShadow = true + // // sun4.target.position.set(0, 0, 0) + // scene.add(sun4) + // // scene.add(sun2.target) // RETURN DATA return { @@ -192,9 +203,9 @@ export default { raycaster: new THREE.Raycaster(), interactive_objects_names: ['Project', 'Content'], interactive_objects: [], - light_opts: { - castShadow: true - }, + // light_opts: { + // castShadow: true + // }, opened_vnode: null, content_data: null } diff --git a/src/components/mixins.js b/src/components/mixins.js index 9a4fbeb..746e447 100644 --- a/src/components/mixins.js +++ b/src/components/mixins.js @@ -4,7 +4,7 @@ export default { deg2rad (deg) { return deg * (Math.PI / 180) }, - createLabelCanvas (text, fontsize, sizefactore, txtcolor) { + createLabelCanvas (text, fontsize, sizefactore, txtcolor, bgcolor) { // console.log('createLabelCanvas', this.data.Titre) const size = fontsize const borderSize = 5 @@ -27,8 +27,10 @@ export default { ctx.font = font ctx.textBaseline = 'top' - // ctx.fillStyle = 'red' - // ctx.fillRect(0, 0, width, height) + if (bgcolor) { + ctx.fillStyle = bgcolor + ctx.fillRect(0, 0, width, height) + } ctx.fillStyle = txtcolor for (var j = 0; j < lines.length; j++) { ctx.fillText(lines[j], borderSize, borderSize + j * size) diff --git a/src/components/objects/ContentBlock.vue b/src/components/objects/ContentBlock.vue index a28cd3f..5e7233f 100644 --- a/src/components/objects/ContentBlock.vue +++ b/src/components/objects/ContentBlock.vue @@ -117,7 +117,7 @@ export default { } }, created () { - console.log('ContentBlock created', this.data) + // console.log('ContentBlock created', this.data) let txtcolor = '#000000' // switch (this.type) { // case 'visible': @@ -138,44 +138,61 @@ export default { this.size.y = this.label_size.y + 0.2 let y = 0 + let top = this.prtPosition.y + this.prtSize.y / 2 + let floor = this.prtPosition.y - this.prtSize.y / 2 switch (this.type) { case 'visible': - y = (this.prtPosition.y + this.prtSize.y / 2) * Math.random() + y = top * Math.random() break case 'context': - y = (this.prtPosition.y - this.prtSize.y / 2) * Math.random() + y = floor / 3 * Math.random() break case 'process': - y = (this.prtPosition.y - this.prtSize.y / 2) * Math.random() + y = floor / 3 + floor / 3 * Math.random() + break + case 'concept': + y = (floor / 3) * 2 + floor / 3 * Math.random() break - default: } this.position.y = y let face = Math.random() - if (face < 0.25) { + // if (face < 0.25) { + // // gauche + // this.face = 'left' + // this.position.x = this.prtPosition.x - this.prtSize.x / 2 + 0.1 + // this.position.z = this.prtPosition.z - this.prtSize.z / 2 + this.size.x / 2 + Math.random() * (this.prtSize.z - this.size.x / 2) + // this.rotation.y = 90 + // } else if (face >= 0.25 && face < 0.5) { + // // fond + // this.face = 'back' + // this.position.z = this.prtPosition.z - this.prtSize.z / 2 + 0.1 + // this.position.x = this.prtPosition.x - this.prtSize.x / 2 + this.size.x / 2 + Math.random() * (this.prtSize.x - this.size.x / 2) + // } else if (face >= 0.5 && face < 0.75) { + // // droite + // this.face = 'right' + // this.position.x = this.prtPosition.x + this.prtSize.x / 2 - 0.1 + // this.position.z = this.prtPosition.z - this.prtSize.z / 2 + this.size.x / 2 + Math.random() * (this.prtSize.z - this.size.x / 2) + // this.rotation.y = -90 + // } else { + // // face + // this.face = 'front' + // this.position.z = this.prtPosition.z + this.prtSize.z / 2 - 0.1 + // this.position.x = this.prtPosition.x - this.prtSize.x / 2 + this.size.x / 2 + Math.random() * (this.prtSize.x - this.size.x / 2) + // this.rotation.y = 180 + // } + if (face < 0.5) { // gauche this.face = 'left' this.position.x = this.prtPosition.x - this.prtSize.x / 2 + 0.1 this.position.z = this.prtPosition.z - this.prtSize.z / 2 + this.size.x / 2 + Math.random() * (this.prtSize.z - this.size.x / 2) this.rotation.y = 90 - } else if (face >= 0.25 && face < 0.5) { - // fond - this.face = 'back' - this.position.z = this.prtPosition.z - this.prtSize.z / 2 + 0.1 - this.position.x = this.prtPosition.x - this.prtSize.x / 2 + this.size.x / 2 + Math.random() * (this.prtSize.x - this.size.x / 2) - } else if (face >= 0.5 && face < 0.75) { + } else { // droite this.face = 'right' this.position.x = this.prtPosition.x + this.prtSize.x / 2 - 0.1 this.position.z = this.prtPosition.z - this.prtSize.z / 2 + this.size.x / 2 + Math.random() * (this.prtSize.z - this.size.x / 2) this.rotation.y = -90 - } else { - // face - this.face = 'front' - this.position.z = this.prtPosition.z + this.prtSize.z / 2 - 0.1 - this.position.x = this.prtPosition.x - this.prtSize.x / 2 + this.size.x / 2 + Math.random() * (this.prtSize.x - this.size.x / 2) - this.rotation.y = 180 } // this.label_position.x = this.position.x - this.size.x / 2 + this.label_size.x / 2 + 0.1 // this.label_position.y = this.position.y + this.size.y / 2 - this.label_size.y / 2 - 0.1 diff --git a/src/components/objects/Project.vue b/src/components/objects/Project.vue index a574be6..d810167 100644 --- a/src/components/objects/Project.vue +++ b/src/components/objects/Project.vue @@ -32,6 +32,14 @@ type="process" :data="item" /> + @@ -44,6 +52,9 @@ import { ThreeBSP } from 'three-js-csg-es6' import mixins from 'components/mixins' import ContentBlock from 'components/objects/ContentBlock' +import BgVertex from 'assets/glsl/BgVertex' +import BuildingFragment from 'assets/glsl/BuildingFragment' + export default { name: 'Project', components: { @@ -58,39 +69,106 @@ export default { let size = { ...this.data.size } let position = { ...this.data.position } - let materialOpts = { - color: 0xffffff, - side: THREE.DoubleSide - // wireframe: true, - // transparent: true, - // opacity: 0.6 - // renderOrder: 0 - } - let material = new THREE.MeshLambertMaterial(materialOpts) - // http://learningthreejs.com/blog/2011/12/10/constructive-solid-geometry-with-csg-js/ - console.log('ThreeBSP', ThreeBSP) + // console.log('ThreeBSP', ThreeBSP) let wallW = 0.001 + let topGeom = new THREE.BoxGeometry(size.x, wallW, size.z) + let topMesh = new THREE.Mesh(topGeom) + topMesh.position.y = -0.5 * size.y + let topBSP = new ThreeBSP(topMesh) + + let floorGeom = new THREE.BoxGeometry(size.x, wallW, size.z) + let floorMesh = new THREE.Mesh(floorGeom) + floorMesh.position.y = 0.5 * size.y + let floorBSP = new ThreeBSP(floorMesh) + let backGeom = new THREE.BoxGeometry(size.x, size.y, wallW) let backMesh = new THREE.Mesh(backGeom) backMesh.position.z = -0.5 * size.z let backBSP = new ThreeBSP(backMesh) + // dig windows on face and back + let winW = 4 + let winH = 8 + let margin = 2 + let nbrWinX = 0 + let paddingX = 0 + let a = 0 + // removing windows until padding is enough + while (paddingX < 0.4) { + nbrWinX = Math.floor((size.x - 2 * margin) / winW) - a + paddingX = (size.x - 2 * margin - winW * nbrWinX) / (nbrWinX - 1) + a++ + } + // console.log('paddingX', paddingX) + let nbrWinY = 0 + let paddingY = 0 + a = 0 + // removing windows until padding is enough + while (paddingY < 0.4) { + nbrWinY = Math.floor((size.y - 2 * margin) / winH) - a + paddingY = (size.y - 2 * margin - winH * nbrWinY) / (nbrWinY - 1) + a++ + } + let winGeom = new THREE.BoxGeometry(winW, winH, wallW) + let winMesh, winBSP + for (var i = 0; i < nbrWinX; i++) { + for (var j = 0; j < nbrWinY; j++) { + // back + winMesh = new THREE.Mesh(winGeom) + winMesh.position.z = -0.5 * size.z + winMesh.position.x = -0.5 * size.x + margin + winW * 0.5 + i * (winW + paddingX) + winMesh.position.y = 0.5 * size.y - margin - winH * 0.5 - j * (winH + paddingY) + winBSP = new ThreeBSP(winMesh) + backBSP = backBSP.subtract(winBSP) + } + } + + // let abovewWaterH = position.y + size.y / 2 + // let underWaterHThd = (-1 * position.y - size.y / 2) / 3 + // let levelH = 4 + // let levelGeom = new THREE.BoxGeometry(size.x, levelH, wallW) + // let levelMesh, levelBSP + // for (var l = 0; l < 2; l++) { + // levelMesh = new THREE.Mesh(levelGeom) + // levelMesh.position.z = -0.5 * size.z + // levelMesh.position.y = 0.5 * size.y - abovewWaterH - underWaterHThd - underWaterHThd * l + levelH * 0.5 + // levelBSP = new ThreeBSP(levelMesh) + // backBSP = backBSP.union(levelBSP) + // } + + backMesh = backBSP.toMesh() + let faceMesh = backMesh.clone() + faceMesh.position.z = 0.5 * size.z + let faceBSP = new ThreeBSP(faceMesh) + let rightGeom = new THREE.BoxGeometry(wallW, size.y, size.z) let rightMesh = new THREE.Mesh(rightGeom) rightMesh.position.x = 0.5 * size.x // rightMesh.position.z = 0.5 * size.z let rightBSP = new ThreeBSP(rightMesh) - let faceGeom = new THREE.BoxGeometry(size.x, size.y, wallW) - let faceMesh = new THREE.Mesh(faceGeom) - faceMesh.position.z = 0.5 * size.z - let faceBSP = new ThreeBSP(faceMesh) + // WE MAY NO NEED TO DIG WINDOWS ON SIDE WALLS + // // dig windows on right + // let nbrWinZ = Math.floor((size.z - 2 * margin) / winW) + // let paddingZ = (size.z - 2 * margin - winW * nbrWinZ) / (nbrWinX - 1) + // winGeom = new THREE.BoxGeometry(wallW, winH, winW) + // for (i = 0; i < nbrWinZ; i++) { + // for (j = 0; j < nbrWinY; j++) { + // // right + // winMesh = new THREE.Mesh(winGeom) + // winMesh.position.x = 0.5 * size.x + // winMesh.position.z = -0.5 * size.z + margin + winW * 0.5 + i * (winW + paddingZ) + // winMesh.position.y = 0.5 * size.y - margin - winH * 0.5 - j * (winH + paddingY) + // winBSP = new ThreeBSP(winMesh) + // rightBSP = rightBSP.subtract(winBSP) + // } + // } + // rightMesh = rightBSP.toMesh() - let leftGeom = new THREE.BoxGeometry(wallW, size.y, size.z) - let leftMesh = new THREE.Mesh(leftGeom) + let leftMesh = rightMesh.clone() leftMesh.position.x = -0.5 * size.x // leftMesh.position.z = 0.5 * size.z let leftBSP = new ThreeBSP(leftMesh) @@ -98,17 +176,47 @@ export default { let buildingBSP = backBSP.union(rightBSP) buildingBSP = buildingBSP.union(faceBSP) buildingBSP = buildingBSP.union(leftBSP) + buildingBSP = buildingBSP.union(topBSP) + buildingBSP = buildingBSP.union(floorBSP) - let holeGeom = new THREE.BoxGeometry(1000, 5, 5) - let holeMesh = new THREE.Mesh(holeGeom) - holeMesh.position.y = 50 - let holeBSP = new ThreeBSP(holeMesh) - - buildingBSP = buildingBSP.subtract(holeBSP) - + // convert back to three.js mesh let building = buildingBSP.toMesh() - building.material = material - // building.geometry.computeVertexNormals() + + // create a custom shaderMaterial to had gradian colors + var uniforms = THREE.UniformsUtils.merge([ + THREE.UniformsLib['lights'], + { + 'topColor': { value: new THREE.Color(0xffffff) }, + 'groundColor': { value: new THREE.Color(0xbcd6e4) }, + 'bottomColor': { value: new THREE.Color(0x07223b) }, + // 'bottomColor': { value: new THREE.Color(0x000000) }, + // 'groundColor': { value: new THREE.Color(0xff0000) }, + // 'bottomColor': { value: new THREE.Color(0x00ff00) }, + lightIntensity: { type: 'f', value: 1.0 } + } + ]) + var buildingMat = new THREE.ShaderMaterial({ + uniforms: uniforms, + vertexShader: BgVertex, + fragmentShader: BuildingFragment, + side: THREE.DoubleSide, + lights: true + }) + building.material = buildingMat + + // create a classical material for building + // let materialOpts = { + // color: 0xffffff, + // side: THREE.DoubleSide + // // wireframe: true, + // // transparent: true, + // // opacity: 0.6 + // // renderOrder: 0 + // } + // building.material = new THREE.MeshLambertMaterial(materialOpts) + + // building.castShadow = true + // building.receiveShadow = true // let buildingGeom = fromCSG(boxCSG) // buildingGeom.computeVertexNormals() @@ -119,8 +227,6 @@ export default { // let buildingPos = { ...position } buildingPos.z -= 0.5 * size.z - // building.castShadow = true - // building.receiveShadow = true return { block3d: null, @@ -160,7 +266,7 @@ export default { created () { console.log('Project created: data', this, this.data) - this.label_canvas = this.createLabelCanvas(this.data.Titre.replace(/ /g, '\n').toUpperCase(), 48, 21, '#000000') + this.label_canvas = this.createLabelCanvas(this.data.Titre.replace(/ /g, '\n').toUpperCase(), 48, 21, '#000000', '#ffffff') this.label_position.x = this.position.x - this.size.x / 2 + this.label_size.x / 2 + 1 this.label_position.y = this.position.y + this.size.y / 2 - this.label_size.y / 2 - 1 this.label_position.z = this.position.z + this.size.z / 2 + 0.5 @@ -171,6 +277,9 @@ export default { // record self references this.block3d = this.$refs.block3d.curObj + // this.block3d.castShadow = true + // this.block3d.receiveShadow = true + this.block3d.userData = { vnode: this }