Set atmosphere and post-process parameters¶
Tune the representative atmosphere parameters and switch every post-process effect on and off
set_atmosphere_parameter.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Set atmosphere and post-process parameters</title>
<meta property="og:description" content="Tune the representative atmosphere parameters and switch every post-process effect on and off" />
<script src="./v0.10.6/mapray.min.js"></script>
<script src="./v0.10.6/maprayui.min.js"></script>
<link rel="stylesheet" href="./v0.10.6/mapray.css">
<style>
body {margin: 0; padding: 0;}
html, body, div#mapray-container { height: 100%; }
.map-overlay {
font: 12px/18px "Robot", sans-serif;
position: absolute;
width: 250px;
top: 0;
left: 0;
padding: 10px;
max-height: 100%;
overflow-y: auto;
box-sizing: border-box;
}
.map-overlay .map-overlay-inner {
background-color: #fff;
color: #000;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
border-radius: 3px;
padding: 10px;
margin-bottom: 10px;
}
.map-overlay-inner h3 {
margin: 0 0 6px;
font-size: 12px;
}
.map-overlay-inner .row {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0 0 4px;
}
.map-overlay-inner .row span {
flex: 0 0 108px;
}
.map-overlay-inner .row input[type=range] {
flex: 1 1 auto;
min-width: 0;
}
.map-overlay-inner .row output {
flex: 0 0 42px;
text-align: right;
color: #555;
}
.map-overlay-inner select {
width: 100%;
margin: 0 0 6px;
}
.map-overlay-inner .note {
margin: 6px 0 0;
color: #777;
}
</style>
</head>
<body>
<div id="mapray-container"></div>
<div class="map-overlay">
<div class="map-overlay-inner">
<h3>Atmosphere</h3>
<select id="Quality"></select>
<select id="Tonemap"></select>
<div id="AtmosphereRows"></div>
<div class="row">
<span>ground lighting</span>
<input type="checkbox" id="GroundPhysical" checked>
</div>
<p class="note">The "minimal" quality preset renders straight to the
canvas, so every post-process effect below is bypassed.</p>
</div>
<div class="map-overlay-inner">
<h3>Post-process</h3>
<div class="row">
<span>bloom</span>
<input type="checkbox" id="BloomEnabled" checked>
</div>
<div id="BloomRows"></div>
<div class="row">
<span>sun shafts</span>
<input type="checkbox" id="ShaftsEnabled">
</div>
<div id="ShaftsRows"></div>
<div class="row">
<span>auto exposure</span>
<input type="checkbox" id="AutoExposure">
</div>
<div id="AeRows"></div>
<div id="ExposureRows"></div>
</div>
</div>
</body>
</html>
<script>
const cloudApi = new mapray.cloud.CloudApiV2({
tokenType: mapray.cloud.CloudApi.TokenType.ACCESS_TOKEN,
token: "<YOUR_MAPRAY_ACCESS_TOKEN>"
});
const uiviewer = new maprayui.StandardUIViewer( "mapray-container", {
dem_provider: new mapray.StandardDemProvider( cloudApi.getDefaultDemAsResource() ),
atmosphere: new mapray.Atmosphere(),
sun_visualizer: new mapray.SunVisualizer( 32 )
} );
// Looking west at the Japan Alps in the late afternoon, so that the sun is
// in frame and the bloom / sun shafts effects are visible.
uiviewer.setCameraPosition({ longitude: 137.85, latitude: 36.24, height: 3800 });
uiviewer.setLookAtPosition({ longitude: 137.5918, latitude: 36.3241, height: 4200 });
/**
* Sun direction in GOCS (ECEF) for a UTC time.
* Meeus ch.25 low-precision solar position + GMST rotation (error < 0.02 deg).
*/
function sunDirectionGocs( date ) {
const DEG = Math.PI / 180;
const jd = date.getTime() / 86400000 + 2440587.5;
const t = ( jd - 2451545.0 ) / 36525.0;
const L0 = 280.46646 + 36000.76983 * t;
const M = ( 357.52911 + 35999.05029 * t ) * DEG;
const C = 1.914602 * Math.sin( M ) + 0.019993 * Math.sin( 2 * M ) + 0.000289 * Math.sin( 3 * M );
const lambda = ( L0 + C ) * DEG;
const eps = ( 23.4392911 - 0.0130042 * t ) * DEG;
const ra = Math.atan2( Math.cos( eps ) * Math.sin( lambda ), Math.cos( lambda ) );
const dec = Math.asin( Math.sin( eps ) * Math.sin( lambda ) );
let gmst = ( 280.46061837 + 360.98564736629 * ( jd - 2451545.0 ) ) % 360;
if ( gmst < 0 ) gmst += 360;
const lon = ra - gmst * DEG;
return [ Math.cos( dec ) * Math.cos( lon ), Math.cos( dec ) * Math.sin( lon ), Math.sin( dec ) ];
}
// 2026-06-21 18:20 JST: the sun sits low in the west-north-west, in frame.
uiviewer.viewer.sun.setSunDirection( sunDirectionGocs( new Date( "2026-06-21T09:20:00Z" ) ) );
const atmosphere = uiviewer.viewer.atmosphere;
// Render effects always exist on the viewer; the viewer syncs them to its
// internal post-process pipeline every frame.
const effects = uiviewer.viewer.render_effects;
function addSelect( element, values, initial, apply ) {
for ( const v of values ) {
const option = document.createElement( "option" );
option.value = v;
option.textContent = v;
element.appendChild( option );
}
element.value = initial;
element.addEventListener( "change", () => apply( element.value ) );
}
function addSlider( parent, label, min, max, step, initial, apply ) {
const row = document.createElement( "div" );
row.className = "row";
row.innerHTML = `<span>${label}</span>`;
const range = document.createElement( "input" );
range.type = "range";
range.min = min; range.max = max; range.step = step; range.value = initial;
const out = document.createElement( "output" );
out.textContent = initial;
range.addEventListener( "input", () => {
const value = Number( range.value );
out.textContent = value;
apply( value );
} );
row.appendChild( range );
row.appendChild( out );
parent.appendChild( row );
}
addSelect( document.getElementById( "Quality" ),
Object.values( mapray.Atmosphere.Quality ),
atmosphere.quality,
v => atmosphere.setQuality( v ) );
addSelect( document.getElementById( "Tonemap" ),
[ "aces", "exponential" ],
effects.tonemap_mode,
v => effects.setTonemapMode( v ) );
const p = atmosphere.parameters;
const atmosphereRows = document.getElementById( "AtmosphereRows" );
addSlider( atmosphereRows, "exposure scale", 0.1, 3.0, 0.01, p.exposure_scale, v => atmosphere.setExposureScale( v ) );
addSlider( atmosphereRows, "mie g", 0.0, 0.999, 0.01, p.mie_g, v => atmosphere.setMieG( v ) );
addSlider( atmosphereRows, "top height m", 1000, 300000, 1000, p.atmosphere_height, v => atmosphere.setAtmosphereHeight( v ) );
addSlider( atmosphereRows, "rayleigh H m", 100, 80000, 100, p.rayleigh_distribution, v => atmosphere.setRayleighDistribution( v ) );
addSlider( atmosphereRows, "mie H m", 100, 32000, 100, p.mie_distribution, v => atmosphere.setMieDistribution( v ) );
addSlider( atmosphereRows, "aerial blend", 0.0, 1.0, 0.01, p.aerial_perspective_blend, v => atmosphere.setAerialPerspectiveBlend( v ) );
addSlider( atmosphereRows, "aerial dist m", 5000, 500000, 1000, p.aerial_perspective_distance, v => atmosphere.setAerialPerspectiveDistance( v ) );
addSlider( atmosphereRows, "ambient", 0.0, 2.0, 0.01, atmosphere.ambient, v => atmosphere.setAmbient( v ) );
addSlider( atmosphereRows, "ground exposure", 0.0, 2.0, 0.01, p.ground_lighting_exposure, v => atmosphere.setGroundLightingExposure( v ) );
const sun_visualizer = uiviewer.viewer.sunVisualizer;
addSlider( atmosphereRows, "sun glow", 0.0, 4.0, 0.01, sun_visualizer.glow_intensity, v => sun_visualizer.setGlowIntensity( v ) );
addSlider( atmosphereRows, "moon lux", 0.0, 1.0, 0.01, uiviewer.viewer.moon.illuminance, v => uiviewer.viewer.moon.setIlluminance( v ) );
document.getElementById( "GroundPhysical" ).addEventListener( "change", ev => {
atmosphere.setGroundPhysicalLighting( ev.target.checked );
} );
// Bloom is switched off by setting its intensity to zero.
let bloom_intensity = 0.5;
document.getElementById( "BloomEnabled" ).addEventListener( "change", ev => {
effects.setBloomIntensity( ev.target.checked ? bloom_intensity : 0.0 );
} );
const bloomRows = document.getElementById( "BloomRows" );
addSlider( bloomRows, "intensity", 0.0, 3.0, 0.01, 0.5, v => {
bloom_intensity = v;
if ( document.getElementById( "BloomEnabled" ).checked ) effects.setBloomIntensity( v );
} );
addSlider( bloomRows, "threshold", 0.0, 8.0, 0.01, 1.0, v => effects.setBloomThreshold( v ) );
addSlider( bloomRows, "radius", 0.1, 4.0, 0.01, 1.0, v => effects.setBloomRadius( v ) );
document.getElementById( "ShaftsEnabled" ).addEventListener( "change", ev => {
effects.setSunShaftsEnabled( ev.target.checked );
} );
const shaftsRows = document.getElementById( "ShaftsRows" );
addSlider( shaftsRows, "intensity", 0.0, 3.0, 0.01, 1.0, v => effects.setSunShaftsIntensity( v ) );
addSlider( shaftsRows, "density", 0.0, 2.0, 0.01, 1.0, v => effects.setSunShaftsDensity( v ) );
addSlider( shaftsRows, "decay", 0.0, 1.0, 0.01, 0.71, v => effects.setSunShaftsDecay( v ) );
addSlider( shaftsRows, "weight", 0.0, 2.0, 0.01, 0.78, v => effects.setSunShaftsWeight( v ) );
document.getElementById( "AutoExposure" ).addEventListener( "change", ev => {
effects.setAutoExposureEnabled( ev.target.checked );
} );
const aeRows = document.getElementById( "AeRows" );
addSlider( aeRows, "ae bias", -4.0, 4.0, 0.1, 0.0, v => effects.setAutoExposureBias( v ) );
addSlider( aeRows, "ae speed", 0.1, 8.0, 0.1, 1.5, v => effects.setAutoExposureSpeed( v ) );
addSlider( document.getElementById( "ExposureRows" ), "exposure", 0.1, 4.0, 0.01, 1.0,
v => effects.setTonemapExposure( v ) );
</script>
Info
このサンプルコードは、<YOUR_MAPRAY_ACCESS_TOKEN>を、あなたのMapray CloudのアカウントのOrganization Tokenに置き換えるまで、期待通りに動作しません。