344 lines
13 KiB
C++
344 lines
13 KiB
C++
/* -*-c++-*- */
|
|
/* osgEarth - Geospatial SDK for OpenSceneGraph
|
|
* Copyright 2018 Pelican Mapping
|
|
* http://osgearth.org
|
|
*
|
|
* osgEarth is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
#pragma once
|
|
|
|
#include <osgEarthImGui/ImGuiPanel>
|
|
#include <osgEarth/Ephemeris>
|
|
#include <osgEarth/Sky>
|
|
#include <osgEarth/ShaderLoader>
|
|
#include <osgEarth/Shadowing>
|
|
#include <osgEarth/VirtualProgram>
|
|
#include <osgEarth/WindLayer>
|
|
|
|
namespace
|
|
{
|
|
const char* render_wind = R"(
|
|
#version 450
|
|
#pragma vp_function oe_ui_render_wind_vert, vertex_view
|
|
out vec3 viewpos3_wind;
|
|
void oe_ui_render_wind_vert(inout vec4 vertex) {
|
|
viewpos3_wind = vertex.xyz;
|
|
}
|
|
[break]
|
|
#version 450
|
|
#pragma vp_function oeui_render_wind_texture, fragment_output
|
|
#pragma import_defines(OE_WIND_TEX)
|
|
#pragma import_defines(OE_WIND_TEX_MATRIX)
|
|
in vec3 viewpos3_wind;
|
|
out vec4 frag_out;
|
|
#ifdef OE_WIND_TEX
|
|
uniform sampler3D OE_WIND_TEX;
|
|
uniform mat4 OE_WIND_TEX_MATRIX;
|
|
uniform vec3 oe_Camera;
|
|
uniform float osg_FrameTime;
|
|
|
|
#pragma import_defines(OE_TWEAKABLE)
|
|
#ifdef OE_TWEAKABLE
|
|
#define tweakable uniform
|
|
#else
|
|
#define tweakable const
|
|
#endif
|
|
tweakable float oe_wind_power = 1.0;
|
|
|
|
#define MAX_WIND_SPEED 50.0
|
|
#endif
|
|
|
|
void oeui_render_wind_texture(inout vec4 color)
|
|
{
|
|
frag_out = color;
|
|
|
|
#ifdef OE_WIND_TEX
|
|
vec4 texel = textureProj(OE_WIND_TEX, (OE_WIND_TEX_MATRIX*vec4(viewpos3_wind,1)));
|
|
float speed = texel.a * oe_wind_power;
|
|
|
|
vec3 wind_view = 2.0*texel.xyz - 1.0;
|
|
vec3 wind_clip = mat3(gl_ProjectionMatrix) * wind_view;
|
|
vec2 wind_screen = wind_clip.xy * oe_Camera.xy;
|
|
|
|
vec2 coord = (gl_FragCoord.xy - 0.5);
|
|
vec2 rv = normalize(wind_screen);
|
|
vec2 coordProj = mat2(rv.x, -rv.y, rv.y, rv.x) * coord;
|
|
|
|
const float oe_wind_animation_speed = 2.8 * MAX_WIND_SPEED * speed; // 32.0
|
|
int cx = int(coordProj.x - int(osg_FrameTime*oe_wind_animation_speed));
|
|
int ci = cx % 32;
|
|
const int stipple = 0x00000001;
|
|
int pattern32 = 0xffffffff & (stipple & (1 << ci));
|
|
if (pattern32 != 0)
|
|
frag_out = vec4(0.5,0.5,1,0.5);
|
|
#endif
|
|
}
|
|
)";
|
|
}
|
|
|
|
namespace osgEarth
|
|
{
|
|
using namespace osgEarth::Util;
|
|
|
|
class EnvironmentGUI : public ImGuiPanel
|
|
{
|
|
private:
|
|
osg::observer_ptr<MapNode> _mapNode;
|
|
osg::observer_ptr<SkyNode> _skyNode;
|
|
osg::observer_ptr<ShadowCaster> _shadowCaster;
|
|
osg::observer_ptr<WindLayer> _windLayer;
|
|
bool _showDetails = false;
|
|
float _hour;
|
|
int _day, _month, _year;
|
|
float _exposure = 3.5f;
|
|
float _contrast = 1.0f;
|
|
float _ambient = 0.033f;
|
|
float _max_ambient_intensity = 0.75;
|
|
bool _first = true;
|
|
bool _shadows = false;
|
|
float _haze_cutoff = 0.0f, _haze_strength = 16.0f;
|
|
float _shadow_darkness = 0.5f, _shadow_blur = 0.001f;
|
|
float _wind_power = 1.0f;
|
|
|
|
public:
|
|
EnvironmentGUI() : ImGuiPanel("Environment/Sky")
|
|
{
|
|
DateTime now;
|
|
_hour = now.hours(), _day = now.day(), _month = now.month(), _year = now.year();
|
|
}
|
|
|
|
void load(const Config& conf) override
|
|
{
|
|
conf.get("ShowDetails", _showDetails);
|
|
//conf.get("Hour", _hour);
|
|
//conf.get("Day", _day);
|
|
//conf.get("Month", _month);
|
|
//conf.get("Year", _year);
|
|
conf.get("Exposure", _exposure);
|
|
conf.get("Contrast", _contrast);
|
|
conf.get("Ambient", _ambient);
|
|
conf.get("HazeCutoff", _haze_cutoff);
|
|
conf.get("HazeStrength", _haze_strength);
|
|
conf.get("WindPower", _wind_power);
|
|
}
|
|
void save(Config& conf) override
|
|
{
|
|
conf.set("ShowDetails", _showDetails);
|
|
//conf.set("Hour", _hour);
|
|
//conf.set("Day", _day);
|
|
//conf.set("Month", _month);
|
|
//conf.set("Year", _year);
|
|
conf.set("Exposure", _exposure);
|
|
conf.set("Contrast", _contrast);
|
|
conf.set("Ambient", _ambient);
|
|
conf.set("HazeCutoff", _haze_cutoff);
|
|
conf.set("HazeStrength", _haze_strength);
|
|
conf.set("WindPower", _wind_power);
|
|
}
|
|
|
|
void draw(osg::RenderInfo& ri) override
|
|
{
|
|
if (!isVisible() || !findNodeOrHide(_mapNode, ri))
|
|
return;
|
|
|
|
if (ImGui::Begin(name(), visible()))
|
|
{
|
|
if (!findNode(_skyNode, ri))
|
|
{
|
|
ImGui::Text("No Sky installed.");
|
|
if (ImGui::Button("Install"))
|
|
{
|
|
auto sky = SkyNode::create();
|
|
auto parent = _mapNode->getParent(0);
|
|
sky->addChild(_mapNode.get());
|
|
parent->addChild(sky);
|
|
parent->removeChild(_mapNode.get());
|
|
sky->attach(view(ri));
|
|
}
|
|
ImGui::End();
|
|
return;
|
|
}
|
|
|
|
if (_first)
|
|
{
|
|
findNode(_shadowCaster, ri);
|
|
if (_shadowCaster.valid())
|
|
_shadows = _shadowCaster->getEnabled();
|
|
|
|
findLayer(_windLayer, ri);
|
|
|
|
_skyNode->setDateTime(DateTime(_year, _month, _day, _hour));
|
|
|
|
// so we can visualize tiume-series layers.
|
|
_skyNode->setSimulationTimeTracksDateTime(true);
|
|
}
|
|
|
|
bool lighting = _skyNode->getLighting();
|
|
ImGui::Checkbox("Lighting", &lighting);
|
|
_skyNode->setLighting(lighting);
|
|
|
|
if (_shadowCaster.valid()) {
|
|
ImGui::SameLine();
|
|
ImGui::Checkbox("Shadows", &_shadows);
|
|
_shadowCaster->setEnabled(_shadows);
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
if (ImGui::Checkbox("Details", &_showDetails)) dirtySettings();
|
|
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Now")) {
|
|
_skyNode->setDateTime(DateTime());
|
|
dirtySettings();
|
|
}
|
|
|
|
ImGui::Separator();
|
|
if (ImGuiLTable::Begin("Environment"))
|
|
{
|
|
ImGuiLTable::Section("Date & Time:");
|
|
|
|
auto mark = _skyNode->getDateTime();
|
|
auto day = mark.day();
|
|
auto month = mark.month();
|
|
auto year = mark.year();
|
|
auto hour = mark.hours();
|
|
|
|
if (ImGuiLTable::SliderDouble("Hour (UTC)", &hour, 0.0f, 24.0f))
|
|
_hour = hour, dirtySettings();
|
|
|
|
if (_showDetails)
|
|
{
|
|
if (ImGuiLTable::SliderInt("Day", &day, 1, 31))
|
|
_day = day, dirtySettings();
|
|
if (ImGuiLTable::SliderInt("Month", &month, 1, 12))
|
|
_month = month, dirtySettings();
|
|
if (ImGuiLTable::SliderInt("Year", &year, 1970, 2061))
|
|
_year = year, dirtySettings();
|
|
}
|
|
_skyNode->setDateTime(DateTime(year, month, day, hour));
|
|
|
|
if (lighting)
|
|
{
|
|
if (ImGuiLTable::SliderFloat("Exposure", &_exposure, 1.0f, 10.0f)) dirtySettings();
|
|
_skyNode->getOrCreateStateSet()->getOrCreateUniform("oe_sky_exposure", osg::Uniform::FLOAT)->set(_exposure);
|
|
|
|
if (ImGuiLTable::SliderFloat("Ambient min", &_ambient, 0.0f, 1.0f)) dirtySettings();
|
|
_skyNode->getSunLight()->setAmbient(osg::Vec4(_ambient, _ambient, _ambient, 1.0f));
|
|
|
|
if (ImGuiLTable::SliderFloat("Ambient max", &_max_ambient_intensity, 0.0f, 1.0f)) dirtySettings();
|
|
_skyNode->getOrCreateStateSet()->getOrCreateUniform("oe_sky_maxAmbientIntensity", osg::Uniform::FLOAT)->set(_max_ambient_intensity);
|
|
|
|
auto diffuse_color = _skyNode->getSunLight()->getDiffuse();
|
|
if (ImGuiLTable::ColorEdit3("Diffuse color", &diffuse_color[0], ImGuiColorEditFlags_Float)) {
|
|
_skyNode->getSunLight()->setDiffuse(diffuse_color);
|
|
dirtySettings();
|
|
}
|
|
|
|
static float normal_boost = 1.0f;
|
|
if (ImGuiLTable::SliderFloat("Normal boost", &normal_boost, 1.0f, 5.0f)) {
|
|
_skyNode->getOrCreateStateSet()->getOrCreateUniform("oe_normal_boost", osg::Uniform::FLOAT)->set(normal_boost);
|
|
dirtySettings();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_shadows = false;
|
|
}
|
|
|
|
if (_windLayer.valid())
|
|
{
|
|
ImGui::Separator();
|
|
ImGuiLTable::Section("Wind");
|
|
|
|
if (ImGuiLTable::SliderFloat("Speed mult", &_wind_power, 0.0f, 9.0f, "%.1f", 0) || _first)
|
|
{
|
|
stateset(ri)->addUniform(new osg::Uniform("oe_wind_power", _wind_power),
|
|
osg::StateAttribute::OVERRIDE | 0x01);
|
|
dirtySettings();
|
|
}
|
|
|
|
static bool show_wind = false;
|
|
if (ImGuiLTable::Checkbox("Debug view", &show_wind))
|
|
{
|
|
if (show_wind)
|
|
ShaderLoader::load(VirtualProgram::getOrCreate(stateset(ri)), render_wind);
|
|
else
|
|
ShaderLoader::unload(VirtualProgram::getOrCreate(stateset(ri)), render_wind);
|
|
}
|
|
}
|
|
|
|
if (_showDetails)
|
|
{
|
|
ImGui::Separator();
|
|
ImGuiLTable::Section("Details");
|
|
|
|
if (_shadows)
|
|
{
|
|
if (ImGuiLTable::SliderFloat("Shadow darkness", &_shadow_darkness, 0.0f, 1.0f))
|
|
stateset(ri)->addUniform(new osg::Uniform("oe_shadow_color", _shadow_darkness), 0x7);
|
|
|
|
if (ImGuiLTable::SliderFloat("Shadow blur", &_shadow_blur, 0.0f, 0.002f))
|
|
stateset(ri)->addUniform(new osg::Uniform("oe_shadow_blur", _shadow_blur), 0x07);
|
|
}
|
|
|
|
if (ImGuiLTable::SliderFloat("Haze cutoff", &_haze_cutoff, 0.0f, 0.2f))
|
|
dirtySettings();
|
|
_skyNode->getOrCreateStateSet()->getOrCreateUniform("atmos_haze_cutoff", osg::Uniform::FLOAT)->set(_haze_cutoff);
|
|
|
|
if (ImGuiLTable::SliderFloat("Haze strength", &_haze_strength, 0.0f, 24.0f))
|
|
dirtySettings();
|
|
_skyNode->getOrCreateStateSet()->getOrCreateUniform("atmos_haze_strength", osg::Uniform::FLOAT)->set(_haze_strength);
|
|
|
|
bool atmos_visible = _skyNode->getAtmosphereVisible();
|
|
ImGuiLTable::Checkbox("Atmosphere", &atmos_visible);
|
|
_skyNode->setAtmosphereVisible(atmos_visible);
|
|
|
|
bool sun_visible = _skyNode->getSunVisible();
|
|
ImGuiLTable::Checkbox("Sun", &sun_visible);
|
|
_skyNode->setSunVisible(sun_visible);
|
|
|
|
bool moon_visible = _skyNode->getMoonVisible();
|
|
ImGuiLTable::Checkbox("Moon", &moon_visible);
|
|
_skyNode->setMoonVisible(moon_visible);
|
|
|
|
bool stars_visible = _skyNode->getStarsVisible();
|
|
ImGuiLTable::Checkbox("Stars", &stars_visible);
|
|
_skyNode->setStarsVisible(stars_visible);
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
DateTime dt = _skyNode->getDateTime();
|
|
|
|
CelestialBody sun = _skyNode->getEphemeris()->getSunPosition(dt);
|
|
ImGuiLTable::Text("Sun:", "RA (%.2f) Decl (%.2f)",
|
|
sun.rightAscension.as(Units::DEGREES),
|
|
sun.declination.as(Units::DEGREES));
|
|
|
|
CelestialBody moon = _skyNode->getEphemeris()->getMoonPosition(dt);
|
|
ImGuiLTable::Text("Moon:", "RA (%.2f) Decl (%.2f)",
|
|
moon.rightAscension.as(Units::DEGREES),
|
|
moon.declination.as(Units::DEGREES));
|
|
}
|
|
|
|
ImGuiLTable::End();
|
|
}
|
|
|
|
_first = false;
|
|
}
|
|
ImGui::End();
|
|
}
|
|
};
|
|
}
|