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:
Michaël Lemaire 2012-01-25 17:31:36 +00:00 committed by ThunderK
parent 1e922ccbce
commit a2307c4746
14 changed files with 117 additions and 47 deletions

2
TODO
View file

@ -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.

View file

@ -6,7 +6,6 @@
#include <QPainter>
#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;
}

View file

@ -5,6 +5,7 @@
#include <QThread>
#include <QProgressBar>
#include <QScrollArea>
#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_

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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) {}

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;