2013-12-08 17:05:18 +00:00
|
|
|
#include "WaterRasterizer.h"
|
2013-02-27 16:38:27 +00:00
|
|
|
|
2013-12-08 17:05:18 +00:00
|
|
|
#include "SoftwareRenderer.h"
|
2013-12-08 19:54:34 +00:00
|
|
|
#include "WaterRenderer.h"
|
2014-08-18 10:17:16 +00:00
|
|
|
#include "CanvasFragment.h"
|
2015-08-23 18:22:37 +00:00
|
|
|
#include "RenderProgress.h"
|
2013-12-08 17:05:18 +00:00
|
|
|
|
2015-08-23 18:22:37 +00:00
|
|
|
WaterRasterizer::WaterRasterizer(SoftwareRenderer* renderer, RenderProgress *progress, int client_id):
|
|
|
|
Rasterizer(renderer, progress, client_id, Color(0.9, 0.95, 1.0))
|
2013-12-08 17:05:18 +00:00
|
|
|
{
|
|
|
|
}
|
2013-02-27 16:38:27 +00:00
|
|
|
|
2014-06-18 18:10:05 +00:00
|
|
|
static inline Vector3 _getFirstPassVertex(SoftwareRenderer* renderer, double x, double z)
|
2013-02-27 16:38:27 +00:00
|
|
|
{
|
|
|
|
Vector3 result;
|
|
|
|
|
|
|
|
result.x = x;
|
2013-12-08 19:54:34 +00:00
|
|
|
result.y = renderer->getWaterRenderer()->getHeight(x, z);
|
2013-02-27 16:38:27 +00:00
|
|
|
result.z = z;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-06-18 18:10:05 +00:00
|
|
|
void WaterRasterizer::rasterizeQuad(CanvasPortion* canvas, 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);
|
|
|
|
|
|
|
|
pushQuad(canvas, v1, v2, v3, v4);
|
|
|
|
}
|
|
|
|
|
2015-08-23 18:22:37 +00:00
|
|
|
int WaterRasterizer::prepareRasterization()
|
|
|
|
{
|
|
|
|
return performTessellation(NULL);
|
|
|
|
}
|
|
|
|
|
2014-06-18 18:10:05 +00:00
|
|
|
void WaterRasterizer::rasterizeToCanvas(CanvasPortion *canvas)
|
|
|
|
{
|
2015-08-23 18:22:37 +00:00
|
|
|
performTessellation(canvas);
|
|
|
|
}
|
|
|
|
|
2015-10-15 22:51:46 +00:00
|
|
|
Color WaterRasterizer::shadeFragment(const CanvasFragment &fragment, const CanvasFragment *) const
|
2015-08-23 18:22:37 +00:00
|
|
|
{
|
|
|
|
Vector3 location = fragment.getLocation();
|
|
|
|
return renderer->getWaterRenderer()->getResult(location.x, location.z).final;
|
|
|
|
}
|
|
|
|
|
2015-09-10 17:33:52 +00:00
|
|
|
void WaterRasterizer::setQuality(double factor)
|
2015-08-23 18:22:37 +00:00
|
|
|
{
|
2015-09-10 17:33:52 +00:00
|
|
|
base_chunk_size = 10.0 / (1.0 + factor * 7.0);
|
|
|
|
if (factor > 0.6)
|
2014-06-18 18:10:05 +00:00
|
|
|
{
|
|
|
|
base_chunk_size *= 0.5;
|
|
|
|
}
|
2015-09-10 17:33:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int WaterRasterizer::performTessellation(CanvasPortion *canvas)
|
|
|
|
{
|
|
|
|
int chunk_factor, chunk_count, i, result;
|
|
|
|
Vector3 cam = renderer->getCameraLocation(VECTOR_ZERO);
|
|
|
|
double radius_int, radius_ext, chunk_size;
|
2014-06-18 18:10:05 +00:00
|
|
|
|
2015-08-23 18:22:37 +00:00
|
|
|
result = 0;
|
2014-06-18 18:10:05 +00:00
|
|
|
chunk_factor = 1;
|
|
|
|
chunk_count = 2;
|
|
|
|
radius_int = 0.0;
|
|
|
|
radius_ext = base_chunk_size;
|
|
|
|
chunk_size = base_chunk_size;
|
|
|
|
|
|
|
|
double cx = cam.x - fmod(cam.x, base_chunk_size);
|
|
|
|
double cz = cam.z - fmod(cam.x, base_chunk_size);
|
|
|
|
|
|
|
|
while (radius_int < 20000.0)
|
|
|
|
{
|
2014-08-19 09:44:54 +00:00
|
|
|
if (interrupted)
|
2014-06-18 18:10:05 +00:00
|
|
|
{
|
2015-08-23 18:22:37 +00:00
|
|
|
return result;
|
2014-06-18 18:10:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < chunk_count - 1; i++)
|
|
|
|
{
|
2015-08-23 18:22:37 +00:00
|
|
|
result++;
|
|
|
|
if (canvas)
|
|
|
|
{
|
|
|
|
rasterizeQuad(canvas, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size);
|
|
|
|
rasterizeQuad(canvas, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size);
|
|
|
|
rasterizeQuad(canvas, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size);
|
|
|
|
rasterizeQuad(canvas, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (canvas)
|
|
|
|
{
|
|
|
|
progress->add(chunk_count - 1);
|
2014-06-18 18:10:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2014-08-18 10:17:16 +00:00
|
|
|
|
2015-08-23 18:22:37 +00:00
|
|
|
return result;
|
2014-08-18 10:17:16 +00:00
|
|
|
}
|