paysages : Water refactoring (WIP).

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@527 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2013-02-27 16:38:27 +00:00 committed by ThunderK
parent 9a7bc290dc
commit e8b3468038
19 changed files with 701 additions and 605 deletions

View file

@ -3,16 +3,15 @@
#include <QColor>
#include <QSlider>
#include <math.h>
#include "../lib_paysages/tools/euclid.h"
#include "../lib_paysages/tools/lighting.h"
#include "../lib_paysages/renderer.h"
#include "../lib_paysages/scenery.h"
#include "../lib_paysages/water.h"
#include "../lib_paysages/water/public.h"
#include "tools.h"
static WaterDefinition _definition;
static WaterDefinition* _definition;
/**************** Previews ****************/
class PreviewWaterCoverage:public BasePreview
@ -20,8 +19,7 @@ class PreviewWaterCoverage:public BasePreview
public:
PreviewWaterCoverage(QWidget* parent):BasePreview(parent)
{
_renderer = terrainCreatePreviewRenderer();
_water = waterCreateDefinition();
_renderer = waterCreatePreviewCoverageRenderer();
_highlight_enabled = true;
addOsd(QString("geolocation"));
@ -33,40 +31,11 @@ public:
protected:
Color getColor(double x, double y)
{
double height;
height = _renderer->terrain->getHeight(_renderer, x, y, 1);
if (height > _definition.height)
{
return terrainGetPreviewColor(_renderer, x, y, scaling);
}
else
{
Vector3 location, look;
Color base;
location.x = x;
location.y = _water.height;
location.z = y;
look.x = 0.0;
look.y = -1.0;
look.z = 0.0;
base = waterGetColor(&_water, _renderer, location, look);
if (_highlight_enabled)
{
Color mask = {0.5, 0.5, 1.0, 0.5};
colorMask(&base, &mask);
}
return base;
}
return waterGetPreviewCoverage(_renderer, x, y, scaling, _highlight_enabled ? 1 : 0);
}
void updateData()
{
waterCopyDefinition(&_definition, &_water);
WaterRendererClass.bind(_renderer, _definition);
// TODO Do this only on full refresh
TerrainDefinition* terrain = (TerrainDefinition*)TerrainDefinitionClass.create();
@ -84,7 +53,6 @@ protected:
}
private:
Renderer* _renderer;
WaterDefinition _water;
bool _highlight_enabled;
};

View file

@ -1,9 +1,9 @@
BUILDMODE = debug
BUILDPATH = ../build/${BUILDMODE}
OBJPATH = ./obj/${BUILDMODE}
SOURCES = $(wildcard *.c atmosphere/*.c clouds/*.c terrain/*.c tools/*.c)
SOURCES = $(wildcard *.c atmosphere/*.c clouds/*.c terrain/*.c water/*.c tools/*.c)
OBJECTS = ${SOURCES:%.c=${OBJPATH}/%.o}
HEADERS = $(wildcard *.h atmosphere/*.h clouds/*.h terrain/*.h tools/*.h shared/*.h)
HEADERS = $(wildcard *.h atmosphere/*.h clouds/*.h terrain/*.h water/*.h tools/*.h shared/*.h)
RESULT = ${BUILDPATH}/libpaysages.so
LIBS = glib-2.0 gthread-2.0 IL ILU
CC_FLAGS = -Wall -fPIC -DHAVE_GLIB=1

View file

@ -1169,7 +1169,7 @@ Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color
Vector3 eye = renderer->getCameraLocation(renderer, location);
Vector3 sun_position = v3Scale(renderer->atmosphere->getSunDirection(renderer), SUN_DISTANCE);
double yoffset = GROUND_OFFSET - renderer->getWaterHeightInfo(renderer).base_height;
double yoffset = GROUND_OFFSET - renderer->water->getHeightInfo(renderer).base_height;
eye.y += yoffset;
location.y += yoffset;
if (eye.y < 0.0)
@ -1212,7 +1212,7 @@ void brunetonGetLightingStatus(Renderer* renderer, LightStatus* status, Vector3
double altitude = lightingGetStatusLocation(status).y;
double yoffset = GROUND_OFFSET - renderer->getWaterHeightInfo(renderer).base_height;
double yoffset = GROUND_OFFSET - renderer->water->getHeightInfo(renderer).base_height;
altitude += yoffset;
if (altitude < 0.0)
{

View file

@ -8,7 +8,6 @@
#include "textures.h"
#include "scenery.h"
#include "system.h"
#include "water.h"
#include "zone.h"
void autoGenRealisticLandscape(int seed)
@ -26,12 +25,6 @@ void autoGenRealisticLandscape(int seed)
sceneryAutoPreset();
/* Water */
water = waterCreateDefinition();
waterAutoPreset(&water, WATER_PRESET_LAKE);
scenerySetWater(&water);
waterDeleteDefinition(&water);
/* Textures */
textures = texturesCreateDefinition();
layer = layersAddLayer(textures.layers, NULL);
@ -87,13 +80,4 @@ void autoGenRealisticLandscape(int seed)
texture->thickness_transparency = 0.015;*/
scenerySetTextures(&textures);
texturesDeleteDefinition(&textures);
/* Atmosphere */
/*atmosphere = atmosphereCreateDefinition();
atmosphere.distance_near = 20.0;
atmosphere.distance_far = 100.0;
atmosphere.full_mask = 0.6;
atmosphere.auto_lock_on_haze = 1;
scenerySetAtmosphere(&atmosphere);
atmosphereDeleteDefinition(&atmosphere);*/
}

View file

