Skip to content

Commit

Permalink
Refactor atmosphere glow mesh and only show it outside the globe peri…
Browse files Browse the repository at this point in the history
…meter
  • Loading branch information
vasturiano committed Dec 15, 2024
1 parent 4b36247 commit 59148e9
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 35 deletions.
8 changes: 4 additions & 4 deletions src/layers/globe.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const THREE = window.THREE
};

import GeoJsonGeometry from 'three-geojson-geometry';
import { createGlowMesh } from '../utils/three-glow-mesh';
import GlowMesh from '../utils/GlowMesh.js';

import Kapsule from 'kapsule';
import { geoGraticule10 } from 'd3-geo';
Expand Down Expand Up @@ -132,12 +132,12 @@ export default Kapsule({
}

if (state.atmosphereColor && state.atmosphereAltitude) {
const obj = state.atmosphereObj = createGlowMesh(state.globeObj.geometry, {
backside: true,
const obj = state.atmosphereObj = new GlowMesh(state.globeObj.geometry, {
color: state.atmosphereColor,
size: GLOBE_RADIUS * state.atmosphereAltitude,
hollowRadius: GLOBE_RADIUS,
coefficient: 0.1,
power: 3.5, // dispersion
coefficient: 0.1
});
obj.visible = !!state.showAtmosphere;
obj.__globeObjType = 'atmosphere'; // Add object type
Expand Down
83 changes: 52 additions & 31 deletions src/utils/three-glow-mesh.js → src/utils/GlowMesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,43 @@ const THREE = window.THREE
ShaderMaterial
};

const vertexShader = `
uniform float hollowRadius;
varying vec3 vVertexWorldPosition;
varying vec3 vVertexNormal;
varying float vCameraDistanceToObjCenter;
varying float vVertexAngularDistanceToHollowRadius;
void main() {
vVertexNormal = normalize(normalMatrix * normal);
vVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
vec4 objCenterViewPosition = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
vCameraDistanceToObjCenter = length(objCenterViewPosition);
float edgeAngle = atan(hollowRadius / vCameraDistanceToObjCenter);
float vertexAngle = acos(dot(normalize(modelViewMatrix * vec4(position, 1.0)), normalize(objCenterViewPosition)));
vVertexAngularDistanceToHollowRadius = vertexAngle - edgeAngle;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}`;

const fragmentShader = `
uniform vec3 color;
uniform float coefficient;
uniform float power;
uniform float hollowRadius;
varying vec3 vVertexNormal;
varying vec3 vVertexWorldPosition;
varying float vCameraDistanceToObjCenter;
varying float vVertexAngularDistanceToHollowRadius;
void main() {
if (vCameraDistanceToObjCenter < hollowRadius) discard; // inside the hollowRadius
if (vVertexAngularDistanceToHollowRadius < 0.0) discard; // frag position is within the hollow radius
vec3 worldCameraToVertex = vVertexWorldPosition - cameraPosition;
vec3 viewCameraToVertex = (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;
viewCameraToVertex = normalize(viewCameraToVertex);
Expand All @@ -33,30 +63,13 @@ void main() {
gl_FragColor = vec4(color, intensity);
}`;

const vertexShader = `
varying vec3 vVertexWorldPosition;
varying vec3 vVertexNormal;
void main() {
vVertexNormal = normalize(normalMatrix * normal);
vVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;

export const defaultOptions = {
backside: true,
coefficient: 0.5,
color: 'gold',
size: 2,
power: 1,
};

// Based off: http://stemkoski.blogspot.fr/2013/07/shaders-in-threejs-glow-and-halo.html
export function createGlowMaterial(coefficient, color, power) {
function createGlowMaterial(coefficient, color, power, hollowRadius) {
return new THREE.ShaderMaterial({
depthWrite: false,
fragmentShader,
transparent: true,
vertexShader,
fragmentShader,
uniforms: {
coefficient: {
value: coefficient,
Expand All @@ -67,13 +80,14 @@ export function createGlowMaterial(coefficient, color, power) {
power: {
value: power,
},
hollowRadius: {
value: hollowRadius,
}
},
vertexShader,
});
}

export function createGlowGeometry(geometry, size) {
// expect BufferGeometry
function createGlowGeometry(geometry, size) {
const glowGeometry = geometry.clone();

// Resize vertex positions according to normals
Expand All @@ -88,15 +102,22 @@ export function createGlowGeometry(geometry, size) {
return glowGeometry;
}

export function createGlowMesh(geometry, options = defaultOptions) {
const { backside, coefficient, color, size, power } = options;
export default class GlowMesh extends THREE.Mesh {
constructor(geometry, {
color= 'gold',
size= 2,
coefficient= 0.5,
power= 1,
hollowRadius= 0,
backside = true
} = {}) {
super();

const glowGeometry = createGlowGeometry(geometry, size);
const glowMaterial = createGlowMaterial(coefficient, color, power);
const glowGeometry = createGlowGeometry(geometry, size);
const glowMaterial = createGlowMaterial(coefficient, color, power, hollowRadius);
backside && (glowMaterial.side = THREE.BackSide);

if (backside) {
glowMaterial.side = THREE.BackSide;
this.geometry = glowGeometry;
this.material = glowMaterial;
}

return new THREE.Mesh(glowGeometry, glowMaterial);
}

0 comments on commit 59148e9

Please sign in to comment.