Skip to content

Commit

Permalink
Apply invisible underground shaders on top of existing reflective mat…
Browse files Browse the repository at this point in the history
…erials
  • Loading branch information
vasturiano committed Oct 30, 2024
1 parent e06d1ce commit 3667081
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 53 deletions.
67 changes: 33 additions & 34 deletions src/layers/hexbin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import {
DoubleSide,
Mesh,
MeshLambertMaterial,
Object3D,
ShaderMaterial
Object3D
} from 'three';

const THREE = window.THREE
Expand All @@ -16,8 +15,7 @@ const THREE = window.THREE
DoubleSide,
Mesh,
MeshLambertMaterial,
Object3D,
ShaderMaterial
Object3D
};

import * as _bfg from 'three/addons/utils/BufferGeometryUtils.js';
Expand All @@ -34,10 +32,10 @@ import { Tween, Easing } from '@tweenjs/tween.js';

import { colorStr2Hex, colorAlpha, color2ShaderArr } from '../utils/color-utils';
import { array2BufferAttr } from '../utils/three-utils';
import { applyShaderExtensionToMaterial, invisibleUndergroundShaderExtend } from '../utils/shaders';
import { emptyObject } from '../utils/gc';
import threeDigest from '../utils/digest';
import { GLOBE_RADIUS } from '../constants';
import { invisibleUndergroundShader } from '../utils/shaders';

//

Expand Down Expand Up @@ -87,8 +85,7 @@ export default Kapsule({
sumWeight: points.reduce((agg, d) => agg + +weightAccessor(d), 0)
}));

const topHexMaterials = {}; // indexed by color
const sideHexMaterials = {}; // indexed by color
const hexMaterials = {}; // indexed by color

const scene = state.hexBinMerge ? new THREE.Object3D() : state.scene; // use fake scene if merging hex points

Expand All @@ -113,8 +110,8 @@ export default Kapsule({
geom.applyMatrix4(obj.matrix);

// color vertices
const topColor = color2ShaderArr(topColorAccessor(d), true, true);
const sideColor = color2ShaderArr(sideColorAccessor(d), true, true);
const topColor = color2ShaderArr(topColorAccessor(d));
const sideColor = color2ShaderArr(sideColorAccessor(d));

const nVertices = geom.getAttribute('position').count;
const topFaceIdx = geom.groups[0].count; // starting vertex index of top group
Expand All @@ -126,11 +123,18 @@ export default Kapsule({
return geom;
}));

const hexPoints = new THREE.Mesh(hexPointsGeometry, new THREE.ShaderMaterial({
...(invisibleUndergroundShader({ vertexColors: true })),
transparent: true,
side: THREE.DoubleSide
}));
const hexPoints = new THREE.Mesh(
hexPointsGeometry,
applyShaderExtensionToMaterial(
new THREE.MeshLambertMaterial({
color: 0xffffff,
transparent: true,
vertexColors: true,
side: THREE.DoubleSide
}),
invisibleUndergroundShaderExtend
)
);

hexPoints.__globeObjType = 'hexBinPoints'; // Add object type
hexPoints.__data = hexBins; // Attach obj data
Expand Down Expand Up @@ -217,26 +221,21 @@ export default Kapsule({
const sideColor = sideColorAccessor(d);
const topColor = topColorAccessor(d);

if (!sideHexMaterials.hasOwnProperty(sideColor)) {
const opacity = colorAlpha(sideColor);
sideHexMaterials[sideColor] = new THREE.ShaderMaterial({
...(invisibleUndergroundShader()),
transparent: opacity < 1,
side: THREE.DoubleSide
});
sideHexMaterials[sideColor].uniforms.color.value = color2ShaderArr(sideColor, true, true);
}
if (!topHexMaterials.hasOwnProperty(topColor)) {
const opacity = colorAlpha(topColor);
topHexMaterials[topColor] = new THREE.MeshLambertMaterial({
color: colorStr2Hex(topColor),
opacity: opacity,
transparent: opacity < 1,
side: THREE.DoubleSide
});
}

obj.material = [sideHexMaterials[sideColor], topHexMaterials[topColor]];
[sideColor, topColor].forEach(color => {
if (!hexMaterials.hasOwnProperty(color)) {
const opacity = colorAlpha(color);
hexMaterials[color] = applyShaderExtensionToMaterial(
new THREE.MeshLambertMaterial({
color: colorStr2Hex(color),
transparent: opacity < 1,
opacity: opacity,
side: THREE.DoubleSide
}),
invisibleUndergroundShaderExtend
);
}
});
obj.material = [sideColor, topColor].map(color => hexMaterials[color]);
}
}
}
Expand Down
30 changes: 12 additions & 18 deletions src/layers/polygons.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import {
LineBasicMaterial,
LineSegments,
Mesh,
MeshBasicMaterial,
ShaderMaterial
MeshBasicMaterial
} from 'three';