@ -69,13 +69,9 @@ void cameraValidateDefinition(CameraDefinition* definition, int check_above)
if (check_above)
{
water = waterCreateDefinition();
sceneryGetWater(&water);
water_height = water.height + 0.5;
waterDeleteDefinition(&water);
renderer = sceneryCreateStandardRenderer();
terrain_height = renderer->terrain->getHeight(renderer, definition->location.x, definition->location.z, 1) + 0.5;
water_height = renderer->water->getHeightInfo(renderer).max_height + 0.5;
rendererDelete(renderer);
if (definition->location.y < water_height || definition->location.y < terrain_height)

View file

@ -7,7 +7,6 @@
#include "tools.h"
static RayCastingResult _RAYCASTING_NULL = {0};
static HeightInfo _WATER_HEIGHT_INFO = {0.0, 0.0, 0.0};
static void* _renderFirstPass(void* data)
{
@ -79,11 +78,6 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
return _RAYCASTING_NULL;
}
static HeightInfo _getWaterHeightInfo(Renderer* renderer)
{
return _WATER_HEIGHT_INFO;
}
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
{
return COLOR_TRANSPARENT;
@ -131,7 +125,6 @@ Renderer* rendererCreate()
result->pushQuad = _pushQuad;
result->rayWalking = _rayWalking;
result->getWaterHeightInfo = _getWaterHeightInfo;
result->applyTextures = _applyTextures;
result->applyLightingToSurface = _applyLightingToSurface;
@ -142,6 +135,7 @@ Renderer* rendererCreate()
result->atmosphere = AtmosphereRendererClass.create();
result->clouds = CloudsRendererClass.create();
result->terrain = TerrainRendererClass.create();
result->water = WaterRendererClass.create();
return result;
}
@ -153,6 +147,7 @@ void rendererDelete(Renderer* renderer)
AtmosphereRendererClass.destroy(renderer->atmosphere);
CloudsRendererClass.destroy(renderer->clouds);
TerrainRendererClass.destroy(renderer->terrain);
WaterRendererClass.destroy(renderer->water);
renderDeleteArea(renderer->render_area);

View file

@ -5,6 +5,7 @@
#include "atmosphere/public.h"
#include "clouds/public.h"
#include "terrain/public.h"
#include "water/public.h"
#include "render.h"
#ifdef __cplusplus
@ -39,7 +40,6 @@ struct Renderer
/* Scenery related */
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);
HeightInfo (*getWaterHeightInfo)(Renderer* renderer);
Color (*applyTextures)(Renderer* renderer, Vector3 location, double precision);
/* Autonomous tools */
@ -49,6 +49,7 @@ struct Renderer
AtmosphereRenderer* atmosphere;
TerrainRenderer* terrain;
CloudsRenderer* clouds;
WaterRenderer* water;
/* Custom data */
void* customData[10];

View file

