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"
|
2013-12-09 10:59:57 +00:00
|
|
|
#include "ParallelQueue.h"
|
2013-12-08 17:05:18 +00:00
|
|
|
|
2014-06-12 15:45:59 +00:00
|
|
|
WaterRasterizer::WaterRasterizer(SoftwareRenderer* renderer, int client_id):
|
|
|
|
Rasterizer(renderer, client_id)
|
2013-12-08 17:05:18 +00:00
|
|
|
{
|
|
|
|
}
|
2013-02-27 16:38:27 +00:00
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
static Color _postProcessFragment(SoftwareRenderer* renderer, const Vector3 &location, void*)
|
2013-02-27 16:38:27 +00:00
|
|
|
{
|
2013-12-08 19:54:34 +00:00
|
|
|
return renderer->getWaterRenderer()->getResult(location.x, location.z).final;
|
2013-02-27 16:38:27 +00:00
|
|
|
}
|
|
|
|
|
2013-12-08 19:54:34 +00:00
|
|
|
static 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;
|
|
|
|
}
|
|
|
|
|
2013-12-08 19:54:34 +00:00
|
|
|
static void _renderQuad(SoftwareRenderer* renderer, double x, double z, double size)
|
2013-02-27 16:38:27 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2013-12-09 10:59:57 +00:00
|
|
|
renderer->pushQuad(v1, v2, v3, v4, _postProcessFragment, NULL);
|
2013-02-27 16:38:27 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 22:45:43 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2013-12-08 17:05:18 +00:00
|
|
|
SoftwareRenderer* renderer;
|
2013-07-06 22:45:43 +00:00
|
|
|
int i;
|
|
|
|
double cx;
|
|
|
|
double cz;
|
|
|
|
double radius_int;
|
|
|
|
double chunk_size;
|
|
|
|
double radius_ext;
|
|
|
|
} ParallelRasterInfo;
|
|
|
|
|
2013-11-17 22:02:36 +00:00
|
|
|
static int _parallelJobCallback(ParallelQueue*, int, void* data, int stopping)
|
2013-07-06 22:45:43 +00:00
|
|
|
{
|
|
|
|
ParallelRasterInfo* info = (ParallelRasterInfo*)data;
|
|
|
|
|
|
|
|
if (!stopping)
|
|
|
|
{
|
|
|
|
_renderQuad(info->renderer, info->cx - info->radius_ext + info->chunk_size * info->i, info->cz - info->radius_ext, info->chunk_size);
|
|
|
|
_renderQuad(info->renderer, info->cx + info->radius_int, info->cz - info->radius_ext + info->chunk_size * info->i, info->chunk_size);
|
|
|
|
_renderQuad(info->renderer, info->cx + info->radius_int - info->chunk_size * info->i, info->cz + info->radius_int, info->chunk_size);
|
|
|
|
_renderQuad(info->renderer, info->cx - info->radius_ext, info->cz + info->radius_int - info->chunk_size * info->i, info->chunk_size);
|
|
|
|
}
|
|
|
|
|
2013-12-17 22:01:36 +00:00
|
|
|
delete info;
|
2013-07-06 22:45:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-12 15:45:59 +00:00
|
|
|
void WaterRasterizer::rasterize()
|
2013-02-27 16:38:27 +00:00
|
|
|
{
|
2013-07-06 22:45:43 +00:00
|
|
|
ParallelRasterInfo* info;
|
|
|
|
ParallelQueue* queue;
|
2013-12-09 10:59:57 +00:00
|
|
|
queue = new ParallelQueue();
|
2013-07-06 22:45:43 +00:00
|
|
|
|
2013-02-27 16:38:27 +00:00
|
|
|
int chunk_factor, chunk_count, i;
|
2013-12-09 10:59:57 +00:00
|
|
|
Vector3 cam = renderer->getCameraLocation(VECTOR_ZERO);
|
2013-02-27 16:38:27 +00:00
|
|
|
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;
|
|
|
|
|
2013-07-06 22:45:08 +00:00
|
|
|
double cx = cam.x - fmod(cam.x, base_chunk_size);
|
|
|
|
double cz = cam.z - fmod(cam.x, base_chunk_size);
|
|
|
|
|
2013-07-03 15:48:54 +00:00
|
|
|
while (radius_int < 20000.0)
|
2013-02-27 16:38:27 +00:00
|
|
|
{
|
2013-12-09 10:59:57 +00:00
|
|
|
if (!renderer->addRenderProgress(0.0))
|
2013-02-27 16:38:27 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < chunk_count - 1; i++)
|
|
|
|
{
|
2013-11-02 15:43:43 +00:00
|
|
|
info = new ParallelRasterInfo;
|
2013-07-06 22:45:43 +00:00
|
|
|
|
|
|
|
info->renderer = renderer;
|
|
|
|
info->cx = cx;
|
|
|
|
info->cz = cz;
|
|
|
|
info->i = i;
|
|
|
|
info->radius_int = radius_int;
|
|
|
|
info->radius_ext = radius_ext;
|
|
|
|
info->chunk_size = chunk_size;
|
|
|
|
|
2013-12-09 10:59:57 +00:00
|
|
|
if (!queue->addJob(_parallelJobCallback, info))
|
2013-07-06 22:45:43 +00:00
|
|
|
{
|
2013-11-02 15:43:43 +00:00
|
|
|
delete info;
|
2013-07-06 22:45:43 +00:00
|
|
|
}
|
2013-02-27 16:38:27 +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;
|
|
|
|
}
|
2013-07-06 22:45:43 +00:00
|
|
|
|
2013-12-09 10:59:57 +00:00
|
|
|
queue->wait();
|
|
|
|
delete queue;
|
2013-02-27 16:38:27 +00:00
|
|
|
}
|