diff --git a/TODO b/TODO index 90006fe..f0d4fba 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,3 @@ -- Refactor fog in a new 'atmosphere' module. -- Make multi-lights work, to restore lighting from skydome. - In GUI, revertConfig should lock the previews while reverting. - All Save and Load methods should have same signature : void ...Save(FILE*, ...*) - All noises should use the same entropy pool (saved separately), and avoid reallocs. diff --git a/gui_qt/dialogrender.cpp b/gui_qt/dialogrender.cpp index 8478a8f..32aa823 100644 --- a/gui_qt/dialogrender.cpp +++ b/gui_qt/dialogrender.cpp @@ -6,7 +6,6 @@ #include #include "../lib_paysages/render.h" -#include "../lib_paysages/renderer.h" #include "../lib_paysages/scenery.h" #include "../lib_paysages/auto.h" #include "../lib_paysages/shared/functions.h" @@ -97,10 +96,22 @@ DialogRender::DialogRender(QWidget *parent): progress_value = 0; } +DialogRender::~DialogRender() +{ + if (render_thread) + { + renderInterrupt(); + render_thread->wait(); + + renderSetPreviewCallbacks(NULL, NULL, NULL, NULL); + + delete render_thread; + } + delete pixbuf; +} + void DialogRender::startRender(int quality, int width, int height) { - Renderer renderer; - renderer = sceneryGetStandardRenderer(quality); renderSetSize(width, height); renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate); @@ -118,17 +129,3 @@ void DialogRender::loadLastRender() exec(); } - -DialogRender::~DialogRender() -{ - if (render_thread) - { - renderInterrupt(); - render_thread->wait(); - - renderSetPreviewCallbacks(NULL, NULL, NULL, NULL); - - delete render_thread; - } - delete pixbuf; -} diff --git a/gui_qt/dialogrender.h b/gui_qt/dialogrender.h index 633b8b7..cee80c0 100644 --- a/gui_qt/dialogrender.h +++ b/gui_qt/dialogrender.h @@ -5,6 +5,7 @@ #include #include #include +#include "../lib_paysages/renderer.h" class DialogRender : public QDialog { @@ -12,10 +13,10 @@ class DialogRender : public QDialog public: explicit DialogRender(QWidget *parent); ~DialogRender(); - + void startRender(int quality, int width, int height); void loadLastRender(); - + QImage* pixbuf; QWidget* area; QScrollArea* scroll; @@ -24,6 +25,7 @@ public: private: QThread* render_thread; + Renderer renderer; }; #endif // _PAYSAGES_QT_DIALOGRENDER_H_ diff --git a/gui_qt/preview.cpp b/gui_qt/preview.cpp index 1cb9216..d19b46d 100644 --- a/gui_qt/preview.cpp +++ b/gui_qt/preview.cpp @@ -117,7 +117,7 @@ void Preview::resizeEvent(QResizeEvent* event) this->pixbuf = new QImage(this->size(), QImage::Format_ARGB32); this->pixbuf->fill(0x00000000); - this->need_rerender = false; + this->need_rerender = true; this->need_render = true; delete image; diff --git a/lib_paysages/auto.c b/lib_paysages/auto.c index 59700bc..64b21c1 100644 --- a/lib_paysages/auto.c +++ b/lib_paysages/auto.c @@ -85,8 +85,10 @@ void autoGenRealisticLandscape(int seed) cloud->ymin = 10.0; cloud->ycenter = 40.0; cloud->ymax = 100.0; - cloud->color = COLOR_WHITE; - cloud->color.a = 0.1; + cloud->color.r = 0.7; + cloud->color.g = 0.7; + cloud->color.b = 0.7; + cloud->color.a = 0.05; cloud->scaling = 50.0; cloud->coverage = 0.5; noiseGenerateBaseNoise(cloud->noise, 262144); diff --git a/lib_paysages/lighting.c b/lib_paysages/lighting.c index 1b4f591..640378a 100644 --- a/lib_paysages/lighting.c +++ b/lib_paysages/lighting.c @@ -19,10 +19,13 @@ static LightDefinition _LIGHT_NULL; void lightingInit() { - _LIGHT_NULL.color = COLOR_BLACK; _LIGHT_NULL.direction.x = 0.0; _LIGHT_NULL.direction.y = 1.0; _LIGHT_NULL.direction.z = 0.0; + _LIGHT_NULL.color = COLOR_BLACK; + _LIGHT_NULL.filtered = 0; + _LIGHT_NULL.masked = 0; + _LIGHT_NULL.amplitude = 0.0; } void lightingSave(FILE* f, LightingDefinition* definition) @@ -33,9 +36,11 @@ void lightingSave(FILE* f, LightingDefinition* definition) toolsSaveInt(f, definition->nblights); for (i = 0; i < definition->nblights; i++) { - colorSave(definition->lights[i].color, f); v3Save(definition->lights[i].direction, f); - toolsSaveDouble(f, definition->lights[i].maxshadow); + colorSave(definition->lights[i].color, f); + toolsSaveInt(f, definition->lights[i].filtered); + toolsSaveInt(f, definition->lights[i].masked); + toolsSaveDouble(f, definition->lights[i].amplitude); } } @@ -47,9 +52,11 @@ void lightingLoad(FILE* f, LightingDefinition* definition) definition->nblights = toolsLoadInt(f); for (i = 0; i < definition->nblights; i++) { - definition->lights[i].color = colorLoad(f); definition->lights[i].direction = v3Load(f); - definition->lights[i].maxshadow = toolsLoadDouble(f); + definition->lights[i].color = colorLoad(f); + definition->lights[i].filtered = toolsLoadInt(f); + definition->lights[i].masked = toolsLoadInt(f); + definition->lights[i].amplitude = toolsLoadDouble(f); } lightingValidateDefinition(definition); @@ -143,7 +150,14 @@ static Color _applyLightCustom(LightDefinition* definition, Renderer* renderer, light = definition->color; direction_inv = v3Scale(definition->direction, -1.0); - light = renderer->filterLight(renderer, light, location, v3Add(location, v3Scale(direction_inv, 1000.0)), direction_inv); + if (definition->masked) + { + light = renderer->maskLight(renderer, light, location, v3Add(location, v3Scale(direction_inv, 1000.0)), direction_inv); + } + if (definition->filtered) + { + light = renderer->filterLight(renderer, light, location, v3Add(location, v3Scale(direction_inv, 1000.0)), direction_inv); + } normal_norm = v3Norm(normal); if (normal_norm > 1.0) @@ -156,13 +170,21 @@ static Color _applyLightCustom(LightDefinition* definition, Renderer* renderer, reflect = v3Sub(v3Scale(normal, 2.0 * v3Dot(direction_inv, normal)), direction_inv); diffuse = v3Dot(direction_inv, normal); - //diffuse = pow(diffuse * 0.5 + 0.5, 2.0); - diffuse = (diffuse * 0.5 + 0.5); + diffuse = pow(diffuse * 0.5 + 0.5, 2.0); + //diffuse = (diffuse * 0.5 + 0.5); if (diffuse > 0.0) { if (material.shininess > 0.0) { - specular = pow(v3Dot(reflect, view) * material.reflection, material.shininess * 10.0 + 1.0); + specular = v3Dot(reflect, view) * material.reflection; + if (specular > 0.0) + { + specular = pow(specular, material.shininess * 10.0 + 1.0); + } + else + { + specular = 0.0; + } } else { @@ -188,18 +210,26 @@ static Color _applyLightCustom(LightDefinition* definition, Renderer* renderer, Color lightingApplyToSurface(LightingDefinition* definition, Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material) { - Color result; + Color result, lighted; int i; - /* TODO Merge lights */ - result = material.base; + result = COLOR_BLACK; + result.a = material.base.a; + for (i = 0; i < definition->nblights; i++) { - result = _applyLightCustom(definition->lights + i, renderer, location, normal, material); + lighted = _applyLightCustom(definition->lights + i, renderer, location, normal, material); + result.r += lighted.r; + result.g += lighted.g; + result.b += lighted.b; } for (i = 0; i < definition->_nbautolights; i++) { - result = _applyLightCustom(definition->_autolights + i, renderer, location, normal, material); + lighted = _applyLightCustom(definition->_autolights + i, renderer, location, normal, material); + result.r += lighted.r; + result.g += lighted.g; + result.b += lighted.b; } + return result; } diff --git a/lib_paysages/lighting.h b/lib_paysages/lighting.h index ad43dc1..90c0459 100644 --- a/lib_paysages/lighting.h +++ b/lib_paysages/lighting.h @@ -13,9 +13,11 @@ extern "C" { typedef struct { - Vector3 direction; - Color color; - double maxshadow; + Vector3 direction; /* Global direction of the light */ + Color color; /* Main color of the light */ + int filtered; /* Should the light be filtered (by atmosphere, water...) */ + int masked; /* Should the light be masked (cast shadows..) */ + double amplitude; /* Angle amplitude of the light source (for multi-sampling, pi / 2.0 for skydome) */ } LightDefinition; typedef struct diff --git a/lib_paysages/render.c b/lib_paysages/render.c index 10534d5..484f245 100644 --- a/lib_paysages/render.c +++ b/lib_paysages/render.c @@ -34,7 +34,7 @@ static volatile double _progress = 0.0; static volatile double _progress_step_start = 0.0; static volatile double _progress_step_length = 1.0; -#define RENDER_INVERSE 1 +/*#define RENDER_INVERSE 1*/ #define RENDER_WIREFRAME 1 static void _previewResize(int width, int height) {} diff --git a/lib_paysages/renderer.c b/lib_paysages/renderer.c index ac5ae54..0301292 100644 --- a/lib_paysages/renderer.c +++ b/lib_paysages/renderer.c @@ -9,6 +9,11 @@ static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_loca return light_color; } +static Color _maskLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light) +{ + return light_color; +} + static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material) { return material.base; @@ -62,6 +67,7 @@ Renderer rendererGetFake() result.camera_location = VECTOR_ZERO; result.filterLight = _filterLight; + result.maskLight = _maskLight; result.applyLightingToSurface = _applyLightingToSurface; result.rayWalking = _rayWalking; result.getTerrainHeight = _getTerrainHeight; diff --git a/lib_paysages/renderer.h b/lib_paysages/renderer.h index 5a3d341..665e92d 100644 --- a/lib_paysages/renderer.h +++ b/lib_paysages/renderer.h @@ -29,6 +29,7 @@ struct Renderer /* Lighting related */ Color (*filterLight)(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light); + Color (*maskLight)(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light); Color (*applyLightingToSurface)(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material); /* Custom data */ diff --git a/lib_paysages/scenery.c b/lib_paysages/scenery.c index 76825de..c839ce3 100644 --- a/lib_paysages/scenery.c +++ b/lib_paysages/scenery.c @@ -210,9 +210,15 @@ void sceneryRenderSecondPass(Renderer* renderer) /******* Standard renderer *********/ static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light) { - light_color = waterLightFilter(&_water, renderer, light_color, at_location, light_location, direction_to_light); - light_color = terrainLightFilter(&_terrain, renderer, light_color, at_location, light_location, direction_to_light); // TODO atmosphere filter + light_color = waterLightFilter(&_water, renderer, light_color, at_location, light_location, direction_to_light); + + return light_color; +} + +static Color _maskLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light) +{ + light_color = terrainLightFilter(&_terrain, renderer, light_color, at_location, light_location, direction_to_light); light_color = cloudsFilterLight(&_clouds, renderer, light_color, at_location, light_location, direction_to_light); return light_color; @@ -294,6 +300,7 @@ Renderer sceneryGetStandardRenderer(int quality) result.render_quality = quality; result.filterLight = _filterLight; + result.maskLight = _maskLight; result.applyLightingToSurface = _applyLightingToSurface; result.rayWalking = _rayWalking; result.getTerrainHeight = _getTerrainHeight; diff --git a/lib_paysages/sky.c b/lib_paysages/sky.c index 956267e..f5d6527 100644 --- a/lib_paysages/sky.c +++ b/lib_paysages/sky.c @@ -92,12 +92,32 @@ int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights) sun_direction.y = sin(sun_angle); sun_direction.z = 0.0; + /* TODO Night lights */ + if (max_lights > 0) { - lights[0].color = colorGradationGet(&sky->sun_color, sky->daytime); + /* Light from the sun */ lights[0].direction = v3Scale(sun_direction, -1.0); - lights[0].maxshadow = 1.0; + lights[0].color = colorGradationGet(&sky->sun_color, sky->daytime); + lights[0].filtered = 1; + lights[0].masked = 1; + lights[0].amplitude = 0.0; nblights = 1; + if (max_lights > 1) + { + /* Skydome lighting */ + lights[1].direction.x = 0.0; + lights[1].direction.y = -1.0; + lights[1].direction.z = 0.0; + lights[1].color = colorGradationGet(&sky->zenith_color, sky->daytime); + lights[1].color.r *= 0.4; + lights[1].color.g *= 0.4; + lights[1].color.b *= 0.4; + lights[1].filtered = 1; + lights[1].masked = 0; + lights[1].amplitude = M_PI / 2.0; + nblights = 2; + } } return nblights; diff --git a/lib_paysages/terrain.c b/lib_paysages/terrain.c index e69c671..67ea150 100644 --- a/lib_paysages/terrain.c +++ b/lib_paysages/terrain.c @@ -171,6 +171,11 @@ Color terrainLightFilter(TerrainDefinition* definition, Renderer* renderer, Colo double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length; direction_to_light = v3Normalize(direction_to_light); + if (fabs(direction_to_light.x) < 0.0001 && fabs(direction_to_light.z) < 0.0001) + { + return light; + } + inc_factor = (double)renderer->render_quality; inc_base = 1.0; inc_value = inc_base / inc_factor; diff --git a/lib_paysages/water.c b/lib_paysages/water.c index 4865fe6..a32a985 100644 --- a/lib_paysages/water.c +++ b/lib_paysages/water.c @@ -137,7 +137,7 @@ Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color li { if (direction_to_light.y > 0.00001) { - factor = (definition->height - location.y) / (direction_to_light.y * 5.0); // TODO Configurable + factor = (definition->height - location.y) / (direction_to_light.y * 3.0); // TODO Configurable if (factor > 1.0) { factor = 1.0;