@ -10,7 +10,7 @@ static CameraDefinition _camera;
static CloudsDefinition* _clouds;
static TerrainDefinition* _terrain;
static TexturesDefinition _textures;
static WaterDefinition _water;
static WaterDefinition* _water;
static SceneryCustomDataCallback _custom_save = NULL;
static SceneryCustomDataCallback _custom_load = NULL;
@ -25,7 +25,7 @@ void sceneryInit()
_clouds = CloudsDefinitionClass.create();
_terrain = TerrainDefinitionClass.create();
_textures = texturesCreateDefinition();
_water = waterCreateDefinition();
_water = WaterDefinitionClass.create();
_custom_save = NULL;
_custom_load = NULL;
@ -38,7 +38,7 @@ void sceneryQuit()
CloudsDefinitionClass.destroy(_clouds);
TerrainDefinitionClass.destroy(_terrain);
texturesDeleteDefinition(&_textures);
waterDeleteDefinition(&_water);
AtmosphereDefinitionClass.destroy(_water);
noiseQuit();
}
@ -47,6 +47,7 @@ void sceneryAutoPreset()
{
terrainAutoPreset(_terrain, TERRAIN_PRESET_STANDARD);
atmosphereAutoPreset(_atmosphere, ATMOSPHERE_PRESET_CLEAR_DAY);
waterAutoPreset(_water, WATER_PRESET_LAKE);
cloudsAutoPreset(_clouds, CLOUDS_PRESET_PARTLY_CLOUDY);
}
@ -65,7 +66,7 @@ void scenerySave(PackStream* stream)
CloudsDefinitionClass.save(stream, _clouds);
TerrainDefinitionClass.save(stream, _terrain);
texturesSave(stream, &_textures);
waterSave(stream, &_water);
WaterDefinitionClass.save(stream, _water);
if (_custom_save)
{
@ -83,11 +84,10 @@ void sceneryLoad(PackStream* stream)
CloudsDefinitionClass.load(stream, _clouds);
TerrainDefinitionClass.load(stream, _terrain);
texturesLoad(stream, &_textures);
waterLoad(stream, &_water);
WaterDefinitionClass.load(stream, _water);
cameraValidateDefinition(&_camera, 0);
texturesValidateDefinition(&_textures);
waterValidateDefinition(&_water);
if (_custom_load)
{
@ -151,21 +151,20 @@ void sceneryGetTextures(TexturesDefinition* textures)
void scenerySetWater(WaterDefinition* water)
{
waterCopyDefinition(water, &_water);
waterValidateDefinition(&_water);
WaterDefinitionClass.copy(water, _water);
cameraValidateDefinition(&_camera, 1);
}
void sceneryGetWater(WaterDefinition* water)
{
waterCopyDefinition(&_water, water);
WaterDefinitionClass.copy(_water, water);
}
void sceneryRenderFirstPass(Renderer* renderer)
{
terrainRenderSurface(renderer);
waterRender(&_water, renderer);
waterRenderSurface(renderer);
atmosphereRenderSkydome(renderer);
}
@ -193,11 +192,6 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
return result;
}
static HeightInfo _getWaterHeightInfo(Renderer* renderer)
{
return waterGetHeightInfo(&_water);
}
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
{
return texturesGetColor(&_textures, renderer, location.x, location.z, precision);
@ -233,7 +227,6 @@ Renderer* sceneryCreateStandardRenderer()
cameraCopyDefinition(&_camera, &result->render_camera);
result->rayWalking = _rayWalking;
result->getWaterHeightInfo = _getWaterHeightInfo;
result->applyTextures = _applyTextures;
result->projectPoint = _projectPoint;
result->unprojectPoint = _unprojectPoint;
@ -242,6 +235,7 @@ Renderer* sceneryCreateStandardRenderer()
AtmosphereRendererClass.bind(result, _atmosphere);
TerrainRendererClass.bind(result, _terrain);
CloudsRendererClass.bind(result, _clouds);
WaterRendererClass.bind(result, _water);
return result;
}

View file

@ -12,9 +12,9 @@
#include "atmosphere/public.h"
#include "clouds/public.h"
#include "terrain/public.h"
#include "water/public.h"
#include "camera.h"
#include "textures.h"
#include "water.h"
#include "renderer.h"
#ifdef __cplusplus

View file

@ -69,7 +69,7 @@ void terrainRenderSurface(Renderer* renderer)
radius_ext = min_chunk_size;
chunk_size = min_chunk_size;
water_height = renderer->getWaterHeightInfo(renderer).max_height;
water_height = renderer->water->getHeightInfo(renderer).max_height;
while (radius_int < 5000.0)
{

View file

@ -1,446 +0,0 @@
#include "water.h"
#include "shared/types.h"
#include "render.h"
#include "tools.h"
#include <math.h>
void waterSave(PackStream* stream, WaterDefinition* definition)
{
packWriteDouble(stream, &definition->height);
materialSave(stream, &definition->material);
colorSave(stream, &definition->depth_color);
packWriteDouble(stream, &definition->transparency_depth);
packWriteDouble(stream, &definition->transparency);
packWriteDouble(stream, &definition->reflection);
packWriteDouble(stream, &definition->lighting_depth);
packWriteDouble(stream, &definition->scaling);
packWriteDouble(stream, &definition->waves_height);
packWriteDouble(stream, &definition->detail_height);
packWriteDouble(stream, &definition->turbulence);
packWriteDouble(stream, &definition->foam_coverage);
materialSave(stream, &definition->foam_material);
noiseSaveGenerator(stream, definition->_waves_noise);
}
void waterLoad(PackStream* stream, WaterDefinition* definition)
{
packReadDouble(stream, &definition->height);
materialLoad(stream, &definition->material);
colorLoad(stream, &definition->depth_color);
packReadDouble(stream, &definition->transparency_depth);
packReadDouble(stream, &definition->transparency);
packReadDouble(stream, &definition->reflection);
packReadDouble(stream, &definition->lighting_depth);
packReadDouble(stream, &definition->scaling);
packReadDouble(stream, &definition->waves_height);
packReadDouble(stream, &definition->detail_height);
packReadDouble(stream, &definition->turbulence);
packReadDouble(stream, &definition->foam_coverage);
materialLoad(stream, &definition->foam_material);
noiseLoadGenerator(stream, definition->_waves_noise);
waterValidateDefinition(definition);
}
WaterDefinition waterCreateDefinition()
{
WaterDefinition result;
result.height = -4.0;
result._waves_noise = noiseCreateGenerator();
waterAutoPreset(&result, WATER_PRESET_LAKE);
return result;
}
void waterDeleteDefinition(WaterDefinition* definition)
{
noiseDeleteGenerator(definition->_waves_noise);
}
void waterAutoPreset(WaterDefinition* definition, WaterPreset preset)
{
noiseRandomizeOffsets(definition->_waves_noise);
if (preset == WATER_PRESET_LAKE)
{
definition->transparency = 0.5;
definition->reflection = 0.4;
definition->transparency_depth = 4.0;
definition->material.base.r = 0.08;
definition->material.base.g = 0.15;
definition->material.base.b = 0.2;
definition->depth_color.r = 0.0;
definition->depth_color.g = 0.1;
definition->depth_color.b = 0.1;
definition->lighting_depth = 6.0;
definition->scaling = 1.0;
definition->waves_height = 0.8;
definition->detail_height = 0.05;
definition->turbulence = 0.1;
definition->foam_coverage = 0.15;
}
else if (preset == WATER_PRESET_SEA)
{
definition->transparency = 0.4;
definition->reflection = 0.35;
definition->transparency_depth = 3.0;
definition->material.base.r = 0.05;
definition->material.base.g = 0.18;
definition->material.base.b = 0.2;
definition->depth_color.r = 0.0;
definition->depth_color.g = 0.18;
definition->depth_color.b = 0.15;
definition->lighting_depth = 4.0;
definition->scaling = 1.5;
definition->waves_height = 1.0;
definition->detail_height = 0.06;
definition->turbulence = 0.3;
definition->foam_coverage = 0.4;
}
definition->depth_color.a = 1.0;
definition->material.base.a = 1.0;
definition->material.reflection = 1.0;
definition->material.shininess = 16.0;
definition->foam_material.base.r = 0.8;
definition->foam_material.base.g = 0.8;
definition->foam_material.base.b = 0.8;
definition->foam_material.base.a = 1.0;
definition->foam_material.reflection = 0.4;
definition->foam_material.shininess = 1.5;
waterValidateDefinition(definition);
}
void waterCopyDefinition(WaterDefinition* source, WaterDefinition* destination)
{
NoiseGenerator* noise;
noise = destination->_waves_noise;
*destination = *source;
destination->_waves_noise = noise;
noiseCopy(source->_waves_noise, destination->_waves_noise);
}
void waterValidateDefinition(WaterDefinition* definition)
{
double scaling = definition->scaling * 0.3;
noiseClearLevels(definition->_waves_noise);
if (definition->waves_height > 0.0)
{
noiseAddLevelsSimple(definition->_waves_noise, 2, scaling, -definition->waves_height * scaling * 0.015, definition->waves_height * scaling * 0.015, 0.5);
}
if (definition->detail_height > 0.0)
{
noiseAddLevelsSimple(definition->_waves_noise, 3, scaling * 0.1, -definition->detail_height * scaling * 0.015, definition->detail_height * scaling * 0.015, 0.5);
}
noiseSetFunctionParams(definition->_waves_noise, NOISE_FUNCTION_SIMPLEX, -definition->turbulence, 0.0);
noiseValidate(definition->_waves_noise);
}
static inline double _getHeight(WaterDefinition* definition, double x, double z)
{
return definition->height + noiseGet2DTotal(definition->_waves_noise, x, z);
}
static inline Vector3 _getNormal(WaterDefinition* definition, Vector3 base, double detail)
{
Vector3 back, right;
double x, z;
x = base.x;
z = base.z;
back.x = x;
back.y = _getHeight(definition, x, z + detail);
back.z = z + detail;
back = v3Sub(back, base);
right.x = x + detail;
right.y = _getHeight(definition, x + detail, z);
right.z = z;
right = v3Sub(right, base);
return v3Normalize(v3Cross(back, right));
}
static inline Vector3 _reflectRay(Vector3 incoming, Vector3 normal)
{
double c;
c = v3Dot(normal, v3Scale(incoming, -1.0));
return v3Add(incoming, v3Scale(normal, 2.0 * c));
}
static inline Vector3 _refractRay(Vector3 incoming, Vector3 normal)
{
double c1, c2, f;
f = 1.0 / 1.33;
c1 = v3Dot(normal, v3Scale(incoming, -1.0));
c2 = sqrt(1.0 - pow(f, 2.0) * (1.0 - pow(c1, 2.0)));
if (c1 >= 0.0)
{
return v3Add(v3Scale(incoming, f), v3Scale(normal, f * c1 - c2));
}
else
{
return v3Add(v3Scale(incoming, f), v3Scale(normal, c2 - f * c1));
}
}
HeightInfo waterGetHeightInfo(WaterDefinition* definition)
{
HeightInfo info;
double noise_minvalue, noise_maxvalue;
info.base_height = definition->height;
noiseGetRange(definition->_waves_noise, &noise_minvalue, &noise_maxvalue);
info.min_height = definition->height + noise_minvalue;
info.max_height = definition->height + noise_maxvalue;
return info;
}
Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
{
double factor;
UNUSED(renderer);
UNUSED(light_location);
if (location.y < definition->height)
{
if (direction_to_light.y > 0.00001)
{
factor = (definition->height - location.y) / (direction_to_light.y * definition->lighting_depth);
if (factor > 1.0)
{
factor = 1.0;
}
factor = 1.0 - 0.8 * factor;
light.r *= factor;
light.g *= factor;
light.b *= factor;
return light;
}
else
{
return COLOR_BLACK;
}
}
else
{
return light;
}
}
static inline void _applyFoam(WaterDefinition* definition, Vector3 location, Vector3 normal, double detail, SurfaceMaterial* material)
{
Color result = definition->foam_material.base;
double foam_factor, normal_diff, location_offset;
location_offset = 2.0 * detail;
foam_factor = 0.0;
location.x += location_offset;
normal_diff = 1.0 - v3Dot(normal, _getNormal(definition, location, detail));
if (normal_diff > foam_factor)
{
foam_factor = normal_diff;
}
location.x -= location_offset * 2.0;
normal_diff = 1.0 - v3Dot(normal, _getNormal(definition, location, detail));
if (normal_diff > foam_factor)
{
foam_factor = normal_diff;
}
location.x += location_offset;
location.z -= location_offset;
normal_diff = 1.0 - v3Dot(normal, _getNormal(definition, location, detail));
if (normal_diff > foam_factor)
{
foam_factor = normal_diff;
}
location.z += location_offset * 2.0;
normal_diff = 1.0 - v3Dot(normal, _getNormal(definition, location, detail));
if (normal_diff > foam_factor)
{
foam_factor = normal_diff;
}
foam_factor *= 10.0;
if (foam_factor > 1.0)
{
foam_factor = 1.0;
}
if (foam_factor <= 1.0 - definition->foam_coverage)
{
return;
}
foam_factor = (foam_factor - (1.0 - definition->foam_coverage)) * definition->foam_coverage;
material->reflection = foam_factor * definition->foam_material.reflection + (1.0 - foam_factor) * material->reflection;
material->shininess = foam_factor * definition->foam_material.shininess + (1.0 - foam_factor) * material->shininess;
/* TODO This should be configurable */
if (foam_factor > 0.2)
{
result.a = 0.8;
}
else
{
result.a = 0.8 * (foam_factor / 0.2);
}
colorMask(&material->base, &result);
}
WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look)
{
WaterResult result;
RayCastingResult refracted;
Vector3 normal;
Color color;
SurfaceMaterial material;
double detail, depth;
detail = renderer->getPrecision(renderer, location) * 0.1;
if (detail < 0.00001)
{
detail = 0.00001;
}
location.y = _getHeight(definition, location.x, location.z);
result.location = location;
normal = _getNormal(definition, location, detail);
look = v3Normalize(look);
result.reflected = renderer->rayWalking(renderer, location, _reflectRay(look, normal), 1, 0, 1, 1).hit_color;
refracted = renderer->rayWalking(renderer, location, _refractRay(look, normal), 1, 0, 1, 1);
depth = v3Norm(v3Sub(location, refracted.hit_location));
if (depth > definition->transparency_depth)
{
result.refracted = definition->depth_color;
}
else
{
depth /= definition->transparency_depth;
result.refracted.r = refracted.hit_color.r * (1.0 - depth) + definition->depth_color.r * depth;
result.refracted.g = refracted.hit_color.g * (1.0 - depth) + definition->depth_color.g * depth;
result.refracted.b = refracted.hit_color.b * (1.0 - depth) + definition->depth_color.b * depth;
result.refracted.a = 1.0;
}
color.r = definition->material.base.r * (1.0 - definition->transparency) + result.reflected.r * definition->reflection + result.refracted.r * definition->transparency;
color.g = definition->material.base.g * (1.0 - definition->transparency) + result.reflected.g * definition->reflection + result.refracted.g * definition->transparency;
color.b = definition->material.base.b * (1.0 - definition->transparency) + result.reflected.b * definition->reflection + result.refracted.b * definition->transparency;
color.a = 1.0;
material = definition->material;
material.base = color;
_applyFoam(definition, location, normal, detail, &material);
color = renderer->applyLightingToSurface(renderer, location, normal, &material);
color = renderer->applyMediumTraversal(renderer, location, color);
result.base = definition->material.base;
result.final = color;
return result;
}
Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look)
{
return waterGetColorDetail(definition, renderer, location, look).final;
}
static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* data)
{
return waterGetColor((WaterDefinition*)data, renderer, location, v3Sub(location, renderer->getCameraLocation(renderer, location)));
}
static Vector3 _getFirstPassVertex(WaterDefinition* definition, double x, double z, double precision)
{
Vector3 result;
UNUSED(precision);
result.x = x;
result.y = _getHeight(definition, x, z);
result.z = z;
return result;
}
static void _renderQuad(WaterDefinition* definition, Renderer* renderer, double x, double z, double size)
{
Vector3 v1, v2, v3, v4;
v1 = _getFirstPassVertex(definition, x, z, size);
v2 = _getFirstPassVertex(definition, x, z + size, size);
v3 = _getFirstPassVertex(definition, x + size, z + size, size);
v4 = _getFirstPassVertex(definition, x + size, z, size);
renderer->pushQuad(renderer, v1, v2, v3, v4, _postProcessFragment, definition);
}
void waterRender(WaterDefinition* definition, Renderer* renderer)
{
int chunk_factor, chunk_count, i;
Vector3 cam = renderer->getCameraLocation(renderer, VECTOR_ZERO);
double cx = cam.x;
double cz = cam.z;
double radius_int, radius_ext, base_chunk_size, chunk_size;
base_chunk_size = 2.0 / (double)renderer->render_quality;
if (renderer->render_quality > 7)
{
base_chunk_size *= 0.5;
}
chunk_factor = 1;
chunk_count = 2;
radius_int = 0.0;
radius_ext = base_chunk_size;
chunk_size = base_chunk_size;
while (radius_int < 5000.0)
{
if (!renderer->addRenderProgress(renderer, 0.0))
{
return;
}
for (i = 0; i < chunk_count - 1; i++)
{
_renderQuad(definition, renderer, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size);
_renderQuad(definition, renderer, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size);
_renderQuad(definition, renderer, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size);
_renderQuad(definition, renderer, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size);
}
if (radius_int > 20.0 && chunk_count % 64 == 0 && (double)chunk_factor < radius_int / 20.0)
{
chunk_count /= 2;
chunk_factor *= 2;
}
chunk_count += 2;
chunk_size = base_chunk_size * chunk_factor;
radius_int = radius_ext;
radius_ext += chunk_size;
}
}

View file

@ -1,71 +0,0 @@
#ifndef _PAYSAGES_WATER_H_
#define _PAYSAGES_WATER_H_
#include "tools/color.h"
#include "tools/euclid.h"
#include "tools/lighting.h"
#include "tools/pack.h"
#include "renderer.h"
#include "noise.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
WATER_PRESET_LAKE,
WATER_PRESET_SEA
} WaterPreset;
typedef struct
{
double height;
double transparency;
double reflection;
SurfaceMaterial material;
Color depth_color;
double transparency_depth;
double lighting_depth;
double scaling;
double turbulence;
double waves_height;
double detail_height;
double foam_coverage;
SurfaceMaterial foam_material;
NoiseGenerator* _waves_noise;
} WaterDefinition;
typedef struct
{
Vector3 location;
Color base;
Color reflected;
Color refracted;
Color foam;
Color final;
} WaterResult;
void waterSave(PackStream* stream, WaterDefinition* definition);
void waterLoad(PackStream* stream, WaterDefinition* definition);
WaterDefinition waterCreateDefinition();
void waterDeleteDefinition(WaterDefinition* definition);
void waterAutoPreset(WaterDefinition* definition, WaterPreset preset);
void waterCopyDefinition(WaterDefinition* source, WaterDefinition* destination);
void waterValidateDefinition(WaterDefinition* definition);
HeightInfo waterGetHeightInfo(WaterDefinition* definition);
Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
void waterRender(WaterDefinition* definition, Renderer* renderer);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,100 @@
#include "private.h"
#include <stdlib.h>
static void _validateDefinition(WaterDefinition* definition)
{
double scaling = definition->scaling * 0.3;
noiseClearLevels(definition->_waves_noise);
if (definition->waves_height > 0.0)
{
noiseAddLevelsSimple(definition->_waves_noise, 2, scaling, -definition->waves_height * scaling * 0.015, definition->waves_height * scaling * 0.015, 0.5);
}
if (definition->detail_height > 0.0)
{
noiseAddLevelsSimple(definition->_waves_noise, 3, scaling * 0.1, -definition->detail_height * scaling * 0.015, definition->detail_height * scaling * 0.015, 0.5);
}
noiseSetFunctionParams(definition->_waves_noise, NOISE_FUNCTION_SIMPLEX, -definition->turbulence, 0.0);
noiseValidate(definition->_waves_noise);
}
static WaterDefinition* _createDefinition()
{
WaterDefinition* definition = malloc(sizeof(WaterDefinition));
definition->height = -4.0;
definition->_waves_noise = noiseCreateGenerator();
waterAutoPreset(definition, WATER_PRESET_LAKE);
return definition;
}
static void _deleteDefinition(WaterDefinition* definition)
{
noiseDeleteGenerator(definition->_waves_noise);
free(definition);
}
static void _copyDefinition(WaterDefinition* source, WaterDefinition* destination)
{
NoiseGenerator* noise;
noise = destination->_waves_noise;
*destination = *source;
destination->_waves_noise = noise;
noiseCopy(source->_waves_noise, destination->_waves_noise);
}
static void _saveDefinition(PackStream* stream, WaterDefinition* definition)
{
packWriteDouble(stream, &definition->height);
materialSave(stream, &definition->material);
colorSave(stream, &definition->depth_color);
packWriteDouble(stream, &definition->transparency_depth);
packWriteDouble(stream, &definition->transparency);
packWriteDouble(stream, &definition->reflection);
packWriteDouble(stream, &definition->lighting_depth);
packWriteDouble(stream, &definition->scaling);
packWriteDouble(stream, &definition->waves_height);
packWriteDouble(stream, &definition->detail_height);
packWriteDouble(stream, &definition->turbulence);
packWriteDouble(stream, &definition->foam_coverage);
materialSave(stream, &definition->foam_material);
noiseSaveGenerator(stream, definition->_waves_noise);
}
static void _loadDefinition(PackStream* stream, WaterDefinition* definition)
{
packReadDouble(stream, &definition->height);
materialLoad(stream, &definition->material);
colorLoad(stream, &definition->depth_color);
packReadDouble(stream, &definition->transparency_depth);
packReadDouble(stream, &definition->transparency);
packReadDouble(stream, &definition->reflection);
packReadDouble(stream, &definition->lighting_depth);
packReadDouble(stream, &definition->scaling);
packReadDouble(stream, &definition->waves_height);
packReadDouble(stream, &definition->detail_height);
packReadDouble(stream, &definition->turbulence);
packReadDouble(stream, &definition->foam_coverage);
materialLoad(stream, &definition->foam_material);
noiseLoadGenerator(stream, definition->_waves_noise);
_validateDefinition(definition);
}
StandardDefinition WaterDefinitionClass = {
(FuncObjectCreate)_createDefinition,
(FuncObjectDelete)_deleteDefinition,
(FuncObjectCopy)_copyDefinition,
(FuncObjectValidate)_validateDefinition,
(FuncObjectSave)_saveDefinition,
(FuncObjectLoad)_loadDefinition
};

