Added render tests from command line

This commit is contained in:
Michaël Lemaire 2015-09-10 00:40:47 +02:00
parent 035c957054
commit 4fcf1d071c
10 changed files with 173 additions and 73 deletions

View file

@ -7,7 +7,9 @@ TARGET = paysages-cli
include(../../common.pri) include(../../common.pri)
SOURCES += \ SOURCES += \
main.cpp main.cpp \
tests.cpp \
render.cpp
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../system/release/ -lpaysages_system win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../system/release/ -lpaysages_system
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../system/debug/ -lpaysages_system else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../system/debug/ -lpaysages_system

View file

@ -1,71 +1,31 @@
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include "CameraDefinition.h"
#include "AtmosphereDefinition.h"
#include "SoftwareCanvasRenderer.h" #include "SoftwareCanvasRenderer.h"
#include "Scenery.h"
#include "RenderConfig.h" #include "RenderConfig.h"
#include "ColorProfile.h" #include "Scenery.h"
#include "Thread.h" #include "AtmosphereDefinition.h"
#include "CameraDefinition.h"
class RenderThread: public Thread #include <cstring>
{
public:
RenderThread(SoftwareCanvasRenderer *renderer, char *outputpath):
renderer(renderer), outputpath(outputpath)
{
}
virtual void run() override void startRender(SoftwareCanvasRenderer *renderer, const char *outputpath);
{ void runTestSuite();
renderer->render();
}
private:
SoftwareCanvasRenderer *renderer;
char *outputpath;
};
static void startRender(SoftwareCanvasRenderer *renderer, char *outputpath)
{
RenderThread thread(renderer, outputpath);
printf("\rRendering %s ... \n", outputpath);
thread.start();
while (thread.isWorking())
{
Thread::timeSleepMs(200);
printf("\rProgress : %0.1f%% ", renderer->getProgress() * 100.0);
fflush(stdout);
}
thread.join();
printf("\rSaving %s ... \n", outputpath);
remove(outputpath);
renderer->saveToDisk(outputpath);
}
static void displayHelp() static void displayHelp()
{ {
printf("Usage : paysages-cli [options]\n"); printf("Usage : paysages-cli [options]\n");
printf("Options :\n"); printf("Options :\n");
printf(" -h Show this help\n"); printf(" -h Show this help\n");
printf(" -f x Saved file to load (str)\n"); printf(" -ts Run the render test suite\n");
printf(" -n Number of pictures in the sequence\n"); printf(" -f x Saved file to load (str)\n");
printf(" -rw x Render width (int)\n"); printf(" -n Number of pictures in the sequence\n");
printf(" -rh x Render height (int)\n"); printf(" -rw x Render width (int)\n");
printf(" -rq x Render quality (int, 1 to 10)\n"); printf(" -rh x Render height (int)\n");
printf(" -ra x Render anti-aliasing (int, 1 to 4)\n"); printf(" -rq x Render quality (int, 1 to 10)\n");
printf(" -di x Day start time (double, 0.0 to 1.0)\n"); printf(" -ra x Render anti-aliasing (int, 1 to 4)\n");
printf(" -ds x Day step time (double)\n"); printf(" -di x Day start time (double, 0.0 to 1.0)\n");
printf(" -cx x Camera X step (double)\n"); printf(" -ds x Day step time (double)\n");
printf(" -cy y Camera Y step (double)\n"); printf(" -cx x Camera X step (double)\n");
printf(" -cz z Camera Z step (double)\n"); printf(" -cy y Camera Y step (double)\n");
printf(" -cz z Camera Z step (double)\n");
} }
int main(int argc, char** argv) int main(int argc, char** argv)
@ -93,6 +53,11 @@ int main(int argc, char** argv)
displayHelp(); displayHelp();
return 0; return 0;
} }
else if (strcmp(*argv, "-ts") == 0 || strcmp(*argv, "--testsuite") == 0)
{
runTestSuite();
return 0;
}
else if (strcmp(*argv, "-f") == 0 || strcmp(*argv, "--file") == 0) else if (strcmp(*argv, "-f") == 0 || strcmp(*argv, "--file") == 0)
{ {
if (argc--) if (argc--)

View file

@ -0,0 +1,42 @@
#include "Thread.h"
#include "SoftwareCanvasRenderer.h"
class RenderThread: public Thread
{
public:
RenderThread(SoftwareCanvasRenderer *renderer, const char *outputpath):
renderer(renderer), outputpath(outputpath)
{
}
virtual void run() override
{
renderer->render();
}
private:
SoftwareCanvasRenderer *renderer;
const char *outputpath;
};
void startRender(SoftwareCanvasRenderer *renderer, const char *outputpath)
{
RenderThread thread(renderer, outputpath);
printf("\rRendering %s ... \n", outputpath);
thread.start();
while (thread.isWorking())
{
Thread::timeSleepMs(200);
printf("\rProgress : %0.1f%% ", renderer->getProgress() * 100.0);
fflush(stdout);
}
thread.join();
printf("\rSaving %s ... \n", outputpath);
remove(outputpath);
renderer->saveToDisk(outputpath);
}

View file

@ -0,0 +1,71 @@
#include "SoftwareCanvasRenderer.h"
#include "Scenery.h"
#include "CameraDefinition.h"
#include "TerrainDefinition.h"
#include "AtmosphereDefinition.h"
#include "TexturesDefinition.h"
#include "TextureLayerDefinition.h"
#include "WaterDefinition.h"
#include "SurfaceMaterial.h"
#include "FloatNode.h"
#include <sstream>
void startRender(SoftwareCanvasRenderer *renderer, const char *outputpath);
static void startTestRender(SoftwareCanvasRenderer *renderer, const std::string &name, int iteration)
{
std::ostringstream stream;
stream << "pic_test_" << name << "_";
stream.width(4);
stream.fill('0');
stream << iteration;
stream << ".png";
startRender(renderer, stream.str().data());
}
static void testGroundShadowQuality()
{
Scenery scenery;
srand(5);
scenery.getTerrain()->applyPreset(TerrainDefinition::TERRAIN_PRESET_STANDARD);
scenery.getTerrain()->propWaterHeight()->setValue(-0.5);
scenery.getWater()->propReflection()->setValue(0.0);
scenery.getWater()->material->base->r = 0.0;
scenery.getWater()->material->base->g = 0.3;
scenery.getWater()->material->base->b = 1.0;
scenery.getWater()->material->reflection = 0.0;
scenery.getWater()->foam_coverage = 0.0;
scenery.getWater()->transparency = 0.0;
scenery.getAtmosphere()->applyPreset(AtmosphereDefinition::ATMOSPHERE_PRESET_CLEAR_SUNSET);
scenery.getAtmosphere()->setDayTime(16, 45);
scenery.getTextures()->clear();
TextureLayerDefinition *texture = scenery.getTextures()->getTextureLayer(scenery.getTextures()->addLayer());
texture->displacement_height = 0.3;
texture->displacement_scaling = 2.0;
texture->displacement_offset = 0.0;
texture->material->setColor(0.6, 0.55, 0.57, 1.0);
texture->material->reflection = 0.006;
texture->material->shininess = 6.0;
texture->validate();
scenery.getCamera()->setLocation(Vector3(10.0, 10.0, -10.0));
scenery.getCamera()->setTarget(VECTOR_ZERO);
scenery.validate();
SoftwareCanvasRenderer renderer(&scenery);
renderer.setSize(400, 300);
for (int i = 1; i <= 10; i++)
{
// TODO keep same rasterization across renders, or keep rasterization quality low
renderer.render_quality = i;
startTestRender(&renderer, "ground_shadow_quality", i);
}
}
void runTestSuite()
{
testGroundShadowQuality();
}

View file

@ -122,7 +122,11 @@ void MainModelerWindow::exit()
void MainModelerWindow::keyReleaseEvent(QKeyEvent *event) void MainModelerWindow::keyReleaseEvent(QKeyEvent *event)
{ {
if (getState() == "Render Dialog") if (event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_Q)
{
exit();
}
else if (getState() == "Render Dialog")
{ {
if (event->key() == Qt::Key_Escape) if (event->key() == Qt::Key_Escape)
{ {
@ -153,13 +157,6 @@ void MainModelerWindow::keyReleaseEvent(QKeyEvent *event)
{ {
Logs::warning() << "Current scenery dump:" << std::endl << scenery->toString() << std::endl; Logs::warning() << "Current scenery dump:" << std::endl << scenery->toString() << std::endl;
} }
else if (event->key() == Qt::Key_Q)
{
if (event->modifiers() & Qt::ControlModifier)
{
exit();
}
}
else if (event->key() == Qt::Key_N) else if (event->key() == Qt::Key_N)
{ {
if (event->modifiers() & Qt::ControlModifier) if (event->modifiers() & Qt::ControlModifier)

View file

@ -14,6 +14,19 @@ paysages::software::RenderProgress::~RenderProgress()
delete lock; delete lock;
} }
void RenderProgress::reset()
{
lock->acquire();
global = 0.0;
while (not subs.empty())
{
subs.pop();
}
lock->release();
}
void RenderProgress::add(int value) void RenderProgress::add(int value)
{ {
lock->acquire(); lock->acquire();

View file

@ -26,6 +26,7 @@ public:
inline double get() const {return global;} inline double get() const {return global;}
void reset();
void add(int value=1); void add(int value=1);
void enterSub(int count); void enterSub(int count);
void exitSub(); void exitSub();

View file

@ -69,6 +69,7 @@ void SoftwareCanvasRenderer::setSize(int width, int height, int samples)
void SoftwareCanvasRenderer::render() void SoftwareCanvasRenderer::render()
{ {
started = true; started = true;
progress->reset();
render_camera->setRenderSize(canvas->getWidth(), canvas->getHeight()); render_camera->setRenderSize(canvas->getWidth(), canvas->getHeight());

View file

@ -24,11 +24,11 @@ void TerrainRayWalker::update()
ymin = info.min_height - disp; ymin = info.min_height - disp;
ymax = info.max_height + disp; ymax = info.max_height + disp;
ydispmax = disp * (0.5 + (double)renderer->render_quality * 0.1); ydispmax = disp * (0.5 + (double)renderer->render_quality * 0.05);
ydispmin = -ydispmax; ydispmin = -ydispmax;
minstep = 1.0 * terrain->scaling / (double)(renderer->render_quality * renderer->render_quality); minstep = 0.5 * terrain->scaling / (double)renderer->render_quality;
maxstep = 10.0 * terrain->scaling / (double)renderer->render_quality; maxstep = 50.0 * terrain->scaling / (double)renderer->render_quality;
} }
static inline Vector3 _getShiftAxis(const Vector3 &direction) static inline Vector3 _getShiftAxis(const Vector3 &direction)
@ -63,7 +63,14 @@ bool TerrainRayWalker::startWalking(const Vector3 &start, Vector3 direction, dou
if (escape_angle != 0.0) if (escape_angle != 0.0)
{ {
// Prepare escape // Prepare escape
shift_step = escape_angle / (double)(renderer->render_quality * renderer->render_quality); if (renderer->render_quality >= 7)
{
shift_step = escape_angle / (double)(renderer->render_quality * renderer->render_quality);
}
else
{
shift_step = escape_angle / (double)renderer->render_quality;
}
shift_matrix = Matrix4::newRotateAxis(-shift_step, _getShiftAxis(direction)); shift_matrix = Matrix4::newRotateAxis(-shift_step, _getShiftAxis(direction));
} }
@ -121,7 +128,7 @@ bool TerrainRayWalker::startWalking(const Vector3 &start, Vector3 direction, dou
previous_cursor = cursor; previous_cursor = cursor;
walked_length += step_length; walked_length += step_length;
step_length = diff * 3.0 / (double)renderer->render_quality; step_length = diff * 10.0 / (double)renderer->render_quality;
if (step_length < minstep) if (step_length < minstep)
{ {
step_length = minstep; step_length = minstep;

View file

@ -175,6 +175,7 @@ bool TerrainRenderer::applyLightFilter(LightComponent &light, const Vector3 &at)
// Walk to find an intersection // Walk to find an intersection
double escape_angle = definition->shadow_smoothing; double escape_angle = definition->shadow_smoothing;
// TODO max length should depend on the sun light angle and altitude range
if (walker->startWalking(at, direction_to_light, escape_angle, 100.0, walk_result)) if (walker->startWalking(at, direction_to_light, escape_angle, 100.0, walk_result))
{ {
if (walk_result.escape_angle == 0.0) if (walk_result.escape_angle == 0.0)