const THREE = window.THREE
Expand All @@ -16,8 +15,7 @@ const THREE = window.THREE
LineBasicMaterial,
LineSegments,
Mesh,
MeshBasicMaterial,
ShaderMaterial
MeshBasicMaterial
};

import { ConicPolygonGeometry } from 'three-conic-polygon-geometry';
Expand All @@ -27,11 +25,11 @@ import Kapsule from 'kapsule';
import accessorFn from 'accessor-fn';
import { Tween, Easing } from '@tweenjs/tween.js';

import { colorStr2Hex, colorAlpha, color2ShaderArr } from '../utils/color-utils';
import { colorStr2Hex, colorAlpha } from '../utils/color-utils';
import { applyShaderExtensionToMaterial, invisibleUndergroundShaderExtend } from '../utils/shaders';
import { emptyObject } from '../utils/gc';
import threeDigest from '../utils/digest';
import { GLOBE_RADIUS } from '../constants';
import { invisibleUndergroundShader } from '../utils/shaders';

//

Expand Down Expand Up @@ -109,11 +107,11 @@ export default Kapsule({
createObj: () => {
const obj = new THREE.Group();

obj.__defaultSideMaterial = new THREE.ShaderMaterial({
...(invisibleUndergroundShader()),
side: THREE.DoubleSide,
depthWrite: true
});
obj.__defaultSideMaterial = applyShaderExtensionToMaterial(
new THREE.MeshBasicMaterial({ side: THREE.DoubleSide, depthWrite: true }),
invisibleUndergroundShaderExtend
);

obj.__defaultCapMaterial = new THREE.MeshBasicMaterial({ side: THREE.DoubleSide, depthWrite: true });

// conic geometry
Expand Down Expand Up @@ -176,13 +174,9 @@ export default Kapsule({
// conic object
const material = conicObj.material[materialIdx];
const opacity = colorAlpha(color);
material.color.set(colorStr2Hex(color));
material.transparent = opacity < 1;
if (material.type !== 'ShaderMaterial') {
material.color.set(colorStr2Hex(color));
material.opacity = opacity;
} else {
material.uniforms.color.value = color2ShaderArr(color, true, true);
}
material.opacity = opacity;
});

if (addStroke) {
Expand All @@ -200,7 +194,7 @@ export default Kapsule({
const { alt } = obj.__currentTargetD = td;
conicObj.scale.x = conicObj.scale.y = conicObj.scale.z = 1 + alt;
addStroke && (strokeObj.scale.x = strokeObj.scale.y = strokeObj.scale.z = 1 + alt + 1e-4); // stroke slightly above the conic mesh
obj.__defaultSideMaterial.uniforms.surfaceRadius.value = GLOBE_RADIUS / (alt + 1); // update side material scale uniform
obj.__defaultSideMaterial.userData.shader && (obj.__defaultSideMaterial.userData.shader.uniforms.surfaceRadius.value = GLOBE_RADIUS / (alt + 1)); // update side material scale uniform
};

const currentTargetD = obj.__currentTargetD || Object.assign({}, targetD, { alt: -1e-3 });
Expand Down
27 changes: 26 additions & 1 deletion src/utils/shaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,29 @@ export const invisibleUndergroundShader = ({ vertexColors = false } = {}) => ({
gl_FragColor = ${vertexColors ? 'vColor' : 'color'};
}
`
});
});

export const invisibleUndergroundShaderExtend = shader => {
shader.uniforms.surfaceRadius = { type: 'float', value: 0 };
shader.vertexShader = ('attribute float surfaceRadius;\nvarying float vSurfaceRadius;\nvarying vec3 vPos;\n' + shader.vertexShader)
.replace('void main() {', [
'void main() {',
'vSurfaceRadius = surfaceRadius;',
'vPos = position;'
].join('\n'));

shader.fragmentShader = ('uniform float surfaceRadius;\nvarying float vSurfaceRadius;\nvarying vec3 vPos;\n' + shader.fragmentShader)
.replace('void main() {', [
'void main() {',
'if (length(vPos) < max(surfaceRadius, vSurfaceRadius)) discard;'
].join('\n'));

return shader;
};

export const applyShaderExtensionToMaterial = (material, extensionFn) => {
material.onBeforeCompile = shader => {
material.userData.shader = extensionFn(shader);
};
return material;
};

0 comments on commit 3667081

Please sign in to comment.