Merged perspective_correction into master

This commit is contained in:
Michaël Lemaire 2013-06-13 18:35:58 +02:00 committed by Michaël Lemaire
commit b793259554
10 changed files with 153 additions and 48 deletions

View file

@ -183,6 +183,15 @@ CameraPerspective cameraGetPerspective(CameraDefinition* camera)
return camera->perspective; return camera->perspective;
} }
double cameraGetRealDepth(CameraDefinition* camera, Vector3 projected)
{
/* TODO Optimize this */
Matrix4 m = m4NewPerspective(camera->perspective.yfov, camera->perspective.xratio, camera->perspective.znear, camera->perspective.zfar);
projected.x = (projected.x / (0.5 * camera->width) - 1.0);
projected.y = -(projected.y / (0.5 * camera->height) - 1.0);
return m4Transform(m4Inverse(m), projected).z;
}
void cameraSetLocation(CameraDefinition* camera, Vector3 location) void cameraSetLocation(CameraDefinition* camera, Vector3 location)
{ {
camera->location = location; camera->location = location;
@ -300,6 +309,11 @@ Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point)
{ {
point.x = (point.x / (0.5 * camera->width) - 1.0); point.x = (point.x / (0.5 * camera->width) - 1.0);
point.y = -(point.y / (0.5 * camera->height) - 1.0); point.y = -(point.y / (0.5 * camera->height) - 1.0);
if (point.z < 1.0)
{
point.x = -point.x;
point.y = -point.y;
}
return m4Transform(camera->unproject, point); return m4Transform(camera->unproject, point);
} }

View file

@ -35,6 +35,7 @@ Vector3 cameraGetDirection(CameraDefinition* camera);
Vector3 cameraGetDirectionNormalized(CameraDefinition* camera); Vector3 cameraGetDirectionNormalized(CameraDefinition* camera);
VectorSpherical cameraGetDirectionSpherical(CameraDefinition* camera); VectorSpherical cameraGetDirectionSpherical(CameraDefinition* camera);
CameraPerspective cameraGetPerspective(CameraDefinition* camera); CameraPerspective cameraGetPerspective(CameraDefinition* camera);
double cameraGetRealDepth(CameraDefinition* camera, Vector3 projected);
void cameraSetLocation(CameraDefinition* camera, Vector3 location); void cameraSetLocation(CameraDefinition* camera, Vector3 location);
void cameraSetLocationCoords(CameraDefinition* camera, double x, double y, double z); void cameraSetLocationCoords(CameraDefinition* camera, double x, double y, double z);

View file

@ -5,6 +5,7 @@
#include <math.h> #include <math.h>
#include "renderer.h" #include "renderer.h"
#include "camera.h"
#include "system.h" #include "system.h"
typedef struct typedef struct
@ -45,6 +46,7 @@ typedef struct
struct RenderArea struct RenderArea
{ {
ColorProfile* hdr_mapping; ColorProfile* hdr_mapping;
Renderer* renderer;
RenderParams params; RenderParams params;
int pixel_count; int pixel_count;
int pixel_done; int pixel_done;
@ -77,7 +79,6 @@ typedef struct {
int pixel_done; int pixel_done;
Thread* thread; Thread* thread;
RenderArea* area; RenderArea* area;
Renderer* renderer;
} RenderChunk; } RenderChunk;
#define RENDER_INVERSE 1 #define RENDER_INVERSE 1
@ -94,11 +95,12 @@ void renderQuit()
{ {
} }
RenderArea* renderCreateArea() RenderArea* renderCreateArea(Renderer* renderer)
{ {
RenderArea* result; RenderArea* result;
result = malloc(sizeof(RenderArea)); result = malloc(sizeof(RenderArea));
result->renderer = renderer;
result->hdr_mapping = colorProfileCreate(); result->hdr_mapping = colorProfileCreate();
result->params.width = 1; result->params.width = 1;
result->params.height = 1; result->params.height = 1;
@ -380,14 +382,18 @@ static void _scanGetDiff(ScanPoint* v1, ScanPoint* v2, ScanPoint* result)
result->callback = v1->callback; result->callback = v1->callback;
} }
static void _scanInterpolate(ScanPoint* v1, ScanPoint* diff, double value, ScanPoint* result) static void _scanInterpolate(CameraDefinition* camera, ScanPoint* v1, ScanPoint* diff, double value, ScanPoint* result)
{ {
double v1depth = cameraGetRealDepth(camera, v1->pixel);
double v2depth = cameraGetRealDepth(camera, v3Add(v1->pixel, diff->pixel));
double factor = ((1.0 - value) / v1depth + value / v2depth);
result->pixel.x = v1->pixel.x + diff->pixel.x * value; result->pixel.x = v1->pixel.x + diff->pixel.x * value;
result->pixel.y = v1->pixel.y + diff->pixel.y * value; result->pixel.y = v1->pixel.y + diff->pixel.y * value;
result->pixel.z = v1->pixel.z + diff->pixel.z * value; result->pixel.z = v1->pixel.z + diff->pixel.z * value;
result->location.x = v1->location.x + diff->location.x * value; result->location.x = ((1.0 - value) * (v1->location.x / v1depth) + value * (v1->location.x + diff->location.x) / v2depth) / factor;
result->location.y = v1->location.y + diff->location.y * value; result->location.y = ((1.0 - value) * (v1->location.y / v1depth) + value * (v1->location.y + diff->location.y) / v2depth) / factor;
result->location.z = v1->location.z + diff->location.z * value; result->location.z = ((1.0 - value) * (v1->location.z / v1depth) + value * (v1->location.z + diff->location.z) / v2depth) / factor;
result->callback = v1->callback; result->callback = v1->callback;
} }
@ -476,7 +482,7 @@ static void _pushScanLineEdge(RenderArea* area, ScanPoint* point1, ScanPoint* po
fx = point2->pixel.x; fx = point2->pixel.x;
} }
fx = fx - point1->pixel.x; fx = fx - point1->pixel.x;
_scanInterpolate(point1, &diff, fx / dx, &point); _scanInterpolate(area->renderer->render_camera, point1, &diff, fx / dx, &point);
/*point.pixel.x = (double)curx;*/ /*point.pixel.x = (double)curx;*/
@ -534,7 +540,7 @@ static void _renderScanLines(RenderArea* area)
fy = fy - down.pixel.y; fy = fy - down.pixel.y;
current.y = cury; current.y = cury;
_scanInterpolate(&down, &diff, fy / dy, &current); _scanInterpolate(area->renderer->render_camera, &down, &diff, fy / dy, &current);
_pushFragment(area, current.x, current.y, current.pixel.z, (cury == starty || cury == endy), current.location, current.callback); _pushFragment(area, current.x, current.y, current.pixel.z, (cury == starty || cury == endy), current.location, current.callback);
} }
@ -601,7 +607,7 @@ void* _renderPostProcessChunk(void* data)
callback = chunk->area->fragment_callbacks[fragment->flags.callback]; callback = chunk->area->fragment_callbacks[fragment->flags.callback];
if (callback.function) if (callback.function)
{ {
col = callback.function(chunk->renderer, fragment->data.location, callback.data); col = callback.function(chunk->area->renderer, fragment->data.location, callback.data);
/*colorNormalize(&col);*/ /*colorNormalize(&col);*/
} }
else else
@ -631,7 +637,7 @@ void* _renderPostProcessChunk(void* data)
} }
#define MAX_CHUNKS 8 #define MAX_CHUNKS 8
void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks) void renderPostProcess(RenderArea* area, int nbchunks)
{ {
volatile RenderChunk chunks[MAX_CHUNKS]; volatile RenderChunk chunks[MAX_CHUNKS];
int i; int i;
@ -659,12 +665,11 @@ void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks)
{ {
chunks[i].thread = NULL; chunks[i].thread = NULL;
chunks[i].area = area; chunks[i].area = area;
chunks[i].renderer = renderer;
} }
running = 0; running = 0;
loops = 0; loops = 0;
while ((y < ny && !renderer->render_interrupt) || running > 0) while ((y < ny && !area->renderer->render_interrupt) || running > 0)
{ {
timeSleepMs(100); timeSleepMs(100);
@ -678,13 +683,13 @@ void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks)
chunks[i].thread = NULL; chunks[i].thread = NULL;
running--; running--;
} }
else if (renderer->render_interrupt) else if (area->renderer->render_interrupt)
{ {
chunks[i].interrupt = 1; chunks[i].interrupt = 1;
} }
} }
if (y < ny && !chunks[i].thread && !renderer->render_interrupt) if (y < ny && !chunks[i].thread && !area->renderer->render_interrupt)
{ {
chunks[i].finished = 0; chunks[i].finished = 0;
chunks[i].interrupt = 0; chunks[i].interrupt = 0;

View file

@ -28,7 +28,7 @@ typedef struct
void renderInit(); void renderInit();
void renderQuit(); void renderQuit();
RenderArea* renderCreateArea(); RenderArea* renderCreateArea(Renderer* renderer);
void renderDeleteArea(RenderArea* area); void renderDeleteArea(RenderArea* area);
void renderSetParams(RenderArea* area, RenderParams params); void renderSetParams(RenderArea* area, RenderParams params);
@ -39,7 +39,7 @@ void renderUpdate(RenderArea* area);
void renderPushTriangle(RenderArea* area, Vector3 pixel1, Vector3 pixel2, Vector3 pixel3, Vector3 location1, Vector3 location2, Vector3 location3, f_RenderFragmentCallback callback, void* callback_data); void renderPushTriangle(RenderArea* area, Vector3 pixel1, Vector3 pixel2, Vector3 pixel3, Vector3 location1, Vector3 location2, Vector3 location3, f_RenderFragmentCallback callback, void* callback_data);
void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks); void renderPostProcess(RenderArea* area, int nbchunks);
int renderSaveToFile(RenderArea* area, const char* path); int renderSaveToFile(RenderArea* area, const char* path);
void renderSetPreviewCallbacks(RenderArea* area, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update); void renderSetPreviewCallbacks(RenderArea* area, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update);

View file

@ -40,7 +40,6 @@ static Vector3 _getCameraDirection(Renderer* renderer, Vector3 target)
static double _getPrecision(Renderer* renderer, Vector3 location) static double _getPrecision(Renderer* renderer, Vector3 location)
{ {
UNUSED(renderer); UNUSED(renderer);
UNUSED(location); UNUSED(location);
return 0.0; return 0.0;
@ -48,21 +47,16 @@ static double _getPrecision(Renderer* renderer, Vector3 location)
static Vector3 _projectPoint(Renderer* renderer, Vector3 point) static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
{ {
return cameraProject(renderer->render_camera, point);
UNUSED(renderer);
return point;
} }
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point) static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
{ {
return cameraUnproject(renderer->render_camera, point);
UNUSED(renderer);
return point;
} }
static void _pushTriangle(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, f_RenderFragmentCallback callback, void* callback_data) static void _pushTriangle(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, f_RenderFragmentCallback callback, void* callback_data)
{ {
Vector3 p1, p2, p3; Vector3 p1, p2, p3;
p1 = renderer->projectPoint(renderer, v1); p1 = renderer->projectPoint(renderer, v1);
@ -74,14 +68,12 @@ static void _pushTriangle(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3
static void _pushQuad(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, f_RenderFragmentCallback callback, void* callback_data) static void _pushQuad(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, f_RenderFragmentCallback callback, void* callback_data)
{ {
renderer->pushTriangle(renderer, v2, v3, v1, callback, callback_data); renderer->pushTriangle(renderer, v2, v3, v1, callback, callback_data);
renderer->pushTriangle(renderer, v4, v1, v3, callback, callback_data); renderer->pushTriangle(renderer, v4, v1, v3, callback, callback_data);
} }
static void _pushDisplacedTriangle(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 ov1, Vector3 ov2, Vector3 ov3, f_RenderFragmentCallback callback, void* callback_data) static void _pushDisplacedTriangle(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 ov1, Vector3 ov2, Vector3 ov3, f_RenderFragmentCallback callback, void* callback_data)
{ {
Vector3 p1, p2, p3; Vector3 p1, p2, p3;
p1 = renderer->projectPoint(renderer, v1); p1 = renderer->projectPoint(renderer, v1);
@ -93,20 +85,17 @@ static void _pushDisplacedTriangle(Renderer* renderer, Vector3 v1, Vector3 v2, V
static void _pushDisplacedQuad(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Vector3 ov1, Vector3 ov2, Vector3 ov3, Vector3 ov4, f_RenderFragmentCallback callback, void* callback_data) static void _pushDisplacedQuad(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Vector3 ov1, Vector3 ov2, Vector3 ov3, Vector3 ov4, f_RenderFragmentCallback callback, void* callback_data)
{ {
renderer->pushDisplacedTriangle(renderer, v2, v3, v1, ov2, ov3, ov1, callback, callback_data); renderer->pushDisplacedTriangle(renderer, v2, v3, v1, ov2, ov3, ov1, callback, callback_data);
renderer->pushDisplacedTriangle(renderer, v4, v1, v3, ov4, ov1, ov3, callback, callback_data); renderer->pushDisplacedTriangle(renderer, v4, v1, v3, ov4, ov1, ov3, callback, callback_data);
} }
static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds) static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds)
{ {
return _RAYCASTING_NULL; return _RAYCASTING_NULL;
} }
static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material) static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material)
{ {
LightStatus* light = lightingCreateStatus(renderer->lighting, location, renderer->getCameraLocation(renderer, location)); LightStatus* light = lightingCreateStatus(renderer->lighting, location, renderer->getCameraLocation(renderer, location));
renderer->atmosphere->getLightingStatus(renderer, light, normal, 0); renderer->atmosphere->getLightingStatus(renderer, light, normal, 0);
Color result = lightingApplyStatus(light, normal, material); Color result = lightingApplyStatus(light, normal, material);
@ -116,7 +105,6 @@ static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vecto
static Color _applyMediumTraversal(Renderer* renderer, Vector3 location, Color color) static Color _applyMediumTraversal(Renderer* renderer, Vector3 location, Color color)
{ {
color = renderer->atmosphere->applyAerialPerspective(renderer, location, color).final; color = renderer->atmosphere->applyAerialPerspective(renderer, location, color).final;
color = renderer->clouds->getColor(renderer, color, renderer->getCameraLocation(renderer, location), location); color = renderer->clouds->getColor(renderer, color, renderer->getCameraLocation(renderer, location), location);
return color; return color;
@ -124,7 +112,6 @@ static Color _applyMediumTraversal(Renderer* renderer, Vector3 location, Color c
Renderer* rendererCreate() Renderer* rendererCreate()
{ {
Renderer* result = malloc(sizeof (Renderer)); Renderer* result = malloc(sizeof (Renderer));
RenderParams params = {1, 1, 1, 5}; RenderParams params = {1, 1, 1, 5};
@ -135,7 +122,7 @@ Renderer* rendererCreate()
result->render_progress = 0.0; result->render_progress = 0.0;
result->is_rendering = 0; result->is_rendering = 0;
result->render_camera = cameraCreateDefinition(); result->render_camera = cameraCreateDefinition();
result->render_area = renderCreateArea(); result->render_area = renderCreateArea(result);
renderSetParams(result->render_area, params); renderSetParams(result->render_area, params);
@ -168,7 +155,6 @@ Renderer* rendererCreate()
void rendererDelete(Renderer* renderer) void rendererDelete(Renderer* renderer)
{ {
cameraDeleteDefinition(renderer->render_camera); cameraDeleteDefinition(renderer->render_camera);
lightingManagerDelete(renderer->lighting); lightingManagerDelete(renderer->lighting);
@ -185,7 +171,6 @@ void rendererDelete(Renderer* renderer)
void rendererSetPreviewCallbacks(Renderer* renderer, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update) void rendererSetPreviewCallbacks(Renderer* renderer, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update)
{ {
renderSetPreviewCallbacks(renderer->render_area, start, draw, update); renderSetPreviewCallbacks(renderer->render_area, start, draw, update);
} }
@ -228,7 +213,7 @@ void rendererStart(Renderer* renderer, RenderParams params)
threadJoin(thread); threadJoin(thread);
renderer->is_rendering = 1; renderer->is_rendering = 1;
renderPostProcess(renderer->render_area, renderer, core_count); renderPostProcess(renderer->render_area, core_count);
renderer->is_rendering = 0; renderer->is_rendering = 0;
} }

View file

@ -186,16 +186,6 @@ static RayCastingResult _rayWalking(Renderer* renderer, Vector3 location, Vector
return result; return result;
} }
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
{
return cameraProject(renderer->render_camera, point);
}
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
{
return cameraUnproject(renderer->render_camera, point);
}
static double _getPrecision(Renderer* renderer, Vector3 location) static double _getPrecision(Renderer* renderer, Vector3 location)
{ {
Vector3 projected; Vector3 projected;
@ -216,8 +206,6 @@ Renderer* sceneryCreateStandardRenderer()
cameraCopyDefinition(_camera, result->render_camera); cameraCopyDefinition(_camera, result->render_camera);
result->rayWalking = _rayWalking; result->rayWalking = _rayWalking;
result->projectPoint = _projectPoint;
result->unprojectPoint = _unprojectPoint;
result->getPrecision = _getPrecision; result->getPrecision = _getPrecision;
sceneryBindRenderer(result); sceneryBindRenderer(result);

View file

@ -8,6 +8,8 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
extern int tests_cpu_count;
static inline void _add_methods_to_case(TCase* tc, ...) static inline void _add_methods_to_case(TCase* tc, ...)
{ {
void* method; void* method;

View file

@ -2,10 +2,13 @@
#include <stdlib.h> #include <stdlib.h>
#include "rendering/main.h" #include "rendering/main.h"
#include "rendering/system.h"
int tests_cpu_count;
extern void test_euclid_case(Suite* s); extern void test_euclid_case(Suite* s);
extern void test_camera_case(Suite* s); extern void test_camera_case(Suite* s);
extern void test_clouds_case(Suite* s); extern void test_clouds_case(Suite* s);
extern void test_render_case(Suite* s);
extern void test_noise_case(Suite* s); extern void test_noise_case(Suite* s);
int main(int argc, char** argv) int main(int argc, char** argv)
@ -15,10 +18,13 @@ int main(int argc, char** argv)
paysagesInit(); paysagesInit();
tests_cpu_count = systemGetCoreCount();
/* TODO Find a way to automate this */ /* TODO Find a way to automate this */
test_euclid_case(s); test_euclid_case(s);
test_camera_case(s); test_camera_case(s);
test_clouds_case(s); test_clouds_case(s);
test_render_case(s);
test_noise_case(s); test_noise_case(s);
SRunner *sr = srunner_create(s); SRunner *sr = srunner_create(s);

View file

@ -17,5 +17,48 @@ START_TEST(test_camera_definition)
} }
END_TEST END_TEST
TEST_CASE(camera, test_camera_definition) START_TEST(test_camera_projection)
{
CameraDefinition* cam;
cam = cameraCreateDefinition();
cameraSetLocationCoords(cam, 0.0, 1.0, 1.0);
cameraSetTargetCoords(cam, 0.0, 0.0, 0.0);
/* Test the reversibility of projection */
Vector3 point = cameraProject(cam, v3(12.0, 5.2, -6.3));
point = cameraUnproject(cam, point);
ck_assert_vector_values(point, 12.0, 5.2, -6.3);
point = cameraProject(cam, v3(-25.1, 8.3, 1.3));
point = cameraUnproject(cam, point);
ck_assert_vector_values(point, -25.1, 8.3, 1.3);
cameraDeleteDefinition(cam);
}
END_TEST
START_TEST(test_camera_depth)
{
CameraDefinition* cam;
cam = cameraCreateDefinition();
cameraSetLocationCoords(cam, 0.0, 0.0, 0.0);
cameraSetTargetCoords(cam, 1.0, 0.0, 0.0);
/* Test the real depth getter */
Vector3 point = cameraProject(cam, v3(12.5, 0.0, 0.0));
ck_assert_double_eq(cameraGetRealDepth(cam, point), 12.5);
point = cameraProject(cam, v3(12.5, 8.0, -3.0));
ck_assert_double_eq(cameraGetRealDepth(cam, point), 12.5);
point = cameraProject(cam, v3(12.5, 12.0, 58.0));
ck_assert_double_eq(cameraGetRealDepth(cam, point), 12.5);
cameraDeleteDefinition(cam);
}
END_TEST
TEST_CASE(camera,
test_camera_definition,
test_camera_projection,
test_camera_depth)

61
src/testing/test_render.c Normal file
View file

@ -0,0 +1,61 @@
#include "testing/common.h"
#include <math.h>
#include "rendering/renderer.h"
#include "rendering/tools.h"
static Color _postProcessFragment(Renderer* renderer, Vector3 location, void* data)
{
UNUSED(renderer);
UNUSED(data);
/* Checker-board */
double x = fmod(location.x, 0.2);
double z = fmod(location.z, 0.2);
if (x < 0.0)
{
x = 0.2 + x;
}
if (z < 0.0)
{
z = 0.2 + z;
}
if ((x > 0.1) ^ (z > 0.1))
{
return COLOR_WHITE;
}
else
{
return COLOR_BLACK;
}
}
START_TEST(test_render_quad)
{
Renderer* renderer = rendererCreate();
renderer->render_width = 800;
renderer->render_height = 600;
renderer->render_quality = 1;
cameraSetLocationCoords(renderer->render_camera, 0.0, 0.5, 2.0);
cameraSetTargetCoords(renderer->render_camera, 0.0, 0.5, 0.0);
cameraSetRenderSize(renderer->render_camera, renderer->render_width, renderer->render_height);
RenderParams params = {renderer->render_width, renderer->render_height, 1, 1};
renderSetParams(renderer->render_area, params);
renderSetBackgroundColor(renderer->render_area, &COLOR_BLUE);
renderClear(renderer->render_area);
renderer->pushQuad(renderer, v3(-1.0, 0.0, 1.0), v3(-1.0, 0.0, -1.0), v3(1.0, 0.0, -1.0), v3(1.0, 0.0, 1.0), _postProcessFragment, NULL);
renderPostProcess(renderer->render_area, tests_cpu_count);
renderSaveToFile(renderer->render_area, "./output/test_render_quad.png");
rendererDelete(renderer);
}
END_TEST
TEST_CASE(render, test_render_quad)