Refactored cloud renderer (currently not working correctly)
This commit is contained in:
parent
7fecdba313
commit
ff27afe675
30 changed files with 679 additions and 1045 deletions
|
@ -4,7 +4,6 @@
|
||||||
#include "desktop_global.h"
|
#include "desktop_global.h"
|
||||||
|
|
||||||
#include "baseformlayer.h"
|
#include "baseformlayer.h"
|
||||||
#include "clouds/public.h"
|
|
||||||
class QWidget;
|
class QWidget;
|
||||||
|
|
||||||
class FormClouds : public BaseFormLayer
|
class FormClouds : public BaseFormLayer
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "atmosphere/public.h"
|
#include "atmosphere/public.h"
|
||||||
#include "clouds/public.h"
|
|
||||||
#include "terrain/public.h"
|
#include "terrain/public.h"
|
||||||
#include "water/public.h"
|
#include "water/public.h"
|
||||||
#include "RenderingScenery.h"
|
#include "RenderingScenery.h"
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include "CloudsAspectPreviewRenderer.h"
|
#include "CloudsAspectPreviewRenderer.h"
|
||||||
|
|
||||||
#include "clouds/public.h"
|
|
||||||
#include "atmosphere/public.h"
|
#include "atmosphere/public.h"
|
||||||
#include "BasePreview.h"
|
#include "BasePreview.h"
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "CloudsDefinition.h"
|
#include "CloudsDefinition.h"
|
||||||
#include "CloudLayerDefinition.h"
|
#include "CloudLayerDefinition.h"
|
||||||
|
#include "CloudsRenderer.h"
|
||||||
|
|
||||||
static void _getLightingStatus(Renderer*, LightStatus* status, Vector3, int)
|
static void _getLightingStatus(Renderer*, LightStatus* status, Vector3, int)
|
||||||
{
|
{
|
||||||
|
@ -61,7 +61,6 @@ CloudsAspectPreviewRenderer::CloudsAspectPreviewRenderer(CloudLayerDefinition* l
|
||||||
CloudsDefinition* clouds = getScenery()->getClouds();
|
CloudsDefinition* clouds = getScenery()->getClouds();
|
||||||
clouds->clear();
|
clouds->clear();
|
||||||
clouds->addLayer();
|
clouds->addLayer();
|
||||||
CloudsRendererClass.bind(this, clouds);
|
|
||||||
|
|
||||||
render_quality = 6;
|
render_quality = 6;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +81,7 @@ void CloudsAspectPreviewRenderer::updateEvent()
|
||||||
|
|
||||||
prepare();
|
prepare();
|
||||||
|
|
||||||
clouds->getLayerDensity = _getDensity;
|
//clouds->getLayerDensity = _getDensity;
|
||||||
atmosphere->getLightingStatus = _getLightingStatus;
|
atmosphere->getLightingStatus = _getLightingStatus;
|
||||||
atmosphere->applyAerialPerspective = _fakeApplyAerialPerspective;
|
atmosphere->applyAerialPerspective = _fakeApplyAerialPerspective;
|
||||||
}
|
}
|
||||||
|
@ -100,5 +99,5 @@ Color CloudsAspectPreviewRenderer::getColor2D(double x, double y, double)
|
||||||
end.z = start.z;
|
end.z = start.z;
|
||||||
end.y = -start.y;
|
end.y = -start.y;
|
||||||
|
|
||||||
return clouds->getColor(this, COLOR_BLUE, start, end);
|
return getCloudsRenderer()->getColor(start, end, COLOR_BLUE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "CloudsCoveragePreviewRenderer.h"
|
#include "CloudsCoveragePreviewRenderer.h"
|
||||||
|
|
||||||
#include "clouds/public.h"
|
|
||||||
#include "BasePreview.h"
|
#include "BasePreview.h"
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "CloudsDefinition.h"
|
#include "CloudsDefinition.h"
|
||||||
#include "CloudLayerDefinition.h"
|
#include "CloudLayerDefinition.h"
|
||||||
|
#include "CloudsRenderer.h"
|
||||||
|
|
||||||
Color _fakeApplyLightingToSurface(Renderer*, Vector3, Vector3, SurfaceMaterial*)
|
Color _fakeApplyLightingToSurface(Renderer*, Vector3, Vector3, SurfaceMaterial*)
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,6 @@ CloudsCoveragePreviewRenderer::CloudsCoveragePreviewRenderer(CloudLayerDefinitio
|
||||||
CloudsDefinition* clouds = getScenery()->getClouds();
|
CloudsDefinition* clouds = getScenery()->getClouds();
|
||||||
clouds->clear();
|
clouds->clear();
|
||||||
clouds->addLayer();
|
clouds->addLayer();
|
||||||
CloudsRendererClass.bind(this, clouds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudsCoveragePreviewRenderer::bindEvent(BasePreview* preview)
|
void CloudsCoveragePreviewRenderer::bindEvent(BasePreview* preview)
|
||||||
|
@ -49,7 +48,7 @@ Color CloudsCoveragePreviewRenderer::getColor2D(double x, double y, double scali
|
||||||
look.z = 1.0;
|
look.z = 1.0;
|
||||||
look = look.normalize();
|
look = look.normalize();
|
||||||
|
|
||||||
return clouds->getColor(this, COLOR_BLUE, eye, eye.add(look.scale(1000.0)));
|
return getCloudsRenderer()->getColor(eye, eye.add(look.scale(1000.0)), COLOR_BLUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -60,7 +59,7 @@ Color CloudsCoveragePreviewRenderer::getColor2D(double x, double y, double scali
|
||||||
start.y = 1000.0;
|
start.y = 1000.0;
|
||||||
end.y = -1000.0;
|
end.y = -1000.0;
|
||||||
|
|
||||||
return clouds->getColor(this, COLOR_BLUE, start, end);
|
return getCloudsRenderer()->getColor(start, end, COLOR_BLUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
80
src/render/software/BaseCloudLayerRenderer.cpp
Normal file
80
src/render/software/BaseCloudLayerRenderer.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#include "BaseCloudLayerRenderer.h"
|
||||||
|
|
||||||
|
#include "CloudLayerDefinition.h"
|
||||||
|
|
||||||
|
BaseCloudLayerRenderer::BaseCloudLayerRenderer(SoftwareRenderer* parent):
|
||||||
|
parent(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseCloudLayerRenderer::~BaseCloudLayerRenderer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double BaseCloudLayerRenderer::getDensity(CloudLayerDefinition *, const Vector3 &)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color BaseCloudLayerRenderer::getColor(CloudLayerDefinition *, const Vector3 &, const Vector3 &)
|
||||||
|
{
|
||||||
|
return COLOR_TRANSPARENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseCloudLayerRenderer::alterLight(CloudLayerDefinition *, LightDefinition *, const Vector3 &, const Vector3 &)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseCloudLayerRenderer::optimizeSearchLimits(CloudLayerDefinition *layer, Vector3 *start, Vector3 *end)
|
||||||
|
{
|
||||||
|
Vector3 diff;
|
||||||
|
|
||||||
|
if (start->y > layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
if (end->y >= layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = v3Sub(*end, *start);
|
||||||
|
*start = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
|
||||||
|
if (end->y < layer->lower_altitude)
|
||||||
|
{
|
||||||
|
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude - end->y) / diff.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (start->y < layer->lower_altitude)
|
||||||
|
{
|
||||||
|
if (end->y <= layer->lower_altitude)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = v3Sub(*end, *start);
|
||||||
|
*start = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
|
||||||
|
if (end->y >= layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude + layer->thickness - end->y) / diff.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* start is inside layer */
|
||||||
|
{
|
||||||
|
diff = v3Sub(*end, *start);
|
||||||
|
if (end->y > layer->lower_altitude + layer->thickness)
|
||||||
|
{
|
||||||
|
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
|
||||||
|
}
|
||||||
|
else if (end->y < layer->lower_altitude)
|
||||||
|
{
|
||||||
|
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
30
src/render/software/BaseCloudLayerRenderer.h
Normal file
30
src/render/software/BaseCloudLayerRenderer.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef BASECLOUDLAYERRENDERER_H
|
||||||
|
#define BASECLOUDLAYERRENDERER_H
|
||||||
|
|
||||||
|
#include "software_global.h"
|
||||||
|
|
||||||
|
#include "tools/lighting.h"
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace software {
|
||||||
|
|
||||||
|
class BaseCloudLayerRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BaseCloudLayerRenderer(SoftwareRenderer* parent);
|
||||||
|
virtual ~BaseCloudLayerRenderer();
|
||||||
|
|
||||||
|
virtual bool optimizeSearchLimits(CloudLayerDefinition *layer, Vector3 *start, Vector3 *end);
|
||||||
|
|
||||||
|
virtual double getDensity(CloudLayerDefinition* layer, const Vector3 &location);
|
||||||
|
virtual Color getColor(CloudLayerDefinition* layer, const Vector3 &eye, const Vector3 &location);
|
||||||
|
virtual bool alterLight(CloudLayerDefinition* layer, LightDefinition* light, const Vector3 &eye, const Vector3 &location);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SoftwareRenderer* parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BASECLOUDLAYERRENDERER_H
|
305
src/render/software/CloudBasicLayerRenderer.cpp
Normal file
305
src/render/software/CloudBasicLayerRenderer.cpp
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
#include "CloudBasicLayerRenderer.h"
|
||||||
|
|
||||||
|
#include "CloudLayerDefinition.h"
|
||||||
|
#include "SoftwareRenderer.h"
|
||||||
|
#include "NoiseGenerator.h"
|
||||||
|
#include "Curve.h"
|
||||||
|
#include "AtmosphereRenderer.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Vector3 start;
|
||||||
|
Vector3 end;
|
||||||
|
double length;
|
||||||
|
} CloudSegment;
|
||||||
|
|
||||||
|
CloudBasicLayerRenderer::CloudBasicLayerRenderer(SoftwareRenderer* parent):
|
||||||
|
BaseCloudLayerRenderer(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double _standardCoverageFunc(CloudLayerDefinition* layer, Vector3 position)
|
||||||
|
{
|
||||||
|
if (position.y < layer->lower_altitude || position.y > (layer->lower_altitude + layer->thickness))
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return layer->base_coverage * layer->_coverage_by_altitude->getValue((position.y - layer->lower_altitude) / layer->thickness);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double _getDistanceToBorder(CloudLayerDefinition* layer, Vector3 position)
|
||||||
|
{
|
||||||
|
double val;
|
||||||
|
double minval, maxval;
|
||||||
|
|
||||||
|
layer->_shape_noise->getRange(&minval, &maxval);
|
||||||
|
|
||||||
|
val = 0.5 * layer->_shape_noise->get3DTotal(position.x / layer->shape_scaling, position.y / layer->shape_scaling, position.z / layer->shape_scaling) / maxval;
|
||||||
|
|
||||||
|
return (val - 0.5 + _standardCoverageFunc(layer, position)) * layer->shape_scaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Vector3 _getNormal(CloudLayerDefinition* layer, Vector3 position, double detail)
|
||||||
|
{
|
||||||
|
Vector3 result = {0.0, 0.0, 0.0};
|
||||||
|
Vector3 dposition;
|
||||||
|
double val, dval;
|
||||||
|
|
||||||
|
val = _getDistanceToBorder(layer, position);
|
||||||
|
|
||||||
|
dposition.x = position.x + detail;
|
||||||
|
dposition.y = position.y;
|
||||||
|
dposition.z = position.z;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.x += dval;
|
||||||
|
|
||||||
|
dposition.x = position.x - detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.x -= dval;
|
||||||
|
|
||||||
|
dposition.x = position.x;
|
||||||
|
dposition.y = position.y + detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.y += dval;
|
||||||
|
|
||||||
|
dposition.y = position.y - detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.y -= dval;
|
||||||
|
|
||||||
|
dposition.y = position.y;
|
||||||
|
dposition.z = position.z + detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.z += dval;
|
||||||
|
|
||||||
|
dposition.z = position.z - detail;
|
||||||
|
dval = val - _getDistanceToBorder(layer, dposition);
|
||||||
|
result.z -= dval;
|
||||||
|
|
||||||
|
return v3Normalize(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go through the cloud layer to find segments (parts of the lookup that are inside the cloud).
|
||||||
|
*
|
||||||
|
* @param definition The cloud layer
|
||||||
|
* @param renderer The renderer environment
|
||||||
|
* @param start Start position of the lookup (already optimized)
|
||||||
|
* @param direction Normalized direction of the lookup
|
||||||
|
* @param detail Level of noise detail required
|
||||||
|
* @param max_segments Maximum number of segments to collect
|
||||||
|
* @param max_inside_length Maximum length to spend inside the cloud
|
||||||
|
* @param max_total_length Maximum lookup length
|
||||||
|
* @param inside_length Resulting length inside cloud (sum of all segments length)
|
||||||
|
* @param total_length Resulting lookup length
|
||||||
|
* @param out_segments Allocated space to fill found segments
|
||||||
|
* @return Number of segments found
|
||||||
|
*/
|
||||||
|
static int _findSegments(CloudLayerDefinition* definition, SoftwareRenderer* renderer, Vector3 start, Vector3 direction, double, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments)
|
||||||
|
{
|
||||||
|
int inside, segment_count;
|
||||||
|
double current_total_length, current_inside_length;
|
||||||
|
double step_length, segment_length, remaining_length;
|
||||||
|
double noise_distance, last_noise_distance;
|
||||||
|
Vector3 walker, step, segment_start;
|
||||||
|
double render_precision;
|
||||||
|
|
||||||
|
if (max_segments <= 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_precision = 15.2 - 1.5 * (double)renderer->render_quality;
|
||||||
|
render_precision = render_precision * definition->shape_scaling / 50.0;
|
||||||
|
if (render_precision > max_total_length / 10.0)
|
||||||
|
{
|
||||||
|
render_precision = max_total_length / 10.0;
|
||||||
|
}
|
||||||
|
else if (render_precision < max_total_length / 2000.0)
|
||||||
|
{
|
||||||
|
render_precision = max_total_length / 2000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
segment_count = 0;
|
||||||
|
current_total_length = 0.0;
|
||||||
|
current_inside_length = 0.0;
|
||||||
|
segment_length = 0.0;
|
||||||
|
walker = start;
|
||||||
|
noise_distance = _getDistanceToBorder(definition, start) * render_precision;
|
||||||
|
inside = (noise_distance > 0.0) ? 1 : 0;
|
||||||
|
step = v3Scale(direction, render_precision);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
walker = v3Add(walker, step);
|
||||||
|
step_length = v3Norm(step);
|
||||||
|
last_noise_distance = noise_distance;
|
||||||
|
noise_distance = _getDistanceToBorder(definition, walker) * render_precision;
|
||||||
|
current_total_length += step_length;
|
||||||
|
|
||||||
|
if (noise_distance > 0.0)
|
||||||
|
{
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
// inside the cloud
|
||||||
|
segment_length += step_length;
|
||||||
|
current_inside_length += step_length;
|
||||||
|
step = v3Scale(direction, (noise_distance < render_precision) ? render_precision : noise_distance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// entering the cloud
|
||||||
|
inside = 1;
|
||||||
|
segment_length = step_length * noise_distance / (noise_distance - last_noise_distance);
|
||||||
|
segment_start = v3Add(walker, v3Scale(direction, -segment_length));
|
||||||
|
current_inside_length += segment_length;
|
||||||
|
step = v3Scale(direction, render_precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
// exiting the cloud
|
||||||
|
remaining_length = step_length * last_noise_distance / (last_noise_distance - noise_distance);
|
||||||
|
segment_length += remaining_length;
|
||||||
|
current_inside_length += remaining_length;
|
||||||
|
|
||||||
|
out_segments->start = segment_start;
|
||||||
|
out_segments->end = v3Add(walker, v3Scale(direction, remaining_length - step_length));
|
||||||
|
out_segments->length = segment_length;
|
||||||
|
out_segments++;
|
||||||
|
if (++segment_count >= max_segments)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
inside = 0;
|
||||||
|
step = v3Scale(direction, render_precision);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// searching for a cloud
|
||||||
|
step = v3Scale(direction, (noise_distance > -render_precision) ? render_precision : -noise_distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (inside || (walker.y >= definition->lower_altitude - 0.001 && walker.y <= (definition->lower_altitude + definition->thickness) + 0.001 && current_total_length < max_total_length && current_inside_length < max_inside_length));
|
||||||
|
|
||||||
|
*total_length = current_total_length;
|
||||||
|
*inside_length = current_inside_length;
|
||||||
|
return segment_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color _applyLayerLighting(CloudLayerDefinition* definition, SoftwareRenderer* renderer, Vector3 position, double)
|
||||||
|
{
|
||||||
|
Vector3 normal;
|
||||||
|
Color col1, col2;
|
||||||
|
|
||||||
|
normal = _getNormal(definition, position, 3.0);
|
||||||
|
if (renderer->render_quality > 5)
|
||||||
|
{
|
||||||
|
normal = v3Add(normal, _getNormal(definition, position, 2.0));
|
||||||
|
normal = v3Add(normal, _getNormal(definition, position, 1.0));
|
||||||
|
}
|
||||||
|
if (renderer->render_quality > 5)
|
||||||
|
{
|
||||||
|
normal = v3Add(normal, _getNormal(definition, position, 0.5));
|
||||||
|
}
|
||||||
|
normal = v3Scale(v3Normalize(normal), definition->hardness);
|
||||||
|
|
||||||
|
// TODO Compute light filter only once
|
||||||
|
col1 = renderer->applyLightingToSurface(renderer, position, normal, definition->material);
|
||||||
|
col2 = renderer->applyLightingToSurface(renderer, position, v3Scale(normal, -1.0), definition->material);
|
||||||
|
|
||||||
|
col1.r = (col1.r + col2.r) / 2.0;
|
||||||
|
col1.g = (col1.g + col2.g) / 2.0;
|
||||||
|
col1.b = (col1.b + col2.b) / 2.0;
|
||||||
|
col1.a = (col1.a + col2.a) / 2.0;
|
||||||
|
|
||||||
|
return col1;
|
||||||
|
}
|
||||||
|
|
||||||
|
double CloudBasicLayerRenderer::getDensity(CloudLayerDefinition* layer, const Vector3 &location)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CloudBasicLayerRenderer::getColor(CloudLayerDefinition* layer, const Vector3 &eye, const Vector3 &location)
|
||||||
|
{
|
||||||
|
int i, segment_count;
|
||||||
|
double max_length, detail, total_length, inside_length;
|
||||||
|
Vector3 start, end, direction;
|
||||||
|
Color result, col;
|
||||||
|
CloudSegment segments[20];
|
||||||
|
|
||||||
|
start = eye;
|
||||||
|
end = location;
|
||||||
|
if (!optimizeSearchLimits(layer, &start, &end))
|
||||||
|
{
|
||||||
|
return COLOR_TRANSPARENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
direction = end.sub(start);
|
||||||
|
max_length = direction.getNorm();
|
||||||
|
direction = direction.normalize();
|
||||||
|
result = COLOR_TRANSPARENT;
|
||||||
|
|
||||||
|
detail = parent->getPrecision(parent, start) / layer->shape_scaling;
|
||||||
|
|
||||||
|
segment_count = _findSegments(layer, parent, start, direction, detail, 20, layer->transparencydepth, max_length, &inside_length, &total_length, segments);
|
||||||
|
for (i = segment_count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
col = _applyLayerLighting(layer, parent, segments[i].start, detail);
|
||||||
|
col.a = (segments[i].length >= layer->transparencydepth) ? 1.0 : (segments[i].length / layer->transparencydepth);
|
||||||
|
colorMask(&result, &col);
|
||||||
|
}
|
||||||
|
if (inside_length >= layer->transparencydepth)
|
||||||
|
{
|
||||||
|
result.a = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double a = result.a;
|
||||||
|
result = parent->getAtmosphereRenderer()->applyAerialPerspective(start, result).final;
|
||||||
|
result.a = a;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CloudBasicLayerRenderer::alterLight(CloudLayerDefinition* layer, LightDefinition* light, const Vector3 &, const Vector3 &location)
|
||||||
|
{
|
||||||
|
Vector3 start, end;
|
||||||
|
double inside_depth, total_depth, factor;
|
||||||
|
CloudSegment segments[20];
|
||||||
|
|
||||||
|
start = location;
|
||||||
|
end = location.add(light->direction.scale(10000.0));
|
||||||
|
if (not optimizeSearchLimits(layer, &start, &end))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_findSegments(layer, parent, start, light->direction, 0.1, 20, layer->lighttraversal, end.sub(start).getNorm(), &inside_depth, &total_depth, segments);
|
||||||
|
|
||||||
|
if (layer->lighttraversal < 0.0001)
|
||||||
|
{
|
||||||
|
factor = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
factor = inside_depth / layer->lighttraversal;
|
||||||
|
if (factor > 1.0)
|
||||||
|
{
|
||||||
|
factor = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
factor = 1.0 - (1.0 - layer->minimumlight) * factor;
|
||||||
|
|
||||||
|
light->color.r *= factor;
|
||||||
|
light->color.g *= factor;
|
||||||
|
light->color.b *= factor;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
26
src/render/software/CloudBasicLayerRenderer.h
Normal file
26
src/render/software/CloudBasicLayerRenderer.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef CLOUDBASICLAYERRENDERER_H
|
||||||
|
#define CLOUDBASICLAYERRENDERER_H
|
||||||
|
|
||||||
|
#include "software_global.h"
|
||||||
|
|
||||||
|
#include "BaseCloudLayerRenderer.h"
|
||||||
|
|
||||||
|
#include "tools/lighting.h"
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace software {
|
||||||
|
|
||||||
|
class SOFTWARESHARED_EXPORT CloudBasicLayerRenderer: public BaseCloudLayerRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CloudBasicLayerRenderer(SoftwareRenderer* parent);
|
||||||
|
|
||||||
|
virtual double getDensity(CloudLayerDefinition* layer, const Vector3 &location) override;
|
||||||
|
virtual Color getColor(CloudLayerDefinition* layer, const Vector3 &eye, const Vector3 &location) override;
|
||||||
|
virtual bool alterLight(CloudLayerDefinition* layer, LightDefinition* light, const Vector3 &eye, const Vector3 &location) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CLOUDBASICLAYERRENDERER_H
|
81
src/render/software/CloudsRenderer.cpp
Normal file
81
src/render/software/CloudsRenderer.cpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#include "CloudsRenderer.h"
|
||||||
|
|
||||||
|
#include "SoftwareRenderer.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
#include "CloudsDefinition.h"
|
||||||
|
#include "BaseCloudLayerRenderer.h"
|
||||||
|
#include "CloudBasicLayerRenderer.h"
|
||||||
|
|
||||||
|
CloudsRenderer::CloudsRenderer(SoftwareRenderer* parent):
|
||||||
|
parent(parent)
|
||||||
|
{
|
||||||
|
fake_renderer = new BaseCloudLayerRenderer(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloudsRenderer::~CloudsRenderer()
|
||||||
|
{
|
||||||
|
for (auto renderer : layer_renderers)
|
||||||
|
{
|
||||||
|
delete renderer;
|
||||||
|
}
|
||||||
|
delete fake_renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloudsRenderer::update()
|
||||||
|
{
|
||||||
|
for (auto renderer : layer_renderers)
|
||||||
|
{
|
||||||
|
delete renderer;
|
||||||
|
}
|
||||||
|
layer_renderers.clear();
|
||||||
|
|
||||||
|
CloudsDefinition* clouds = parent->getScenery()->getClouds();
|
||||||
|
int n = clouds->count();
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
layer_renderers.push_back(new CloudBasicLayerRenderer(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseCloudLayerRenderer* CloudsRenderer::getLayerRenderer(unsigned int layer)
|
||||||
|
{
|
||||||
|
if (layer < layer_renderers.size())
|
||||||
|
{
|
||||||
|
return layer_renderers[layer];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return fake_renderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CloudsRenderer::getColor(const Vector3 &eye, const Vector3 &location, const Color &base)
|
||||||
|
{
|
||||||
|
CloudsDefinition* definition = parent->getScenery()->getClouds();
|
||||||
|
|
||||||
|
int n = definition->count();
|
||||||
|
if (n < 1)
|
||||||
|
{
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO Iter layers in sorted order */
|
||||||
|
Color cumul = base;
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
CloudLayerDefinition* layer = definition->getCloudLayer(i);
|
||||||
|
BaseCloudLayerRenderer* layer_renderer = getLayerRenderer(i);
|
||||||
|
|
||||||
|
Color layer_color = layer_renderer->getColor(layer, eye, location);
|
||||||
|
|
||||||
|
colorMask(&cumul, &layer_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cumul;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CloudsRenderer::alterLight(LightDefinition* light, const Vector3 &eye, const Vector3 &location)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
52
src/render/software/CloudsRenderer.h
Normal file
52
src/render/software/CloudsRenderer.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef CLOUDSRENDERER_H
|
||||||
|
#define CLOUDSRENDERER_H
|
||||||
|
|
||||||
|
#include "software_global.h"
|
||||||
|
|
||||||
|
#include "tools/lighting.h"
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace software {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Software renderer of a group of cloud layers.
|
||||||
|
*/
|
||||||
|
class SOFTWARESHARED_EXPORT CloudsRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CloudsRenderer(SoftwareRenderer* parent);
|
||||||
|
virtual ~CloudsRenderer();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Update the renderer with the bound scenery.
|
||||||
|
*/
|
||||||
|
void update();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the layer renderer for a given layer.
|
||||||
|
*
|
||||||
|
* The returned renderer is managed by this object and should not be deleted.
|
||||||
|
*/
|
||||||
|
virtual BaseCloudLayerRenderer* getLayerRenderer(unsigned int layer);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the composited color, as applied on a base color and location.
|
||||||
|
*/
|
||||||
|
virtual Color getColor(const Vector3 &eye, const Vector3 &location, const Color &base);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Alter a light, as if passed through all layers.
|
||||||
|
*
|
||||||
|
* Return true if the light was altered.
|
||||||
|
*/
|
||||||
|
virtual bool alterLight(LightDefinition* light, const Vector3 &eye, const Vector3 &location);
|
||||||
|
private:
|
||||||
|
SoftwareRenderer* parent;
|
||||||
|
std::vector<BaseCloudLayerRenderer*> layer_renderers;
|
||||||
|
BaseCloudLayerRenderer* fake_renderer;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CLOUDSRENDERER_H
|
|
@ -1,12 +1,19 @@
|
||||||
#include "public.h"
|
#include "SkyRasterizer.h"
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
#include <math.h>
|
#include "Vector3.h"
|
||||||
#include <stdlib.h>
|
#include "Color.h"
|
||||||
#include "../renderer.h"
|
#include "SoftwareRenderer.h"
|
||||||
#include "clouds/public.h"
|
#include "AtmosphereRenderer.h"
|
||||||
|
#include "CloudsRenderer.h"
|
||||||
|
|
||||||
static Color _postProcessFragment(Renderer* renderer, Vector3 location, void*)
|
#define SPHERE_SIZE 20000.0
|
||||||
|
|
||||||
|
SkyRasterizer::SkyRasterizer(SoftwareRenderer* renderer):
|
||||||
|
renderer(renderer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color _postProcessFragment(SoftwareRenderer* renderer, Vector3 location, void*)
|
||||||
{
|
{
|
||||||
Vector3 camera_location, direction;
|
Vector3 camera_location, direction;
|
||||||
Color result;
|
Color result;
|
||||||
|
@ -16,12 +23,12 @@ static Color _postProcessFragment(Renderer* renderer, Vector3 location, void*)
|
||||||
|
|
||||||
/* TODO Don't compute result->color if it's fully covered by clouds */
|
/* TODO Don't compute result->color if it's fully covered by clouds */
|
||||||
result = renderer->atmosphere->getSkyColor(renderer, v3Normalize(direction)).final;
|
result = renderer->atmosphere->getSkyColor(renderer, v3Normalize(direction)).final;
|
||||||
result = renderer->clouds->getColor(renderer, result, camera_location, v3Add(camera_location, v3Scale(direction, 10.0)));
|
result = renderer->getCloudsRenderer()->getColor(camera_location, v3Add(camera_location, v3Scale(direction, 10.0)), result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void atmosphereRenderSkydome(Renderer* renderer)
|
void SkyRasterizer::rasterize()
|
||||||
{
|
{
|
||||||
int res_i, res_j;
|
int res_i, res_j;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -71,7 +78,7 @@ void atmosphereRenderSkydome(Renderer* renderer)
|
||||||
vertex4 = v3Add(camera_location, direction);
|
vertex4 = v3Add(camera_location, direction);
|
||||||
|
|
||||||
/* TODO Triangles at poles */
|
/* TODO Triangles at poles */
|
||||||
renderer->pushQuad(renderer, vertex1, vertex4, vertex3, vertex2, _postProcessFragment, NULL);
|
renderer->pushQuad(renderer, vertex1, vertex4, vertex3, vertex2, (f_RenderFragmentCallback)_postProcessFragment, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
22
src/render/software/SkyRasterizer.h
Normal file
22
src/render/software/SkyRasterizer.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef SKYRASTERIZER_H
|
||||||
|
#define SKYRASTERIZER_H
|
||||||
|
|
||||||
|
#include "software_global.h"
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace software {
|
||||||
|
|
||||||
|
class SOFTWARESHARED_EXPORT SkyRasterizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SkyRasterizer(SoftwareRenderer* renderer);
|
||||||
|
void rasterize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SoftwareRenderer* renderer;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SKYRASTERIZER_H
|
|
@ -5,12 +5,14 @@
|
||||||
#include "FluidMediumManager.h"
|
#include "FluidMediumManager.h"
|
||||||
#include "AtmosphereRenderer.h"
|
#include "AtmosphereRenderer.h"
|
||||||
#include "AtmosphereDefinition.h"
|
#include "AtmosphereDefinition.h"
|
||||||
|
#include "CloudsRenderer.h"
|
||||||
|
#include "SkyRasterizer.h"
|
||||||
|
|
||||||
|
|
||||||
// Legacy compatibility
|
// Legacy compatibility
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "terrain/public.h"
|
#include "terrain/public.h"
|
||||||
#include "clouds/public.h"
|
#include "terrain/ter_raster.h"
|
||||||
#include "textures/public.h"
|
#include "textures/public.h"
|
||||||
#include "water/public.h"
|
#include "water/public.h"
|
||||||
static AtmosphereResult _legacyApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
|
static AtmosphereResult _legacyApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
|
||||||
|
@ -29,8 +31,9 @@ static Vector3 _legacyGetSunDirection(Renderer* renderer)
|
||||||
{
|
{
|
||||||
return ((SoftwareRenderer*)renderer)->getAtmosphereRenderer()->getSunDirection();
|
return ((SoftwareRenderer*)renderer)->getAtmosphereRenderer()->getSunDirection();
|
||||||
}
|
}
|
||||||
static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector3 direction, int, int, int, int)
|
static RayCastingResult _rayWalking(Renderer* renderer_, Vector3 location, Vector3 direction, int, int, int, int)
|
||||||
{
|
{
|
||||||
|
SoftwareRenderer* renderer = (SoftwareRenderer*)renderer_;
|
||||||
RayCastingResult result;
|
RayCastingResult result;
|
||||||
Color sky_color;
|
Color sky_color;
|
||||||
|
|
||||||
|
@ -41,7 +44,7 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
|
||||||
|
|
||||||
result.hit = 1;
|
result.hit = 1;
|
||||||
result.hit_location = v3Add(location, v3Scale(direction, 1000.0));
|
result.hit_location = v3Add(location, v3Scale(direction, 1000.0));
|
||||||
result.hit_color = renderer->clouds->getColor(renderer, sky_color, location, result.hit_location);
|
result.hit_color = renderer->getCloudsRenderer()->getColor(location, result.hit_location, sky_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -60,6 +63,7 @@ static double _getPrecision(Renderer* renderer, Vector3 location)
|
||||||
SoftwareRenderer::SoftwareRenderer(Scenery* scenery)
|
SoftwareRenderer::SoftwareRenderer(Scenery* scenery)
|
||||||
{
|
{
|
||||||
atmosphere_renderer = new BaseAtmosphereRenderer(this);
|
atmosphere_renderer = new BaseAtmosphereRenderer(this);
|
||||||
|
clouds_renderer = new CloudsRenderer(this);
|
||||||
|
|
||||||
fluid_medium = new FluidMediumManager(this);
|
fluid_medium = new FluidMediumManager(this);
|
||||||
|
|
||||||
|
@ -78,6 +82,7 @@ SoftwareRenderer::SoftwareRenderer(Scenery* scenery)
|
||||||
SoftwareRenderer::~SoftwareRenderer()
|
SoftwareRenderer::~SoftwareRenderer()
|
||||||
{
|
{
|
||||||
delete atmosphere_renderer;
|
delete atmosphere_renderer;
|
||||||
|
delete clouds_renderer;
|
||||||
|
|
||||||
delete fluid_medium;
|
delete fluid_medium;
|
||||||
|
|
||||||
|
@ -103,6 +108,10 @@ void SoftwareRenderer::prepare()
|
||||||
delete atmosphere_renderer;
|
delete atmosphere_renderer;
|
||||||
atmosphere_renderer = new SoftwareBrunetonAtmosphereRenderer(this);
|
atmosphere_renderer = new SoftwareBrunetonAtmosphereRenderer(this);
|
||||||
|
|
||||||
|
delete clouds_renderer;
|
||||||
|
clouds_renderer = new CloudsRenderer(this);
|
||||||
|
clouds_renderer->update();
|
||||||
|
|
||||||
// Setup transitional renderers (for C-legacy subsystems)
|
// Setup transitional renderers (for C-legacy subsystems)
|
||||||
rayWalking = _rayWalking;
|
rayWalking = _rayWalking;
|
||||||
getPrecision = _getPrecision;
|
getPrecision = _getPrecision;
|
||||||
|
@ -116,7 +125,6 @@ void SoftwareRenderer::prepare()
|
||||||
scenery->getCamera()->copy(render_camera);
|
scenery->getCamera()->copy(render_camera);
|
||||||
TerrainRendererClass.bind(this, scenery->getTerrain());
|
TerrainRendererClass.bind(this, scenery->getTerrain());
|
||||||
TexturesRendererClass.bind(this, scenery->getTextures());
|
TexturesRendererClass.bind(this, scenery->getTextures());
|
||||||
CloudsRendererClass.bind(this, scenery->getClouds());
|
|
||||||
WaterRendererClass.bind(this, scenery->getWater());
|
WaterRendererClass.bind(this, scenery->getWater());
|
||||||
|
|
||||||
// Prepare global tools
|
// Prepare global tools
|
||||||
|
@ -124,8 +132,21 @@ void SoftwareRenderer::prepare()
|
||||||
//fluid_medium->registerMedium(water_renderer);
|
//fluid_medium->registerMedium(water_renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Color SoftwareRenderer::applyMediumTraversal(Vector3 location, Color color)
|
void SoftwareRenderer::rasterize()
|
||||||
{
|
{
|
||||||
Vector3 eye = cameraGetLocation(scenery->getCamera());
|
terrainRenderSurface(this);
|
||||||
return fluid_medium->applyTraversal(eye, location, color);
|
waterRenderSurface(this);
|
||||||
}*/
|
|
||||||
|
SkyRasterizer sky(this);
|
||||||
|
sky.rasterize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color SoftwareRenderer::applyMediumTraversal(Vector3 location, Color color)
|
||||||
|
{
|
||||||
|
color = atmosphere->applyAerialPerspective(this, location, color).final;
|
||||||
|
color = clouds_renderer->getColor(getCameraLocation(this, location), location, color);
|
||||||
|
return color;
|
||||||
|
|
||||||
|
/*Vector3 eye = cameraGetLocation(scenery->getCamera());
|
||||||
|
return fluid_medium->applyTraversal(eye, location, color);*/
|
||||||
|
}
|
||||||
|
|
|
@ -33,17 +33,26 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void prepare() override;
|
virtual void prepare() override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Start the rasterization process.
|
||||||
|
*/
|
||||||
|
virtual void rasterize() override;
|
||||||
|
|
||||||
inline Scenery* getScenery() const {return scenery;}
|
inline Scenery* getScenery() const {return scenery;}
|
||||||
|
|
||||||
inline BaseAtmosphereRenderer* getAtmosphereRenderer() const {return atmosphere_renderer;}
|
inline BaseAtmosphereRenderer* getAtmosphereRenderer() const {return atmosphere_renderer;}
|
||||||
|
inline CloudsRenderer* getCloudsRenderer() const {return clouds_renderer;}
|
||||||
|
|
||||||
inline FluidMediumManager* getFluidMediumManager() const {return fluid_medium;}
|
inline FluidMediumManager* getFluidMediumManager() const {return fluid_medium;}
|
||||||
|
|
||||||
//virtual Color applyMediumTraversal(Vector3 location, Color color) override;
|
virtual Color applyMediumTraversal(Vector3 location, Color color) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Scenery* scenery;
|
Scenery* scenery;
|
||||||
bool own_scenery;
|
bool own_scenery;
|
||||||
FluidMediumManager* fluid_medium;
|
FluidMediumManager* fluid_medium;
|
||||||
BaseAtmosphereRenderer* atmosphere_renderer;
|
BaseAtmosphereRenderer* atmosphere_renderer;
|
||||||
|
CloudsRenderer* clouds_renderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,21 @@ include(../../common.pri)
|
||||||
SOURCES += SoftwareRenderer.cpp \
|
SOURCES += SoftwareRenderer.cpp \
|
||||||
FluidMediumInterface.cpp \
|
FluidMediumInterface.cpp \
|
||||||
FluidMediumManager.cpp \
|
FluidMediumManager.cpp \
|
||||||
AtmosphereRenderer.cpp
|
AtmosphereRenderer.cpp \
|
||||||
|
CloudsRenderer.cpp \
|
||||||
|
BaseCloudLayerRenderer.cpp \
|
||||||
|
SkyRasterizer.cpp \
|
||||||
|
CloudBasicLayerRenderer.cpp
|
||||||
|
|
||||||
HEADERS += SoftwareRenderer.h\
|
HEADERS += SoftwareRenderer.h\
|
||||||
software_global.h \
|
software_global.h \
|
||||||
FluidMediumInterface.h \
|
FluidMediumInterface.h \
|
||||||
FluidMediumManager.h \
|
FluidMediumManager.h \
|
||||||
AtmosphereRenderer.h
|
AtmosphereRenderer.h \
|
||||||
|
CloudsRenderer.h \
|
||||||
|
BaseCloudLayerRenderer.h \
|
||||||
|
SkyRasterizer.h \
|
||||||
|
CloudBasicLayerRenderer.h
|
||||||
|
|
||||||
unix:!symbian {
|
unix:!symbian {
|
||||||
maemo5 {
|
maemo5 {
|
||||||
|
|
|
@ -21,6 +21,9 @@ namespace software {
|
||||||
|
|
||||||
class BaseAtmosphereRenderer;
|
class BaseAtmosphereRenderer;
|
||||||
class SoftwareBrunetonAtmosphereRenderer;
|
class SoftwareBrunetonAtmosphereRenderer;
|
||||||
|
|
||||||
|
class CloudsRenderer;
|
||||||
|
class BaseCloudLayerRenderer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,13 +55,3 @@ void RenderingScenery::bindToRenderer(Renderer* renderer)
|
||||||
renderer->setScenery(this);
|
renderer->setScenery(this);
|
||||||
renderer->prepare();
|
renderer->prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Transitional C-API
|
|
||||||
|
|
||||||
void sceneryRenderFirstPass(Renderer* renderer)
|
|
||||||
{
|
|
||||||
terrainRenderSurface(renderer);
|
|
||||||
waterRenderSurface(renderer);
|
|
||||||
atmosphereRenderSkydome(renderer);
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,8 +34,4 @@ private:
|
||||||
void* _custom_data;
|
void* _custom_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Transitional C-API
|
|
||||||
|
|
||||||
RENDERINGSHARED_EXPORT void sceneryRenderFirstPass(Renderer* renderer);
|
|
||||||
|
|
||||||
#endif // SCENERY_H
|
#endif // SCENERY_H
|
||||||
|
|
|
@ -38,8 +38,6 @@ public:
|
||||||
|
|
||||||
RENDERINGSHARED_EXPORT extern StandardRenderer AtmosphereRendererClass;
|
RENDERINGSHARED_EXPORT extern StandardRenderer AtmosphereRendererClass;
|
||||||
|
|
||||||
RENDERINGSHARED_EXPORT void atmosphereRenderSkydome(Renderer* renderer);
|
|
||||||
|
|
||||||
RENDERINGSHARED_EXPORT void atmosphereInitResult(AtmosphereResult* result);
|
RENDERINGSHARED_EXPORT void atmosphereInitResult(AtmosphereResult* result);
|
||||||
RENDERINGSHARED_EXPORT void atmosphereUpdateResult(AtmosphereResult* result);
|
RENDERINGSHARED_EXPORT void atmosphereUpdateResult(AtmosphereResult* result);
|
||||||
|
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
#include "clo_density.h"
|
|
||||||
|
|
||||||
#include "NoiseGenerator.h"
|
|
||||||
#include "CloudLayerDefinition.h"
|
|
||||||
#include "Curve.h"
|
|
||||||
|
|
||||||
double cloudsGetLayerCoverage(CloudLayerDefinition* layer, Vector3 location)
|
|
||||||
{
|
|
||||||
if (layer->base_coverage <= 0.0)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double coverage = 0.5 + layer->_coverage_noise->get2DTotal(location.x / layer->shape_scaling, location.z / layer->shape_scaling);
|
|
||||||
coverage -= (1.0 - layer->base_coverage);
|
|
||||||
|
|
||||||
coverage *= layer->_coverage_by_altitude->getValue((location.y - layer->lower_altitude) / layer->thickness);
|
|
||||||
|
|
||||||
if (coverage < 0.0)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
else if (coverage >= 1.0)
|
|
||||||
{
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return coverage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double cloudsGetLayerDensity(CloudLayerDefinition* layer, Vector3 location, double coverage)
|
|
||||||
{
|
|
||||||
if (coverage <= 0.0)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
else if (coverage >= 1.0)
|
|
||||||
{
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double density = layer->_shape_noise->get3DTotal(location.x / layer->shape_scaling, location.y / layer->shape_scaling, location.z / layer->shape_scaling);
|
|
||||||
density -= (0.5 - coverage);
|
|
||||||
return (density <= 0.0) ? 0.0 : density;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double cloudsGetEdgeDensity(CloudLayerDefinition* layer, Vector3 location, double layer_density)
|
|
||||||
{
|
|
||||||
if (layer_density <= 0.0)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
else if (layer_density >= 1.0)
|
|
||||||
{
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double density = layer->_edge_noise->get3DTotal(location.x / layer->edge_scaling, location.y / layer->edge_scaling, location.z / layer->edge_scaling);
|
|
||||||
density -= (0.5 - layer_density);
|
|
||||||
return (density <= 0.0) ? 0.0 : density;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static double _fakeGetDensity(Renderer*, CloudLayerDefinition*, Vector3)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double _fakeGetEdgeDensity(Renderer*, CloudLayerDefinition*, Vector3, double)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsBindFakeDensityToRenderer(CloudsRenderer* renderer)
|
|
||||||
{
|
|
||||||
renderer->getLayerDensity = _fakeGetDensity;
|
|
||||||
renderer->getEdgeDensity = _fakeGetEdgeDensity;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double _realGetDensity(Renderer*, CloudLayerDefinition* layer, Vector3 location)
|
|
||||||
{
|
|
||||||
double coverage = cloudsGetLayerCoverage(layer, location);
|
|
||||||
|
|
||||||
return cloudsGetLayerDensity(layer, location, coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
static double _realGetEdgeDensity(Renderer*, CloudLayerDefinition* layer, Vector3 location, double layer_density)
|
|
||||||
{
|
|
||||||
return cloudsGetEdgeDensity(layer, location, layer_density);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsBindRealDensityToRenderer(CloudsRenderer* renderer)
|
|
||||||
{
|
|
||||||
renderer->getLayerDensity = _realGetDensity;
|
|
||||||
renderer->getEdgeDensity = _realGetEdgeDensity;
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
#ifndef _PAYSAGES_CLOUDS_DENSITY_H_
|
|
||||||
#define _PAYSAGES_CLOUDS_DENSITY_H_
|
|
||||||
|
|
||||||
#include "public.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Coverage/density management in a cloud layer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the coverage of a cloud layer [0.0;1.0]
|
|
||||||
*
|
|
||||||
* 0.0 means no cloud is present.
|
|
||||||
* 1.0 means full layer.
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT double cloudsGetLayerCoverage(CloudLayerDefinition* layer, Vector3 location);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the global density of a cloud layer at a given point [0.0;1.0].
|
|
||||||
*
|
|
||||||
* 0.0 means no cloud is present.
|
|
||||||
* 1.0 means full density (deep inside cloud).
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT double cloudsGetLayerDensity(CloudLayerDefinition* layer, Vector3 location, double coverage);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the local density of a cloud layer at a given point inside an edge [0.0;1.0].
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT double cloudsGetEdgeDensity(CloudLayerDefinition* layer, Vector3 location, double layer_density);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bind fake density functions to a renderer.
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsBindFakeDensityToRenderer(CloudsRenderer* renderer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bind real density functions to a renderer.
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsBindRealDensityToRenderer(CloudsRenderer* renderer);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,278 +0,0 @@
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "../renderer.h"
|
|
||||||
#include "clo_density.h"
|
|
||||||
#include "clo_walking.h"
|
|
||||||
#include "atmosphere/public.h"
|
|
||||||
#include "CloudsDefinition.h"
|
|
||||||
#include "CloudLayerDefinition.h"
|
|
||||||
|
|
||||||
/******************** Fake ********************/
|
|
||||||
static int _fakeAlterLight(Renderer*, LightDefinition*, Vector3)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _fakeGetColor(Renderer*, Color base, Vector3, Vector3)
|
|
||||||
{
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************** Real ********************/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double light_power;
|
|
||||||
double out_scattering; /* Amount of light scattered away by heavy particles */
|
|
||||||
} AccumulatedLightData;
|
|
||||||
|
|
||||||
static void _walkerFilterCallback(CloudsWalker* walker)
|
|
||||||
{
|
|
||||||
CloudWalkerStepInfo* segment = cloudsWalkerGetLastSegment(walker);
|
|
||||||
Renderer* renderer = segment->renderer;
|
|
||||||
AccumulatedLightData* data = (AccumulatedLightData*)segment->data;
|
|
||||||
|
|
||||||
assert(data != NULL);
|
|
||||||
|
|
||||||
double density_integral;
|
|
||||||
if (segment->subdivided)
|
|
||||||
{
|
|
||||||
density_integral = segment->length * (segment->start.local_density + segment->end.local_density) / 2.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!segment->refined && segment->start.global_density == 0.0 && segment->end.global_density > 0.0)
|
|
||||||
{
|
|
||||||
cloudsWalkerOrderRefine(walker, 1.0 / (double)renderer->render_quality);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if ((segment->start.global_density > 0.0 || segment->end.global_density > 0.0) && (segment->start.global_density < 1.0 || segment->end.global_density < 1.0))
|
|
||||||
{
|
|
||||||
cloudsWalkerOrderSubdivide(walker, renderer->render_quality + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->out_scattering += 0.3 * density_integral;
|
|
||||||
|
|
||||||
if (data->out_scattering > data->light_power)
|
|
||||||
{
|
|
||||||
cloudsWalkerOrderStop(walker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
|
||||||
{
|
|
||||||
CloudsDefinition* definition = renderer->clouds->definition;
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
AccumulatedLightData data;
|
|
||||||
data.out_scattering = 0.0;
|
|
||||||
data.light_power = colorGetPower(&light->color);
|
|
||||||
|
|
||||||
/* TODO Iter layers in sorted order */
|
|
||||||
n = definition->count();
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
CloudLayerDefinition* layer = definition->getCloudLayer(i);
|
|
||||||
Vector3 ostart, oend;
|
|
||||||
|
|
||||||
ostart = location;
|
|
||||||
oend = v3Add(location, v3Scale(light->direction, -10000.0));
|
|
||||||
if (!cloudsOptimizeWalkingBounds(layer, &ostart, &oend))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CloudsWalker* walker;
|
|
||||||
|
|
||||||
walker = cloudsCreateWalker(renderer, layer, ostart, oend);
|
|
||||||
cloudsWalkerSetStepSize(walker, -1.0);
|
|
||||||
cloudsWalkerSetVoidSkipping(walker, 1);
|
|
||||||
cloudsStartWalking(walker, _walkerFilterCallback, &data);
|
|
||||||
cloudsDeleteWalker(walker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double max_power = data.light_power - data.out_scattering;
|
|
||||||
if (max_power < 0.0)
|
|
||||||
{
|
|
||||||
light->color = COLOR_BLACK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colorLimitPower(&light->color, max_power);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.out_scattering > 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double out_scattering; /* Amount of light scattered away by heavy particles */
|
|
||||||
Color in_scattering; /* Amount of light redirected toward the viewer */
|
|
||||||
int entry_found; /* 1 if a cloud entry has been found */
|
|
||||||
Vector3 entry; /* Point of entry in the clouds */
|
|
||||||
} AccumulatedMaterialData;
|
|
||||||
|
|
||||||
static inline void _applyOutScattering(Color* col, double out_scattering)
|
|
||||||
{
|
|
||||||
if (out_scattering >= 1.0)
|
|
||||||
{
|
|
||||||
col->r = col->g = col->b = 0.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
col->r *= (1.0 - out_scattering);
|
|
||||||
col->g *= (1.0 - out_scattering);
|
|
||||||
col->b *= (1.0 - out_scattering);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _walkerMaterialCallback(CloudsWalker* walker)
|
|
||||||
{
|
|
||||||
CloudWalkerStepInfo* segment = cloudsWalkerGetLastSegment(walker);
|
|
||||||
AccumulatedMaterialData* data = (AccumulatedMaterialData*)segment->data;
|
|
||||||
Renderer* renderer = segment->renderer;
|
|
||||||
CloudLayerDefinition* layer = segment->layer;
|
|
||||||
|
|
||||||
assert(data != NULL);
|
|
||||||
|
|
||||||
double density_integral;
|
|
||||||
if (segment->subdivided)
|
|
||||||
{
|
|
||||||
density_integral = segment->length * (segment->start.local_density + segment->end.local_density) / 2.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!segment->refined && segment->start.global_density == 0.0 && segment->end.global_density > 0.0)
|
|
||||||
{
|
|
||||||
cloudsWalkerOrderRefine(walker, 1.0 / (double)(renderer->render_quality * renderer->render_quality));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if ((segment->start.global_density > 0.0 || segment->end.global_density > 0.0) && (segment->start.global_density < 1.0 || segment->end.global_density < 1.0))
|
|
||||||
{
|
|
||||||
cloudsWalkerOrderSubdivide(walker, renderer->render_quality + 3);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (density_integral > 0.0)
|
|
||||||
{
|
|
||||||
data->out_scattering += 0.3 * density_integral;
|
|
||||||
|
|
||||||
Color in_scattering = renderer->applyLightingToSurface(renderer, segment->start.location, VECTOR_ZERO, layer->material);
|
|
||||||
in_scattering.r *= density_integral * 5.0;
|
|
||||||
in_scattering.g *= density_integral * 5.0;
|
|
||||||
in_scattering.b *= density_integral * 5.0;
|
|
||||||
_applyOutScattering(&in_scattering, data->out_scattering);
|
|
||||||
|
|
||||||
data->in_scattering.r += in_scattering.r;
|
|
||||||
data->in_scattering.g += in_scattering.g;
|
|
||||||
data->in_scattering.b += in_scattering.b;
|
|
||||||
|
|
||||||
if (!data->entry_found)
|
|
||||||
{
|
|
||||||
data->entry_found = 1;
|
|
||||||
data->entry = segment->start.location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 end)
|
|
||||||
{
|
|
||||||
CloudsDefinition* definition = renderer->clouds->definition;
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
n = definition->count();
|
|
||||||
if (n < 1)
|
|
||||||
{
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO Iter layers in sorted order */
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
CloudLayerDefinition* layer = definition->getCloudLayer(i);
|
|
||||||
Vector3 ostart, oend;
|
|
||||||
|
|
||||||
ostart = start;
|
|
||||||
oend = end;
|
|
||||||
if (!cloudsOptimizeWalkingBounds(layer, &ostart, &oend))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CloudsWalker* walker;
|
|
||||||
AccumulatedMaterialData data;
|
|
||||||
data.out_scattering = 0.0;
|
|
||||||
data.in_scattering = COLOR_BLACK;
|
|
||||||
data.entry = ostart;
|
|
||||||
data.entry_found = 0;
|
|
||||||
|
|
||||||
walker = cloudsCreateWalker(renderer, layer, ostart, oend);
|
|
||||||
cloudsWalkerSetStepSize(walker, -1.0);
|
|
||||||
cloudsWalkerSetVoidSkipping(walker, 1);
|
|
||||||
cloudsStartWalking(walker, _walkerMaterialCallback, &data);
|
|
||||||
cloudsDeleteWalker(walker);
|
|
||||||
|
|
||||||
/* Apply final out_scattering to base */
|
|
||||||
_applyOutScattering(&base, data.out_scattering);
|
|
||||||
|
|
||||||
/* Apply in_scattering */
|
|
||||||
base.r += data.in_scattering.r;
|
|
||||||
base.g += data.in_scattering.g;
|
|
||||||
base.b += data.in_scattering.b;
|
|
||||||
|
|
||||||
/* Apply aerial perspective approximation */
|
|
||||||
base = renderer->atmosphere->applyAerialPerspective(renderer, data.entry, base).final;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************** Renderer ********************/
|
|
||||||
static CloudsRenderer* _createRenderer()
|
|
||||||
{
|
|
||||||
CloudsRenderer* result;
|
|
||||||
|
|
||||||
result = new CloudsRenderer;
|
|
||||||
result->definition = new CloudsDefinition(NULL);
|
|
||||||
|
|
||||||
result->getColor = _fakeGetColor;
|
|
||||||
result->alterLight = (FuncLightingAlterLight)_fakeAlterLight;
|
|
||||||
|
|
||||||
cloudsBindFakeDensityToRenderer(result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _deleteRenderer(CloudsRenderer* renderer)
|
|
||||||
{
|
|
||||||
delete renderer->definition;
|
|
||||||
delete renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _bindRenderer(Renderer* renderer, CloudsDefinition* definition)
|
|
||||||
{
|
|
||||||
definition->copy(renderer->clouds->definition);
|
|
||||||
|
|
||||||
renderer->clouds->getColor = _getColor;
|
|
||||||
renderer->clouds->alterLight = (FuncLightingAlterLight)_alterLight;
|
|
||||||
|
|
||||||
cloudsBindRealDensityToRenderer(renderer->clouds);
|
|
||||||
|
|
||||||
lightingManagerRegisterFilter(renderer->lighting, (FuncLightingAlterLight)_alterLight, renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
StandardRenderer CloudsRendererClass = {
|
|
||||||
(FuncObjectCreate)_createRenderer,
|
|
||||||
(FuncObjectDelete)_deleteRenderer,
|
|
||||||
(FuncObjectBind)_bindRenderer
|
|
||||||
};
|
|
|
@ -1,364 +0,0 @@
|
||||||
#include "clo_walking.h"
|
|
||||||
|
|
||||||
#include "../renderer.h"
|
|
||||||
#include "CloudLayerDefinition.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Control of the next walking order.
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
CLOUD_WALKING_CONTINUE,
|
|
||||||
CLOUD_WALKING_STOP,
|
|
||||||
CLOUD_WALKING_REFINE,
|
|
||||||
CLOUD_WALKING_SUBDIVIDE
|
|
||||||
} CloudWalkingOrder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Additional info for walking orders.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
CloudWalkingOrder order;
|
|
||||||
double precision;
|
|
||||||
int max_segments;
|
|
||||||
} CloudWalkingNextAction;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Private structure for the walker.
|
|
||||||
*/
|
|
||||||
struct CloudsWalker
|
|
||||||
{
|
|
||||||
Vector3 start;
|
|
||||||
Vector3 end;
|
|
||||||
Vector3 diff;
|
|
||||||
|
|
||||||
double cursor;
|
|
||||||
double max_length;
|
|
||||||
double step_size;
|
|
||||||
int skip_void;
|
|
||||||
int local_density;
|
|
||||||
|
|
||||||
int started;
|
|
||||||
CloudWalkerStepInfo last_segment;
|
|
||||||
|
|
||||||
int subdivision_current;
|
|
||||||
int subdivision_count;
|
|
||||||
CloudWalkerStepInfo subdivision_parent;
|
|
||||||
|
|
||||||
CloudWalkingNextAction next_action;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int cloudsOptimizeWalkingBounds(CloudLayerDefinition* layer, Vector3* start, Vector3* end)
|
|
||||||
{
|
|
||||||
Vector3 diff;
|
|
||||||
|
|
||||||
if (start->y > layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
if (end->y >= layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
diff = v3Sub(*end, *start);
|
|
||||||
*start = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
|
|
||||||
if (end->y < layer->lower_altitude)
|
|
||||||
{
|
|
||||||
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude - end->y) / diff.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (start->y < layer->lower_altitude)
|
|
||||||
{
|
|
||||||
if (end->y <= layer->lower_altitude)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
diff = v3Sub(*end, *start);
|
|
||||||
*start = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
|
|
||||||
if (end->y >= layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
*end = v3Add(*end, v3Scale(diff, (layer->lower_altitude + layer->thickness - end->y) / diff.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* start is inside layer */
|
|
||||||
{
|
|
||||||
diff = v3Sub(*end, *start);
|
|
||||||
if (end->y > layer->lower_altitude + layer->thickness)
|
|
||||||
{
|
|
||||||
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude + layer->thickness - start->y) / diff.y));
|
|
||||||
}
|
|
||||||
else if (end->y < layer->lower_altitude)
|
|
||||||
{
|
|
||||||
*end = v3Add(*start, v3Scale(diff, (layer->lower_altitude - start->y) / diff.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudLayerDefinition* layer, Vector3 start, Vector3 end)
|
|
||||||
{
|
|
||||||
CloudsWalker* result;
|
|
||||||
|
|
||||||
result = (CloudsWalker*)malloc(sizeof (CloudsWalker));
|
|
||||||
|
|
||||||
result->start = start;
|
|
||||||
result->end = end;
|
|
||||||
result->diff = v3Sub(end, start);
|
|
||||||
result->max_length = v3Norm(result->diff);
|
|
||||||
result->cursor = 0.0;
|
|
||||||
result->step_size = 1.0;
|
|
||||||
result->skip_void = 0;
|
|
||||||
result->local_density = -1;
|
|
||||||
|
|
||||||
result->started = 0;
|
|
||||||
result->subdivision_count = 0;
|
|
||||||
result->last_segment.renderer = renderer;
|
|
||||||
result->last_segment.layer = layer;
|
|
||||||
|
|
||||||
result->next_action.order = CLOUD_WALKING_CONTINUE;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsDeleteWalker(CloudsWalker* walker)
|
|
||||||
{
|
|
||||||
free(walker);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsWalkerSetStepSize(CloudsWalker* walker, double step)
|
|
||||||
{
|
|
||||||
if (step > 0.0)
|
|
||||||
{
|
|
||||||
walker->step_size = step;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* TODO Automatic settings (using rendering quality and cloud feature size) */
|
|
||||||
walker->step_size = 5.0 / (double)walker->last_segment.renderer->render_quality;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsWalkerToggleLocalDensity(CloudsWalker* walker, int enabled)
|
|
||||||
{
|
|
||||||
walker->local_density = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsWalkerSetVoidSkipping(CloudsWalker* walker, int enabled)
|
|
||||||
{
|
|
||||||
walker->skip_void = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _getPoint(CloudsWalker* walker, double cursor, CloudWalkerPoint* out_point)
|
|
||||||
{
|
|
||||||
out_point->distance_from_start = cursor;
|
|
||||||
out_point->location = v3Add(walker->start, v3Scale(walker->diff, out_point->distance_from_start / walker->max_length));
|
|
||||||
|
|
||||||
Renderer* renderer = walker->last_segment.renderer;
|
|
||||||
CloudLayerDefinition* layer = walker->last_segment.layer;
|
|
||||||
out_point->global_density = renderer->clouds->getLayerDensity(renderer, layer, out_point->location);
|
|
||||||
|
|
||||||
if (walker->local_density > 0 || (walker->local_density < 0 && walker->subdivision_count > 0))
|
|
||||||
{
|
|
||||||
out_point->local_density = renderer->clouds->getEdgeDensity(renderer, layer, out_point->location, out_point->global_density);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out_point->local_density = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _refineSegment(CloudsWalker* walker, double start_cursor, double start_density, double end_cursor, double end_density, double precision, CloudWalkerPoint* result)
|
|
||||||
{
|
|
||||||
CloudWalkerPoint middle;
|
|
||||||
|
|
||||||
_getPoint(walker, (start_cursor + end_cursor) / 2.0, &middle);
|
|
||||||
|
|
||||||
if (start_density == 0.0)
|
|
||||||
{
|
|
||||||
/* Looking for entry */
|
|
||||||
if (middle.distance_from_start - start_cursor < precision)
|
|
||||||
{
|
|
||||||
*result = middle;
|
|
||||||
}
|
|
||||||
else if (middle.global_density == 0.0)
|
|
||||||
{
|
|
||||||
_refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Looking for exit */
|
|
||||||
if (end_cursor - middle.distance_from_start < precision)
|
|
||||||
{
|
|
||||||
*result = middle;
|
|
||||||
}
|
|
||||||
else if (middle.global_density == 0.0)
|
|
||||||
{
|
|
||||||
_refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cloudsWalkerPerformStep(CloudsWalker* walker)
|
|
||||||
{
|
|
||||||
int result = -1;
|
|
||||||
|
|
||||||
if (!walker->started)
|
|
||||||
{
|
|
||||||
_getPoint(walker, 0.0, &walker->last_segment.end);
|
|
||||||
walker->started = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (result < 0)
|
|
||||||
{
|
|
||||||
if (walker->next_action.order == CLOUD_WALKING_STOP || walker->cursor >= walker->max_length)
|
|
||||||
{
|
|
||||||
walker->next_action.order = CLOUD_WALKING_STOP;
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
else if (walker->subdivision_count > 0)
|
|
||||||
{
|
|
||||||
if (walker->subdivision_current >= walker->subdivision_count)
|
|
||||||
{
|
|
||||||
/* Exit subdivision */
|
|
||||||
walker->subdivision_count = 0;
|
|
||||||
walker->last_segment = walker->subdivision_parent;
|
|
||||||
walker->next_action.order = CLOUD_WALKING_CONTINUE;
|
|
||||||
walker->cursor = walker->subdivision_parent.end.distance_from_start;
|
|
||||||
|
|
||||||
/* Recursive call to progress */
|
|
||||||
result = cloudsWalkerPerformStep(walker);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Continue subdivision */
|
|
||||||
walker->last_segment.start = walker->last_segment.end;
|
|
||||||
|
|
||||||
walker->cursor += walker->subdivision_parent.length / (double)walker->subdivision_count;
|
|
||||||
|
|
||||||
_getPoint(walker, walker->cursor, &walker->last_segment.end);
|
|
||||||
walker->last_segment.length = walker->subdivision_parent.length / (double)walker->subdivision_count;
|
|
||||||
walker->last_segment.refined = 0;
|
|
||||||
walker->last_segment.subdivided = walker->subdivision_count;
|
|
||||||
|
|
||||||
walker->subdivision_current++;
|
|
||||||
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (walker->next_action.order == CLOUD_WALKING_CONTINUE)
|
|
||||||
{
|
|
||||||
/* TODO Limit to lookup end */
|
|
||||||
walker->last_segment.start = walker->last_segment.end;
|
|
||||||
|
|
||||||
walker->cursor += walker->step_size;
|
|
||||||
|
|
||||||
_getPoint(walker, walker->cursor, &walker->last_segment.end);
|
|
||||||
walker->last_segment.length = walker->step_size;
|
|
||||||
walker->last_segment.refined = 0;
|
|
||||||
walker->last_segment.subdivided = 0;
|
|
||||||
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
else if (walker->next_action.order == CLOUD_WALKING_REFINE)
|
|
||||||
{
|
|
||||||
/* Refine segment with dichotomy */
|
|
||||||
_refineSegment(walker,
|
|
||||||
walker->last_segment.start.distance_from_start,
|
|
||||||
walker->last_segment.start.global_density,
|
|
||||||
walker->last_segment.end.distance_from_start,
|
|
||||||
walker->last_segment.end.global_density,
|
|
||||||
walker->next_action.precision,
|
|
||||||
(walker->last_segment.start.global_density == 0.0) ? (&walker->last_segment.start) : (&walker->last_segment.end));
|
|
||||||
walker->last_segment.length = walker->last_segment.end.distance_from_start - walker->last_segment.start.distance_from_start;
|
|
||||||
walker->last_segment.refined = 1;
|
|
||||||
walker->last_segment.subdivided = 0;
|
|
||||||
|
|
||||||
walker->next_action.order = CLOUD_WALKING_CONTINUE;
|
|
||||||
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
else if (walker->next_action.order == CLOUD_WALKING_SUBDIVIDE)
|
|
||||||
{
|
|
||||||
/* Starting subdivision */
|
|
||||||
walker->subdivision_count = walker->next_action.max_segments;
|
|
||||||
walker->subdivision_current = 0;
|
|
||||||
walker->subdivision_parent = walker->last_segment;
|
|
||||||
walker->cursor = walker->subdivision_parent.start.distance_from_start;
|
|
||||||
|
|
||||||
/* Copy parent segment start, to be used as first subdivided segment start */
|
|
||||||
walker->last_segment.end = walker->subdivision_parent.start;
|
|
||||||
|
|
||||||
/* Recursive call to get first subdivided segment */
|
|
||||||
cloudsWalkerPerformStep(walker);
|
|
||||||
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Unknown order... */
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we need to loop */
|
|
||||||
if (result > 0 && walker->skip_void && walker->last_segment.start.global_density == 0.0 && walker->last_segment.end.global_density == 0.0)
|
|
||||||
{
|
|
||||||
/* Last segment is considered void, and skipping is enabled */
|
|
||||||
result = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsWalkerOrderStop(CloudsWalker* walker)
|
|
||||||
{
|
|
||||||
walker->next_action.order = CLOUD_WALKING_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsWalkerOrderRefine(CloudsWalker* walker, double precision)
|
|
||||||
{
|
|
||||||
if (walker->subdivision_count == 0)
|
|
||||||
{
|
|
||||||
walker->next_action.order = CLOUD_WALKING_REFINE;
|
|
||||||
walker->next_action.precision = precision;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsWalkerOrderSubdivide(CloudsWalker* walker, double max_segments)
|
|
||||||
{
|
|
||||||
if (walker->subdivision_count == 0)
|
|
||||||
{
|
|
||||||
walker->next_action.order = CLOUD_WALKING_SUBDIVIDE;
|
|
||||||
walker->next_action.max_segments = max_segments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker)
|
|
||||||
{
|
|
||||||
return &walker->last_segment;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data)
|
|
||||||
{
|
|
||||||
walker->last_segment.data = data;
|
|
||||||
while (cloudsWalkerPerformStep(walker))
|
|
||||||
{
|
|
||||||
callback(walker);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,149 +0,0 @@
|
||||||
#ifndef _PAYSAGES_CLOUDS_WALKING_H_
|
|
||||||
#define _PAYSAGES_CLOUDS_WALKING_H_
|
|
||||||
|
|
||||||
#include "public.h"
|
|
||||||
|
|
||||||
#include "Vector3.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Functions to walk through a cloud layer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double distance_from_start;
|
|
||||||
Vector3 location;
|
|
||||||
double global_density;
|
|
||||||
double local_density;
|
|
||||||
} CloudWalkerPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information on a segment yielded by walking.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Renderer* renderer;
|
|
||||||
CloudLayerDefinition* layer;
|
|
||||||
|
|
||||||
CloudWalkerPoint start;
|
|
||||||
CloudWalkerPoint end;
|
|
||||||
double length;
|
|
||||||
|
|
||||||
int refined;
|
|
||||||
int subdivided;
|
|
||||||
|
|
||||||
void* data;
|
|
||||||
} CloudWalkerStepInfo;
|
|
||||||
|
|
||||||
typedef struct CloudsWalker CloudsWalker;
|
|
||||||
|
|
||||||
typedef void (*FuncCloudsWalkingCallback)(CloudsWalker* walker);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optimize the search limits in a layer.
|
|
||||||
*
|
|
||||||
* @param layer The cloud layer
|
|
||||||
* @param start Start of the search to optimize
|
|
||||||
* @param end End of the search to optimize
|
|
||||||
* @return 0 if the search is useless
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT int cloudsOptimizeWalkingBounds(CloudLayerDefinition* layer, Vector3* start, Vector3* end);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a cloud walker.
|
|
||||||
*
|
|
||||||
* For better performance, the segment should by optimized using cloudsOptimizeWalkingBounds.
|
|
||||||
* @param renderer Renderer context
|
|
||||||
* @param layer The cloud layer to traverse
|
|
||||||
* @param start Start of the walk
|
|
||||||
* @param end End of the walk
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudLayerDefinition* layer, Vector3 start, Vector3 end);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a cloud walker.
|
|
||||||
*
|
|
||||||
* @param walker The walker to free
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsDeleteWalker(CloudsWalker* walker);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the segment size for next steps.
|
|
||||||
*
|
|
||||||
* @param walker The walker to configure
|
|
||||||
* @param step The step length, negative for automatic
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsWalkerSetStepSize(CloudsWalker* walker, double step);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the void skipping mode.
|
|
||||||
*
|
|
||||||
* @param walker The walker to configure
|
|
||||||
* @param enabled 1 to enable the void skipping, 0 to disable
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsWalkerSetVoidSkipping(CloudsWalker* walker, int enabled);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle the local density computing.
|
|
||||||
*
|
|
||||||
* When this option is set, the CloudWalkerStepInfo will contain information about local density.
|
|
||||||
* The automatic setting will set to 1 on subdivided steps, and 0 elsewhere.
|
|
||||||
* @param walker The walker to configure
|
|
||||||
* @param enabled 1 to enable local density, 0 to disable it, -1 for automatic setting.
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsWalkerToggleLocalDensity(CloudsWalker* walker, int enabled);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a single step.
|
|
||||||
*
|
|
||||||
* @param walker The walker to use
|
|
||||||
* @return 1 to continue the loop, 0 to stop
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT int cloudsWalkerPerformStep(CloudsWalker* walker);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Order the walker to stop.
|
|
||||||
*
|
|
||||||
* @param walker The walker to use
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsWalkerOrderStop(CloudsWalker* walker);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Order the walker to refine the search for cloud entry or exit.
|
|
||||||
*
|
|
||||||
* The refinement will next yield a shorter version of the segment, containing only the cloud-inside portion, with a
|
|
||||||
* tolerance fixed by precision. For an entry point, this will discard the part before cloud entry. For en exit point,
|
|
||||||
* the portion after this point will be part of the next step, as normal walking resumes.
|
|
||||||
* @param walker The walker to use
|
|
||||||
* @param precision Precision wanted for the refinement
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsWalkerOrderRefine(CloudsWalker* walker, double precision);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Order the walker to subdivide the previous segment in smaller segments.
|
|
||||||
*
|
|
||||||
* Next steps will yield subdivided segments. Once subdivided segments have been processed, normal walking
|
|
||||||
* will resume automatically.
|
|
||||||
* @param walker The walker to use
|
|
||||||
* @param max_segments Maximal number of segments
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsWalkerOrderSubdivide(CloudsWalker* walker, double max_segments);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the last segment information.
|
|
||||||
*
|
|
||||||
* @param walker The walker to use
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start walking automatically through a segment.
|
|
||||||
*
|
|
||||||
* The callback will be called with each segment found, giving info and asking for desired alteration on walking.
|
|
||||||
* @param walker The walker to use
|
|
||||||
* @param callback Callback to be called with each found segment
|
|
||||||
* @param data User data that will be passed back in the callback
|
|
||||||
*/
|
|
||||||
RENDERINGSHARED_EXPORT void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,14 +0,0 @@
|
||||||
#ifndef _PAYSAGES_CLOUDS_PRIVATE_H_
|
|
||||||
#define _PAYSAGES_CLOUDS_PRIVATE_H_
|
|
||||||
|
|
||||||
#include "public.h"
|
|
||||||
|
|
||||||
#define CLOUDS_MAX_LAYERS 6
|
|
||||||
#define MAX_SEGMENT_COUNT 100
|
|
||||||
|
|
||||||
void cloudsLayerValidateDefinition(CloudLayerDefinition* definition);
|
|
||||||
|
|
||||||
Color cloudsLayerFilterLight(CloudLayerDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
|
|
||||||
Color cloudsApplyLayer(CloudLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef _PAYSAGES_CLOUDS_PUBLIC_H_
|
|
||||||
#define _PAYSAGES_CLOUDS_PUBLIC_H_
|
|
||||||
|
|
||||||
#include "../rendering_global.h"
|
|
||||||
|
|
||||||
#include "../shared/types.h"
|
|
||||||
#include "../tools/lighting.h"
|
|
||||||
#include "SurfaceMaterial.h"
|
|
||||||
|
|
||||||
typedef Color (*FuncCloudsGetColor)(Renderer* renderer, Color base, Vector3 start, Vector3 end);
|
|
||||||
typedef double (*FuncCloudsGetLayerDensity)(Renderer* renderer, CloudLayerDefinition* layer, Vector3 location);
|
|
||||||
typedef double (*FuncCloudsGetEdgeDensity)(Renderer* renderer, CloudLayerDefinition* layer, Vector3 location, double layer_density);
|
|
||||||
|
|
||||||
class CloudsRenderer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CloudsDefinition* definition;
|
|
||||||
|
|
||||||
FuncCloudsGetColor getColor;
|
|
||||||
FuncLightingAlterLight alterLight;
|
|
||||||
FuncCloudsGetLayerDensity getLayerDensity;
|
|
||||||
FuncCloudsGetEdgeDensity getEdgeDensity;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
RENDERINGSHARED_EXPORT extern StandardRenderer CloudsRendererClass;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "RenderingScenery.h"
|
#include "RenderingScenery.h"
|
||||||
#include "CameraDefinition.h"
|
#include "CameraDefinition.h"
|
||||||
#include "atmosphere/public.h"
|
#include "atmosphere/public.h"
|
||||||
#include "clouds/public.h"
|
|
||||||
#include "terrain/public.h"
|
#include "terrain/public.h"
|
||||||
#include "textures/public.h"
|
#include "textures/public.h"
|
||||||
#include "water/public.h"
|
#include "water/public.h"
|
||||||
|
@ -18,7 +17,7 @@ static void* _renderFirstPass(void* data)
|
||||||
{
|
{
|
||||||
Renderer* renderer = (Renderer*)data;
|
Renderer* renderer = (Renderer*)data;
|
||||||
|
|
||||||
sceneryRenderFirstPass(renderer);
|
renderer->rasterize();
|
||||||
renderer->is_rendering = 0;
|
renderer->is_rendering = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +138,6 @@ Renderer::Renderer()
|
||||||
lighting = lightingManagerCreate();
|
lighting = lightingManagerCreate();
|
||||||
|
|
||||||
atmosphere = (AtmosphereRenderer*)AtmosphereRendererClass.create();
|
atmosphere = (AtmosphereRenderer*)AtmosphereRendererClass.create();
|
||||||
clouds = (CloudsRenderer*)CloudsRendererClass.create();
|
|
||||||
terrain = (TerrainRenderer*)TerrainRendererClass.create();
|
terrain = (TerrainRenderer*)TerrainRendererClass.create();
|
||||||
textures = (TexturesRenderer*)TexturesRendererClass.create();
|
textures = (TexturesRenderer*)TexturesRendererClass.create();
|
||||||
water = (WaterRenderer*)WaterRendererClass.create();
|
water = (WaterRenderer*)WaterRendererClass.create();
|
||||||
|
@ -151,7 +149,6 @@ Renderer::~Renderer()
|
||||||
lightingManagerDelete(lighting);
|
lightingManagerDelete(lighting);
|
||||||
|
|
||||||
AtmosphereRendererClass.destroy(atmosphere);
|
AtmosphereRendererClass.destroy(atmosphere);
|
||||||
CloudsRendererClass.destroy(clouds);
|
|
||||||
TerrainRendererClass.destroy(terrain);
|
TerrainRendererClass.destroy(terrain);
|
||||||
TexturesRendererClass.destroy(textures);
|
TexturesRendererClass.destroy(textures);
|
||||||
WaterRendererClass.destroy(water);
|
WaterRendererClass.destroy(water);
|
||||||
|
@ -159,10 +156,8 @@ Renderer::~Renderer()
|
||||||
renderDeleteArea(render_area);
|
renderDeleteArea(render_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Renderer::applyMediumTraversal(Vector3 location, Color color)
|
Color Renderer::applyMediumTraversal(Vector3, Color color)
|
||||||
{
|
{
|
||||||
color = atmosphere->applyAerialPerspective(this, location, color).final;
|
|
||||||
color = clouds->getColor(this, color, getCameraLocation(this, location), location);
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ class LightingManager;
|
||||||
class AtmosphereRenderer;
|
class AtmosphereRenderer;
|
||||||
class TerrainRenderer;
|
class TerrainRenderer;
|
||||||
class TexturesRenderer;
|
class TexturesRenderer;
|
||||||
class CloudsRenderer;
|
|
||||||
class WaterRenderer;
|
class WaterRenderer;
|
||||||
|
|
||||||
class Renderer
|
class Renderer
|
||||||
|
@ -19,6 +18,7 @@ public:
|
||||||
virtual ~Renderer();
|
virtual ~Renderer();
|
||||||
|
|
||||||
virtual void prepare() {}
|
virtual void prepare() {}
|
||||||
|
virtual void rasterize() {}
|
||||||
virtual void setScenery(Scenery*) {}
|
virtual void setScenery(Scenery*) {}
|
||||||
|
|
||||||
/* Render base configuration */
|
/* Render base configuration */
|
||||||
|
@ -57,7 +57,6 @@ public:
|
||||||
AtmosphereRenderer* atmosphere;
|
AtmosphereRenderer* atmosphere;
|
||||||
TerrainRenderer* terrain;
|
TerrainRenderer* terrain;
|
||||||
TexturesRenderer* textures;
|
TexturesRenderer* textures;
|
||||||
CloudsRenderer* clouds;
|
|
||||||
WaterRenderer* water;
|
WaterRenderer* water;
|
||||||
|
|
||||||
/* Custom data */
|
/* Custom data */
|
||||||
|
|
|
@ -12,11 +12,7 @@ SOURCES += main.cpp \
|
||||||
renderer.cpp \
|
renderer.cpp \
|
||||||
render.cpp \
|
render.cpp \
|
||||||
atmosphere/atm_render.cpp \
|
atmosphere/atm_render.cpp \
|
||||||
atmosphere/atm_raster.cpp \
|
|
||||||
atmosphere/atm_bruneton.cpp \
|
atmosphere/atm_bruneton.cpp \
|
||||||
clouds/clo_walking.cpp \
|
|
||||||
clouds/clo_rendering.cpp \
|
|
||||||
clouds/clo_density.cpp \
|
|
||||||
terrain/ter_render.cpp \
|
terrain/ter_render.cpp \
|
||||||
terrain/ter_raster.cpp \
|
terrain/ter_raster.cpp \
|
||||||
terrain/ter_painting.cpp \
|
terrain/ter_painting.cpp \
|
||||||
|
@ -38,10 +34,6 @@ HEADERS += \
|
||||||
main.h \
|
main.h \
|
||||||
atmosphere/public.h \
|
atmosphere/public.h \
|
||||||
atmosphere/private.h \
|
atmosphere/private.h \
|
||||||
clouds/public.h \
|
|
||||||
clouds/private.h \
|
|
||||||
clouds/clo_walking.h \
|
|
||||||
clouds/clo_density.h \
|
|
||||||
shared/types.h \
|
shared/types.h \
|
||||||
terrain/ter_raster.h \
|
terrain/ter_raster.h \
|
||||||
terrain/public.h \
|
terrain/public.h \
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
#include "BaseTestCase.h"
|
#include "BaseTestCase.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "renderer.h"
|
#include "SoftwareRenderer.h"
|
||||||
#include "clouds/public.h"
|
|
||||||
#include "clouds/clo_density.h"
|
|
||||||
#include "clouds/clo_walking.h"
|
|
||||||
#include "CloudLayerDefinition.h"
|
#include "CloudLayerDefinition.h"
|
||||||
#include "NoiseGenerator.h"
|
#include "NoiseGenerator.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
TEST(Clouds, Density)
|
TEST(Clouds, Density)
|
||||||
{
|
{
|
||||||
/* Setup */
|
/* Setup */
|
||||||
|
@ -448,3 +447,5 @@ TEST(Clouds, WalkingLocal)
|
||||||
ASSERT_DOUBLE_EQ(segment->end.global_density, 0.809016994375);
|
ASSERT_DOUBLE_EQ(segment->end.global_density, 0.809016994375);
|
||||||
ASSERT_DOUBLE_EQ(segment->end.local_density, 0.654508497187);
|
ASSERT_DOUBLE_EQ(segment->end.local_density, 0.654508497187);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue