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:
parent
9a7bc290dc
commit
e8b3468038
19 changed files with 701 additions and 605 deletions
|
@ -3,16 +3,15 @@
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "../lib_paysages/tools/euclid.h"
|
#include "../lib_paysages/tools/euclid.h"
|
||||||
#include "../lib_paysages/tools/lighting.h"
|
#include "../lib_paysages/tools/lighting.h"
|
||||||
#include "../lib_paysages/renderer.h"
|
#include "../lib_paysages/renderer.h"
|
||||||
#include "../lib_paysages/scenery.h"
|
#include "../lib_paysages/scenery.h"
|
||||||
#include "../lib_paysages/water.h"
|
#include "../lib_paysages/water/public.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
static WaterDefinition _definition;
|
static WaterDefinition* _definition;
|
||||||
|
|
||||||
/**************** Previews ****************/
|
/**************** Previews ****************/
|
||||||
class PreviewWaterCoverage:public BasePreview
|
class PreviewWaterCoverage:public BasePreview
|
||||||
|
@ -20,8 +19,7 @@ class PreviewWaterCoverage:public BasePreview
|
||||||
public:
|
public:
|
||||||
PreviewWaterCoverage(QWidget* parent):BasePreview(parent)
|
PreviewWaterCoverage(QWidget* parent):BasePreview(parent)
|
||||||
{
|
{
|
||||||
_renderer = terrainCreatePreviewRenderer();
|
_renderer = waterCreatePreviewCoverageRenderer();
|
||||||
_water = waterCreateDefinition();
|
|
||||||
_highlight_enabled = true;
|
_highlight_enabled = true;
|
||||||
|
|
||||||
addOsd(QString("geolocation"));
|
addOsd(QString("geolocation"));
|
||||||
|
@ -33,40 +31,11 @@ public:
|
||||||
protected:
|
protected:
|
||||||
Color getColor(double x, double y)
|
Color getColor(double x, double y)
|
||||||
{
|
{
|
||||||
double height;
|
return waterGetPreviewCoverage(_renderer, x, y, scaling, _highlight_enabled ? 1 : 0);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void updateData()
|
void updateData()
|
||||||
{
|
{
|
||||||
waterCopyDefinition(&_definition, &_water);
|
WaterRendererClass.bind(_renderer, _definition);
|
||||||
|
|
||||||
// TODO Do this only on full refresh
|
// TODO Do this only on full refresh
|
||||||
TerrainDefinition* terrain = (TerrainDefinition*)TerrainDefinitionClass.create();
|
TerrainDefinition* terrain = (TerrainDefinition*)TerrainDefinitionClass.create();
|
||||||
|
@ -84,7 +53,6 @@ protected:
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Renderer* _renderer;
|
Renderer* _renderer;
|
||||||
WaterDefinition _water;
|
|
||||||
bool _highlight_enabled;
|
bool _highlight_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
BUILDMODE = debug
|
BUILDMODE = debug
|
||||||
BUILDPATH = ../build/${BUILDMODE}
|
BUILDPATH = ../build/${BUILDMODE}
|
||||||
OBJPATH = ./obj/${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}
|
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
|
RESULT = ${BUILDPATH}/libpaysages.so
|
||||||
LIBS = glib-2.0 gthread-2.0 IL ILU
|
LIBS = glib-2.0 gthread-2.0 IL ILU
|
||||||
CC_FLAGS = -Wall -fPIC -DHAVE_GLIB=1
|
CC_FLAGS = -Wall -fPIC -DHAVE_GLIB=1
|
||||||
|
|
|
@ -1169,7 +1169,7 @@ Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color
|
||||||
Vector3 eye = renderer->getCameraLocation(renderer, location);
|
Vector3 eye = renderer->getCameraLocation(renderer, location);
|
||||||
Vector3 sun_position = v3Scale(renderer->atmosphere->getSunDirection(renderer), SUN_DISTANCE);
|
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;
|
eye.y += yoffset;
|
||||||
location.y += yoffset;
|
location.y += yoffset;
|
||||||
if (eye.y < 0.0)
|
if (eye.y < 0.0)
|
||||||
|
@ -1212,7 +1212,7 @@ void brunetonGetLightingStatus(Renderer* renderer, LightStatus* status, Vector3
|
||||||
|
|
||||||
double altitude = lightingGetStatusLocation(status).y;
|
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;
|
altitude += yoffset;
|
||||||
if (altitude < 0.0)
|
if (altitude < 0.0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "textures.h"
|
#include "textures.h"
|
||||||
#include "scenery.h"
|
#include "scenery.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "water.h"
|
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
|
|
||||||
void autoGenRealisticLandscape(int seed)
|
void autoGenRealisticLandscape(int seed)
|
||||||
|
@ -26,12 +25,6 @@ void autoGenRealisticLandscape(int seed)
|
||||||
|
|
||||||
sceneryAutoPreset();
|
sceneryAutoPreset();
|
||||||
|
|
||||||
/* Water */
|
|
||||||
water = waterCreateDefinition();
|
|
||||||
waterAutoPreset(&water, WATER_PRESET_LAKE);
|
|
||||||
scenerySetWater(&water);
|
|
||||||
waterDeleteDefinition(&water);
|
|
||||||
|
|
||||||
/* Textures */
|
/* Textures */
|
||||||
textures = texturesCreateDefinition();
|
textures = texturesCreateDefinition();
|
||||||
layer = layersAddLayer(textures.layers, NULL);
|
layer = layersAddLayer(textures.layers, NULL);
|
||||||
|
@ -87,13 +80,4 @@ void autoGenRealisticLandscape(int seed)
|
||||||
texture->thickness_transparency = 0.015;*/
|
texture->thickness_transparency = 0.015;*/
|
||||||
scenerySetTextures(&textures);
|
scenerySetTextures(&textures);
|
||||||
texturesDeleteDefinition(&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);*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,13 +69,9 @@ void cameraValidateDefinition(CameraDefinition* definition, int check_above)
|
||||||
|
|
||||||
if (check_above)
|
if (check_above)
|
||||||
{
|
{
|
||||||
water = waterCreateDefinition();
|
|
||||||
sceneryGetWater(&water);
|
|
||||||
water_height = water.height + 0.5;
|
|
||||||
waterDeleteDefinition(&water);
|
|
||||||
|
|
||||||
renderer = sceneryCreateStandardRenderer();
|
renderer = sceneryCreateStandardRenderer();
|
||||||
terrain_height = renderer->terrain->getHeight(renderer, definition->location.x, definition->location.z, 1) + 0.5;
|
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);
|
rendererDelete(renderer);
|
||||||
|
|
||||||
if (definition->location.y < water_height || definition->location.y < terrain_height)
|
if (definition->location.y < water_height || definition->location.y < terrain_height)
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
static RayCastingResult _RAYCASTING_NULL = {0};
|
static RayCastingResult _RAYCASTING_NULL = {0};
|
||||||
static HeightInfo _WATER_HEIGHT_INFO = {0.0, 0.0, 0.0};
|
|
||||||
|
|
||||||
static void* _renderFirstPass(void* data)
|
static void* _renderFirstPass(void* data)
|
||||||
{
|
{
|
||||||
|
@ -79,11 +78,6 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
|
||||||
return _RAYCASTING_NULL;
|
return _RAYCASTING_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HeightInfo _getWaterHeightInfo(Renderer* renderer)
|
|
||||||
{
|
|
||||||
return _WATER_HEIGHT_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
|
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
|
||||||
{
|
{
|
||||||
return COLOR_TRANSPARENT;
|
return COLOR_TRANSPARENT;
|
||||||
|
@ -131,7 +125,6 @@ Renderer* rendererCreate()
|
||||||
result->pushQuad = _pushQuad;
|
result->pushQuad = _pushQuad;
|
||||||
|
|
||||||
result->rayWalking = _rayWalking;
|
result->rayWalking = _rayWalking;
|
||||||
result->getWaterHeightInfo = _getWaterHeightInfo;
|
|
||||||
result->applyTextures = _applyTextures;
|
result->applyTextures = _applyTextures;
|
||||||
|
|
||||||
result->applyLightingToSurface = _applyLightingToSurface;
|
result->applyLightingToSurface = _applyLightingToSurface;
|
||||||
|
@ -142,6 +135,7 @@ Renderer* rendererCreate()
|
||||||
result->atmosphere = AtmosphereRendererClass.create();
|
result->atmosphere = AtmosphereRendererClass.create();
|
||||||
result->clouds = CloudsRendererClass.create();
|
result->clouds = CloudsRendererClass.create();
|
||||||
result->terrain = TerrainRendererClass.create();
|
result->terrain = TerrainRendererClass.create();
|
||||||
|
result->water = WaterRendererClass.create();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -153,6 +147,7 @@ void rendererDelete(Renderer* renderer)
|
||||||
AtmosphereRendererClass.destroy(renderer->atmosphere);
|
AtmosphereRendererClass.destroy(renderer->atmosphere);
|
||||||
CloudsRendererClass.destroy(renderer->clouds);
|
CloudsRendererClass.destroy(renderer->clouds);
|
||||||
TerrainRendererClass.destroy(renderer->terrain);
|
TerrainRendererClass.destroy(renderer->terrain);
|
||||||
|
WaterRendererClass.destroy(renderer->water);
|
||||||
|
|
||||||
renderDeleteArea(renderer->render_area);
|
renderDeleteArea(renderer->render_area);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "atmosphere/public.h"
|
#include "atmosphere/public.h"
|
||||||
#include "clouds/public.h"
|
#include "clouds/public.h"
|
||||||
#include "terrain/public.h"
|
#include "terrain/public.h"
|
||||||
|
#include "water/public.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -39,7 +40,6 @@ struct Renderer
|
||||||
|
|
||||||
/* Scenery related */
|
/* Scenery related */
|
||||||
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);
|
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);
|
Color (*applyTextures)(Renderer* renderer, Vector3 location, double precision);
|
||||||
|
|
||||||
/* Autonomous tools */
|
/* Autonomous tools */
|
||||||
|
@ -49,6 +49,7 @@ struct Renderer
|
||||||
AtmosphereRenderer* atmosphere;
|
AtmosphereRenderer* atmosphere;
|
||||||
TerrainRenderer* terrain;
|
TerrainRenderer* terrain;
|
||||||
CloudsRenderer* clouds;
|
CloudsRenderer* clouds;
|
||||||
|
WaterRenderer* water;
|
||||||
|
|
||||||
/* Custom data */
|
/* Custom data */
|
||||||
void* customData[10];
|
void* customData[10];
|
||||||
|
|
|
@ -10,7 +10,7 @@ static CameraDefinition _camera;
|
||||||
static CloudsDefinition* _clouds;
|
static CloudsDefinition* _clouds;
|
||||||
static TerrainDefinition* _terrain;
|
static TerrainDefinition* _terrain;
|
||||||
static TexturesDefinition _textures;
|
static TexturesDefinition _textures;
|
||||||
static WaterDefinition _water;
|
static WaterDefinition* _water;
|
||||||
|
|
||||||
static SceneryCustomDataCallback _custom_save = NULL;
|
static SceneryCustomDataCallback _custom_save = NULL;
|
||||||
static SceneryCustomDataCallback _custom_load = NULL;
|
static SceneryCustomDataCallback _custom_load = NULL;
|
||||||
|
@ -25,7 +25,7 @@ void sceneryInit()
|
||||||
_clouds = CloudsDefinitionClass.create();
|
_clouds = CloudsDefinitionClass.create();
|
||||||
_terrain = TerrainDefinitionClass.create();
|
_terrain = TerrainDefinitionClass.create();
|
||||||
_textures = texturesCreateDefinition();
|
_textures = texturesCreateDefinition();
|
||||||
_water = waterCreateDefinition();
|
_water = WaterDefinitionClass.create();
|
||||||
|
|
||||||
_custom_save = NULL;
|
_custom_save = NULL;
|
||||||
_custom_load = NULL;
|
_custom_load = NULL;
|
||||||
|
@ -38,7 +38,7 @@ void sceneryQuit()
|
||||||
CloudsDefinitionClass.destroy(_clouds);
|
CloudsDefinitionClass.destroy(_clouds);
|
||||||
TerrainDefinitionClass.destroy(_terrain);
|
TerrainDefinitionClass.destroy(_terrain);
|
||||||
texturesDeleteDefinition(&_textures);
|
texturesDeleteDefinition(&_textures);
|
||||||
waterDeleteDefinition(&_water);
|
AtmosphereDefinitionClass.destroy(_water);
|
||||||
|
|
||||||
noiseQuit();
|
noiseQuit();
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ void sceneryAutoPreset()
|
||||||
{
|
{
|
||||||
terrainAutoPreset(_terrain, TERRAIN_PRESET_STANDARD);
|
terrainAutoPreset(_terrain, TERRAIN_PRESET_STANDARD);
|
||||||
atmosphereAutoPreset(_atmosphere, ATMOSPHERE_PRESET_CLEAR_DAY);
|
atmosphereAutoPreset(_atmosphere, ATMOSPHERE_PRESET_CLEAR_DAY);
|
||||||
|
waterAutoPreset(_water, WATER_PRESET_LAKE);
|
||||||
cloudsAutoPreset(_clouds, CLOUDS_PRESET_PARTLY_CLOUDY);
|
cloudsAutoPreset(_clouds, CLOUDS_PRESET_PARTLY_CLOUDY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ void scenerySave(PackStream* stream)
|
||||||
CloudsDefinitionClass.save(stream, _clouds);
|
CloudsDefinitionClass.save(stream, _clouds);
|
||||||
TerrainDefinitionClass.save(stream, _terrain);
|
TerrainDefinitionClass.save(stream, _terrain);
|
||||||
texturesSave(stream, &_textures);
|
texturesSave(stream, &_textures);
|
||||||
waterSave(stream, &_water);
|
WaterDefinitionClass.save(stream, _water);
|
||||||
|
|
||||||
if (_custom_save)
|
if (_custom_save)
|
||||||
{
|
{
|
||||||
|
@ -83,11 +84,10 @@ void sceneryLoad(PackStream* stream)
|
||||||
CloudsDefinitionClass.load(stream, _clouds);
|
CloudsDefinitionClass.load(stream, _clouds);
|
||||||
TerrainDefinitionClass.load(stream, _terrain);
|
TerrainDefinitionClass.load(stream, _terrain);
|
||||||
texturesLoad(stream, &_textures);
|
texturesLoad(stream, &_textures);
|
||||||
waterLoad(stream, &_water);
|
WaterDefinitionClass.load(stream, _water);
|
||||||
|
|
||||||
cameraValidateDefinition(&_camera, 0);
|
cameraValidateDefinition(&_camera, 0);
|
||||||
texturesValidateDefinition(&_textures);
|
texturesValidateDefinition(&_textures);
|
||||||
waterValidateDefinition(&_water);
|
|
||||||
|
|
||||||
if (_custom_load)
|
if (_custom_load)
|
||||||
{
|
{
|
||||||
|
@ -151,21 +151,20 @@ void sceneryGetTextures(TexturesDefinition* textures)
|
||||||
|
|
||||||
void scenerySetWater(WaterDefinition* water)
|
void scenerySetWater(WaterDefinition* water)
|
||||||
{
|
{
|
||||||
waterCopyDefinition(water, &_water);
|
WaterDefinitionClass.copy(water, _water);
|
||||||
waterValidateDefinition(&_water);
|
|
||||||
|
|
||||||
cameraValidateDefinition(&_camera, 1);
|
cameraValidateDefinition(&_camera, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sceneryGetWater(WaterDefinition* water)
|
void sceneryGetWater(WaterDefinition* water)
|
||||||
{
|
{
|
||||||
waterCopyDefinition(&_water, water);
|
WaterDefinitionClass.copy(_water, water);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sceneryRenderFirstPass(Renderer* renderer)
|
void sceneryRenderFirstPass(Renderer* renderer)
|
||||||
{
|
{
|
||||||
terrainRenderSurface(renderer);
|
terrainRenderSurface(renderer);
|
||||||
waterRender(&_water, renderer);
|
waterRenderSurface(renderer);
|
||||||
atmosphereRenderSkydome(renderer);
|
atmosphereRenderSkydome(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,11 +192,6 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HeightInfo _getWaterHeightInfo(Renderer* renderer)
|
|
||||||
{
|
|
||||||
return waterGetHeightInfo(&_water);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
|
static Color _applyTextures(Renderer* renderer, Vector3 location, double precision)
|
||||||
{
|
{
|
||||||
return texturesGetColor(&_textures, renderer, location.x, location.z, precision);
|
return texturesGetColor(&_textures, renderer, location.x, location.z, precision);
|
||||||
|
@ -233,7 +227,6 @@ Renderer* sceneryCreateStandardRenderer()
|
||||||
cameraCopyDefinition(&_camera, &result->render_camera);
|
cameraCopyDefinition(&_camera, &result->render_camera);
|
||||||
|
|
||||||
result->rayWalking = _rayWalking;
|
result->rayWalking = _rayWalking;
|
||||||
result->getWaterHeightInfo = _getWaterHeightInfo;
|
|
||||||
result->applyTextures = _applyTextures;
|
result->applyTextures = _applyTextures;
|
||||||
result->projectPoint = _projectPoint;
|
result->projectPoint = _projectPoint;
|
||||||
result->unprojectPoint = _unprojectPoint;
|
result->unprojectPoint = _unprojectPoint;
|
||||||
|
@ -242,6 +235,7 @@ Renderer* sceneryCreateStandardRenderer()
|
||||||
AtmosphereRendererClass.bind(result, _atmosphere);
|
AtmosphereRendererClass.bind(result, _atmosphere);
|
||||||
TerrainRendererClass.bind(result, _terrain);
|
TerrainRendererClass.bind(result, _terrain);
|
||||||
CloudsRendererClass.bind(result, _clouds);
|
CloudsRendererClass.bind(result, _clouds);
|
||||||
|
WaterRendererClass.bind(result, _water);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
#include "atmosphere/public.h"
|
#include "atmosphere/public.h"
|
||||||
#include "clouds/public.h"
|
#include "clouds/public.h"
|
||||||
#include "terrain/public.h"
|
#include "terrain/public.h"
|
||||||
|
#include "water/public.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "textures.h"
|
#include "textures.h"
|
||||||
#include "water.h"
|
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -69,7 +69,7 @@ void terrainRenderSurface(Renderer* renderer)
|
||||||
radius_ext = min_chunk_size;
|
radius_ext = min_chunk_size;
|
||||||
chunk_size = 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)
|
while (radius_int < 5000.0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
|
100
lib_paysages/water/definition.c
Normal file
100
lib_paysages/water/definition.c
Normal 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
|
||||||
|
};
|
56
lib_paysages/water/presets.c
Normal file
56
lib_paysages/water/presets.c
Normal 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);
|
||||||
|
}
|
44
lib_paysages/water/preview.c
Normal file
44
lib_paysages/water/preview.c
Normal 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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
7
lib_paysages/water/private.h
Normal file
7
lib_paysages/water/private.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef _PAYSAGES_WATER_PRIVATE_H_
|
||||||
|
#define _PAYSAGES_WATER_PRIVATE_H_
|
||||||
|
|
||||||
|
#include "public.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
82
lib_paysages/water/public.h
Normal file
82
lib_paysages/water/public.h
Normal 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
|
82
lib_paysages/water/raster.c
Normal file
82
lib_paysages/water/raster.c
Normal 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
304
lib_paysages/water/render.c
Normal 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
|
||||||
|
};
|
Loading…
Reference in a new issue