View file

@ -0,0 +1,56 @@
#include "private.h"
void waterAutoPreset(WaterDefinition* definition, WaterPreset preset)
{
noiseRandomizeOffsets(definition->_waves_noise);
if (preset == WATER_PRESET_LAKE)
{
definition->transparency = 0.5;
definition->reflection = 0.4;
definition->transparency_depth = 4.0;
definition->material.base.r = 0.08;
definition->material.base.g = 0.15;
definition->material.base.b = 0.2;
definition->depth_color.r = 0.0;
definition->depth_color.g = 0.1;
definition->depth_color.b = 0.1;
definition->lighting_depth = 6.0;
definition->scaling = 1.0;
definition->waves_height = 0.8;
definition->detail_height = 0.05;
definition->turbulence = 0.1;
definition->foam_coverage = 0.15;
}
else if (preset == WATER_PRESET_SEA)
{
definition->transparency = 0.4;
definition->reflection = 0.35;
definition->transparency_depth = 3.0;
definition->material.base.r = 0.05;
definition->material.base.g = 0.18;
definition->material.base.b = 0.2;
definition->depth_color.r = 0.0;
definition->depth_color.g = 0.18;
definition->depth_color.b = 0.15;
definition->lighting_depth = 4.0;
definition->scaling = 1.5;
definition->waves_height = 1.0;
definition->detail_height = 0.06;
definition->turbulence = 0.3;
definition->foam_coverage = 0.4;
}
definition->depth_color.a = 1.0;
definition->material.base.a = 1.0;
definition->material.reflection = 1.0;
definition->material.shininess = 16.0;
definition->foam_material.base.r = 0.8;
definition->foam_material.base.g = 0.8;
definition->foam_material.base.b = 0.8;
definition->foam_material.base.a = 1.0;
definition->foam_material.reflection = 0.4;
definition->foam_material.shininess = 1.5;
WaterDefinitionClass.validate(definition);
}

