diff --git a/TODO b/TODO index fd9d5dd..1af76b4 100644 --- a/TODO +++ b/TODO @@ -9,11 +9,6 @@ Technology Preview 2 : - Finalize Preetham's model usage => Apply model to atmosphere (aerial perspective) => Find a proper model for night sky (maybe Shirley) -- Merge atmosphere and sky in a coherent model. - => All stopper rendering (terrain, water and skydome) should pass through an atmosphere walker. - => The atmosphere walker collects callbacks (clouds, water...) to alter the medium. - => God rays are possible with particle lighting through the walker. -- Keep skydome lights in cache for a render. - Clouds should keep distance to ground. - Rethink the quality settings and detail smoothing in the distance. => When quality setting is set to 10, add boost options diff --git a/gui_qt/explorerchunksky.cpp b/gui_qt/explorerchunksky.cpp index 07c1e98..1449571 100644 --- a/gui_qt/explorerchunksky.cpp +++ b/gui_qt/explorerchunksky.cpp @@ -4,9 +4,8 @@ #include "baseexplorerchunk.h" #include "../lib_paysages/camera.h" -ExplorerChunkSky::ExplorerChunkSky(Renderer* renderer, SkyDefinition* sky, double size, SkyboxOrientation orientation) : BaseExplorerChunk(renderer) +ExplorerChunkSky::ExplorerChunkSky(Renderer* renderer, double size, SkyboxOrientation orientation) : BaseExplorerChunk(renderer) { - _sky = sky; _box_size = size; _orientation = orientation; @@ -131,5 +130,5 @@ Color ExplorerChunkSky::getTextureColor(double x, double y) location.z = y; break; } - return skyGetColor(_sky, renderer(), VECTOR_ZERO, v3Normalize(location)); + return renderer()->atmosphere->getSkyColor(renderer(), v3Normalize(location)); } diff --git a/gui_qt/explorerchunksky.h b/gui_qt/explorerchunksky.h index 838acf7..391dd66 100644 --- a/gui_qt/explorerchunksky.h +++ b/gui_qt/explorerchunksky.h @@ -4,7 +4,6 @@ #include "baseexplorerchunk.h" #include "../lib_paysages/renderer.h" #include "../lib_paysages/euclid.h" -#include "../lib_paysages/sky.h" enum SkyboxOrientation { @@ -19,14 +18,13 @@ enum SkyboxOrientation class ExplorerChunkSky:public BaseExplorerChunk { public: - ExplorerChunkSky(Renderer* renderer, SkyDefinition* sky, double size, SkyboxOrientation orientation); + ExplorerChunkSky(Renderer* renderer, double size, SkyboxOrientation orientation); void onRenderEvent(QGLWidget* widget); double getDisplayedSizeHint(CameraDefinition* camera); Color getTextureColor(double x, double y); private: - SkyDefinition* _sky; SkyboxOrientation _orientation; double _box_size; diff --git a/gui_qt/formatmosphere.cpp b/gui_qt/formatmosphere.cpp index 1c13eda..84b3bf8 100644 --- a/gui_qt/formatmosphere.cpp +++ b/gui_qt/formatmosphere.cpp @@ -1,91 +1,131 @@ #include "formatmosphere.h" #include "tools.h" -#include "../lib_paysages/atmosphere.h" -#include "../lib_paysages/scenery.h" -#include "../lib_paysages/euclid.h" -#include "../lib_paysages/color.h" -static AtmosphereDefinition _definition; +#include +#include +#include + +#include "../lib_paysages/atmosphere/atmosphere.h" +#include "../lib_paysages/scenery.h" +#include "../lib_paysages/renderer.h" + +static AtmosphereDefinition* _definition; /**************** Previews ****************/ -class PreviewAtmosphereColor:public BasePreview +class PreviewSkyEast:public BasePreview { public: - PreviewAtmosphereColor(QWidget* parent): + PreviewSkyEast(QWidget* parent): BasePreview(parent) { _renderer = rendererCreate(); - _preview_definition = atmosphereCreateDefinition(); - configScaling(100.0, 1000.0, 20.0, 200.0); + configScaling(0.5, 5.0, 0.5, 2.5); } protected: QColor getColor(double x, double y) { - Vector3 eye, look, location; - - eye.x = 0.0; - eye.y = scaling * 5.0; - eye.z = -10.0 * scaling; - _renderer.camera_location = eye; - look.x = x * 0.01 / scaling; - look.y = -y * 0.01 / scaling - 0.3; - look.z = 1.0; - look = v3Normalize(look); - - if (look.y > -0.0001) + y -= 100.0 * scaling; + if (y > 0.0) { - return colorToQColor(COLOR_BLUE); + return QColor(0, 0, 0); } + else + { + Vector3 look; - location.x = eye.x - look.x * eye.y / look.y; - location.y = 0.0; - location.z = eye.z - look.z * eye.y / look.y; + look.x = 1.0; + look.y = -y; + look.z = x; - return colorToQColor(atmosphereApply(&_preview_definition, &_renderer, location, COLOR_BLACK)); + return colorToQColor(_renderer.atmosphere->getSkyColor(&_renderer, look)); + } } void updateData() { - atmosphereCopyDefinition(&_definition, &_preview_definition); + AtmosphereRendererClass.bind(_renderer.atmosphere, _definition); + } +private: + Renderer _renderer; +}; + +class PreviewSkyWest:public BasePreview +{ +public: + PreviewSkyWest(QWidget* parent): + BasePreview(parent) + { + _renderer = rendererCreate(); + + configScaling(0.5, 5.0, 0.5, 2.5); + } +protected: + QColor getColor(double x, double y) + { + y -= 100.0 * scaling; + if (y > 0.0) + { + return QColor(0, 0, 0); + } + else + { + Vector3 look; + + look.x = -1.0; + look.y = -y; + look.z = -x; + + return colorToQColor(_renderer.atmosphere->getSkyColor(&_renderer, look)); + } + } + void updateData() + { + AtmosphereRendererClass.bind(_renderer.atmosphere, _definition); } private: Renderer _renderer; - AtmosphereDefinition _preview_definition; }; /**************** Form ****************/ FormAtmosphere::FormAtmosphere(QWidget *parent): BaseForm(parent) { - _definition = atmosphereCreateDefinition(); + BaseInput* input; + + _definition = (AtmosphereDefinition*)AtmosphereDefinitionClass.create(); - previewColor = new PreviewAtmosphereColor(this); - addPreview(previewColor, QString(tr("Color preview"))); + previewWest = new PreviewSkyWest(this); + addPreview(previewWest, QString(tr("West preview"))); + previewEast = new PreviewSkyEast(this); + addPreview(previewEast, QString(tr("East preview"))); - addInputDouble(tr("Start distance"), &_definition.distance_near, -500.0, 500.0, 5.0, 50.0); - addInputDouble(tr("End distance"), &_definition.distance_far, -500.0, 500.0, 5.0, 50.0); - addInputDouble(tr("Masking power"), &_definition.full_mask, 0.0, 1.0, 0.01, 0.1); - addInputBoolean(tr("Lock on horizon color"), &_definition.auto_lock_on_haze); - addInputColor(tr("Color"), &_definition.color)->setEnabledCondition(&_definition.auto_lock_on_haze, 0); + addInputEnum(tr("Color model"), (int*)&_definition->model, QStringList(tr("Preetham/Shirley analytic model")) << tr("Bruneton/Neyret precomputed model")); + addInputDouble(tr("Day time"), &_definition->daytime, 0.14, 0.86, 0.002, 0.1); + addInputColor(tr("Sun color"), &_definition->sun_color); + addInputDouble(tr("Sun radius"), &_definition->sun_radius, 0.0, 0.4, 0.004, 0.04); + addInputDouble(tr("Sun halo radius"), &_definition->sun_halo_size, 0.0, 0.4, 0.004, 0.04); + addInputCurve(tr("Sun halo profile"), _definition->sun_halo_profile, 0.0, 1.0, 0.0, 1.0, tr("Distance to center of the sun"), tr("Light influence (halo opacity)")); + addInputDouble(tr("Influence of skydome on lighting"), &_definition->dome_lighting, 0.0, 2.0, 0.01, 0.1); + input = addInputDouble(tr("Humidity"), &_definition->humidity, 1.8, 6.0, 0.05, 0.5); revertConfig(); } void FormAtmosphere::revertConfig() { - sceneryGetAtmosphere(&_definition); + sceneryGetAtmosphere(_definition); BaseForm::revertConfig(); } void FormAtmosphere::applyConfig() { - scenerySetAtmosphere(&_definition); + scenerySetAtmosphere(_definition); BaseForm::applyConfig(); } void FormAtmosphere::configChangeEvent() { - atmosphereValidateDefinition(&_definition); + AtmosphereDefinitionClass.validate(_definition); BaseForm::configChangeEvent(); } diff --git a/gui_qt/formatmosphere.h b/gui_qt/formatmosphere.h index 52d6347..ba28f38 100644 --- a/gui_qt/formatmosphere.h +++ b/gui_qt/formatmosphere.h @@ -20,7 +20,8 @@ protected slots: virtual void configChangeEvent(); private: - BasePreview* previewColor; + BasePreview* previewEast; + BasePreview* previewWest; }; #endif diff --git a/gui_qt/formrender.cpp b/gui_qt/formrender.cpp index 4d975db..62c7bdf 100644 --- a/gui_qt/formrender.cpp +++ b/gui_qt/formrender.cpp @@ -19,7 +19,6 @@ public: _renderer.getTerrainHeight = _getTerrainHeight; _renderer.alterLight = _alterLight; _renderer.getLightStatus = _getLightStatus; - _renderer.getSkyDomeLights = _getSkyDomeLights; _renderer.camera_location.x = 0.0; _renderer.camera_location.y = 50.0; _renderer.camera_location.z = 0.0; @@ -28,13 +27,12 @@ public: _textures = texturesCreateDefinition(); _lighting = lightingCreateDefinition(); _water = waterCreateDefinition(); - _sky = skyCreateDefinition(); + _atmosphere = (AtmosphereDefinition*)AtmosphereDefinitionClass.create(); _renderer.customData[0] = &_terrain; _renderer.customData[1] = &_textures; _renderer.customData[2] = &_lighting; _renderer.customData[3] = &_water; - _renderer.customData[4] = &_sky; addOsd(QString("geolocation")); @@ -66,7 +64,9 @@ protected: sceneryGetLighting(&_lighting); sceneryGetTextures(&_textures); sceneryGetWater(&_water); - sceneryGetSky(&_sky); + + sceneryGetAtmosphere(_atmosphere); + AtmosphereRendererClass.bind(_renderer.atmosphere, _atmosphere); } private: Renderer _renderer; @@ -74,7 +74,7 @@ private: WaterDefinition _water; TexturesDefinition _textures; LightingDefinition _lighting; - SkyDefinition _sky; + AtmosphereDefinition* _atmosphere; static double _getTerrainHeight(Renderer* renderer, double x, double z) { @@ -86,11 +86,6 @@ private: return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision); } - static int _getSkyDomeLights(Renderer* renderer, LightDefinition* array, int max_lights) - { - return skyGetLights((SkyDefinition*)(renderer->customData[4]), renderer, array, max_lights); - } - static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location) { light->color = terrainLightFilter((TerrainDefinition*)(renderer->customData[0]), renderer, light->color, location, v3Scale(light->direction, -1000.0), v3Scale(light->direction, -1.0)); diff --git a/gui_qt/formsky.cpp b/gui_qt/formsky.cpp deleted file mode 100644 index 1a7a16c..0000000 --- a/gui_qt/formsky.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include "formsky.h" - -#include "tools.h" - -#include -#include -#include - -#include "../lib_paysages/sky.h" -#include "../lib_paysages/scenery.h" -#include "../lib_paysages/renderer.h" - -static SkyDefinition _definition; - -/**************** Previews ****************/ -class PreviewSkyEast:public BasePreview -{ -public: - PreviewSkyEast(QWidget* parent): - BasePreview(parent) - { - _renderer = rendererCreate(); - _preview_definition = skyCreateDefinition(); - - configScaling(0.5, 5.0, 0.5, 2.5); - } -protected: - QColor getColor(double x, double y) - { - y -= 100.0 * scaling; - if (y > 0.0) - { - return QColor(0, 0, 0); - } - else - { - Vector3 eye = {0.0, 0.0, 0.0}; - Vector3 look; - - look.x = 1.0; - look.y = -y; - look.z = x; - - return colorToQColor(skyGetColor(&_preview_definition, &_renderer, eye, look)); - } - } - void updateData() - { - skyCopyDefinition(&_definition, &_preview_definition); - } -private: - Renderer _renderer; - SkyDefinition _preview_definition; -}; - -class PreviewSkyWest:public BasePreview -{ -public: - PreviewSkyWest(QWidget* parent): - BasePreview(parent) - { - _renderer = rendererCreate(); - _preview_definition = skyCreateDefinition(); - - configScaling(0.5, 5.0, 0.5, 2.5); - } -protected: - QColor getColor(double x, double y) - { - y -= 100.0 * scaling; - if (y > 0.0) - { - return QColor(0, 0, 0); - } - else - { - Vector3 eye = {0.0, 0.0, 0.0}; - Vector3 look; - - look.x = -1.0; - look.y = -y; - look.z = -x; - - return colorToQColor(skyGetColor(&_preview_definition, &_renderer, eye, look)); - } - } - void updateData() - { - skyCopyDefinition(&_definition, &_preview_definition); - } -private: - Renderer _renderer; - SkyDefinition _preview_definition; -}; - -/**************** Form ****************/ -FormSky::FormSky(QWidget *parent): - BaseForm(parent) -{ - BaseInput* input; - - _definition = skyCreateDefinition(); - - previewWest = new PreviewSkyWest(this); - addPreview(previewWest, QString(tr("West preview"))); - previewEast = new PreviewSkyEast(this); - addPreview(previewEast, QString(tr("East preview"))); - - addInputEnum(tr("Color model"), (int*)&_definition.model, QStringList(tr("Custom model")) << tr("Rayleigh/Mie scattering") << tr("Preetham/Shirley analytic model")); - addInputDouble(tr("Day time"), &_definition.daytime, 0.14, 0.86, 0.002, 0.1); - addInputColor(tr("Sun color"), &_definition.sun_color); - addInputDouble(tr("Sun radius"), &_definition.sun_radius, 0.0, 0.4, 0.004, 0.04); - addInputDouble(tr("Sun halo radius"), &_definition.sun_halo_size, 0.0, 0.4, 0.004, 0.04); - addInputCurve(tr("Sun halo profile"), _definition.sun_halo_profile, 0.0, 1.0, 0.0, 1.0, tr("Distance to center of the sun"), tr("Light influence (halo opacity)")); - addInputDouble(tr("Influence of skydome on lighting"), &_definition.dome_lighting, 0.0, 2.0, 0.01, 0.1); - input = addInputBoolean(tr("Auto colors from daytime"), &_definition.model_custom.auto_from_daytime); - input->setVisibilityCondition((int*)&_definition.model, SKY_MODEL_CUSTOM); - input = addInputColor(tr("Zenith color"), &_definition.model_custom.zenith_color); - input->setVisibilityCondition((int*)&_definition.model, SKY_MODEL_CUSTOM); - input->setEnabledCondition(&_definition.model_custom.auto_from_daytime, 0); - input = addInputColor(tr("Haze color"), &_definition.model_custom.haze_color); - input->setVisibilityCondition((int*)&_definition.model, SKY_MODEL_CUSTOM); - input->setEnabledCondition(&_definition.model_custom.auto_from_daytime, 0); - input = addInputDouble(tr("Haze height"), &_definition.model_custom.haze_height, 0.0, 1.0, 0.01, 0.1); - input->setVisibilityCondition((int*)&_definition.model, SKY_MODEL_CUSTOM); - input = addInputDouble(tr("Haze smoothing"), &_definition.model_custom.haze_smoothing, 0.0, 1.0, 0.01, 0.1); - input->setVisibilityCondition((int*)&_definition.model, SKY_MODEL_CUSTOM); - input = addInputDouble(tr("Turbidity"), &_definition.model_preetham.turbidity, 1.8, 6.0, 0.05, 0.5); - input->setVisibilityCondition((int*)&_definition.model, SKY_MODEL_PREETHAM); - - revertConfig(); -} - -void FormSky::revertConfig() -{ - sceneryGetSky(&_definition); - BaseForm::revertConfig(); -} - -void FormSky::applyConfig() -{ - scenerySetSky(&_definition); - BaseForm::applyConfig(); -} - -void FormSky::configChangeEvent() -{ - skyValidateDefinition(&_definition); - - if (_definition.model == SKY_MODEL_CUSTOM && _definition.model_custom.auto_from_daytime) - { - BaseForm::revertConfig(); - } - - BaseForm::configChangeEvent(); -} diff --git a/gui_qt/formsky.h b/gui_qt/formsky.h deleted file mode 100644 index e3142bf..0000000 --- a/gui_qt/formsky.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _PAYSAGES_QT_FORMSKY_H_ -#define _PAYSAGES_QT_FORMSKY_H_ - -#include -#include "basepreview.h" -#include "baseform.h" - -class FormSky : public BaseForm -{ - Q_OBJECT - -public: - explicit FormSky(QWidget *parent = 0); - -public slots: - virtual void revertConfig(); - virtual void applyConfig(); - -protected slots: - virtual void configChangeEvent(); - -private: - BasePreview* previewEast; - BasePreview* previewWest; -}; - -#endif diff --git a/gui_qt/mainwindow.cpp b/gui_qt/mainwindow.cpp index 5a7462d..4aab54b 100644 --- a/gui_qt/mainwindow.cpp +++ b/gui_qt/mainwindow.cpp @@ -12,10 +12,9 @@ #include #include "basepreview.h" -#include "formatmosphere.h" #include "formclouds.h" #include "formlighting.h" -#include "formsky.h" +#include "formatmosphere.h" #include "formterrain.h" #include "formtextures.h" #include "formwater.h" @@ -93,11 +92,6 @@ QMainWindow(parent) QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection); _forms.append(form); - form = new FormSky(tabs); - tabs->addTab(form, tr("Sky")); - QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection); - _forms.append(form); - form = new FormAtmosphere(tabs); tabs->addTab(form, tr("Atmosphere")); QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection); diff --git a/gui_qt/widgetexplorer.cpp b/gui_qt/widgetexplorer.cpp index fb6dbd6..0e60c5d 100644 --- a/gui_qt/widgetexplorer.cpp +++ b/gui_qt/widgetexplorer.cpp @@ -58,11 +58,6 @@ static Color _applyTextures(Renderer* renderer, Vector3 location, double precisi return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision); } -static int _getSkyDomeLights(Renderer* renderer, LightDefinition* array, int max_lights) -{ - return skyGetLights((SkyDefinition*)(renderer->customData[4]), renderer, array, max_lights); -} - static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location) { light->color = terrainLightFilter((TerrainDefinition*)(renderer->customData[0]), renderer, light->color, location, v3Scale(light->direction, -1000.0), v3Scale(light->direction, -1.0)); @@ -84,8 +79,6 @@ WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera): _water = waterCreateDefinition(); sceneryGetWater(&_water); - _sky = skyCreateDefinition(); - sceneryGetSky(&_sky); _terrain = terrainCreateDefinition(); sceneryGetTerrain(&_terrain); _textures = texturesCreateDefinition(); @@ -93,16 +86,14 @@ WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera): _lighting = lightingCreateDefinition(); sceneryGetLighting(&_lighting); - _renderer = rendererCreate(); + _renderer = sceneryCreateStandardRenderer(); _renderer.render_quality = 3; _renderer.customData[0] = &_terrain; _renderer.customData[1] = &_textures; _renderer.customData[2] = &_lighting; _renderer.customData[3] = &_water; - _renderer.customData[4] = &_sky; _renderer.applyTextures = _applyTextures; _renderer.getTerrainHeight = _getTerrainHeight; - _renderer.getSkyDomeLights = _getSkyDomeLights; _renderer.alterLight = _alterLight; _renderer.getLightStatus = _getLightStatus; @@ -126,7 +117,7 @@ WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera): // Add skybox for (int orientation = 0; orientation < 6; orientation++) { - ExplorerChunkSky* chunk = new ExplorerChunkSky(&_renderer, &_sky, 500.0, (SkyboxOrientation)orientation); + ExplorerChunkSky* chunk = new ExplorerChunkSky(&_renderer, 500.0, (SkyboxOrientation)orientation); _chunks.append(chunk); _updateQueue.append(chunk); } @@ -437,8 +428,7 @@ void WidgetExplorer::paintGL() gluLookAt(_current_camera.location.x, _current_camera.location.y, _current_camera.location.z, _current_camera.target.x, _current_camera.target.y, _current_camera.target.z, _current_camera.up.x, _current_camera.up.y, _current_camera.up.z); // Background - Color zenith_color = skyGetZenithColor(&_sky); - glClearColor(zenith_color.r, zenith_color.g, zenith_color.b, 0.0); + glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Render water diff --git a/gui_qt/widgetexplorer.h b/gui_qt/widgetexplorer.h index 18149fa..28d314b 100644 --- a/gui_qt/widgetexplorer.h +++ b/gui_qt/widgetexplorer.h @@ -6,7 +6,6 @@ #include "../lib_paysages/camera.h" #include "../lib_paysages/water.h" #include "../lib_paysages/renderer.h" -#include "../lib_paysages/sky.h" #include "../lib_paysages/terrain.h" #include "../lib_paysages/textures.h" #include "../lib_paysages/lighting.h" @@ -51,7 +50,6 @@ private: QMutex _lock_chunks; WaterDefinition _water; - SkyDefinition _sky; TerrainDefinition _terrain; TexturesDefinition _textures; LightingDefinition _lighting; diff --git a/lib_paysages/Makefile b/lib_paysages/Makefile index b107f59..854b8da 100644 --- a/lib_paysages/Makefile +++ b/lib_paysages/Makefile @@ -1,9 +1,9 @@ BUILDMODE = debug BUILDPATH = ../build/${BUILDMODE} OBJPATH = ./obj/${BUILDMODE} -SOURCES = $(wildcard *.c) +SOURCES = $(wildcard *.c atmosphere/*.c) OBJECTS = ${SOURCES:%.c=${OBJPATH}/%.o} -HEADERS = $(wildcard shared/*.h *.h) +HEADERS = $(wildcard shared/*.h atmosphere/*.h *.h) RESULT = ${BUILDPATH}/libpaysages.so CC_FLAGS = -Wall -fPIC $(shell pkg-config --cflags glib-2.0 gthread-2.0) -DHAVE_GLIB=1 CC_LDFLAGS = $(shell pkg-config --libs glib-2.0 gthread-2.0) -lIL -lILU @@ -27,6 +27,7 @@ clean: rm -f ${RESULT} ${OBJPATH}/%.o:%.c ${HEADERS} + mkdir -p `dirname $@` ${CC} -c ${CC_FLAGS} $< -o $@ ${RESULT}:${OBJECTS} diff --git a/lib_paysages/atmosphere.c b/lib_paysages/atmosphere.c deleted file mode 100644 index 101e2d5..0000000 --- a/lib_paysages/atmosphere.c +++ /dev/null @@ -1,104 +0,0 @@ -#include "atmosphere.h" - -#include "scenery.h" -#include "euclid.h" -#include "color.h" -#include "tools.h" - -void atmosphereSave(PackStream* stream, AtmosphereDefinition* definition) -{ - packWriteDouble(stream, &definition->distance_near); - packWriteDouble(stream, &definition->distance_far); - packWriteDouble(stream, &definition->full_mask); - packWriteInt(stream, &definition->auto_lock_on_haze); - colorSave(stream, &definition->color); -} - -void atmosphereLoad(PackStream* stream, AtmosphereDefinition* definition) -{ - packReadDouble(stream, &definition->distance_near); - packReadDouble(stream, &definition->distance_far); - packReadDouble(stream, &definition->full_mask); - packReadInt(stream, &definition->auto_lock_on_haze); - colorLoad(stream, &definition->color); - - atmosphereValidateDefinition(definition); -} - -AtmosphereDefinition atmosphereCreateDefinition() -{ - AtmosphereDefinition definition; - - definition.distance_near = 0.0; - definition.distance_far = 1.0; - definition.full_mask = 0.0; - definition.auto_lock_on_haze = 0; - definition.color = COLOR_BLACK; - - atmosphereValidateDefinition(&definition); - - return definition; -} - -void atmosphereDeleteDefinition(AtmosphereDefinition* definition) -{ -} - -void atmosphereCopyDefinition(AtmosphereDefinition* source, AtmosphereDefinition* destination) -{ - *destination = *source; -} - -void atmosphereValidateDefinition(AtmosphereDefinition* definition) -{ - SkyDefinition sky; - - if (definition->distance_far <= definition->distance_near) - { - definition->distance_far = definition->distance_near + 1.0; - } - if (definition->full_mask < 0.0) - { - definition->full_mask = 0.0; - } - if (definition->full_mask > 1.0) - { - definition->full_mask = 1.0; - } - if (definition->auto_lock_on_haze) - { - sky = skyCreateDefinition(); - sceneryGetSky(&sky); - definition->color = skyGetHorizonColor(&sky); - skyDeleteDefinition(&sky); - } -} - -Color atmosphereApply(AtmosphereDefinition* definition, Renderer* renderer, Vector3 location, Color base) -{ - Color mask = definition->color; - double distance = v3Norm(v3Sub(renderer->camera_location, location)); - double value; - double alpha; - - if (distance < definition->distance_near) - { - return base; - } - else if (distance > definition->distance_far) - { - distance = definition->distance_far; - } - - alpha = base.a; - base.a = 1.0; - - value = definition->full_mask * (distance - definition->distance_near) / (definition->distance_far - definition->distance_near); - - mask.a = value; - colorMask(&base, &mask); - - base.a = alpha; - - return base; -} diff --git a/lib_paysages/atmosphere.h b/lib_paysages/atmosphere.h deleted file mode 100644 index 1ec855f..0000000 --- a/lib_paysages/atmosphere.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _PAYSAGES_ATMOSPHERE_H_ -#define _PAYSAGES_ATMOSPHERE_H_ - -#include "shared/types.h" -#include "pack.h" -#include "lighting.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - double distance_near; - double distance_far; - double full_mask; - int auto_lock_on_haze; - Color color; -} AtmosphereDefinition; - -void atmosphereSave(PackStream* stream, AtmosphereDefinition* definition); -void atmosphereLoad(PackStream* stream, AtmosphereDefinition* definition); - -AtmosphereDefinition atmosphereCreateDefinition(); -void atmosphereDeleteDefinition(AtmosphereDefinition* definition); -void atmosphereCopyDefinition(AtmosphereDefinition* source, AtmosphereDefinition* destination); -void atmosphereValidateDefinition(AtmosphereDefinition* definition); - -Color atmosphereApply(AtmosphereDefinition* definition, Renderer* renderer, Vector3 location, Color base); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib_paysages/atmosphere/atmosphere.c b/lib_paysages/atmosphere/atmosphere.c new file mode 100644 index 0000000..e2a3763 --- /dev/null +++ b/lib_paysages/atmosphere/atmosphere.c @@ -0,0 +1,407 @@ +#include "atmosphere.h" + +#include +#include +#include +#include "../tools.h" +#include "../renderer.h" +#include "../lighting.h" +#include "../system.h" + +#define SPHERE_SIZE 1000.0 +#define MAX_SKYDOME_LIGHTS 100 + +typedef struct +{ + Mutex* lock; + int nblights; + LightDefinition lights[MAX_SKYDOME_LIGHTS]; +} AtmosphereRendererCache; + +/******************** Definition ********************/ +static void _validateDefinition(AtmosphereDefinition* definition) +{ + UNUSED(definition); +} + +static AtmosphereDefinition* _createDefinition() +{ + AtmosphereDefinition* result; + + result = malloc(sizeof(AtmosphereDefinition)); + result->model = ATMOSPHERE_MODEL_PREETHAM; + result->daytime = 0.0; + result->sun_color = COLOR_BLACK; + result->sun_color.r = 1.0; + result->sun_color.g = 0.95; + result->sun_color.b = 0.9; + result->sun_color.a = 1.0; + result->sun_radius = 0.02; + result->sun_halo_size = 0.3; + result->sun_halo_profile = curveCreate(); + curveQuickAddPoint(result->sun_halo_profile, 0.0, 1.0); + curveQuickAddPoint(result->sun_halo_profile, 0.1, 0.2); + curveQuickAddPoint(result->sun_halo_profile, 1.0, 0.0); + result->dome_lighting = 0.6; + result->humidity = 2.0; + + _validateDefinition(result); + + return result; +} + +static void _deleteDefinition(AtmosphereDefinition* definition) +{ + curveDelete(definition->sun_halo_profile); + free(definition); +} + +static void _copyDefinition(AtmosphereDefinition* source, AtmosphereDefinition* destination) +{ + destination->model = source->model; + destination->daytime = source->daytime; + destination->sun_color = source->sun_color; + destination->sun_radius = source->sun_radius; + destination->sun_halo_size = source->sun_halo_size; + destination->dome_lighting = source->dome_lighting; + destination->humidity = source->humidity; + + curveCopy(source->sun_halo_profile, destination->sun_halo_profile); + + _validateDefinition(destination); +} + +static void _saveDefinition(PackStream* stream, AtmosphereDefinition* definition) +{ + packWriteInt(stream, (int*)&definition->model); + packWriteDouble(stream, &definition->daytime); + colorSave(stream, &definition->sun_color); + packWriteDouble(stream, &definition->sun_radius); + packWriteDouble(stream, &definition->sun_halo_size); + curveSave(stream, definition->sun_halo_profile); + packWriteDouble(stream, &definition->dome_lighting); + packWriteDouble(stream, &definition->humidity); +} + +static void _loadDefinition(PackStream* stream, AtmosphereDefinition* definition) +{ + packReadInt(stream, (int*)&definition->model); + packReadDouble(stream, &definition->daytime); + colorLoad(stream, &definition->sun_color); + packReadDouble(stream, &definition->sun_radius); + packReadDouble(stream, &definition->sun_halo_size); + curveLoad(stream, definition->sun_halo_profile); + packReadDouble(stream, &definition->dome_lighting); + packReadDouble(stream, &definition->humidity); + + _validateDefinition(definition); +} + +StandardDefinition AtmosphereDefinitionClass = { + (FuncObjectCreate)_createDefinition, + (FuncObjectDelete)_deleteDefinition, + (FuncObjectCopy)_copyDefinition, + (FuncObjectValidate)_validateDefinition, + (FuncObjectSave)_saveDefinition, + (FuncObjectLoad)_loadDefinition +}; + +/******************** Binding ********************/ +extern Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position); +extern Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position); + +static Color _fakeApplyAerialPerspective(Renderer* renderer, Vector3 direction, Color base) +{ + UNUSED(renderer); + UNUSED(direction); + return base; +} +static Color _fakeGetSkyColor(Renderer* renderer, Vector3 direction) +{ + UNUSED(renderer); + UNUSED(direction); + return COLOR_WHITE; +} +static int _fakeGetSkydomeLights(Renderer* renderer, LightDefinition* lights, int max_lights) +{ + UNUSED(renderer); + UNUSED(lights); + UNUSED(max_lights); + return 0; +} + +static Color _getSkyColor(Renderer* renderer, Vector3 direction) +{ + AtmosphereDefinition* definition; + double dist; + Vector3 sun_position; + Color sky_color, sun_color; + + definition = renderer->atmosphere->definition; + + sun_position = renderer->atmosphere->getSunDirection(renderer); + direction = v3Normalize(direction); + dist = v3Norm(v3Sub(direction, sun_position)); + + /* Get base scattering*/ + switch (definition->model) + { + case ATMOSPHERE_MODEL_BRUNETON: + sky_color = brunetonGetSkyColor(definition, renderer->camera_location, direction, sun_position); + break; + case ATMOSPHERE_MODEL_PREETHAM: + sky_color = preethamGetSkyColor(definition, renderer->camera_location, direction, sun_position); + break; + default: + sky_color = COLOR_BLUE; + } + + /* Get sun halo */ + if (dist < definition->sun_radius + definition->sun_halo_size) + { + sun_color = definition->sun_color; + if (dist <= definition->sun_radius) + { + return sun_color; + } + else + { + dist = (dist - definition->sun_radius) / definition->sun_halo_size; + sun_color.a = curveGetValue(definition->sun_halo_profile, dist); + colorMask(&sky_color, &sun_color); + return sky_color; + } + } + else + { + return sky_color; + } +} + +static Vector3 _getSunDirection(Renderer* renderer) +{ + Vector3 result; + double sun_angle = (renderer->atmosphere->definition->daytime + 0.75) * M_PI * 2.0; + result.x = cos(sun_angle); + result.y = sin(sun_angle); + result.z = 0.0; + return result; +} + +static inline void _addDomeLight(Renderer* renderer, LightDefinition* light, Vector3 direction, double factor) +{ + light->direction = v3Scale(direction, -1.0); + light->color = renderer->atmosphere->getSkyColor(renderer, direction); + light->color.r *= factor; + light->color.g *= factor; + light->color.b *= factor; + light->reflection = 0.0; + light->filtered = 0; + light->masked = 0; +} + +static int _getSkydomeLights(Renderer* renderer, LightDefinition* lights, int max_lights) +{ + AtmosphereRendererCache* cache = (AtmosphereRendererCache*)renderer->atmosphere->_internal_data; + AtmosphereDefinition* definition; + double sun_angle; + Vector3 sun_direction; + int nblights = 0; + + mutexAcquire(cache->lock); + if (cache->nblights < 0) + { + definition = renderer->atmosphere->definition; + + sun_angle = (definition->daytime + 0.75) * M_PI * 2.0; + sun_direction.x = cos(sun_angle); + sun_direction.y = sin(sun_angle); + sun_direction.z = 0.0; + + /* TODO Moon light */ + + if (max_lights > MAX_SKYDOME_LIGHTS) + { + max_lights = MAX_SKYDOME_LIGHTS; + } + + if (max_lights > 0) + { + /* Direct light from the sun */ + cache->lights[0].direction = v3Scale(sun_direction, -1.0); + cache->lights[0].color = definition->sun_color; + cache->lights[0].reflection = 1.0; + cache->lights[0].filtered = 1; + cache->lights[0].masked = 1; + nblights = 1; + max_lights--; + } + + if (max_lights > 0) + { + /* Indirect lighting by skydome scattering */ + int xsamples, ysamples, samples, x, y; + double xstep, ystep, factor; + Vector3 direction; + + samples = (renderer->render_quality < 5) ? 9 : (renderer->render_quality * 4 + 1); + samples = samples > max_lights ? max_lights : samples; + + factor = definition->dome_lighting / (double)samples; + + _addDomeLight(renderer, cache->lights + nblights, VECTOR_UP, factor); + nblights++; + samples--; + + if (samples >= 2) + { + xsamples = samples / 2; + ysamples = samples / xsamples; + + xstep = M_PI * 2.0 / (double)xsamples; + ystep = M_PI * 0.5 / (double)ysamples; + + for (x = 0; x < xsamples; x++) + { + for (y = 0; y < ysamples; y++) + { + direction.x = cos(x * xstep) * cos(y * ystep); + direction.y = -sin(y * ystep); + direction.z = sin(x * xstep) * cos(y * ystep); + + _addDomeLight(renderer, cache->lights + nblights, direction, factor); + nblights++; + } + } + } + } + + cache->nblights = nblights; + } + mutexRelease(cache->lock); + + memcpy(lights, cache->lights, sizeof(LightDefinition) * cache->nblights); + return cache->nblights; +} + +/******************** Renderer ********************/ +static AtmosphereRenderer* _createRenderer() +{ + AtmosphereRenderer* result; + AtmosphereRendererCache* cache; + + result = malloc(sizeof(AtmosphereRenderer)); + result->definition = AtmosphereDefinitionClass.create(); + + result->getSunDirection = _getSunDirection; + result->applyAerialPerspective = _fakeApplyAerialPerspective; + result->getSkydomeLights = _fakeGetSkydomeLights; + result->getSkyColor = _fakeGetSkyColor; + + cache = malloc(sizeof(AtmosphereRendererCache)); + cache->lock = mutexCreate(); + cache->nblights = -1; + result->_internal_data = cache; + + return result; +} + +static void _deleteRenderer(AtmosphereRenderer* renderer) +{ + AtmosphereRendererCache* cache = (AtmosphereRendererCache*)renderer->_internal_data; + mutexDestroy(cache->lock); + free(cache); + + AtmosphereDefinitionClass.destroy(renderer->definition); + free(renderer); +} + +static void _bindRenderer(AtmosphereRenderer* renderer, AtmosphereDefinition* definition) +{ + AtmosphereRendererCache* cache = (AtmosphereRendererCache*)renderer->_internal_data; + + AtmosphereDefinitionClass.copy(definition, renderer->definition); + + renderer->getSkyColor = _getSkyColor; + renderer->getSkydomeLights = _getSkydomeLights; + + mutexAcquire(cache->lock); + cache->nblights = -1; + mutexRelease(cache->lock); +} + +StandardRenderer AtmosphereRendererClass = { + (FuncObjectCreate)_createRenderer, + (FuncObjectDelete)_deleteRenderer, + (FuncObjectBind)_bindRenderer +}; + +/******************** Utilities ********************/ +static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* data) +{ + Vector3 direction; + Color result; + + UNUSED(data); + + direction = v3Sub(location, renderer->camera_location); + + /* TODO Don't compute result->color if it's fully covered by clouds */ + result = renderer->atmosphere->getSkyColor(renderer, v3Normalize(direction)); + result = renderer->applyClouds(renderer, result, renderer->camera_location, v3Add(renderer->camera_location, v3Scale(direction, 10.0))); + + return result; +} + +void atmosphereRenderSkydome(Renderer* renderer) +{ + int res_i, res_j; + int i, j; + double step_i, step_j; + double current_i, current_j; + Vector3 vertex1, vertex2, vertex3, vertex4; + Vector3 direction; + + res_i = renderer->render_quality * 40; + res_j = renderer->render_quality * 20; + step_i = M_PI * 2.0 / (double)res_i; + step_j = M_PI / (double)res_j; + + for (j = 0; j < res_j; j++) + { + if (!renderer->addRenderProgress(renderer, 0.0)) + { + return; + } + + current_j = (double)(j - res_j / 2) * step_j; + + for (i = 0; i < res_i; i++) + { + current_i = (double)i * step_i; + + direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j); + direction.y = SPHERE_SIZE * sin(current_j); + direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j); + vertex1 = v3Add(renderer->camera_location, direction); + + direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j); + direction.y = SPHERE_SIZE * sin(current_j); + direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j); + vertex2 = v3Add(renderer->camera_location, direction); + + direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j + step_j); + direction.y = SPHERE_SIZE * sin(current_j + step_j); + direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j + step_j); + vertex3 = v3Add(renderer->camera_location, direction); + + direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j + step_j); + direction.y = SPHERE_SIZE * sin(current_j + step_j); + direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j + step_j); + vertex4 = v3Add(renderer->camera_location, direction); + + /* TODO Triangles at poles */ + renderer->pushQuad(renderer, vertex1, vertex4, vertex3, vertex2, _postProcessFragment, NULL); + } + } +} diff --git a/lib_paysages/atmosphere/atmosphere.h b/lib_paysages/atmosphere/atmosphere.h new file mode 100644 index 0000000..93f4d27 --- /dev/null +++ b/lib_paysages/atmosphere/atmosphere.h @@ -0,0 +1,83 @@ +#ifndef _PAYSAGES_ATMOSPHERE_INTERFACE_H_ +#define _PAYSAGES_ATMOSPHERE_INTERFACE_H_ + +#include "../shared/types.h" +#include "../euclid.h" +#include "../color.h" +#include "../pack.h" +#include "../layers.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /*** TO EXTRACT ***/ +typedef void* (*FuncObjectCreate)(); +typedef void (*FuncObjectDelete)(void* object); +typedef void (*FuncObjectCopy)(void* source, void* destination); +typedef void (*FuncObjectValidate)(void* object); +typedef void (*FuncObjectSave)(PackStream* stream, void* object); +typedef void (*FuncObjectLoad)(PackStream* stream, void* object); +typedef void (*FuncObjectBind)(void* base, void* sub); + +typedef struct { + FuncObjectCreate create; + FuncObjectDelete destroy; + FuncObjectCopy copy; + FuncObjectValidate validate; + FuncObjectSave save; + FuncObjectLoad load; +} StandardDefinition; + +typedef struct { + FuncObjectCreate create; + FuncObjectDelete destroy; + FuncObjectBind bind; +} StandardRenderer; + /*** TO EXTRACT ***/ + +typedef enum +{ + ATMOSPHERE_MODEL_PREETHAM = 0, + ATMOSPHERE_MODEL_BRUNETON = 1 +} AtmosphereModel; + +typedef struct +{ + AtmosphereModel model; + double daytime; + double humidity; + Color sun_color; + double sun_radius; + double sun_halo_size; + Curve* sun_halo_profile; + double dome_lighting; +} AtmosphereDefinition; + +typedef int (*FuncAtmosphereGetSkydomeLights)(Renderer* renderer, LightDefinition* array, int max_lights); +typedef Color (*FuncAtmosphereApplyAerialPerspective)(Renderer* renderer, Vector3 location, Color base); +typedef Color (*FuncAtmosphereGetSkyColor)(Renderer* renderer, Vector3 direction); +typedef Vector3 (*FuncAtmosphereGetSunDirection)(Renderer* renderer); + +typedef struct +{ + AtmosphereDefinition* definition; + + FuncAtmosphereGetSkydomeLights getSkydomeLights; + FuncAtmosphereApplyAerialPerspective applyAerialPerspective; + FuncAtmosphereGetSkyColor getSkyColor; + FuncAtmosphereGetSunDirection getSunDirection; + + void* _internal_data; +} AtmosphereRenderer; + +extern StandardDefinition AtmosphereDefinitionClass; +extern StandardRenderer AtmosphereRendererClass; + +void atmosphereRenderSkydome(Renderer* renderer); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib_paysages/atmosphere/bruneton.c b/lib_paysages/atmosphere/bruneton.c new file mode 100644 index 0000000..1e86ffc --- /dev/null +++ b/lib_paysages/atmosphere/bruneton.c @@ -0,0 +1,6 @@ +#include "atmosphere.h" + +Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position) +{ + return COLOR_BLACK; +} diff --git a/lib_paysages/skypreetham.c b/lib_paysages/atmosphere/preetham.c similarity index 90% rename from lib_paysages/skypreetham.c rename to lib_paysages/atmosphere/preetham.c index f8c3db8..0167bf2 100644 --- a/lib_paysages/skypreetham.c +++ b/lib_paysages/atmosphere/preetham.c @@ -1,6 +1,7 @@ -#include "skypreetham.h" +#include "atmosphere.h" #include +#include "../renderer.h" static inline double _angleBetween(double thetav, double phiv, double theta, double phi) { @@ -50,13 +51,13 @@ static inline void _directionToThetaPhi(Vector3 direction, double* theta, double *theta = M_PI_2 - asin(direction.y); } -Color skyPreethamGetColor(Vector3 viewer, Vector3 direction, Vector3 sun_direction, double turbidity) +Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position) { double theta, phi; double thetaSun, phiSun; _directionToThetaPhi(direction, &theta, &phi); - _directionToThetaPhi(sun_direction, &thetaSun, &phiSun); + _directionToThetaPhi(sun_position, &thetaSun, &phiSun); if (theta > M_PI / 2.0) { @@ -74,7 +75,7 @@ Color skyPreethamGetColor(Vector3 viewer, Vector3 direction, Vector3 sun_directi cosTheta = cos(theta); } - double T = turbidity; + double T = definition->humidity; double T2 = T * T; double suntheta = thetaSun; double suntheta2 = thetaSun * thetaSun; @@ -129,9 +130,3 @@ Color skyPreethamGetColor(Vector3 viewer, Vector3 direction, Vector3 sun_directi return _xyYToRGB(x, y, Y); } - -Color skyPreethamApplyToObject(Vector3 viewer, Vector3 object_location, Vector3 sun_direction, double turbidity, Color object_color) -{ - /* TODO Aerial perspective */ - return object_color; -} diff --git a/lib_paysages/auto.c b/lib_paysages/auto.c index 52c48a0..08a2cab 100644 --- a/lib_paysages/auto.c +++ b/lib_paysages/auto.c @@ -13,7 +13,6 @@ #include "terrain.h" #include "textures.h" #include "scenery.h" -#include "sky.h" #include "system.h" #include "water.h" #include "zone.h" @@ -25,9 +24,7 @@ void autoSetDaytime(int hour, int minute) void autoSetDaytimeFraction(double daytime) { - SkyDefinition sky; - /*ColorGradation grad_sun; - Color sun;*/ + AtmosphereDefinition* atmosphere; daytime = fmod(daytime, 1.0); if (daytime < 0.0) @@ -35,33 +32,18 @@ void autoSetDaytimeFraction(double daytime) daytime += 1.0; } - /*lightingSetSunAngle(0.0, (daytime + 0.25) * M_PI * 2.0); - - grad_sun = colorGradationCreate(); - colorGradationAddRgba(&grad_sun, 0.2, 0.1, 0.1, 0.1, 1.0); - colorGradationAddRgba(&grad_sun, 0.25, 0.9, 0.5, 0.5, 1.0); - colorGradationAddRgba(&grad_sun, 0.3, 0.8, 0.8, 0.8, 1.0); - colorGradationAddRgba(&grad_sun, 0.5, 1.0, 1.0, 1.0, 1.0); - colorGradationAddRgba(&grad_sun, 0.7, 0.8, 0.8, 0.8, 1.0); - colorGradationAddRgba(&grad_sun, 0.75, 0.7, 0.6, 0.5, 1.0); - colorGradationAddRgba(&grad_sun, 0.8, 0.1, 0.1, 0.1, 1.0); - sun = colorGradationGet(&grad_sun, daytime); - lightingSetSunColor(sun);*/ - - sky = skyCreateDefinition(); - sceneryGetSky(&sky); - sky.daytime = daytime; - scenerySetSky(&sky); - skyDeleteDefinition(&sky); + atmosphere = AtmosphereDefinitionClass.create(); + sceneryGetAtmosphere(atmosphere); + atmosphere->daytime = daytime; + scenerySetAtmosphere(atmosphere); + AtmosphereDefinitionClass.destroy(atmosphere); } void autoGenRealisticLandscape(int seed) { - AtmosphereDefinition atmosphere; TerrainDefinition terrain; WaterDefinition water; CloudsDefinition clouds; - SkyDefinition sky; TexturesDefinition textures; TextureLayerDefinition* texture; int layer; @@ -84,36 +66,6 @@ void autoGenRealisticLandscape(int seed) scenerySetWater(&water); waterDeleteDefinition(&water); - /* Sky */ - sky = skyCreateDefinition(); - sky.model = SKY_MODEL_PREETHAM; - sky.daytime = 0.0; - sky.sun_color.r = 1.0; - sky.sun_color.g = 0.95; - sky.sun_color.b = 0.9; - sky.sun_color.a = 1.0; - sky.sun_radius = 0.02; - sky.sun_halo_size = 0.3; - sky.dome_lighting = 0.6; - curveClear(sky.sun_halo_profile); - curveQuickAddPoint(sky.sun_halo_profile, 0.0, 1.0); - curveQuickAddPoint(sky.sun_halo_profile, 0.1, 0.2); - curveQuickAddPoint(sky.sun_halo_profile, 1.0, 0.0); - sky.model_custom.auto_from_daytime = 1; - sky.model_custom.zenith_color.r = 0.52; - sky.model_custom.zenith_color.g = 0.63; - sky.model_custom.zenith_color.b = 0.8; - sky.model_custom.zenith_color.a = 1.0; - sky.model_custom.haze_color.r = 0.92; - sky.model_custom.haze_color.g = 0.93; - sky.model_custom.haze_color.b = 1.0; - sky.model_custom.haze_color.a = 1.0; - sky.model_custom.haze_height = 0.75; - sky.model_custom.haze_smoothing = 0.3; - sky.model_preetham.turbidity = 2.0; - scenerySetSky(&sky); - skyDeleteDefinition(&sky); - /* Terrain */ terrain = terrainCreateDefinition(); noiseClearLevels(terrain.height_noise); @@ -180,11 +132,11 @@ void autoGenRealisticLandscape(int seed) texturesDeleteDefinition(&textures); /* Atmosphere */ - atmosphere = atmosphereCreateDefinition(); + /*atmosphere = atmosphereCreateDefinition(); atmosphere.distance_near = 20.0; atmosphere.distance_far = 100.0; atmosphere.full_mask = 0.6; atmosphere.auto_lock_on_haze = 1; scenerySetAtmosphere(&atmosphere); - atmosphereDeleteDefinition(&atmosphere); + atmosphereDeleteDefinition(&atmosphere);*/ } diff --git a/lib_paysages/clouds.c b/lib_paysages/clouds.c index bd6e3cc..3ea3f5d 100644 --- a/lib_paysages/clouds.c +++ b/lib_paysages/clouds.c @@ -579,7 +579,7 @@ Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* { col = _applyLayerLighting(definition, renderer, segments[i].start, detail); col.a = 1.0; - col = renderer->applyAtmosphere(renderer, start, col); + col = renderer->atmosphere->applyAerialPerspective(renderer, start, col); col.a = (segments[i].length >= definition->transparencydepth) ? 1.0 : (segments[i].length / definition->transparencydepth); colorMask(&base, &col); } diff --git a/lib_paysages/lighting.c b/lib_paysages/lighting.c index f5bb5f3..1515d64 100644 --- a/lib_paysages/lighting.c +++ b/lib_paysages/lighting.c @@ -10,7 +10,6 @@ #include "euclid.h" #include "renderer.h" #include "scenery.h" -#include "sky.h" #include "terrain.h" #include "tools.h" #include "water.h" @@ -224,7 +223,7 @@ void lightingGetStatus(LightingDefinition* definition, Renderer* renderer, Vecto /* Apply skydome lights */ /* TODO Cache skydome lights for same render */ - skydome_lights_count = renderer->getSkyDomeLights(renderer, skydome_lights, LIGHTING_MAX_LIGHTS); + skydome_lights_count = renderer->atmosphere->getSkydomeLights(renderer, skydome_lights, LIGHTING_MAX_LIGHTS); for (i = 0; i < skydome_lights_count; i++) { if (_getLightStatus(skydome_lights + i, renderer, location, result->lights + result->nblights)) diff --git a/lib_paysages/renderer.c b/lib_paysages/renderer.c index a56fe67..baf0f93 100644 --- a/lib_paysages/renderer.c +++ b/lib_paysages/renderer.c @@ -54,11 +54,6 @@ static void _pushQuad(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, Ve renderer->pushTriangle(renderer, v4, v1, v3, callback, callback_data); } -static int _getSkyDomeLights(Renderer* renderer, LightDefinition* array, int max_lights) -{ - return 0; -} - static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location) { } @@ -93,11 +88,6 @@ static Color _applyTextures(Renderer* renderer, Vector3 location, double precisi return COLOR_TRANSPARENT; } -static Color _applyAtmosphere(Renderer* renderer, Vector3 location, Color base) -{ - return base; -} - static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3 end) { return base; @@ -131,19 +121,20 @@ Renderer rendererCreate() result.getTerrainHeight = _getTerrainHeight; result.getWaterHeightInfo = _getWaterHeightInfo; result.applyTextures = _applyTextures; - result.applyAtmosphere = _applyAtmosphere; result.applyClouds = _applyClouds; - result.getSkyDomeLights = _getSkyDomeLights; result.alterLight = _alterLight; result.getLightStatus = _getLightStatus; result.applyLightStatus = _applyLightStatus; + + result.atmosphere = AtmosphereRendererClass.create(); return result; } void rendererDelete(Renderer* renderer) { + AtmosphereRendererClass.destroy(renderer->atmosphere); renderDeleteArea(renderer->render_area); } diff --git a/lib_paysages/renderer.h b/lib_paysages/renderer.h index c9a672d..01d64e5 100644 --- a/lib_paysages/renderer.h +++ b/lib_paysages/renderer.h @@ -2,13 +2,12 @@ #define _PAYSAGES_RENDERER_H_ #include "shared/types.h" +#include "atmosphere/atmosphere.h" #ifdef __cplusplus extern "C" { #endif -typedef struct Renderer Renderer; - struct Renderer { /* Render base configuration */ @@ -35,14 +34,15 @@ struct Renderer double (*getTerrainHeight)(Renderer* renderer, double x, double z); HeightInfo (*getWaterHeightInfo)(Renderer* renderer); Color (*applyTextures)(Renderer* renderer, Vector3 location, double precision); - Color (*applyAtmosphere)(Renderer* renderer, Vector3 location, Color base); Color (*applyClouds)(Renderer* renderer, Color base, Vector3 start, Vector3 end); /* Lighting related */ - int (*getSkyDomeLights)(Renderer* renderer, LightDefinition* array, int max_lights); void (*alterLight)(Renderer* renderer, LightDefinition* light, Vector3 location); void (*getLightStatus)(Renderer* renderer, LightStatus* status, Vector3 location); Color (*applyLightStatus)(Renderer* renderer, LightStatus* status, Vector3 location, Vector3 normal, SurfaceMaterial material); + + /* Autonomous sub-renderers */ + AtmosphereRenderer* atmosphere; /* Custom data */ void* customData[10]; diff --git a/lib_paysages/scenery.c b/lib_paysages/scenery.c index 38ddd16..c56bce7 100644 --- a/lib_paysages/scenery.c +++ b/lib_paysages/scenery.c @@ -6,11 +6,10 @@ #include "render.h" #include "system.h" -static AtmosphereDefinition _atmosphere; +static AtmosphereDefinition* _atmosphere; static CameraDefinition _camera; static CloudsDefinition _clouds; static LightingDefinition _lighting; -static SkyDefinition _sky; static TerrainDefinition _terrain; static TexturesDefinition _textures; static WaterDefinition _water; @@ -24,11 +23,10 @@ void sceneryInit() noiseInit(); lightingInit(); - _atmosphere = atmosphereCreateDefinition(); + _atmosphere = AtmosphereDefinitionClass.create(); _camera = cameraCreateDefinition(); _clouds = cloudsCreateDefinition(); _lighting = lightingCreateDefinition(); - _sky = skyCreateDefinition(); _terrain = terrainCreateDefinition(); _textures = texturesCreateDefinition(); _water = waterCreateDefinition(); @@ -39,11 +37,10 @@ void sceneryInit() void sceneryQuit() { - atmosphereDeleteDefinition(&_atmosphere); + AtmosphereDefinitionClass.destroy(_atmosphere); cameraDeleteDefinition(&_camera); cloudsDeleteDefinition(&_clouds); lightingDeleteDefinition(&_lighting); - skyDeleteDefinition(&_sky); terrainDeleteDefinition(&_terrain); texturesDeleteDefinition(&_textures); waterDeleteDefinition(&_water); @@ -62,11 +59,10 @@ void scenerySetCustomDataCallback(SceneryCustomDataCallback callback_save, Scene void scenerySave(PackStream* stream) { noiseSave(stream); - atmosphereSave(stream, &_atmosphere); + AtmosphereDefinitionClass.save(stream, _atmosphere); cameraSave(stream, &_camera); cloudsSave(stream, &_clouds); lightingSave(stream, &_lighting); - skySave(stream, &_sky); terrainSave(stream, &_terrain); texturesSave(stream, &_textures); waterSave(stream, &_water); @@ -82,20 +78,17 @@ void sceneryLoad(PackStream* stream) /* TODO Use intermediary definitions ? */ noiseLoad(stream); - atmosphereLoad(stream, &_atmosphere); + AtmosphereDefinitionClass.load(stream, _atmosphere); cameraLoad(stream, &_camera); cloudsLoad(stream, &_clouds); lightingLoad(stream, &_lighting); - skyLoad(stream, &_sky); terrainLoad(stream, &_terrain); texturesLoad(stream, &_textures); waterLoad(stream, &_water); - atmosphereValidateDefinition(&_atmosphere); cameraValidateDefinition(&_camera, 0); cloudsValidateDefinition(&_clouds); lightingValidateDefinition(&_lighting); - skyValidateDefinition(&_sky); terrainValidateDefinition(&_terrain); texturesValidateDefinition(&_textures); waterValidateDefinition(&_water); @@ -108,13 +101,13 @@ void sceneryLoad(PackStream* stream) void scenerySetAtmosphere(AtmosphereDefinition* atmosphere) { - atmosphereCopyDefinition(atmosphere, &_atmosphere); - atmosphereValidateDefinition(&_atmosphere); + AtmosphereDefinitionClass.copy(atmosphere, _atmosphere); + AtmosphereDefinitionClass.validate(_atmosphere); } void sceneryGetAtmosphere(AtmosphereDefinition* atmosphere) { - atmosphereCopyDefinition(&_atmosphere, atmosphere); + AtmosphereDefinitionClass.copy(_atmosphere, atmosphere); } void scenerySetCamera(CameraDefinition* camera) @@ -150,20 +143,6 @@ void sceneryGetLighting(LightingDefinition* lighting) lightingCopyDefinition(&_lighting, lighting); } -void scenerySetSky(SkyDefinition* sky) -{ - skyCopyDefinition(sky, &_sky); - skyValidateDefinition(&_sky); - - atmosphereValidateDefinition(&_atmosphere); - lightingValidateDefinition(&_lighting); -} - -void sceneryGetSky(SkyDefinition* sky) -{ - skyCopyDefinition(&_sky, sky); -} - void scenerySetTerrain(TerrainDefinition* terrain) { terrainCopyDefinition(terrain, &_terrain); @@ -205,7 +184,7 @@ void sceneryRenderFirstPass(Renderer* renderer) { terrainRender(&_terrain, renderer); waterRender(&_water, renderer); - skyRender(&_sky, renderer); + atmosphereRenderSkydome(renderer); } @@ -214,11 +193,6 @@ void sceneryRenderFirstPass(Renderer* renderer) /******* Standard renderer *********/ -static int _getSkyDomeLights(Renderer* renderer, LightDefinition* array, int max_lights) -{ - return skyGetLights(&_sky, renderer, array, max_lights); -} - static void _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location) { Vector3 light_location; @@ -256,7 +230,7 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector if (!terrainProjectRay(&_terrain, renderer, location, direction, &result.hit_location, &result.hit_color)) { - sky_color = skyGetColor(&_sky, renderer, location, direction); + sky_color = renderer->atmosphere->getSkyColor(renderer, direction); result.hit_location = v3Add(location, v3Scale(direction, 1000.0)); result.hit_color = renderer->applyClouds(renderer, sky_color, location, result.hit_location); } @@ -280,11 +254,6 @@ static Color _applyTextures(Renderer* renderer, Vector3 location, double precisi return texturesGetColor(&_textures, renderer, location.x, location.z, precision); } -static Color _applyAtmosphere(Renderer* renderer, Vector3 location, Color base) -{ - return atmosphereApply(&_atmosphere, renderer, location, base); -} - static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3 end) { return cloudsApply(&_clouds, base, renderer, start, end); @@ -320,7 +289,6 @@ Renderer sceneryCreateStandardRenderer() cameraCopyDefinition(&_camera, &result.render_camera); result.camera_location = _camera.location; - result.getSkyDomeLights = _getSkyDomeLights; result.alterLight = _alterLight; result.getLightStatus = _getLightStatus; result.applyLightStatus = _applyLightStatus; @@ -328,11 +296,12 @@ Renderer sceneryCreateStandardRenderer() result.getTerrainHeight = _getTerrainHeight; result.getWaterHeightInfo = _getWaterHeightInfo; result.applyTextures = _applyTextures; - result.applyAtmosphere = _applyAtmosphere; result.applyClouds = _applyClouds; result.projectPoint = _projectPoint; result.unprojectPoint = _unprojectPoint; result.getPrecision = _getPrecision; + + AtmosphereRendererClass.bind(result.atmosphere, _atmosphere); return result; } diff --git a/lib_paysages/scenery.h b/lib_paysages/scenery.h index acd0595..8b5a9df 100644 --- a/lib_paysages/scenery.h +++ b/lib_paysages/scenery.h @@ -8,11 +8,10 @@ * a standard renderer. */ -#include "atmosphere.h" +#include "atmosphere/atmosphere.h" #include "camera.h" #include "clouds.h" #include "lighting.h" -#include "sky.h" #include "terrain.h" #include "textures.h" #include "water.h" @@ -45,9 +44,6 @@ void sceneryGetClouds(CloudsDefinition* clouds); void scenerySetLighting(LightingDefinition* lighting); void sceneryGetLighting(LightingDefinition* lighting); -void scenerySetSky(SkyDefinition* sky); -void sceneryGetSky(SkyDefinition* sky); - void scenerySetTerrain(TerrainDefinition* terrain); void sceneryGetTerrain(TerrainDefinition* terrain); diff --git a/lib_paysages/shared/types.h b/lib_paysages/shared/types.h index 82ead42..c75ef0c 100644 --- a/lib_paysages/shared/types.h +++ b/lib_paysages/shared/types.h @@ -8,7 +8,7 @@ extern "C" { #endif -struct Renderer; +typedef struct Renderer Renderer; typedef struct LightDefinition LightDefinition; typedef struct LightStatus LightStatus; diff --git a/lib_paysages/sky.c b/lib_paysages/sky.c deleted file mode 100644 index 592c62b..0000000 --- a/lib_paysages/sky.c +++ /dev/null @@ -1,374 +0,0 @@ -#include "sky.h" - -#include -#include - -#include "shared/types.h" -#include "color.h" -#include "clouds.h" -#include "euclid.h" -#include "lighting.h" -#include "render.h" -#include "tools.h" -#include "skypreetham.h" -#include "skyrayleigh.h" - -#define SPHERE_SIZE 1000.0 - -/******************************** Configuration ********************************/ -void skySave(PackStream* stream, SkyDefinition* definition) -{ - packWriteInt(stream, (int*)&definition->model); - packWriteDouble(stream, &definition->daytime); - colorSave(stream, &definition->sun_color); - packWriteDouble(stream, &definition->sun_radius); - packWriteDouble(stream, &definition->sun_halo_size); - curveSave(stream, definition->sun_halo_profile); - packWriteDouble(stream, &definition->dome_lighting); - - packWriteInt(stream, &definition->model_custom.auto_from_daytime); - colorSave(stream, &definition->model_custom.zenith_color); - colorSave(stream, &definition->model_custom.haze_color); - packWriteDouble(stream, &definition->model_custom.haze_height); - packWriteDouble(stream, &definition->model_custom.haze_smoothing); - - packWriteDouble(stream, &definition->model_preetham.turbidity); -} - -void skyLoad(PackStream* stream, SkyDefinition* definition) -{ - packReadInt(stream, (int*)&definition->model); - packReadDouble(stream, &definition->daytime); - colorLoad(stream, &definition->sun_color); - packReadDouble(stream, &definition->sun_radius); - packReadDouble(stream, &definition->sun_halo_size); - curveLoad(stream, definition->sun_halo_profile); - packReadDouble(stream, &definition->dome_lighting); - - packReadInt(stream, &definition->model_custom.auto_from_daytime); - colorLoad(stream, &definition->model_custom.zenith_color); - colorLoad(stream, &definition->model_custom.haze_color); - packReadDouble(stream, &definition->model_custom.haze_height); - packReadDouble(stream, &definition->model_custom.haze_smoothing); - - packReadDouble(stream, &definition->model_preetham.turbidity); - - skyValidateDefinition(definition); -} - -SkyDefinition skyCreateDefinition() -{ - SkyDefinition def; - - def.model = SKY_MODEL_CUSTOM; - def.daytime = 0.0; - def.sun_color = COLOR_BLACK; - def.sun_radius = 1.0; - def.sun_halo_size = 0.0; - def.sun_halo_profile = curveCreate(); - def.dome_lighting = 0.0; - def.model_custom.auto_from_daytime = 0; - def.model_custom.zenith_color = COLOR_BLACK; - def.model_custom.haze_color = COLOR_BLACK; - def.model_custom.haze_height = 0.0; - def.model_custom.haze_smoothing = 0.0; - def.model_custom._sky_gradation = colorGradationCreate(); - def.model_preetham.turbidity = 0.0; - - skyValidateDefinition(&def); - - return def; -} - -void skyDeleteDefinition(SkyDefinition* definition) -{ - curveDelete(definition->sun_halo_profile); - colorGradationDelete(definition->model_custom._sky_gradation); -} - -void skyCopyDefinition(SkyDefinition* source, SkyDefinition* destination) -{ - destination->model = source->model; - destination->daytime = source->daytime; - destination->sun_color = source->sun_color; - destination->sun_radius = source->sun_radius; - destination->sun_halo_size = source->sun_halo_size; - destination->dome_lighting = source->dome_lighting; - destination->model_custom.auto_from_daytime = source->model_custom.auto_from_daytime; - destination->model_custom.zenith_color = source->model_custom.zenith_color; - destination->model_custom.haze_color = source->model_custom.haze_color; - destination->model_custom.haze_height = source->model_custom.haze_height; - destination->model_custom.haze_smoothing = source->model_custom.haze_smoothing; - destination->model_preetham.turbidity = source->model_preetham.turbidity; - - curveCopy(source->sun_halo_profile, destination->sun_halo_profile); - - skyValidateDefinition(destination); -} - -static void _setAutoCustomModel(SkyDefinition* definition) -{ - ColorGradation* zenith_gradation; - ColorGradation* haze_gradation; - - zenith_gradation = colorGradationCreate(); - haze_gradation = colorGradationCreate(); - - colorGradationQuickAddRgb(zenith_gradation, 0.2, 0.03, 0.03, 0.05); - colorGradationQuickAddRgb(zenith_gradation, 0.25, 0.25, 0.33, 0.37); - colorGradationQuickAddRgb(zenith_gradation, 0.35, 0.52, 0.63, 0.8); - colorGradationQuickAddRgb(zenith_gradation, 0.65, 0.52, 0.63, 0.8); - colorGradationQuickAddRgb(zenith_gradation, 0.75, 0.25, 0.33, 0.37); - colorGradationQuickAddRgb(zenith_gradation, 0.8, 0.03, 0.03, 0.05); - colorGradationQuickAddRgb(haze_gradation, 0.2, 0.05, 0.05, 0.08); - colorGradationQuickAddRgb(haze_gradation, 0.25, 0.55, 0.42, 0.42); - colorGradationQuickAddRgb(haze_gradation, 0.3, 0.6, 0.6, 0.6); - colorGradationQuickAddRgb(haze_gradation, 0.4, 0.92, 0.93, 1.0); - colorGradationQuickAddRgb(haze_gradation, 0.6, 0.92, 0.93, 1.0); - colorGradationQuickAddRgb(haze_gradation, 0.7, 0.6, 0.6, 0.8); - colorGradationQuickAddRgb(haze_gradation, 0.75, 0.62, 0.50, 0.42); - colorGradationQuickAddRgb(haze_gradation, 0.8, 0.05, 0.05, 0.08); - - definition->model_custom.zenith_color = colorGradationGet(zenith_gradation, definition->daytime); - definition->model_custom.haze_color = colorGradationGet(haze_gradation, definition->daytime); - - colorGradationDelete(zenith_gradation); - colorGradationDelete(haze_gradation); -} - -void skyValidateDefinition(SkyDefinition* definition) -{ - if (definition->model == SKY_MODEL_CUSTOM) - { - if (definition->model_custom.auto_from_daytime) - { - _setAutoCustomModel(definition); - } - colorGradationClear(definition->model_custom._sky_gradation); - colorGradationQuickAdd(definition->model_custom._sky_gradation, 0.0, &definition->model_custom.haze_color); - colorGradationQuickAdd(definition->model_custom._sky_gradation, definition->model_custom.haze_height - definition->model_custom.haze_smoothing, &definition->model_custom.haze_color); - colorGradationQuickAdd(definition->model_custom._sky_gradation, definition->model_custom.haze_height, &definition->model_custom.zenith_color); - colorGradationQuickAdd(definition->model_custom._sky_gradation, 1.0, &definition->model_custom.zenith_color); - } -} - -static inline void _addDomeLight(SkyDefinition* sky, Renderer* renderer, LightDefinition* light, Vector3 direction, double factor) -{ - light->direction = v3Scale(direction, -1.0); - light->color = skyGetColor(sky, renderer, VECTOR_ZERO, direction); - light->color.r *= factor; - light->color.g *= factor; - light->color.b *= factor; - light->reflection = 0.0; - light->filtered = 0; - light->masked = 0; -} - -int skyGetLights(SkyDefinition* sky, Renderer* renderer, LightDefinition* lights, int max_lights) -{ - double sun_angle; - Vector3 sun_direction; - int nblights = 0; - - sun_angle = (sky->daytime + 0.75) * M_PI * 2.0; - sun_direction.x = cos(sun_angle); - sun_direction.y = sin(sun_angle); - sun_direction.z = 0.0; - - /* TODO Moon light */ - - if (max_lights > 0) - { - /* Direct light from the sun */ - lights[0].direction = v3Scale(sun_direction, -1.0); - lights[0].color = sky->sun_color; - lights[0].reflection = 1.0; - lights[0].filtered = 1; - lights[0].masked = 1; - nblights = 1; - max_lights--; - } - - if (max_lights > 0) - { - /* Indirect lighting by skydome scattering */ - int xsamples, ysamples, samples, x, y; - double xstep, ystep, factor; - Vector3 direction; - - samples = (renderer->render_quality < 5) ? 9 : (renderer->render_quality * 4 + 1); - samples = samples > max_lights ? max_lights : samples; - - factor = sky->dome_lighting / (double)samples; - - _addDomeLight(sky, renderer, lights + nblights, VECTOR_UP, factor); - nblights++; - samples--; - - if (samples >= 2) - { - xsamples = samples / 2; - ysamples = samples / xsamples; - - xstep = M_PI * 2.0 / (double)xsamples; - ystep = M_PI * 0.5 / (double)ysamples; - - for (x = 0; x < xsamples; x++) - { - for (y = 0; y < ysamples; y++) - { - direction.x = cos(x * xstep) * cos(y * ystep); - direction.y = -sin(y * ystep); - direction.z = sin(x * xstep) * cos(y * ystep); - - _addDomeLight(sky, renderer, lights + nblights, direction, factor); - nblights++; - } - } - } - } - - return nblights; -} - -/******************************** Rendering ********************************/ -Color skyGetColor(SkyDefinition* definition, Renderer* renderer, Vector3 eye, Vector3 look) -{ - double dist; - Vector3 sun_position; - Color sun_color, sky_color; - - sun_position = skyGetSunDirection(definition); - - look = v3Normalize(look); - dist = v3Norm(v3Sub(look, sun_position)); - - if (definition->model == SKY_MODEL_PREETHAM) - { - sky_color = skyPreethamGetColor(eye, look, sun_position, definition->model_preetham.turbidity); - } - else if (definition->model == SKY_MODEL_RAYLEIGH_MIE) - { - sky_color = skyRayleighGetColor(eye, look, sun_position); - } - else - { - sky_color = colorGradationGet(definition->model_custom._sky_gradation, look.y * 0.5 + 0.5); - } - - if (dist < definition->sun_radius + definition->sun_halo_size) - { - sun_color = definition->sun_color; - if (dist <= definition->sun_radius) - { - return sun_color; - } - else - { - dist = (dist - definition->sun_radius) / definition->sun_halo_size; - sun_color.a = curveGetValue(definition->sun_halo_profile, dist); - colorMask(&sky_color, &sun_color); - return sky_color; - } - } - else - { - return sky_color; - } -} - -static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* data) -{ - Vector3 direction; - Color result; - SkyDefinition* definition; - - definition = (SkyDefinition*)data; - - direction = v3Sub(location, renderer->camera_location); - - result = skyGetColor(definition, renderer, renderer->camera_location, v3Normalize(direction)); - result = renderer->applyClouds(renderer, result, renderer->camera_location, v3Add(renderer->camera_location, v3Scale(direction, 10.0))); - - return result; -} - -void skyRender(SkyDefinition* definition, Renderer* renderer) -{ - int res_i, res_j; - int i, j; - double step_i, step_j; - double current_i, current_j; - Vector3 vertex1, vertex2, vertex3, vertex4; - Vector3 direction; - - res_i = renderer->render_quality * 40; - res_j = renderer->render_quality * 20; - step_i = M_PI * 2.0 / (double)res_i; - step_j = M_PI / (double)res_j; - - for (j = 0; j < res_j; j++) - { - if (!renderer->addRenderProgress(renderer, 0.0)) - { - return; - } - - current_j = (double)(j - res_j / 2) * step_j; - - for (i = 0; i < res_i; i++) - { - current_i = (double)i * step_i; - - direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j); - direction.y = SPHERE_SIZE * sin(current_j); - direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j); - vertex1 = v3Add(renderer->camera_location, direction); - - direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j); - direction.y = SPHERE_SIZE * sin(current_j); - direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j); - vertex2 = v3Add(renderer->camera_location, direction); - - direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j + step_j); - direction.y = SPHERE_SIZE * sin(current_j + step_j); - direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j + step_j); - vertex3 = v3Add(renderer->camera_location, direction); - - direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j + step_j); - direction.y = SPHERE_SIZE * sin(current_j + step_j); - direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j + step_j); - vertex4 = v3Add(renderer->camera_location, direction); - - /* TODO Triangles at poles */ - renderer->pushQuad(renderer, vertex1, vertex4, vertex3, vertex2, _postProcessFragment, definition); - } - } -} - -Vector3 skyGetSunDirection(SkyDefinition* definition) -{ - Vector3 result; - double sun_angle = (definition->daytime + 0.75) * M_PI * 2.0; - result.x = cos(sun_angle); - result.y = sin(sun_angle); - result.z = 0.0; - return result; -} - -Color skyGetSunColor(SkyDefinition* definition) -{ - return definition->sun_color; -} - -Color skyGetZenithColor(SkyDefinition* definition) -{ - Vector3 look = {0.0, 1.0, 0.0}; - return skyGetColor(definition, NULL, VECTOR_ZERO, look); -} - -Color skyGetHorizonColor(SkyDefinition* definition) -{ - Vector3 look = {0.0, 0.0, 1.0}; - return skyGetColor(definition, NULL, VECTOR_ZERO, look); -} diff --git a/lib_paysages/sky.h b/lib_paysages/sky.h deleted file mode 100644 index 9b41d3b..0000000 --- a/lib_paysages/sky.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _PAYSAGES_SKY_H_ -#define _PAYSAGES_SKY_H_ - -#include "shared/types.h" -#include "color.h" -#include "lighting.h" -#include "pack.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum -{ - SKY_MODEL_CUSTOM = 0, - SKY_MODEL_RAYLEIGH_MIE = 1, - SKY_MODEL_PREETHAM = 2 -} SkyModel; - -typedef struct -{ - SkyModel model; - double daytime; - Color sun_color; - double sun_radius; - double sun_halo_size; - Curve* sun_halo_profile; - double dome_lighting; - struct { - int auto_from_daytime; - Color zenith_color; - Color haze_color; - double haze_height; - double haze_smoothing; - ColorGradation* _sky_gradation; - } model_custom; - struct { - double turbidity; - } model_preetham; -} SkyDefinition; - -void skySave(PackStream* stream, SkyDefinition* definition); -void skyLoad(PackStream* stream, SkyDefinition* definition); - -SkyDefinition skyCreateDefinition(); -void skyDeleteDefinition(SkyDefinition* definition); -void skyCopyDefinition(SkyDefinition* source, SkyDefinition* destination); -void skyValidateDefinition(SkyDefinition* definition); - -int skyGetLights(SkyDefinition* sky, Renderer* renderer, LightDefinition* lights, int max_lights); -Color skyGetColor(SkyDefinition* definition, Renderer* renderer, Vector3 eye, Vector3 look); -void skyRender(SkyDefinition* definition, Renderer* renderer); -Vector3 skyGetSunDirection(SkyDefinition* definition); -Color skyGetSunColor(SkyDefinition* definition); -Color skyGetZenithColor(SkyDefinition* definition); -Color skyGetHorizonColor(SkyDefinition* definition); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib_paysages/skypreetham.h b/lib_paysages/skypreetham.h deleted file mode 100644 index 2415f10..0000000 --- a/lib_paysages/skypreetham.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _PAYSAGES_PREETHAM_H_ -#define _PAYSAGES_PREETHAM_H_ - -/* Implementation of Preetham/Shirley light scattering */ - -#include "color.h" -#include "euclid.h" - -#ifdef __cplusplus -extern "C" { -#endif - -Color skyPreethamGetColor(Vector3 viewer, Vector3 direction, Vector3 sun_direction, double turbidity); -Color skyPreethamApplyToObject(Vector3 viewer, Vector3 object_location, Vector3 sun_direction, double turbidity, Color object_color); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib_paysages/skyrayleigh.c b/lib_paysages/skyrayleigh.c deleted file mode 100644 index 88310b1..0000000 --- a/lib_paysages/skyrayleigh.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "skyrayleigh.h" - -#include - -#if 0 -static Vector3 _betaR = {5.5e-6, 13.0e-6, 22.4e-6}; /* Rayleigh scattering coefficients at sea level */ -static Vector3 _betaM = {21e-6, 0.0, 0.0}; /* Mie scattering coefficients at sea level */ -static double _Hr = 7994; /* Rayleigh scale height */ -static double _Hm = 1200; /* Mie scale height */ -static double _radiusEarth = 6360e3; /* Earth radius */ -static double _radiusAtmosphere = 6420e3; /* Atmosphere radius */ -static double _sunIntensity = 20.0; /* Sun intensity */ -static double _g = 0.76; /* Mean cosine */ -#endif - -/*typedef struct -{ - double tmin; - double tmax; -} Ray; - -static Vector3 _computeIncidentLight(Ray r) -{ - double t0, t1; - int numSamples = 16; - int numSamplesLight = 8; - int i, j; - - if (!intersect(r, radiusAtmosphere, t0, t1) || t1 < 0) return Vec3(0); - if (t0 > r.tmin && t0 > 0) r.tmin = t0; - if (t1 < r.tmax) r.tmax = t1; - double segmentLength = (r.tmax - r.tmin) / (double)numSamples; - double tCurrent = r.tmin; - Vector3 sumR = VECTOR_ZERO; - Vector3 sumM = VECTOR_ZERO; - double opticalDepthR = 0.0; - double opticalDepthM = 0.0; - double mu = r.direction.dot(sunDirection); - double phaseR = 3.0 / (16.0 * M_PI) * (1.0 + mu * mu); - double phaseM = 3.0 / (8.0 * M_PI) * ((1.0 - _g * _g) * (1 + mu * mu)) / ((2 + _g * _g) * pow(1 + _g * _g - 2 * _g * mu, 1.5)); - for (i = 0; i < numSamples; ++i) - { - Vector3 samplePosition = r(tCurrent + T(0.5) * segmentLength); - double height = samplePosition.magnitude() - radiusEarth; - double hr = exp(-height / _Hr) * segmentLength; - double hm = exp(-height / _Hm) * segmentLength; - opticalDepthR += hr; - opticalDepthM += hm; - Ray lightRay(samplePosition, sunDirection); - intersect(lightRay, radiusAtmosphere, lightRay.tmin, lightRay.tmax); - double segmentLengthLight = lightRay.tmax / numSamplesLight; - double tCurrentLight = 0.0; - double opticalDepthLightR = 0.0; - double opticalDepthLightM = 0.0; - for (j = 0; j < numSamplesLight; ++j) { - Vector3 samplePositionLight = lightRay(tCurrentLight + T(0.5) * segmentLengthLight); - T heightLight = samplePositionLight.magnitude() - radiusEarth; - if (heightLight < 0) break; - opticalDepthLightR += exp(-heightLight / Hr) * segmentLengthLight; - opticalDepthLightM += exp(-heightLight / Hm) * segmentLengthLight; - tCurrentLight += segmentLengthLight; - } - if (j == numSamplesLight) { - Vec3 tau = betaR * (opticalDepthR + opticalDepthLightR) + betaM * 1.1 * (opticalDepthM + opticalDepthLightM); - Vec3 attenuation(exp(-tau.x), exp(-tau.y), exp(-tau.z)); - sumR += hr * attenuation; - sumM += hm * attenuation; - } - tCurrent += segmentLength; - } - return 20 * (sumR * phaseR * _betaR + sumM * phaseM * _betaM); -}*/ - -Color skyRayleighGetColor(Vector3 viewer, Vector3 direction, Vector3 sun_direction) -{ - return COLOR_BLACK; -} - -Color skyRayleighApplyToObject(Vector3 viewer, Vector3 object_location, Vector3 sun_direction, Color object_color) -{ - return COLOR_BLACK; -} diff --git a/lib_paysages/skyrayleigh.h b/lib_paysages/skyrayleigh.h deleted file mode 100644 index 0dfffbb..0000000 --- a/lib_paysages/skyrayleigh.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _PAYSAGES_RAYLEIGH_H_ -#define _PAYSAGES_RAYLEIGH_H_ - -/* Implementation of Rayleigh/Mie atmospheric light scattering */ - -#include "color.h" -#include "euclid.h" - -#ifdef __cplusplus -extern "C" { -#endif - -Color skyRayleighGetColor(Vector3 viewer, Vector3 direction, Vector3 sun_direction); -Color skyRayleighApplyToObject(Vector3 viewer, Vector3 object_location, Vector3 sun_direction, Color object_color); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib_paysages/terrain.c b/lib_paysages/terrain.c index 141d0cf..39f716c 100644 --- a/lib_paysages/terrain.c +++ b/lib_paysages/terrain.c @@ -231,7 +231,7 @@ static Color _getColor(TerrainDefinition* definition, Renderer* renderer, Vector Color color; color = renderer->applyTextures(renderer, point, precision); - color = renderer->applyAtmosphere(renderer, point, color); + color = renderer->atmosphere->applyAerialPerspective(renderer, point, color); color = renderer->applyClouds(renderer, color, renderer->camera_location, point); return color; diff --git a/lib_paysages/water.c b/lib_paysages/water.c index f0f6aed..48f6277 100644 --- a/lib_paysages/water.c +++ b/lib_paysages/water.c @@ -357,7 +357,7 @@ WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, renderer->getLightStatus(renderer, &light, location); color = renderer->applyLightStatus(renderer, &light, location, normal, material); - color = renderer->applyAtmosphere(renderer, location, color); + color = renderer->atmosphere->applyAerialPerspective(renderer, location, color); color = renderer->applyClouds(renderer, color, renderer->camera_location, location); result.base = definition->material.base;