2012-01-23 23:45:33 +00:00
|
|
|
#include "water.h"
|
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
#include "shared/types.h"
|
2012-01-29 17:39:56 +00:00
|
|
|
#include "color.h"
|
|
|
|
#include "euclid.h"
|
2012-01-24 13:16:20 +00:00
|
|
|
#include "render.h"
|
2012-01-22 18:39:42 +00:00
|
|
|
#include "lighting.h"
|
2012-01-29 17:39:56 +00:00
|
|
|
#include "tools.h"
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
2012-04-22 17:12:39 +00:00
|
|
|
void waterSave(PackStream* stream, WaterDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-06-17 09:40:40 +00:00
|
|
|
packWriteDouble(stream, &definition->height);
|
2012-04-22 17:12:39 +00:00
|
|
|
materialSave(stream, &definition->material);
|
|
|
|
colorSave(stream, &definition->depth_color);
|
2012-06-17 09:40:40 +00:00
|
|
|
packWriteDouble(stream, &definition->transparency_depth);
|
|
|
|
packWriteDouble(stream, &definition->transparency);
|
|
|
|
packWriteDouble(stream, &definition->reflection);
|
|
|
|
packWriteDouble(stream, &definition->lighting_depth);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-11 10:52:03 +00:00
|
|
|
packWriteDouble(stream, &definition->scaling);
|
|
|
|
packWriteDouble(stream, &definition->waves_height);
|
|
|
|
packWriteDouble(stream, &definition->detail_height);
|
|
|
|
packWriteDouble(stream, &definition->turbulence);
|
2012-11-19 20:40:57 +00:00
|
|
|
|
|
|
|
packWriteDouble(stream, &definition->foam_coverage);
|
|
|
|
materialSave(stream, &definition->foam_material);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-11 10:52:03 +00:00
|
|
|
noiseSaveGenerator(stream, definition->_waves_noise);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-04-22 17:12:39 +00:00
|
|
|
void waterLoad(PackStream* stream, WaterDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-06-17 09:40:40 +00:00
|
|
|
packReadDouble(stream, &definition->height);
|
2012-04-22 17:12:39 +00:00
|
|
|
materialLoad(stream, &definition->material);
|
|
|
|
colorLoad(stream, &definition->depth_color);
|
2012-06-17 09:40:40 +00:00
|
|
|
packReadDouble(stream, &definition->transparency_depth);
|
|
|
|
packReadDouble(stream, &definition->transparency);
|
|
|
|
packReadDouble(stream, &definition->reflection);
|
|
|
|
packReadDouble(stream, &definition->lighting_depth);
|
2012-11-11 10:52:03 +00:00
|
|
|
|
|
|
|
packReadDouble(stream, &definition->scaling);
|
|
|
|
packReadDouble(stream, &definition->waves_height);
|
|
|
|
packReadDouble(stream, &definition->detail_height);
|
|
|
|
packReadDouble(stream, &definition->turbulence);
|
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
packReadDouble(stream, &definition->foam_coverage);
|
|
|
|
materialLoad(stream, &definition->foam_material);
|
|
|
|
|
2012-11-11 10:52:03 +00:00
|
|
|
noiseLoadGenerator(stream, definition->_waves_noise);
|
2012-01-23 23:45:33 +00:00
|
|
|
|
|
|
|
waterValidateDefinition(definition);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WaterDefinition waterCreateDefinition()
|
|
|
|
{
|
|
|
|
WaterDefinition result;
|
2011-12-19 20:59:39 +00:00
|
|
|
|
2012-11-11 10:52:03 +00:00
|
|
|
result.height = -4.0;
|
|
|
|
result._waves_noise = noiseCreateGenerator();
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-24 14:19:43 +00:00
|
|
|
waterAutoPreset(&result, WATER_PRESET_LAKE);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void waterDeleteDefinition(WaterDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-11-11 10:52:03 +00:00
|
|
|
noiseDeleteGenerator(definition->_waves_noise);
|
|
|
|
}
|
|
|
|
|
|
|
|
void waterAutoPreset(WaterDefinition* definition, WaterPreset preset)
|
|
|
|
{
|
2012-11-24 12:30:51 +00:00
|
|
|
if (preset == WATER_PRESET_LAKE)
|
2012-11-11 10:52:03 +00:00
|
|
|
{
|
|
|
|
definition->transparency = 0.5;
|
|
|
|
definition->reflection = 0.4;
|
2012-11-24 12:30:51 +00:00
|
|
|
definition->transparency_depth = 4.0;
|
|
|
|
definition->material.base.r = 0.08;
|
2012-11-11 10:52:03 +00:00
|
|
|
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;
|
2012-11-24 12:30:51 +00:00
|
|
|
definition->lighting_depth = 6.0;
|
2012-11-11 10:52:03 +00:00
|
|
|
definition->scaling = 1.0;
|
2012-11-24 12:30:51 +00:00
|
|
|
definition->waves_height = 0.8;
|
2012-11-11 10:52:03 +00:00
|
|
|
definition->detail_height = 0.05;
|
2012-11-24 12:30:51 +00:00
|
|
|
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;
|
2012-11-11 10:52:03 +00:00
|
|
|
definition->turbulence = 0.3;
|
2012-11-19 20:40:57 +00:00
|
|
|
definition->foam_coverage = 0.4;
|
2012-11-11 10:52:03 +00:00
|
|
|
}
|
2012-11-24 12:30:51 +00:00
|
|
|
|
|
|
|
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;
|
2012-11-24 14:19:43 +00:00
|
|
|
definition->foam_material.base.a = 1.0;
|
2012-11-24 12:30:51 +00:00
|
|
|
definition->foam_material.reflection = 0.4;
|
|
|
|
definition->foam_material.shininess = 1.5;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-11 10:52:03 +00:00
|
|
|
waterValidateDefinition(definition);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void waterCopyDefinition(WaterDefinition* source, WaterDefinition* destination)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
NoiseGenerator* noise;
|
2011-12-19 20:59:39 +00:00
|
|
|
|
2012-11-11 10:52:03 +00:00
|
|
|
noise = destination->_waves_noise;
|
2012-01-24 13:16:20 +00:00
|
|
|
*destination = *source;
|
2012-11-11 10:52:03 +00:00
|
|
|
destination->_waves_noise = noise;
|
|
|
|
noiseCopy(source->_waves_noise, destination->_waves_noise);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
void waterValidateDefinition(WaterDefinition* definition)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-11-11 10:52:03 +00:00
|
|
|
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.03);
|
|
|
|
}
|
|
|
|
if (definition->detail_height > 0.0)
|
|
|
|
{
|
|
|
|
noiseAddLevelsSimple(definition->_waves_noise, 3, scaling * 0.1, definition->detail_height * scaling * 0.03);
|
|
|
|
}
|
|
|
|
noiseSetFunctionParams(definition->_waves_noise, NOISE_FUNCTION_SIMPLEX, -definition->turbulence);
|
|
|
|
noiseValidate(definition->_waves_noise);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-11-11 10:52:03 +00:00
|
|
|
static inline double _getHeight(WaterDefinition* definition, double x, double z)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-11-11 10:52:03 +00:00
|
|
|
return definition->height + noiseGet2DTotal(definition->_waves_noise, x, z);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-06-17 09:40:40 +00:00
|
|
|
static inline Vector3 _getNormal(WaterDefinition* definition, Vector3 base, double detail)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Vector3 back, right;
|
2012-06-17 09:40:40 +00:00
|
|
|
double x, z;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
x = base.x;
|
|
|
|
z = base.z;
|
|
|
|
|
|
|
|
back.x = x;
|
2012-11-11 10:52:03 +00:00
|
|
|
back.y = _getHeight(definition, x, z + detail);
|
2011-12-10 13:25:22 +00:00
|
|
|
back.z = z + detail;
|
|
|
|
back = v3Sub(back, base);
|
|
|
|
|
|
|
|
right.x = x + detail;
|
2012-11-11 10:52:03 +00:00
|
|
|
right.y = _getHeight(definition, x + detail, z);
|
2011-12-10 13:25:22 +00:00
|
|
|
right.z = z;
|
|
|
|
right = v3Sub(right, base);
|
|
|
|
|
|
|
|
return v3Normalize(v3Cross(back, right));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Vector3 _reflectRay(Vector3 incoming, Vector3 normal)
|
|
|
|
{
|
2012-06-17 09:40:40 +00:00
|
|
|
double c;
|
2011-12-19 20:59:39 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
c = v3Dot(normal, v3Scale(incoming, -1.0));
|
|
|
|
return v3Add(incoming, v3Scale(normal, 2.0 * c));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Vector3 _refractRay(Vector3 incoming, Vector3 normal)
|
|
|
|
{
|
2012-06-17 09:40:40 +00:00
|
|
|
double c1, c2, f;
|
2011-12-19 20:59:39 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-29 17:53:12 +00:00
|
|
|
HeightInfo waterGetHeightInfo(WaterDefinition* definition)
|
|
|
|
{
|
|
|
|
HeightInfo info;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-01-29 17:53:12 +00:00
|
|
|
info.base_height = definition->height;
|
2012-11-11 10:52:03 +00:00
|
|
|
info.min_height = definition->height - noiseGetMaxValue(definition->_waves_noise);
|
|
|
|
info.max_height = definition->height + noiseGetMaxValue(definition->_waves_noise);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-01-29 17:53:12 +00:00
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-06-17 09:40:40 +00:00
|
|
|
double factor;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
UNUSED(renderer);
|
|
|
|
UNUSED(light_location);
|
2011-12-19 20:59:39 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
if (location.y < definition->height)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
if (direction_to_light.y > 0.00001)
|
|
|
|
{
|
2012-01-28 18:32:08 +00:00
|
|
|
factor = (definition->height - location.y) / (direction_to_light.y * definition->lighting_depth);
|
2012-01-23 23:45:33 +00:00
|
|
|
if (factor > 1.0)
|
|
|
|
{
|
|
|
|
factor = 1.0;
|
|
|
|
}
|
|
|
|
factor = 1.0 - 0.8 * factor;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
light.r *= factor;
|
|
|
|
light.g *= factor;
|
|
|
|
light.b *= factor;
|
|
|
|
|
|
|
|
return light;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return COLOR_BLACK;
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
return light;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
2012-01-23 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
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;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
location_offset = 2.0 * detail;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
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;
|
|
|
|
}
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
foam_factor *= 10.0;
|
|
|
|
if (foam_factor > 1.0)
|
|
|
|
{
|
|
|
|
foam_factor = 1.0;
|
|
|
|
}
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
if (foam_factor <= 1.0 - definition->foam_coverage)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
foam_factor = (foam_factor - (1.0 - definition->foam_coverage)) * definition->foam_coverage;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
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;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look)
|
|
|
|
{
|
|
|
|
WaterResult result;
|
|
|
|
RayCastingResult refracted;
|
|
|
|
Vector3 normal;
|
|
|
|
Color color;
|
2012-06-05 20:22:12 +00:00
|
|
|
LightStatus light;
|
2012-01-23 23:45:33 +00:00
|
|
|
SurfaceMaterial material;
|
2012-06-17 09:40:40 +00:00
|
|
|
double detail, depth;
|
2012-01-23 23:45:33 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
detail = renderer->getPrecision(renderer, location) * 0.1;
|
|
|
|
if (detail < 0.00001)
|
|
|
|
{
|
|
|
|
detail = 0.00001;
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-11-11 10:52:03 +00:00
|
|
|
location.y = _getHeight(definition, location.x, location.z);
|
2011-12-10 13:25:22 +00:00
|
|
|
result.location = location;
|
|
|
|
|
|
|
|
normal = _getNormal(definition, location, detail);
|
|
|
|
look = v3Normalize(look);
|
2012-01-24 13:16:20 +00:00
|
|
|
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);
|
2011-12-19 20:59:39 +00:00
|
|
|
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;
|
|
|
|
}
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-28 18:32:08 +00:00
|
|
|
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;
|
2011-12-10 13:25:22 +00:00
|
|
|
color.a = 1.0;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-01-28 18:32:08 +00:00
|
|
|
material = definition->material;
|
2012-01-22 18:39:42 +00:00
|
|
|
material.base = color;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-11-19 20:40:57 +00:00
|
|
|
_applyFoam(definition, location, normal, detail, &material);
|
|
|
|
|
2012-06-05 20:22:12 +00:00
|
|
|
renderer->getLightStatus(renderer, &light, location);
|
|
|
|
color = renderer->applyLightStatus(renderer, &light, location, normal, material);
|
2012-11-25 21:53:01 +00:00
|
|
|
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color);
|
2012-01-31 09:48:38 +00:00
|
|
|
color = renderer->applyClouds(renderer, color, renderer->camera_location, location);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-01-28 18:32:08 +00:00
|
|
|
result.base = definition->material.base;
|
2011-12-10 13:25:22 +00:00
|
|
|
result.final = color;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-01-23 23:45:33 +00:00
|
|
|
Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-23 23:45:33 +00:00
|
|
|
return waterGetColorDetail(definition, renderer, location, look).final;
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-06-17 09:40:40 +00:00
|
|
|
static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* data)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-06-17 09:40:40 +00:00
|
|
|
return waterGetColor((WaterDefinition*)data, renderer, location, v3Sub(location, renderer->camera_location));
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-06-17 09:40:40 +00:00
|
|
|
static Vector3 _getFirstPassVertex(WaterDefinition* definition, double x, double z, double precision)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-06-17 09:40:40 +00:00
|
|
|
Vector3 result;
|
|
|
|
|
|
|
|
result.x = x;
|
2012-11-11 10:52:03 +00:00
|
|
|
result.y = _getHeight(definition, x, z);
|
2012-06-17 09:40:40 +00:00
|
|
|
result.z = z;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-06-17 09:40:40 +00:00
|
|
|
static void _renderQuad(WaterDefinition* definition, Renderer* renderer, double x, double z, double size)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-06-17 09:40:40 +00:00
|
|
|
Vector3 v1, v2, v3, v4;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-01-24 13:16:20 +00:00
|
|
|
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);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-06-17 09:40:40 +00:00
|
|
|
renderer->pushQuad(renderer, v1, v2, v3, v4, _postProcessFragment, definition);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-29 21:45:58 +00:00
|
|
|
void waterRender(WaterDefinition* definition, Renderer* renderer)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
int chunk_factor, chunk_count, i;
|
2012-06-17 09:40:40 +00:00
|
|
|
double cx = renderer->camera_location.x;
|
|
|
|
double cz = renderer->camera_location.z;
|
|
|
|
double radius_int, radius_ext, base_chunk_size, chunk_size;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
2012-06-17 09:40:40 +00:00
|
|
|
base_chunk_size = 2.0 / (double)renderer->render_quality;
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
chunk_factor = 1;
|
|
|
|
chunk_count = 2;
|
|
|
|
radius_int = 0.0;
|
|
|
|
radius_ext = base_chunk_size;
|
|
|
|
chunk_size = base_chunk_size;
|
|
|
|
|
2013-01-16 15:26:33 +00:00
|
|
|
while (radius_int < 5000.0)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-29 21:45:58 +00:00
|
|
|
if (!renderer->addRenderProgress(renderer, 0.0))
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2011-12-19 20:59:39 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
for (i = 0; i < chunk_count - 1; i++)
|
|
|
|
{
|
2012-01-24 13:16:20 +00:00
|
|
|
_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);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-06-17 09:40:40 +00:00
|
|
|
if (radius_int > 20.0 && chunk_count % 64 == 0 && (double)chunk_factor < radius_int / 20.0)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
chunk_count /= 2;
|
|
|
|
chunk_factor *= 2;
|
|
|
|
}
|
|
|
|
chunk_count += 2;
|
|
|
|
chunk_size = base_chunk_size * chunk_factor;
|
|
|
|
radius_int = radius_ext;
|
|
|
|
radius_ext += chunk_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|