View file

@ -0,0 +1,44 @@
#include "private.h"
#include "../terrain/public.h"
#include "../renderer.h"
#include "../tools.h"
Renderer* waterCreatePreviewCoverageRenderer()
{
return terrainCreatePreviewRenderer();
}
Color waterGetPreviewCoverage(Renderer* renderer, double x, double y, double scaling, int highlight_enabled)
{
double height;
height = renderer->terrain->getHeight(renderer, x, y, 1);
if (height > renderer->water->definition.height)
{
return terrainGetPreviewColor(renderer, x, y, scaling);
}
else
{
Color base;
base = renderer->water->getResult(renderer, x, y).final;
if (highlight_enabled)
{
Color mask = {0.5, 0.5, 1.0, 0.5};
colorMask(&base, &mask);
}
return base;
}
}
Renderer* waterCreatePreviewColorRenderer()
{
}
Color waterGetPreviewColor(Renderer* renderer, double x, double y, double scaling)
{
}

View file

@ -0,0 +1,7 @@
#ifndef _PAYSAGES_WATER_PRIVATE_H_
#define _PAYSAGES_WATER_PRIVATE_H_
#include "public.h"
#endif

View file

@ -0,0 +1,82 @@
#ifndef _PAYSAGES_WATER_PUBLIC_H_
#define _PAYSAGES_WATER_PUBLIC_H_
#include "../shared/types.h"
#include "../tools/lighting.h"
#include "../tools/curve.h"
#include "../tools/euclid.h"
#include "../noise.h"
#include "../layers.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
WATER_PRESET_LAKE,
WATER_PRESET_SEA
} WaterPreset;
typedef struct
{
double height;
double transparency;
double reflection;
SurfaceMaterial material;
Color depth_color;
double transparency_depth;
double lighting_depth;
double scaling;
double turbulence;
double waves_height;
double detail_height;
double foam_coverage;
SurfaceMaterial foam_material;
NoiseGenerator* _waves_noise;
} WaterDefinition;
typedef struct
{
Vector3 location;
Color base;
Color reflected;
Color refracted;
Color foam;
Color final;
} WaterResult;
typedef HeightInfo (*FuncWaterGetHeightInfo)(Renderer* renderer);
typedef double (*FuncWaterGetHeight)(Renderer* renderer, double x, double z);
typedef WaterResult (*FuncWaterGetResult)(Renderer* renderer, double x, double z);
typedef struct
{
WaterDefinition* definition;
FuncWaterGetHeightInfo getHeightInfo;
FuncWaterGetHeight getHeight;
FuncWaterGetResult getResult;
} WaterRenderer;
extern StandardDefinition WaterDefinitionClass;
extern StandardRenderer WaterRendererClass;
void waterRenderSurface(Renderer* renderer);
void waterAutoPreset(WaterDefinition* definition, WaterPreset preset);
Renderer* waterCreatePreviewCoverageRenderer();
Color waterGetPreviewCoverage(Renderer* renderer, double x, double y, double scaling, int highlight_enabled);
Renderer* waterCreatePreviewColorRenderer();
Color waterGetPreviewColor(Renderer* renderer, double x, double y, double scaling);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,82 @@
#include "public.h"
#include "private.h"
#include <stdlib.h>
#include "../renderer.h"
#include "../tools.h"
static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* data)
{
UNUSED(data);
return renderer->water->getResult(renderer, location.x, location.z).final;
}
static Vector3 _getFirstPassVertex(Renderer* renderer, double x, double z)
{
Vector3 result;
result.x = x;
result.y = renderer->water->getHeight(renderer, x, z);
result.z = z;
return result;
}
static void _renderQuad(Renderer* renderer, double x, double z, double size)
{
Vector3 v1, v2, v3, v4;
v1 = _getFirstPassVertex(renderer, x, z);
v2 = _getFirstPassVertex(renderer, x, z + size);
v3 = _getFirstPassVertex(renderer, x + size, z + size);
v4 = _getFirstPassVertex(renderer, x + size, z);
renderer->pushQuad(renderer, v1, v2, v3, v4, _postProcessFragment, NULL);
}
void waterRenderSurface(Renderer* renderer)
{
int chunk_factor, chunk_count, i;
Vector3 cam = renderer->getCameraLocation(renderer, VECTOR_ZERO);
double cx = cam.x;
double cz = cam.z;
double radius_int, radius_ext, base_chunk_size, chunk_size;
base_chunk_size = 2.0 / (double)renderer->render_quality;
if (renderer->render_quality > 7)
{
base_chunk_size *= 0.5;
}
chunk_factor = 1;
chunk_count = 2;
radius_int = 0.0;
radius_ext = base_chunk_size;
chunk_size = base_chunk_size;
while (radius_int < 5000.0)
{
if (!renderer->addRenderProgress(renderer, 0.0))
{
return;
}
for (i = 0; i < chunk_count - 1; i++)
{
_renderQuad(renderer, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size);
_renderQuad(renderer, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size);
_renderQuad(renderer, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size);
_renderQuad(renderer, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size);
}
if (radius_int > 20.0 && chunk_count % 64 == 0 && (double)chunk_factor < radius_int / 20.0)
{
chunk_count /= 2;
chunk_factor *= 2;
}
chunk_count += 2;
chunk_size = base_chunk_size * chunk_factor;
radius_int = radius_ext;
radius_ext += chunk_size;
}
}

