paysages: Made multi-light working.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@236 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
1e922ccbce
commit
a2307c4746
14 changed files with 117 additions and 47 deletions
2
TODO
2
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.
|
- In GUI, revertConfig should lock the previews while reverting.
|
||||||
- All Save and Load methods should have same signature : void ...Save(FILE*, ...*)
|
- 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.
|
- All noises should use the same entropy pool (saved separately), and avoid reallocs.
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
#include "../lib_paysages/render.h"
|
#include "../lib_paysages/render.h"
|
||||||
#include "../lib_paysages/renderer.h"
|
|
||||||
#include "../lib_paysages/scenery.h"
|
#include "../lib_paysages/scenery.h"
|
||||||
#include "../lib_paysages/auto.h"
|
#include "../lib_paysages/auto.h"
|
||||||
#include "../lib_paysages/shared/functions.h"
|
#include "../lib_paysages/shared/functions.h"
|
||||||
|
@ -97,10 +96,22 @@ DialogRender::DialogRender(QWidget *parent):
|
||||||
progress_value = 0;
|
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)
|
void DialogRender::startRender(int quality, int width, int height)
|
||||||
{
|
{
|
||||||
Renderer renderer;
|
|
||||||
|
|
||||||
renderer = sceneryGetStandardRenderer(quality);
|
renderer = sceneryGetStandardRenderer(quality);
|
||||||
renderSetSize(width, height);
|
renderSetSize(width, height);
|
||||||
renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate);
|
renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate);
|
||||||
|
@ -118,17 +129,3 @@ void DialogRender::loadLastRender()
|
||||||
|
|
||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogRender::~DialogRender()
|
|
||||||
{
|
|
||||||
if (render_thread)
|
|
||||||
{
|
|
||||||
renderInterrupt();
|
|
||||||
render_thread->wait();
|
|
||||||
|
|
||||||
renderSetPreviewCallbacks(NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
delete render_thread;
|
|
||||||
}
|
|
||||||
delete pixbuf;
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
#include "../lib_paysages/renderer.h"
|
||||||
|
|
||||||
class DialogRender : public QDialog
|
class DialogRender : public QDialog
|
||||||
{
|
{
|
||||||
|
@ -12,10 +13,10 @@ class DialogRender : public QDialog
|
||||||
public:
|
public:
|
||||||
explicit DialogRender(QWidget *parent);
|
explicit DialogRender(QWidget *parent);
|
||||||
~DialogRender();
|
~DialogRender();
|
||||||
|
|
||||||
void startRender(int quality, int width, int height);
|
void startRender(int quality, int width, int height);
|
||||||
void loadLastRender();
|
void loadLastRender();
|
||||||
|
|
||||||
QImage* pixbuf;
|
QImage* pixbuf;
|
||||||
QWidget* area;
|
QWidget* area;
|
||||||
QScrollArea* scroll;
|
QScrollArea* scroll;
|
||||||
|
@ -24,6 +25,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QThread* render_thread;
|
QThread* render_thread;
|
||||||
|
Renderer renderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _PAYSAGES_QT_DIALOGRENDER_H_
|
#endif // _PAYSAGES_QT_DIALOGRENDER_H_
|
||||||
|
|
|
@ -117,7 +117,7 @@ void Preview::resizeEvent(QResizeEvent* event)
|
||||||
this->pixbuf = new QImage(this->size(), QImage::Format_ARGB32);
|
this->pixbuf = new QImage(this->size(), QImage::Format_ARGB32);
|
||||||
|
|
||||||
this->pixbuf->fill(0x00000000);
|
this->pixbuf->fill(0x00000000);
|
||||||
this->need_rerender = false;
|
this->need_rerender = true;
|
||||||
this->need_render = true;
|
this->need_render = true;
|
||||||
|
|
||||||
delete image;
|
delete image;
|
||||||
|
|
|
@ -85,8 +85,10 @@ void autoGenRealisticLandscape(int seed)
|
||||||
cloud->ymin = 10.0;
|
cloud->ymin = 10.0;
|
||||||
cloud->ycenter = 40.0;
|
cloud->ycenter = 40.0;
|
||||||
cloud->ymax = 100.0;
|
cloud->ymax = 100.0;
|
||||||
cloud->color = COLOR_WHITE;
|
cloud->color.r = 0.7;
|
||||||
cloud->color.a = 0.1;
|
cloud->color.g = 0.7;
|
||||||
|
cloud->color.b = 0.7;
|
||||||
|
cloud->color.a = 0.05;
|
||||||
cloud->scaling = 50.0;
|
cloud->scaling = 50.0;
|
||||||
cloud->coverage = 0.5;
|
cloud->coverage = 0.5;
|
||||||
noiseGenerateBaseNoise(cloud->noise, 262144);
|
noiseGenerateBaseNoise(cloud->noise, 262144);
|
||||||
|
|
|
@ -19,10 +19,13 @@ static LightDefinition _LIGHT_NULL;
|
||||||
|
|
||||||
void lightingInit()
|
void lightingInit()
|
||||||
{
|
{
|
||||||
_LIGHT_NULL.color = COLOR_BLACK;
|
|
||||||
_LIGHT_NULL.direction.x = 0.0;
|
_LIGHT_NULL.direction.x = 0.0;
|
||||||
_LIGHT_NULL.direction.y = 1.0;
|
_LIGHT_NULL.direction.y = 1.0;
|
||||||
_LIGHT_NULL.direction.z = 0.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)
|
void lightingSave(FILE* f, LightingDefinition* definition)
|
||||||
|
@ -33,9 +36,11 @@ void lightingSave(FILE* f, LightingDefinition* definition)
|
||||||
toolsSaveInt(f, definition->nblights);
|
toolsSaveInt(f, definition->nblights);
|
||||||
for (i = 0; i < definition->nblights; i++)
|
for (i = 0; i < definition->nblights; i++)
|
||||||
{
|
{
|
||||||
colorSave(definition->lights[i].color, f);
|
|
||||||
v3Save(definition->lights[i].direction, 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);
|
definition->nblights = toolsLoadInt(f);
|
||||||
for (i = 0; i < definition->nblights; i++)
|
for (i = 0; i < definition->nblights; i++)
|
||||||
{
|
{
|
||||||
definition->lights[i].color = colorLoad(f);
|
|
||||||
definition->lights[i].direction = v3Load(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);
|
lightingValidateDefinition(definition);
|
||||||
|
@ -143,7 +150,14 @@ static Color _applyLightCustom(LightDefinition* definition, Renderer* renderer,
|
||||||
light = definition->color;
|
light = definition->color;
|
||||||
|
|
||||||
direction_inv = v3Scale(definition->direction, -1.0);
|
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);
|
normal_norm = v3Norm(normal);
|
||||||
if (normal_norm > 1.0)
|
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);
|
reflect = v3Sub(v3Scale(normal, 2.0 * v3Dot(direction_inv, normal)), direction_inv);
|
||||||
|
|
||||||
diffuse = v3Dot(direction_inv, normal);
|
diffuse = v3Dot(direction_inv, normal);
|
||||||
//diffuse = pow(diffuse * 0.5 + 0.5, 2.0);
|
diffuse = pow(diffuse * 0.5 + 0.5, 2.0);
|
||||||
diffuse = (diffuse * 0.5 + 0.5);
|
//diffuse = (diffuse * 0.5 + 0.5);
|
||||||
if (diffuse > 0.0)
|
if (diffuse > 0.0)
|
||||||
{
|
{
|
||||||
if (material.shininess > 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
|
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 lightingApplyToSurface(LightingDefinition* definition, Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material)
|
||||||
{
|
{
|
||||||
Color result;
|
Color result, lighted;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* TODO Merge lights */
|
result = COLOR_BLACK;
|
||||||
result = material.base;
|
result.a = material.base.a;
|
||||||
|
|
||||||
for (i = 0; i < definition->nblights; i++)
|
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++)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,11 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Vector3 direction;
|
Vector3 direction; /* Global direction of the light */
|
||||||
Color color;
|
Color color; /* Main color of the light */
|
||||||
double maxshadow;
|
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;
|
} LightDefinition;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -34,7 +34,7 @@ static volatile double _progress = 0.0;
|
||||||
static volatile double _progress_step_start = 0.0;
|
static volatile double _progress_step_start = 0.0;
|
||||||
static volatile double _progress_step_length = 1.0;
|
static volatile double _progress_step_length = 1.0;
|
||||||
|
|
||||||
#define RENDER_INVERSE 1
|
/*#define RENDER_INVERSE 1*/
|
||||||
#define RENDER_WIREFRAME 1
|
#define RENDER_WIREFRAME 1
|
||||||
|
|
||||||
static void _previewResize(int width, int height) {}
|
static void _previewResize(int width, int height) {}
|
||||||
|
|
|
@ -9,6 +9,11 @@ static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_loca
|
||||||
return light_color;
|
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)
|
static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material)
|
||||||
{
|
{
|
||||||
return material.base;
|
return material.base;
|
||||||
|
@ -62,6 +67,7 @@ Renderer rendererGetFake()
|
||||||
result.camera_location = VECTOR_ZERO;
|
result.camera_location = VECTOR_ZERO;
|
||||||
|
|
||||||
result.filterLight = _filterLight;
|
result.filterLight = _filterLight;
|
||||||
|
result.maskLight = _maskLight;
|
||||||
result.applyLightingToSurface = _applyLightingToSurface;
|
result.applyLightingToSurface = _applyLightingToSurface;
|
||||||
result.rayWalking = _rayWalking;
|
result.rayWalking = _rayWalking;
|
||||||
result.getTerrainHeight = _getTerrainHeight;
|
result.getTerrainHeight = _getTerrainHeight;
|
||||||
|
|
|
@ -29,6 +29,7 @@ struct Renderer
|
||||||
|
|
||||||
/* Lighting related */
|
/* Lighting related */
|
||||||
Color (*filterLight)(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light);
|
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);
|
Color (*applyLightingToSurface)(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material);
|
||||||
|
|
||||||
/* Custom data */
|
/* Custom data */
|
||||||
|
|
|
@ -210,9 +210,15 @@ void sceneryRenderSecondPass(Renderer* renderer)
|
||||||
/******* Standard renderer *********/
|
/******* Standard renderer *********/
|
||||||
static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light)
|
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
|
// 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);
|
light_color = cloudsFilterLight(&_clouds, renderer, light_color, at_location, light_location, direction_to_light);
|
||||||
|
|
||||||
return light_color;
|
return light_color;
|
||||||
|
@ -294,6 +300,7 @@ Renderer sceneryGetStandardRenderer(int quality)
|
||||||
result.render_quality = quality;
|
result.render_quality = quality;
|
||||||
|
|
||||||
result.filterLight = _filterLight;
|
result.filterLight = _filterLight;
|
||||||
|
result.maskLight = _maskLight;
|
||||||
result.applyLightingToSurface = _applyLightingToSurface;
|
result.applyLightingToSurface = _applyLightingToSurface;
|
||||||
result.rayWalking = _rayWalking;
|
result.rayWalking = _rayWalking;
|
||||||
result.getTerrainHeight = _getTerrainHeight;
|
result.getTerrainHeight = _getTerrainHeight;
|
||||||
|
|
|
@ -92,12 +92,32 @@ int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights)
|
||||||
sun_direction.y = sin(sun_angle);
|
sun_direction.y = sin(sun_angle);
|
||||||
sun_direction.z = 0.0;
|
sun_direction.z = 0.0;
|
||||||
|
|
||||||
|
/* TODO Night lights */
|
||||||
|
|
||||||
if (max_lights > 0)
|
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].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;
|
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;
|
return nblights;
|
||||||
|
|
|
@ -171,6 +171,11 @@ Color terrainLightFilter(TerrainDefinition* definition, Renderer* renderer, Colo
|
||||||
double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length;
|
double inc_value, inc_base, inc_factor, height, diff, light_factor, smoothing, length;
|
||||||
|
|
||||||
direction_to_light = v3Normalize(direction_to_light);
|
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_factor = (double)renderer->render_quality;
|
||||||
inc_base = 1.0;
|
inc_base = 1.0;
|
||||||
inc_value = inc_base / inc_factor;
|
inc_value = inc_base / inc_factor;
|
||||||
|
|
|
@ -137,7 +137,7 @@ Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color li
|
||||||
{
|
{
|
||||||
if (direction_to_light.y > 0.00001)
|
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)
|
if (factor > 1.0)
|
||||||
{
|
{
|
||||||
factor = 1.0;
|
factor = 1.0;
|
||||||
|
|
Loading…
Reference in a new issue