From 657ae38f8815aea5c21b7dd39f003ecc459301ab Mon Sep 17 00:00:00 2001 From: "P. Douglas Reeder" Date: Mon, 6 Mar 2023 15:57:29 -0500 Subject: [PATCH] window-color now mixed with cubemap, adjusted by window-opacity --- README.md | 16 ++++++++++++---- dist/main.js | 2 +- example-simple.html | 6 ++++-- example.html | 8 +++++++- package.json | 2 +- src/buildingsShader.js | 9 ++++++--- src/buildingsShaderFrag.glsl | 3 ++- src/index.js | 1 + 8 files changed, 34 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f97a0b1..3c1bb4b 100644 --- a/README.md +++ b/README.md @@ -110,19 +110,27 @@ default: none reference to equirectangular image of a building interior, for faux-3D windows. Only images of a room that's nearly cubical will look good. -Overrides `px`, `nx`, etc. and `window-color` +Overrides `px`, `nx`, etc. ### px, nx, py, ny, nz default: none references to separate cubemap textures of a building interior, for faux-3D windows. +No positive-z image is needed, as that's the window side. Only images of a room that's nearly cubical will look good. -Overrides `window-color`. +Overridden by `equirectangular`. ### window-color -default: '#181818' +default: 'black' -the base color of windows, if `px`, `nx`, etc. or `equirectangular` is not set or hasn't loaded yet. +the base color of windows. Mixed with the image in `equirectangular` or `px`, `nx`, etc. + +### window-opacity +default: 0.5 + +how much light the windows block. +If neither equirectangular nor px, nx, etc. are set, should be set to about 0.9. +Without a cubemap, this will be mixed with white. ### sun-position default: {x:-1.0, y:1.0, z:-1.0} diff --git a/dist/main.js b/dist/main.js index abb79d1..c424541 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1 +1 @@ -(()=>{var e={227:e=>{e.exports="\nconst float PI = 3.1415926535897932384626433832795;\n\nuniform float elevation;\nuniform float xProportion;\nuniform float zProportion;\nuniform float yProportion;\nuniform float windowWidth;\nuniform float windowHeight;\nuniform bool useWallMap;\nuniform sampler2D wallMap;\nuniform float wallZoom;\nuniform vec3 wallColor;\nuniform bool useWindowCube;\nuniform samplerCube windowCube;\nuniform vec3 windowColor;\n\nvarying vec3 pos;\nvarying float sunFactor;\nvarying float vIntensityTweak;\n// vIntensityTweak > 0: 1.0 is no change to wall color\n// vIntensityTweak <= 0: 0.0 is black, 1.0 is white\n\nvarying vec3 vViewDirTangent;\nvarying vec2 vUv;\n\nfloat min3 (vec3 v) {\n return min (min (v.x, v.y), v.z);\n}\n\nvoid main() {\n vec3 wallIdealColor = useWallMap ?\n texture2D(wallMap, vec2((pos.x+pos.z)/wallZoom, pos.y/wallZoom)).rgb :\n wallColor;\n\n vec3 wallTweakedColor = vIntensityTweak > 0.0 ?\n wallIdealColor * vec3(vIntensityTweak) :\n vec3(-vIntensityTweak);\n\n vec4 wallPixelColor = vec4(wallTweakedColor * sunFactor, 1.);\n\n\n vec2 uv = fract(vUv);\n vec3 sampleDir = normalize(vViewDirTangent);\n\n sampleDir *= vec3(-1., -1., 1.);\n vec3 viewInv = 1. / sampleDir;\n\n vec3 uvPos = vec3(uv * 2.0 - 1.0, -1.0);\n\n float fmin = min3(abs(viewInv) - viewInv * uvPos);\n sampleDir = sampleDir * fmin + uvPos;\n\n vec4 windowPixelColor = useWindowCube ? texture(windowCube, sampleDir) : vec4(windowColor, 1.);\n\n\n float xx1 = step(windowWidth, sin(pos.x * 2.0 * PI / xProportion - PI / 2.0));\n float xx2 = step(0.8, sin(pos.z * 2.0 * PI / zProportion + PI / 2.0));\n\n float zz1 = step(windowWidth, sin(pos.z * 2.0 * PI / zProportion - PI / 2.0));\n float zz2 = step(0.8, sin(pos.x * 2.0 * PI / xProportion + PI / 2.0));\n\n float yy1 = step(windowHeight, sin((pos.y - elevation) * 2.0 * PI / yProportion - 2.0));\n\n gl_FragColor = mix(wallPixelColor, windowPixelColor, (xx1 * xx2 + zz1 * zz2) * yy1);\n}\n\n// Interior cubemap shader code by Mosen Heydari\n// https://github.com/mohsenheydari/three-interior-mapping\n"},106:e=>{e.exports="\nuniform vec3 sunNormal;\n\nattribute vec4 tangent;\nattribute float intensityTweak;\n\nvarying vec3 pos;\nvarying vec3 vViewDirTangent;\nvarying vec2 vUv;\nvarying float sunFactor;\nvarying float vIntensityTweak;\n\nvoid main() {\n pos = position;\n\n sunFactor = 0.5 + max(dot(normal, sunNormal), 0.0);\n\n vUv = uv;\n vec3 vNormal = normalMatrix * normal;\n vec3 vTangent = normalMatrix * tangent.xyz;\n vec3 vBitangent = normalize( cross(vNormal, vTangent) * tangent.w);\n\n mat3 mTBN = transpose(mat3(vTangent, vBitangent, vNormal));\n\n vec4 cameraSpacePosition = modelViewMatrix * vec4(position, 1.0);\n vec3 viewDir = -cameraSpacePosition.xyz;\n vViewDirTangent = mTBN * viewDir;\n\n gl_Position = projectionMatrix * cameraSpacePosition;\n\n vIntensityTweak = intensityTweak;\n}\n\n// Interior cubemap code by Mosen Heydari\n// https://github.com/mohsenheydari/three-interior-mapping\n"}},t={};function n(o){var r=t[o];if(void 0!==r)return r.exports;var i=t[o]={exports:{}};return e[o](i,i.exports,n),i.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";var e=n(106),t=n.n(e),o=n(227),r=n.n(o);AFRAME.registerShader("buildings",{schema:{elevation:{type:"number",default:0},xProportion:{type:"number",default:5},zProportion:{type:"number",default:5},yProportion:{type:"number",default:4},windowWidth:{type:"number",default:0,min:-1,max:1},windowHeight:{type:"number",default:-.4,min:-1,max:1},wallSrc:{type:"selector"},wallZoom:{type:"number",default:2,min:.001},wallColor:{type:"color",default:"#909090"},equirectangular:{type:"selector"},px:{type:"selector"},nx:{type:"selector"},py:{type:"selector"},ny:{type:"selector"},nz:{type:"selector"},windowColor:{type:"color",default:"#181818"},sunPosition:{type:"vec3",default:{x:-1,y:1,z:-1}}},init:function(e){const n=new THREE.Vector3(e.sunPosition.x,e.sunPosition.y,e.sunPosition.z),o={elevation:{value:e.elevation},xProportion:{value:e.xProportion},zProportion:{value:e.zProportion},yProportion:{value:e.yProportion},windowWidth:{value:-e.windowWidth},windowHeight:{value:-e.windowHeight},useWallMap:{value:!1},wallMap:{value:null},wallZoom:{value:e.wallZoom},wallColor:{value:new THREE.Color(e.wallColor)},useWindowCube:{value:!1},windowCube:{value:null},windowColor:{value:new THREE.Color(e.windowColor)},sunNormal:{value:n.normalize()}};this.material=new THREE.ShaderMaterial({uniforms:o,vertexShader:t(),fragmentShader:r()})},update:function(e){this.material.uniforms.elevation.value=e.elevation,this.material.uniforms.xProportion.value=e.xProportion,this.material.uniforms.zProportion.value=e.zProportion,this.material.uniforms.yProportion.value=e.yProportion,this.material.uniforms.windowWidth.value=-e.windowWidth,this.material.uniforms.windowHeight.value=-e.windowHeight,this.material.uniforms.wallZoom.value=e.wallZoom,this.material.uniforms.wallColor.value.set(e.wallColor),this.material.uniforms.windowColor.value.set(e.windowColor);let t=new THREE.Vector3(e.sunPosition.x,e.sunPosition.y,e.sunPosition.z);this.material.uniforms.sunNormal.value=t.normalize(),e.wallSrc!==this.wallSrc&&(this.loadTexture(e.wallSrc),this.wallSrc=e.wallSrc),e.equirectangular&&e.equirectangular!==this.equirectangular?(this.loadEquirectangular(e.equirectangular),this.equirectangular=e.equirectangular):e.px===this.px&&e.nx===this.nx&&e.py===this.py&&e.nz===this.nz||(this.loadCubeTexture(e.px,e.nx,e.py,e.ny,e.nz),this.px=e.px,this.nx=e.nx,this.py=e.py,this.ny=e.ny,this.nz=e.nz)},loadTexture:function(e){e?.currentSrc&&(new THREE.TextureLoader).load(e.currentSrc,(e=>{this.material.uniforms.wallMap.value=e,e.wrapS=THREE.RepeatWrapping,e.wrapT=THREE.RepeatWrapping,e.repeat.set(2,3),e.magFilfer=THREE.LinearMipmapNearestFilter,e.minFilfer=THREE.LinearMipmapNearestFilter,this.material.uniforms.useWallMap.value=!0}))},loadEquirectangular:function(e){e.currentSrc&&(new THREE.TextureLoader).load(e.currentSrc,(e=>{e.mapping=THREE.EquirectangularReflectionMapping,e.encoding=THREE.sRGBEncoding;const t=new THREE.WebGLCubeRenderTarget(e.source.data.height,{}).fromEquirectangularTexture(AFRAME.scenes[0].renderer,e);this.material.uniforms.windowCube.value=t.texture,this.material.uniforms.useWindowCube.value=!0,console.log("cube texture from equirect:",e)}))},loadCubeTexture:function(e,t,n,o,r){e?.currentSrc&&(this.windowTexture=null,(new THREE.CubeTextureLoader).load([e?.currentSrc,t?.currentSrc,n?.currentSrc,o?.currentSrc,r?.currentSrc,r?.currentSrc],(e=>{this.material.uniforms.windowCube.value=this.windowTexture=e,e.encoding=THREE.sRGBEncoding,this.material.uniforms.useWindowCube.value=!0,console.log("cube texture:",e)})))}}),AFRAME.registerGeometry("ell",{schema:{elevation:{type:"number",default:0},xProportion:{type:"number",default:5,min:1},zProportion:{type:"number",default:5,min:1},yProportion:{type:"number",default:4,min:2},buildings:{type:"string",default:"[{}]"}},init:function(e){const t=JSON.parse(e.buildings),n=30,o=90,r=new Float32Array(t.length*o),i=new Float32Array(t.length*o),a=60,l=new Float32Array(t.length*a),s=[],u=new Float32Array(t.length*n);for(let m=0;m{var e={227:e=>{e.exports="\nconst float PI = 3.1415926535897932384626433832795;\n\nuniform float elevation;\nuniform float xProportion;\nuniform float zProportion;\nuniform float yProportion;\nuniform float windowWidth;\nuniform float windowHeight;\nuniform bool useWallMap;\nuniform sampler2D wallMap;\nuniform float wallZoom;\nuniform vec3 wallColor;\nuniform bool useWindowCube;\nuniform samplerCube windowCube;\nuniform vec3 windowColor;\nuniform float windowOpacity;\n\nvarying vec3 pos;\nvarying float sunFactor;\nvarying float vIntensityTweak;\n// vIntensityTweak > 0: 1.0 is no change to wall color\n// vIntensityTweak <= 0: 0.0 is black, 1.0 is white\n\nvarying vec3 vViewDirTangent;\nvarying vec2 vUv;\n\nfloat min3 (vec3 v) {\n return min (min (v.x, v.y), v.z);\n}\n\nvoid main() {\n vec3 wallIdealColor = useWallMap ?\n texture2D(wallMap, vec2((pos.x+pos.z)/wallZoom, pos.y/wallZoom)).rgb :\n wallColor;\n\n vec3 wallTweakedColor = vIntensityTweak > 0.0 ?\n wallIdealColor * vec3(vIntensityTweak) :\n vec3(-vIntensityTweak);\n\n vec4 wallPixelColor = vec4(wallTweakedColor * sunFactor, 1.);\n\n\n vec2 uv = fract(vUv);\n vec3 sampleDir = normalize(vViewDirTangent);\n\n sampleDir *= vec3(-1., -1., 1.);\n vec3 viewInv = 1. / sampleDir;\n\n vec3 uvPos = vec3(uv * 2.0 - 1.0, -1.0);\n\n float fmin = min3(abs(viewInv) - viewInv * uvPos);\n sampleDir = sampleDir * fmin + uvPos;\n\n vec4 windowPixelColor = mix(texture(windowCube, sampleDir), vec4(windowColor, 1.), windowOpacity);\n\n\n float xx1 = step(windowWidth, sin(pos.x * 2.0 * PI / xProportion - PI / 2.0));\n float xx2 = step(0.8, sin(pos.z * 2.0 * PI / zProportion + PI / 2.0));\n\n float zz1 = step(windowWidth, sin(pos.z * 2.0 * PI / zProportion - PI / 2.0));\n float zz2 = step(0.8, sin(pos.x * 2.0 * PI / xProportion + PI / 2.0));\n\n float yy1 = step(windowHeight, sin((pos.y - elevation) * 2.0 * PI / yProportion - 2.0));\n\n gl_FragColor = mix(wallPixelColor, windowPixelColor, (xx1 * xx2 + zz1 * zz2) * yy1);\n}\n\n// Interior cubemap shader code by Mosen Heydari\n// https://github.com/mohsenheydari/three-interior-mapping\n"},106:e=>{e.exports="\nuniform vec3 sunNormal;\n\nattribute vec4 tangent;\nattribute float intensityTweak;\n\nvarying vec3 pos;\nvarying vec3 vViewDirTangent;\nvarying vec2 vUv;\nvarying float sunFactor;\nvarying float vIntensityTweak;\n\nvoid main() {\n pos = position;\n\n sunFactor = 0.5 + max(dot(normal, sunNormal), 0.0);\n\n vUv = uv;\n vec3 vNormal = normalMatrix * normal;\n vec3 vTangent = normalMatrix * tangent.xyz;\n vec3 vBitangent = normalize( cross(vNormal, vTangent) * tangent.w);\n\n mat3 mTBN = transpose(mat3(vTangent, vBitangent, vNormal));\n\n vec4 cameraSpacePosition = modelViewMatrix * vec4(position, 1.0);\n vec3 viewDir = -cameraSpacePosition.xyz;\n vViewDirTangent = mTBN * viewDir;\n\n gl_Position = projectionMatrix * cameraSpacePosition;\n\n vIntensityTweak = intensityTweak;\n}\n\n// Interior cubemap code by Mosen Heydari\n// https://github.com/mohsenheydari/three-interior-mapping\n"}},t={};function n(o){var r=t[o];if(void 0!==r)return r.exports;var i=t[o]={exports:{}};return e[o](i,i.exports,n),i.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";var e=n(106),t=n.n(e),o=n(227),r=n.n(o);AFRAME.registerShader("buildings",{schema:{elevation:{type:"number",default:0},xProportion:{type:"number",default:5},zProportion:{type:"number",default:5},yProportion:{type:"number",default:4},windowWidth:{type:"number",default:0,min:-1,max:1},windowHeight:{type:"number",default:-.4,min:-1,max:1},wallSrc:{type:"selector"},wallZoom:{type:"number",default:2,min:.001},wallColor:{type:"color",default:"#909090"},equirectangular:{type:"selector"},px:{type:"selector"},nx:{type:"selector"},py:{type:"selector"},ny:{type:"selector"},nz:{type:"selector"},windowColor:{type:"color",default:"black"},windowOpacity:{default:.5,min:0,max:1},sunPosition:{type:"vec3",default:{x:-1,y:1,z:-1}}},init:function(e){const n=new THREE.Vector3(e.sunPosition.x,e.sunPosition.y,e.sunPosition.z),o={elevation:{value:e.elevation},xProportion:{value:e.xProportion},zProportion:{value:e.zProportion},yProportion:{value:e.yProportion},windowWidth:{value:-e.windowWidth},windowHeight:{value:-e.windowHeight},useWallMap:{value:!1},wallMap:{value:null},wallZoom:{value:e.wallZoom},wallColor:{value:new THREE.Color(e.wallColor)},useWindowCube:{value:!1},windowCube:{value:null},windowColor:{value:new THREE.Color(e.windowColor)},windowOpacity:{value:e.windowOpacity},sunNormal:{value:n.normalize()}};this.material=new THREE.ShaderMaterial({uniforms:o,vertexShader:t(),fragmentShader:r()})},update:function(e){this.material.uniforms.elevation.value=e.elevation,this.material.uniforms.xProportion.value=e.xProportion,this.material.uniforms.zProportion.value=e.zProportion,this.material.uniforms.yProportion.value=e.yProportion,this.material.uniforms.windowWidth.value=-e.windowWidth,this.material.uniforms.windowHeight.value=-e.windowHeight,this.material.uniforms.wallZoom.value=e.wallZoom,this.material.uniforms.wallColor.value.set(e.wallColor),this.material.uniforms.windowColor.value.set(e.windowColor),this.material.uniforms.windowOpacity.value=e.windowOpacity;let t=new THREE.Vector3(e.sunPosition.x,e.sunPosition.y,e.sunPosition.z);this.material.uniforms.sunNormal.value=t.normalize(),e.wallSrc!==this.wallSrc&&(this.loadTexture(e.wallSrc),this.wallSrc=e.wallSrc),e.equirectangular&&e.equirectangular!==this.equirectangular?(this.loadEquirectangular(e.equirectangular),this.equirectangular=e.equirectangular):e.px===this.px&&e.nx===this.nx&&e.py===this.py&&e.nz===this.nz||(this.loadCubeTexture(e.px,e.nx,e.py,e.ny,e.nz),this.px=e.px,this.nx=e.nx,this.py=e.py,this.ny=e.ny,this.nz=e.nz)},loadTexture:function(e){e?.currentSrc&&(new THREE.TextureLoader).load(e.currentSrc,(e=>{this.material.uniforms.wallMap.value=e,e.wrapS=THREE.RepeatWrapping,e.wrapT=THREE.RepeatWrapping,e.repeat.set(2,3),e.magFilfer=THREE.LinearMipmapNearestFilter,e.minFilfer=THREE.LinearMipmapNearestFilter,this.material.uniforms.useWallMap.value=!0}))},loadEquirectangular:function(e){e.currentSrc&&(new THREE.TextureLoader).load(e.currentSrc,(e=>{e.mapping=THREE.EquirectangularReflectionMapping,e.encoding=THREE.sRGBEncoding;const t=new THREE.WebGLCubeRenderTarget(e.source.data.height,{}).fromEquirectangularTexture(AFRAME.scenes[0].renderer,e);this.material.uniforms.windowCube.value=t.texture,this.material.uniforms.useWindowCube.value=!0}))},loadCubeTexture:function(e,t,n,o,r){e?.currentSrc&&(this.windowTexture=null,(new THREE.CubeTextureLoader).load([e?.currentSrc,t?.currentSrc,n?.currentSrc,o?.currentSrc,r?.currentSrc,r?.currentSrc],(e=>{this.material.uniforms.windowCube.value=this.windowTexture=e,e.encoding=THREE.sRGBEncoding,this.material.uniforms.useWindowCube.value=!0})))}}),AFRAME.registerGeometry("ell",{schema:{elevation:{type:"number",default:0},xProportion:{type:"number",default:5,min:1},zProportion:{type:"number",default:5,min:1},yProportion:{type:"number",default:4,min:2},buildings:{type:"string",default:"[{}]"}},init:function(e){const t=JSON.parse(e.buildings),n=30,o=90,r=new Float32Array(t.length*o),i=new Float32Array(t.length*o),a=60,l=new Float32Array(t.length*a),s=[],u=new Float32Array(t.length*n);for(let m=0;m + - - + diff --git a/example.html b/example.html index a34607c..1b93e3d 100644 --- a/example.html +++ b/example.html @@ -26,6 +26,7 @@ buildingEls[0].setAttribute('py', '#py'); buildingEls[0].setAttribute('ny', '#ny'); buildingEls[0].setAttribute('nz', '#nz'); + buildingEls[0].setAttribute('window-opacity', '0.2'); buildingEls[1] = document.createElement('a-shader-buildings'); buildingEls[1].setAttribute('x-proportion-geometry', 4); @@ -39,6 +40,7 @@ buildingEls[1].setAttribute('wall-src', '#brick'); buildingEls[1].setAttribute('wall-zoom', 2.25); buildingEls[1].setAttribute('wall-color', '#6e2b11'); // brick red + buildingEls[1].setAttribute('window-opacity', '0.9'); buildingEls[2] = document.createElement('a-shader-buildings'); buildingEls[2].setAttribute('x-proportion-geometry', 6); @@ -57,6 +59,7 @@ buildingEls[2].setAttribute('py', '#py'); buildingEls[2].setAttribute('ny', '#ny'); buildingEls[2].setAttribute('nz', '#nz'); + buildingEls[2].setAttribute('window-opacity', '0.3'); buildingEls[3] = document.createElement('a-shader-buildings'); buildingEls[3].setAttribute('x-proportion-geometry', 6); @@ -71,6 +74,7 @@ buildingEls[3].setAttribute('wall-zoom', 3.0); buildingEls[3].setAttribute('wall-color', '#a0a0a0'); // light gray buildingEls[3].setAttribute('equirectangular', '#equirectangular'); + buildingEls[3].setAttribute('window-opacity', '0.8'); buildingEls[4] = document.createElement('a-shader-buildings'); buildingEls[4].setAttribute('y-proportion-geometry', 5); @@ -85,6 +89,7 @@ buildingEls[4].setAttribute('py', '#py'); buildingEls[4].setAttribute('ny', '#ny'); buildingEls[4].setAttribute('nz', '#nz'); + buildingEls[4].setAttribute('window-opacity', '0.4'); buildingEls[5] = document.createElement('a-shader-buildings'); buildingEls[5].setAttribute('window-width', 0.8); @@ -93,6 +98,7 @@ buildingEls[5].setAttribute('wall-zoom', 5.0); buildingEls[5].setAttribute('wall-color', '#675342'); // brown brick buildingEls[5].setAttribute('equirectangular', '#equirectangular'); + buildingEls[5].setAttribute('window-opacity', '0.7'); for (let s=0; s - diff --git a/package.json b/package.json index 04f406e..eb9e2b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aframe-shader-buildings", - "version": "1.2.0beta1", + "version": "2.0.0beta1", "description": "An A-Frame WebVR component for cheaply creating thousands of boxy buildings.", "scripts": { "watch": "webpack --mode=development --watch", diff --git a/src/buildingsShader.js b/src/buildingsShader.js index 2641044..e1bb3d7 100644 --- a/src/buildingsShader.js +++ b/src/buildingsShader.js @@ -22,7 +22,8 @@ AFRAME.registerShader('buildings', { ny: {type: 'selector'}, // positive Z is never used - it's the window side of the cube nz: {type: 'selector'}, - windowColor: {type: 'color', default: '#181818'}, // dark gray, like tinted windows + windowColor: {type: 'color', default: 'black'}, // like tinted windows + windowOpacity: {default: 0.5, min: 0, max: 1}, sunPosition: {type: 'vec3', default: {x:-1.0, y:1.0, z:-1.0}} }, @@ -46,6 +47,7 @@ AFRAME.registerShader('buildings', { useWindowCube: {value: false}, windowCube: {value: null}, windowColor: {value: new THREE.Color(data.windowColor)}, + windowOpacity: {value: data.windowOpacity}, sunNormal: {value: sunPos.normalize()} } @@ -74,6 +76,7 @@ AFRAME.registerShader('buildings', { // useWindowCube isn't updated from data // windowCube must be asynchronously loaded this.material.uniforms.windowColor.value.set(data.windowColor); + this.material.uniforms.windowOpacity.value = data.windowOpacity; let sunPos = new THREE.Vector3(data.sunPosition.x, data.sunPosition.y, data.sunPosition.z); this.material.uniforms.sunNormal.value = sunPos.normalize(); @@ -118,7 +121,7 @@ AFRAME.registerShader('buildings', { const formatted = new THREE.WebGLCubeRenderTarget(texture.source.data.height, {}).fromEquirectangularTexture(AFRAME.scenes[0].renderer, texture); this.material.uniforms.windowCube.value = formatted.texture; this.material.uniforms.useWindowCube.value = true; - console.log("cube texture from equirect:", texture) + // console.log("cube texture from equirect:", texture) }); } }, @@ -135,7 +138,7 @@ AFRAME.registerShader('buildings', { this.material.uniforms.windowCube.value = this.windowTexture = texture; texture.encoding = THREE.sRGBEncoding this.material.uniforms.useWindowCube.value = true; - console.log("cube texture:", texture) + // console.log("cube texture:", texture) }); } }, diff --git a/src/buildingsShaderFrag.glsl b/src/buildingsShaderFrag.glsl index 4a8dd7d..c85241f 100644 --- a/src/buildingsShaderFrag.glsl +++ b/src/buildingsShaderFrag.glsl @@ -14,6 +14,7 @@ uniform vec3 wallColor; uniform bool useWindowCube; uniform samplerCube windowCube; uniform vec3 windowColor; +uniform float windowOpacity; varying vec3 pos; varying float sunFactor; @@ -51,7 +52,7 @@ void main() { float fmin = min3(abs(viewInv) - viewInv * uvPos); sampleDir = sampleDir * fmin + uvPos; - vec4 windowPixelColor = useWindowCube ? texture(windowCube, sampleDir) : vec4(windowColor, 1.); + vec4 windowPixelColor = mix(texture(windowCube, sampleDir), vec4(windowColor, 1.), windowOpacity); float xx1 = step(windowWidth, sin(pos.x * 2.0 * PI / xProportion - PI / 2.0)); diff --git a/src/index.js b/src/index.js index b46fcb9..fcff735 100644 --- a/src/index.js +++ b/src/index.js @@ -175,6 +175,7 @@ AFRAME.registerPrimitive('a-shader-buildings', { 'ny': 'material.ny', 'nz': 'material.nz', 'window-color': 'material.windowColor', + 'window-opacity': 'material.windowOpacity', 'sun-position': 'material.sunPosition', } });