304
lib_paysages/water/render.c Normal file
View file

@ -0,0 +1,304 @@
#include "private.h"
#include <stdlib.h>
#include <math.h>
#include "../tools.h"
#include "../renderer.h"
static HeightInfo _FAKE_HEIGHT_INFO = {0.0, 0.0, 0.0};
static WaterResult _FAKE_RESULT = {};
/******************** Fake ********************/
static HeightInfo _fakeGetHeightInfo(Renderer* renderer)
{
UNUSED(renderer);
return _FAKE_HEIGHT_INFO;
}
static double _fakeGetHeight(Renderer* renderer, double x, double z)
{
UNUSED(renderer);
UNUSED(x);
UNUSED(z);
return 0.0;
}
static WaterResult _fakeGetResult(Renderer* renderer, double x, double z)
{
WaterResult result;
result.location.x = x;
result.location.y = 0.0;
result.location.z = z;
result.base = COLOR_BLUE;
result.reflected = COLOR_BLACK;
result.refracted = COLOR_BLACK;
result.foam = COLOR_BLACK;
result.final = COLOR_BLUE;
return result;
}
/******************** Helpers ********************/
static inline double _getHeight(WaterDefinition* definition, double x, double z)
{
return definition->height + noiseGet2DTotal(definition->_waves_noise, x, z);
}
static inline Vector3 _getNormal(WaterDefinition* definition, Vector3 base, double detail)
{
Vector3 back, right;
double x, z;
x = base.x;
z = base.z;
back.x = x;
back.y = _getHeight(definition, x, z + detail);
back.z = z + detail;
back = v3Sub(back, base);
right.x = x + detail;
right.y = _getHeight(definition, x + detail, z);
right.z = z;
right = v3Sub(right, base);
return v3Normalize(v3Cross(back, right));
}
static inline Vector3 _reflectRay(Vector3 incoming, Vector3 normal)
{
double c;
c = v3Dot(normal, v3Scale(incoming, -1.0));
return v3Add(incoming, v3Scale(normal, 2.0 * c));
}
static inline Vector3 _refractRay(Vector3 incoming, Vector3 normal)
{
double c1, c2, f;
f = 1.0 / 1.33;
c1 = v3Dot(normal, v3Scale(incoming, -1.0));
c2 = sqrt(1.0 - pow(f, 2.0) * (1.0 - pow(c1, 2.0)));
if (c1 >= 0.0)
{
return v3Add(v3Scale(incoming, f), v3Scale(normal, f * c1 - c2));
}
else
{
return v3Add(v3Scale(incoming, f), v3Scale(normal, c2 - f * c1));
}
}
static inline void _applyFoam(WaterDefinition* definition, Vector3 location, Vector3 normal, double detail, SurfaceMaterial* material)
{
Color result = definition->foam_material.base;
double foam_factor, normal_diff, location_offset;
location_offset = 2.0 * detail;
foam_factor = 0.0;
location.x += location_offset;
normal_diff = 1.0 - v3Dot(normal, _getNormal(definition, location, detail));
if (normal_diff > foam_factor)
{
foam_factor = normal_diff;
}
location.x -= location_offset * 2.0;
normal_diff = 1.0 - v3Dot(normal, _getNormal(definition, location, detail));
if (normal_diff > foam_factor)
{
foam_factor = normal_diff;
}
location.x += location_offset;
location.z -= location_offset;
normal_diff = 1.0 - v3Dot(normal, _getNormal(definition, location, detail));
if (normal_diff > foam_factor)
{
foam_factor = normal_diff;
}
location.z += location_offset * 2.0;
normal_diff = 1.0 - v3Dot(normal, _getNormal(definition, location, detail));
if (normal_diff > foam_factor)
{
foam_factor = normal_diff;
}
foam_factor *= 10.0;
if (foam_factor > 1.0)
{
foam_factor = 1.0;
}
if (foam_factor <= 1.0 - definition->foam_coverage)
{
return;
}
foam_factor = (foam_factor - (1.0 - definition->foam_coverage)) * definition->foam_coverage;
material->reflection = foam_factor * definition->foam_material.reflection + (1.0 - foam_factor) * material->reflection;
material->shininess = foam_factor * definition->foam_material.shininess + (1.0 - foam_factor) * material->shininess;
/* TODO This should be configurable */
if (foam_factor > 0.2)
{
result.a = 0.8;
}
else
{
result.a = 0.8 * (foam_factor / 0.2);
}
colorMask(&material->base, &result);
}
static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 at)
{
WaterDefinition* definition = renderer->water->definition;
double factor;
if (at.y < definition->height)
{
if (light->direction.y < 0.00001)
{
factor = (definition->height - at.y) / (-light->direction.y * definition->lighting_depth);
if (factor > 1.0)
{
factor = 1.0;
}
factor = 1.0 - 0.8 * factor;
light->color.r *= factor;
light->color.g *= factor;
light->color.b *= factor;
return 1;
}
else
{
light->color = COLOR_BLACK;
return 1;
}
}
else
{
return 0;
}
}
/******************** Real ********************/
static HeightInfo _realGetHeightInfo(Renderer* renderer)
{
WaterDefinition* definition = renderer->water->definition;
HeightInfo info;
double noise_minvalue, noise_maxvalue;
info.base_height = definition->height;
noiseGetRange(definition->_waves_noise, &noise_minvalue, &noise_maxvalue);
info.min_height = definition->height + noise_minvalue;
info.max_height = definition->height + noise_maxvalue;
return info;
}
static double _realGetHeight(Renderer* renderer, double x, double z)
{
return _getHeight(renderer->water->definition, x, z);
}
static WaterResult _realGetResult(Renderer* renderer, double x, double z)
{
WaterDefinition* definition = renderer->water->definition;
WaterResult result;
RayCastingResult refracted;
Vector3 location, normal, look;
Color color;
SurfaceMaterial material;
double detail, depth;
location.x = x;
location.y = _getHeight(definition, x, z);
location.z = z;
result.location = location;
detail = renderer->getPrecision(renderer, location) * 0.1;
if (detail < 0.00001)
{
detail = 0.00001;
}
normal = _getNormal(definition, location, detail);
look = v3Normalize(renderer->getCameraDirection(renderer, location));
result.reflected = renderer->rayWalking(renderer, location, _reflectRay(look, normal), 1, 0, 1, 1).hit_color;
refracted = renderer->rayWalking(renderer, location, _refractRay(look, normal), 1, 0, 1, 1);
depth = v3Norm(v3Sub(location, refracted.hit_location));
if (depth > definition->transparency_depth)
{
result.refracted = definition->depth_color;
}
else
{
depth /= definition->transparency_depth;
result.refracted.r = refracted.hit_color.r * (1.0 - depth) + definition->depth_color.r * depth;
result.refracted.g = refracted.hit_color.g * (1.0 - depth) + definition->depth_color.g * depth;
result.refracted.b = refracted.hit_color.b * (1.0 - depth) + definition->depth_color.b * depth;
result.refracted.a = 1.0;
}
color.r = definition->material.base.r * (1.0 - definition->transparency) + result.reflected.r * definition->reflection + result.refracted.r * definition->transparency;
color.g = definition->material.base.g * (1.0 - definition->transparency) + result.reflected.g * definition->reflection + result.refracted.g * definition->transparency;
color.b = definition->material.base.b * (1.0 - definition->transparency) + result.reflected.b * definition->reflection + result.refracted.b * definition->transparency;
color.a = 1.0;
material = definition->material;
material.base = color;
_applyFoam(definition, location, normal, detail, &material);
color = renderer->applyLightingToSurface(renderer, location, normal, &material);
color = renderer->applyMediumTraversal(renderer, location, color);
result.base = definition->material.base;
result.final = color;
return result;
}
/******************** Renderer ********************/
static WaterRenderer* _createRenderer()
{
WaterRenderer* result;
result = malloc(sizeof(WaterRenderer));
result->definition = WaterDefinitionClass.create();
result->getHeightInfo = _fakeGetHeightInfo;
result->getHeight = _fakeGetHeight;
result->getResult = _fakeGetResult;
return result;
}
static void _deleteRenderer(WaterRenderer* renderer)
{
WaterDefinitionClass.destroy(renderer->definition);
free(renderer);
}
static void _bindRenderer(Renderer* renderer, WaterDefinition* definition)
{
WaterDefinitionClass.copy(definition, renderer->water->definition);
renderer->water->getHeightInfo = _realGetHeightInfo;
renderer->water->getHeight = _realGetHeight;
renderer->water->getResult = _realGetResult;
lightingManagerRegisterFilter(renderer->lighting, (FuncLightingAlterLight)_alterLight, renderer);
}
StandardRenderer CloudsRendererClass = {
(FuncObjectCreate)_createRenderer,
(FuncObjectDelete)_deleteRenderer,
(FuncObjectBind)_bindRenderer
};