diff --git a/data/gui.glade b/data/gui.glade
index 11a43ab..81622de 100644
--- a/data/gui.glade
+++ b/data/gui.glade
@@ -1064,6 +1064,337 @@ A small entropy will make the noise repeat more often.
False
+
+
+
+ 2
+
+
+
+
+ True
+ False
+ Sky
+
+
+ 2
+ False
+
+
True
@@ -1096,9 +1427,6 @@ A small entropy will make the noise repeat more often.
True
True
clouds_layers_model
-
-
-
Altitude
@@ -1223,7 +1551,7 @@ A small entropy will make the noise repeat more often.
- 2
+ 3
@@ -1233,7 +1561,7 @@ A small entropy will make the noise repeat more often.
Clouds
- 2
+ 3
False
@@ -1483,7 +1811,7 @@ This method is currently largely inaccurate and slower than two-pass rendering.<
- 3
+ 4
False
@@ -1494,7 +1822,7 @@ This method is currently largely inaccurate and slower than two-pass rendering.<
Render
- 3
+ 4
False
diff --git a/src/auto.c b/src/auto.c
index a63c10e..66dcf4f 100644
--- a/src/auto.c
+++ b/src/auto.c
@@ -11,6 +11,7 @@
#include "water.h"
#include "clouds.h"
+#include "sky.h"
static int _cpu_count = 1;
static int _is_rendering = 0;
@@ -19,7 +20,7 @@ void autoInit()
{
_cpu_count = (int)sysconf(_SC_NPROCESSORS_ONLN);
renderSetBackgroundColor(&COLOR_BLACK);
-
+
terrainInit();
waterInit();
}
@@ -67,15 +68,16 @@ void autoSetDaytime(int hour, int minute)
void autoSetDaytimeFraction(double daytime)
{
+ SkyDefinition sky;
+ ColorGradation grad_sun;
+ Color sun;
+
daytime = fmod(daytime, 1.0);
if (daytime < 0.0)
{
daytime += 1.0;
}
- ColorGradation grad_zenith, grad_haze, grad_sky, grad_sun;
- Color sun, zenith, haze;
-
lightingSetSunAngle(0.0, (daytime + 0.25) * M_PI * 2.0);
grad_sun = colorGradationCreate();
@@ -89,41 +91,18 @@ void autoSetDaytimeFraction(double daytime)
sun = colorGradationGet(&grad_sun, daytime);
lightingSetSunColor(sun);
- grad_zenith = colorGradationCreate();
- colorGradationAddRgba(&grad_zenith, 0.2, 0.03, 0.03, 0.05, 1.0);
- colorGradationAddRgba(&grad_zenith, 0.25, 0.25, 0.33, 0.37, 1.0);
- colorGradationAddRgba(&grad_zenith, 0.35, 0.52, 0.63, 0.8, 1.0);
- colorGradationAddRgba(&grad_zenith, 0.65, 0.52, 0.63, 0.8, 1.0);
- colorGradationAddRgba(&grad_zenith, 0.75, 0.25, 0.33, 0.37, 1.0);
- colorGradationAddRgba(&grad_zenith, 0.8, 0.03, 0.03, 0.05, 1.0);
- zenith = colorGradationGet(&grad_zenith, daytime);
+ sky = skyGetDefinition();
+ sky.daytime = daytime;
+ skySetDefinition(sky);
- grad_haze = colorGradationCreate();
- colorGradationAddRgba(&grad_haze, 0.2, 0.05, 0.05, 0.08, 1.0);
- colorGradationAddRgba(&grad_haze, 0.25, 0.55, 0.42, 0.42, 1.0);
- colorGradationAddRgba(&grad_haze, 0.3, 0.6, 0.6, 0.6, 1.0);
- colorGradationAddRgba(&grad_haze, 0.4, 0.92, 0.93, 1.0, 1.0);
- colorGradationAddRgba(&grad_haze, 0.6, 0.92, 0.93, 1.0, 1.0);
- colorGradationAddRgba(&grad_haze, 0.7, 0.6, 0.6, 0.8, 1.0);
- colorGradationAddRgba(&grad_haze, 0.75, 0.62, 0.50, 0.42, 1.0);
- colorGradationAddRgba(&grad_haze, 0.8, 0.05, 0.05, 0.08, 1.0);
- haze = colorGradationGet(&grad_haze, daytime);
-
- grad_sky = colorGradationCreate();
- colorGradationAdd(&grad_sky, 0.0, &haze);
- colorGradationAdd(&grad_sky, 0.45, &haze);
- colorGradationAdd(&grad_sky, 0.75, &zenith);
- colorGradationAdd(&grad_sky, 1.0, &zenith);
- skySetGradation(grad_sky);
-
- fogSetColor(haze);
+ fogSetColor(colorGradationGet(&sky.haze_color, daytime));
}
void autoSetRenderQuality(int quality)
{
WaterQuality water;
CloudsQuality clouds;
-
+
if (quality < 1)
{
quality = 1;
@@ -150,6 +129,7 @@ void autoGenRealisticLandscape(int seed)
Texture* tex;
WaterDefinition water;
CloudsDefinition cloud;
+ SkyDefinition sky;
int layer;
HeightModifier* mod;
Zone* zone;
@@ -187,7 +167,7 @@ void autoGenRealisticLandscape(int seed)
noiseAddLevelSimple(cloud.noise, 50.0 / 1000.0, 0.0005);
layer = cloudsAddLayer();
cloudsSetDefinition(layer, cloud);
-
+
/* Water */
water.height = 0.0;
water.transparency = 0.4;
@@ -203,6 +183,28 @@ void autoGenRealisticLandscape(int seed)
waterSetDefinition(water);
noiseDeleteGenerator(water.height_noise);
+ /* Sky */
+ sky.zenith_color = colorGradationCreate();
+ colorGradationAddRgba(&sky.zenith_color, 0.2, 0.03, 0.03, 0.05, 1.0);
+ colorGradationAddRgba(&sky.zenith_color, 0.25, 0.25, 0.33, 0.37, 1.0);
+ colorGradationAddRgba(&sky.zenith_color, 0.35, 0.52, 0.63, 0.8, 1.0);
+ colorGradationAddRgba(&sky.zenith_color, 0.65, 0.52, 0.63, 0.8, 1.0);
+ colorGradationAddRgba(&sky.zenith_color, 0.75, 0.25, 0.33, 0.37, 1.0);
+ colorGradationAddRgba(&sky.zenith_color, 0.8, 0.03, 0.03, 0.05, 1.0);
+ sky.haze_color = colorGradationCreate();
+ colorGradationAddRgba(&sky.haze_color, 0.2, 0.05, 0.05, 0.08, 1.0);
+ colorGradationAddRgba(&sky.haze_color, 0.25, 0.55, 0.42, 0.42, 1.0);
+ colorGradationAddRgba(&sky.haze_color, 0.3, 0.6, 0.6, 0.6, 1.0);
+ colorGradationAddRgba(&sky.haze_color, 0.4, 0.92, 0.93, 1.0, 1.0);
+ colorGradationAddRgba(&sky.haze_color, 0.6, 0.92, 0.93, 1.0, 1.0);
+ colorGradationAddRgba(&sky.haze_color, 0.7, 0.6, 0.6, 0.8, 1.0);
+ colorGradationAddRgba(&sky.haze_color, 0.75, 0.62, 0.50, 0.42, 1.0);
+ colorGradationAddRgba(&sky.haze_color, 0.8, 0.05, 0.05, 0.08, 1.0);
+ sky.daytime = 0.0;
+ sky.haze_height = 0.75;
+ sky.haze_smoothing = 0.3;
+ skySetDefinition(sky);
+
noise = noiseCreateGenerator();
noiseGenerateBaseNoise(noise, 1048576);
noiseAddLevelsSimple(noise, 10, 10.0, 1.0);
@@ -233,7 +235,7 @@ void autoGenRealisticLandscape(int seed)
zone = zoneCreate(0.0);
zoneAddHeightRange(zone, 1.0, 3.0, 4.0, 100.0, 100.0);
terrainAddTexture(tex, 0.5, zone, 0.1);*/
-
+
/* DEBUG */
mod = modifierCreate();
zone = modifierGetZone(mod);
@@ -313,13 +315,13 @@ void autoRenderSceneTwoPass(int postonly)
static int _postProcessRayTracingOverlay(RenderFragment* fragment)
{
Vector3 terrain_hit, look;
-
+
look = v3Sub(fragment->vertex.location, camera_location);
if (!terrainProjectRay(camera_location, look, &terrain_hit, &fragment->vertex.color))
{
fragment->vertex.color = skyProjectRay(camera_location, look);
}
-
+
return 1;
}
@@ -328,7 +330,7 @@ void autoRenderSceneRayTracing()
renderClear();
cameraPushOverlay(COLOR_RED, _postProcessRayTracingOverlay);
renderUpdate();
-
+
if (renderSetNextProgressStep(0.0, 1.0))
{
renderPostProcess(_cpu_count);
diff --git a/src/color.c b/src/color.c
index b3f395c..76d0f66 100644
--- a/src/color.c
+++ b/src/color.c
@@ -58,7 +58,7 @@ void colorMask(Color* base, Color* mask)
base->g = (mask->g * mask->a + base->g * base->a - base->g * base->a * mask->a) / new_a;
base->b = (mask->b * mask->a + base->b * base->a - base->b * base->a * mask->a) / new_a;
base->a = new_a;
-
+
/*double mask_weight = mask->a;
double base_weight = 1.0 - mask_weight;
@@ -182,3 +182,28 @@ Color colorGradationGet(ColorGradation* gradation, double value)
}
}
+void colorGradationSave(FILE* f, ColorGradation gradation)
+{
+ int i;
+
+ toolsSaveInt(f, gradation.nbparts);
+ for (i = 0; i < gradation.nbparts; i++)
+ {
+ toolsSaveDouble(f, gradation.parts[i].start);
+ colorSave(gradation.parts[i].col, f);
+ }
+}
+
+ColorGradation colorGradationLoad(FILE* f)
+{
+ ColorGradation result;
+ int i;
+
+ result.nbparts = toolsLoadInt(f);
+ for (i = 0; i < result.nbparts; i++)
+ {
+ result.parts[i].start = toolsLoadDouble(f);
+ result.parts[i].col = colorLoad(f);
+ }
+
+}
diff --git a/src/gui/tab_sky.c b/src/gui/tab_sky.c
new file mode 100644
index 0000000..2987a8f
--- /dev/null
+++ b/src/gui/tab_sky.c
@@ -0,0 +1,177 @@
+/* Terrain tab */
+
+#include "common.h"
+#include "../shared/functions.h"
+#include "../shared/constants.h"
+#include "../sky.h"
+#include
+
+static SmallPreview* _preview_horizon;
+static SkyDefinition _definition;
+
+static Color _cbPreviewHorizon(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
+{
+ Color result;
+ double height;
+
+ height = terrainGetHeight(x, y);
+ if (height <= _definition.height)
+ {
+ return _definition.main_color;
+ }
+ else
+ {
+ result.r = result.g = result.b = terrainGetHeightNormalized(x, y);
+ result.a = 1.0;
+
+ return result;
+ }
+}
+
+static Color _cbPreviewRender(SmallPreview* preview, double x, double y, double xoffset, double yoffset, double scaling)
+{
+ Vector3 eye, look, location;
+ WaterDefinition definition;
+ WaterEnvironment environment;
+ WaterQuality quality;
+
+ eye.x = 0.0;
+ eye.y = scaling;
+ eye.z = -10.0 * scaling;
+ 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)
+ {
+ return _rayCastFromWater(eye, look).hit_color;
+ }
+
+ location.x = eye.x - look.x * eye.y / look.y;
+ location.y = 0.0;
+ location.z = eye.z - look.z * eye.y / look.y;
+
+ if (location.z > 0.0)
+ {
+ return _rayCastFromWater(eye, look).hit_color;
+ }
+
+ definition = _definition;
+ definition.height = 0.0;
+ environment.reflection_function = _rayCastFromWater;
+ environment.refraction_function = _rayCastFromWater;
+ environment.toggle_fog = 0;
+ environment.toggle_shadows = 0;
+ quality.force_detail = 0.0001;
+
+ return waterGetColorCustom(location, look, &definition, &quality, &environment).final;
+}
+
+static void _cbEditNoiseDone(NoiseGenerator* generator)
+{
+ noiseCopy(generator, _definition.height_noise);
+ guiPreviewRedraw(_preview_render);
+}
+
+static void _cbEditNoise(GtkWidget* widget, gpointer data)
+{
+ guiNoiseEdit(_definition.height_noise, _cbEditNoiseDone);
+}
+
+static void _cbHeightChanged(GtkRange* range, gpointer data)
+{
+ _definition.height = gtk_range_get_value(range);
+ guiPreviewRedraw(_preview_coverage);
+}
+
+static void _cbTransparencyChanged(GtkRange* range, gpointer data)
+{
+ _definition.transparency = gtk_range_get_value(range);
+ guiPreviewRedraw(_preview_render);
+}
+
+static void _cbReflectionChanged(GtkRange* range, gpointer data)
+{
+ _definition.reflection = gtk_range_get_value(range);
+ guiPreviewRedraw(_preview_render);
+}
+
+static void _cbColorChanged(GtkColorButton* colorbutton, gpointer data)
+{
+ GdkRGBA col;
+
+ gtk_color_button_get_rgba(colorbutton, &col);
+ _definition.main_color.r = col.red;
+ _definition.main_color.g = col.green;
+ _definition.main_color.b = col.blue;
+ _definition.main_color.a = 1.0;
+
+ guiPreviewRedraw(_preview_render);
+ guiPreviewRedraw(_preview_coverage);
+}
+
+static void _cbRevertConfig(GtkWidget* widget, gpointer data)
+{
+ GdkRGBA col;
+
+ waterCopyDefinition(waterGetDefinition(), &_definition);
+
+ gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_height")), _definition.height);
+ gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_transparency")), _definition.transparency);
+ gtk_range_set_value(GTK_RANGE(GET_WIDGET("water_reflection")), _definition.reflection);
+ col.red = _definition.main_color.r;
+ col.green = _definition.main_color.g;
+ col.blue = _definition.main_color.b;
+ col.alpha = 1.0;
+ gtk_color_button_set_rgba(GTK_COLOR_BUTTON(GET_WIDGET("water_color")), &col);
+
+ guiPreviewRedraw(_preview_render);
+ guiPreviewRedraw(_preview_coverage);
+}
+
+static void _cbApplyConfig(GtkWidget* widget, gpointer data)
+{
+ waterSetDefinition(_definition);
+ guiUpdate();
+}
+
+void guiWaterInit()
+{
+ _definition = waterCreateDefinition();
+
+ /* Buttons */
+ g_signal_connect(GET_WIDGET("water_noise_edit"), "clicked", G_CALLBACK(_cbEditNoise), NULL);
+ g_signal_connect(GET_WIDGET("water_apply"), "clicked", G_CALLBACK(_cbApplyConfig), NULL);
+ g_signal_connect(GET_WIDGET("water_revert"), "clicked", G_CALLBACK(_cbRevertConfig), NULL);
+
+ /* Configs */
+ gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_height")), -20.0, 20.0);
+ gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_transparency")), 0.0, 1.0);
+ gtk_range_set_range(GTK_RANGE(GET_WIDGET("water_reflection")), 0.0, 1.0);
+
+ /* Config signals */
+ g_signal_connect(GET_WIDGET("water_height"), "value-changed", G_CALLBACK(_cbHeightChanged), NULL);
+ g_signal_connect(GET_WIDGET("water_transparency"), "value-changed", G_CALLBACK(_cbTransparencyChanged), NULL);
+ g_signal_connect(GET_WIDGET("water_reflection"), "value-changed", G_CALLBACK(_cbReflectionChanged), NULL);
+ g_signal_connect(GET_WIDGET("water_color"), "color-set", G_CALLBACK(_cbColorChanged), NULL);
+
+ /* Previews */
+ _preview_coverage = guiPreviewNew(GTK_IMAGE(GET_WIDGET("water_preview_coverage")));
+ guiPreviewConfigScaling(_preview_coverage, 0.01, 1.0, 0.05);
+ guiPreviewConfigScrolling(_preview_coverage, -1000.0, 1000.0, -1000.0, 1000.0);
+ guiPreviewSetViewport(_preview_coverage, 0.0, 0.0, 0.2);
+ guiPreviewSetRenderer(_preview_coverage, _cbPreviewCoverage);
+ _preview_render = guiPreviewNew(GTK_IMAGE(GET_WIDGET("water_preview_render")));
+ guiPreviewConfigScaling(_preview_render, 0.1, 1.0, 0.1);
+ guiPreviewConfigScrolling(_preview_render, -10.0, 10.0, -10.0, 10.0);
+ guiPreviewSetViewport(_preview_render, 0.0, 0.0, 0.5);
+ guiPreviewSetRenderer(_preview_render, _cbPreviewRender);
+
+ guiWaterUpdate();
+}
+
+void guiWaterUpdate()
+{
+ _cbRevertConfig(NULL, NULL);
+}
diff --git a/src/shared/functions.h b/src/shared/functions.h
index 3276c27..30c6277 100644
--- a/src/shared/functions.h
+++ b/src/shared/functions.h
@@ -49,6 +49,8 @@ ColorGradation colorGradationCreate();
void colorGradationAdd(ColorGradation* gradation, double value, Color* col);
void colorGradationAddRgba(ColorGradation* gradation, double value, double r, double g, double b, double a);
Color colorGradationGet(ColorGradation* gradation, double value);
+void colorGradationSave(FILE* f, ColorGradation gradation);
+ColorGradation colorGradationLoad(FILE* f);
/* euclid.c */
void v3Save(Vector3 v, FILE* f);
diff --git a/src/sky.c b/src/sky.c
index df4afbb..8b05ec1 100644
--- a/src/sky.c
+++ b/src/sky.c
@@ -6,22 +6,106 @@
#include "shared/globals.h"
#include "shared/constants.h"
#include "clouds.h"
+#include "sky.h"
-ColorGradation _gradation;
#define SPHERE_SIZE 1000.0
+SkyDefinition _definition;
+SkyQuality _quality;
+SkyEnvironment _environment;
+
+void skyInit()
+{
+ skySetDefinition(skyCreateDefinition());
+}
+
void skySave(FILE* f)
{
+ toolsSaveDouble(f, _definition.daytime);
+ colorGradationSave(f, _definition.sun_color);
+ toolsSaveDouble(f, _definition.sun_radius);
+ colorGradationSave(f, _definition.zenith_color);
+ colorGradationSave(f, _definition.haze_color);
+ toolsSaveDouble(f, _definition.haze_height);
+ toolsSaveDouble(f, _definition.haze_smoothing);
}
void skyLoad(FILE* f)
{
+
+ SkyDefinition def;
+
+ def.daytime = toolsLoadDouble(f);
+ def.sun_color = colorGradationLoad(f);
+ def.sun_radius = toolsLoadDouble(f);
+ def.zenith_color = colorGradationLoad(f);
+ def.haze_color = colorGradationLoad(f);
+ def.haze_height = toolsLoadDouble(f);
+ def.haze_smoothing = toolsLoadDouble(f);
+
+ skySetDefinition(def);
}
-Color skyGetColor(Vector3 start, Vector3 direction)
+SkyDefinition skyCreateDefinition()
{
- direction = v3Normalize(direction);
- return colorGradationGet(&_gradation, direction.y * 0.5 + 0.5);
+ SkyDefinition def;
+
+ def.daytime = 0.0;
+ def.sun_color = colorGradationCreate();
+ def.sun_radius = 1.0;
+ def.zenith_color = colorGradationCreate();
+ def.haze_color = colorGradationCreate();
+ def.haze_height = 0.0;
+ def.haze_smoothing = 0.0;
+
+ skyValidateDefinition(&def);
+
+ return def;
+}
+
+void skyDeleteDefinition(SkyDefinition definition)
+{
+}
+
+void skyCopyDefinition(SkyDefinition source, SkyDefinition* destination)
+{
+ *destination = source;
+}
+
+void skyValidateDefinition(SkyDefinition* definition)
+{
+ Color zenith, haze;
+
+ zenith = colorGradationGet(&definition->zenith_color, definition->daytime);
+ haze = colorGradationGet(&definition->haze_color, definition->daytime);
+
+ definition->_sky_gradation = colorGradationCreate();
+ colorGradationAdd(&definition->_sky_gradation, 0.0, &haze);
+ colorGradationAdd(&definition->_sky_gradation, definition->haze_height - definition->haze_smoothing, &haze);
+ colorGradationAdd(&definition->_sky_gradation, definition->haze_height, &zenith);
+ colorGradationAdd(&definition->_sky_gradation, 1.0, &zenith);
+}
+
+void skySetDefinition(SkyDefinition definition)
+{
+ skyValidateDefinition(&definition);
+ _definition = definition;
+}
+
+SkyDefinition skyGetDefinition()
+{
+ return _definition;
+}
+
+Color skyGetColorCustom(Vector3 eye, Vector3 look, SkyDefinition* definition, SkyQuality* quality, SkyEnvironment* environment)
+{
+ look = v3Normalize(look);
+ return colorGradationGet(&_definition._sky_gradation, look.y * 0.5 + 0.5);
+}
+
+Color skyGetColor(Vector3 eye, Vector3 look)
+{
+ return skyGetColorCustom(eye, look, &_definition, &_quality, &_environment);
}
Color skyProjectRay(Vector3 start, Vector3 direction)
@@ -29,20 +113,15 @@ Color skyProjectRay(Vector3 start, Vector3 direction)
Color color_sky, color_clouds;
direction = v3Normalize(direction);
-
+
color_sky = skyGetColor(start, direction);
color_clouds = cloudsGetColor(start, v3Add(start, v3Scale(direction, SPHERE_SIZE)));
-
+
colorMask(&color_sky, &color_clouds);
return color_sky;
}
-void skySetGradation(ColorGradation grad)
-{
- _gradation = grad;
-}
-
static int _postProcessFragment(RenderFragment* fragment)
{
Vector3 location, direction;
@@ -53,7 +132,7 @@ static int _postProcessFragment(RenderFragment* fragment)
color_sky = skyGetColor(camera_location, v3Normalize(direction));
color_clouds = cloudsGetColor(camera_location, v3Add(camera_location, v3Scale(direction, 10.0)));
-
+
colorMask(&color_sky, &color_clouds);
fragment->vertex.color = color_sky;
@@ -85,7 +164,7 @@ void skyRender(RenderProgressCallback callback)
{
return;
}
-
+
current_j = (double)(j - res_j / 2) * step_j;
for (i = 0; i < res_i; i++)
diff --git a/src/sky.h b/src/sky.h
new file mode 100644
index 0000000..39bd97f
--- /dev/null
+++ b/src/sky.h
@@ -0,0 +1,49 @@
+#ifndef _PAYSAGES_SKY_H_
+#define _PAYSAGES_SKY_H_
+
+#include "shared/types.h"
+#include
+
+typedef struct
+{
+ double daytime;
+ ColorGradation sun_color;
+ double sun_radius;
+ ColorGradation zenith_color;
+ ColorGradation haze_color;
+ double haze_height;
+ double haze_smoothing;
+ ColorGradation _sky_gradation;
+} SkyDefinition;
+
+typedef struct
+{
+ int unused;
+} SkyQuality;
+
+typedef struct
+{
+ int unused;
+} SkyEnvironment;
+
+void skyInit();
+void skySave(FILE* f);
+void skyLoad(FILE* f);
+
+SkyDefinition skyCreateDefinition();
+void skyDeleteDefinition(SkyDefinition definition);
+void skyCopyDefinition(SkyDefinition source, SkyDefinition* destination);
+void skyValidateDefinition(SkyDefinition* definition);
+void skySetDefinition(SkyDefinition definition);
+SkyDefinition skyGetDefinition();
+
+void skySetQuality(SkyQuality quality);
+SkyQuality skyGetQuality();
+
+Color skyGetColorCustom(Vector3 eye, Vector3 look, SkyDefinition* definition, SkyQuality* quality, SkyEnvironment* environment);
+Color skyGetColor(Vector3 eye, Vector3 look);
+
+Color skyProjectRay(Vector3 start, Vector3 direction);
+void skyRender(RenderProgressCallback callback);
+
+#endif