コンテンツにスキップ

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に置き換えるまで、期待通りに動作しません。