Skip to content

Commit

Permalink
Raw code from Lecture 13.
Browse files Browse the repository at this point in the history
- Multi-threaded rendering, via CXXPTL.
- Interactive mode (can be used for look-around at the moment).
  Camera commanded by keys, keypad keys, and mouse.
- Setup SDL to be tolerant to multi-threaded updates to the
  screen (SDL_ASYNCBLIT).
- Trim down meshes.qdmg - remove AA, remove wineglass and the
  glossy balls.
  • Loading branch information
anrieff committed Jan 13, 2016
1 parent be8d64c commit 9379177
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 23 deletions.
7 changes: 5 additions & 2 deletions data/meshes.qdmg
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ GlobalSettings {
ambientLight (0.28, 0.30, 0.35)
maxTraceDepth 5
saturation 0.25
numThreads 0
wantAA false
interactive true
}

PointLight {
Expand Down Expand Up @@ -145,7 +148,7 @@ Refl ball_sfc {
glossiness 0.92
numSamples 10
}

/*
Node ball1 {
geometry ball
shader ball_sfc
Expand All @@ -171,7 +174,7 @@ Node wineglass {
translate (126, 0, 80)
scale (17, 17, 17)
}

*/
Node dice {
geometry dice
shader flat
Expand Down
14 changes: 14 additions & 0 deletions src/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "scene.h"
#include "random_generator.h"
using std::min;
using std::max;

void Camera::beginFrame()
{
Expand Down Expand Up @@ -112,3 +113,16 @@ Ray Camera::getDOFRay(double xScreen, double yScreen, int whichCamera)
ray.dir.normalize();
return ray;
}

void Camera::move(double sideways, double front_back)
{
position += rightDir * sideways + frontDir * front_back;
}

void Camera::rotate(double yawDiff, double pitchDiff)
{
yaw += yawDiff;
pitch += pitchDiff;
pitch = min(90.0, pitch);
pitch = max(-90.0, pitch);
}
4 changes: 4 additions & 0 deletions src/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ class Camera: public SceneElement {

Ray getScreenRay(double xScreen, double yScreen, int whichCamera = CAMERA_CENTRAL);
Ray getDOFRay(double xScreen, double yScreen, int whichCamera = CAMERA_CENTRAL);

void move(double sideways, double front_back);
void rotate(double yawDiff, double pitchDiff);

};

#endif // __CAMERA_H__
119 changes: 101 additions & 18 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <SDL/SDL.h>
#include <SDL/SDL_events.h>
#include <math.h>
#include <vector>
#include "vector.h"
Expand All @@ -13,12 +14,15 @@
#include "random_generator.h"
#include "scene.h"
#include "lights.h"
#include "cxxptl_sdl.h"

using std::vector;


Color vfb[VFB_MAX_SIZE][VFB_MAX_SIZE];

bool visibilityCheck(const Vector& start, const Vector& end);
ThreadPool pool;

Color raytrace(const Ray& ray)
{
Expand Down Expand Up @@ -299,12 +303,33 @@ Color renderPixel(int x, int y)
}
}

class MTRend: public Parallel {
const vector<Rect>& buckets;
InterlockedInt counter;
public:

MTRend(const vector<Rect>& buckets): buckets(buckets), counter(0) {}

void entry(int threadIdx, int threadCount)
{
int i;
while ((i = counter++) < int(buckets.size())) {
const Rect& r = buckets[i];
for (int y = r.y0; y < r.y1; y++)
for (int x = r.x0; x < r.x1; x++) {
vfb[y][x] = renderPixel(x, y);
}
if (!scene.settings.interactive && !displayVFBRect(r, vfb)) return;
}
}
};

void render()
{
scene.beginFrame();
vector<Rect> buckets = getBucketsList();

if (scene.settings.wantPrepass || scene.settings.gi) {
if (!scene.settings.interactive && (scene.settings.wantPrepass || scene.settings.gi)) {
// We render the whole screen in three passes.
// 1) First pass - use very coarse resolution rendering, tracing a single ray for a 16x16 block:
for (Rect& r: buckets) {
Expand All @@ -319,14 +344,11 @@ void render()
}
}
}

MTRend mtrend(buckets);

pool.run(&mtrend, scene.settings.numThreads);

for (Rect& r: buckets) {
for (int y = r.y0; y < r.y1; y++)
for (int x = r.x0; x < r.x1; x++) {
vfb[y][x] = renderPixel(x, y);
}
if (!displayVFBRect(r, vfb)) return;
}
}

int renderSceneThread(void* /*unused*/)
Expand All @@ -336,6 +358,57 @@ int renderSceneThread(void* /*unused*/)
return 0;
}

void mainloop(void)
{
SDL_ShowCursor(0);
bool running = true;
Camera& cam = *scene.camera;
const double movement = 2;
const double rotation = 5;
const double SENSITIVITY = 0.1;

while (running) {
render();
displayVFB(vfb);
//
SDL_Event ev;

while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
{
switch (ev.key.keysym.sym) {
case SDLK_ESCAPE:
running = false;
break;
default:
break;
}
break;
}
}
}

Uint8* keystate = SDL_GetKeyState(NULL);
if (keystate[SDLK_UP]) cam.move(0, +movement);
if (keystate[SDLK_DOWN]) cam.move(0, -movement);
if (keystate[SDLK_LEFT]) cam.move(-movement, 0);
if (keystate[SDLK_RIGHT]) cam.move(+movement, 0);

if (keystate[SDLK_KP8]) cam.rotate(0, +rotation);
if (keystate[SDLK_KP2]) cam.rotate(0, -rotation);
if (keystate[SDLK_KP4]) cam.rotate(+rotation, 0);
if (keystate[SDLK_KP6]) cam.rotate(-rotation, 0);

int deltax, deltay;
SDL_GetRelativeMouseState(&deltax, &deltay);
cam.rotate(-SENSITIVITY * deltax, -SENSITIVITY*deltay);
}
}

const char* DEFAULT_SCENE = "data/smallpt.qdmg";

int main ( int argc, char** argv )
Expand All @@ -348,20 +421,30 @@ int main ( int argc, char** argv )
return -1;
}

initGraphics(scene.settings.frameWidth, scene.settings.frameHeight);
initGraphics(scene.settings.frameWidth, scene.settings.frameHeight, scene.settings.interactive);
setWindowCaption("Quad Damage: preparing...");

scene.beginRender();
if (scene.settings.numThreads == 0)
scene.settings.numThreads = get_processor_count();

pool.preload_threads(scene.settings.numThreads);

setWindowCaption("Quad Damage: rendering...");
Uint32 startTicks = SDL_GetTicks();
renderScene_threaded();
Uint32 elapsedMs = SDL_GetTicks() - startTicks;
printf("Render took %.2fs\n", elapsedMs / 1000.0f);
setWindowCaption("Quad Damage: rendered in %.2fs\n", elapsedMs / 1000.0f);
scene.beginRender();

displayVFB(vfb);
waitForUserExit();
if (scene.settings.interactive) {
mainloop();
} else {

setWindowCaption("Quad Damage: rendering...");
Uint32 startTicks = SDL_GetTicks();
renderScene_threaded();
Uint32 elapsedMs = SDL_GetTicks() - startTicks;
printf("Render took %.2fs\n", elapsedMs / 1000.0f);
setWindowCaption("Quad Damage: rendered in %.2fs\n", elapsedMs / 1000.0f);

displayVFB(vfb);
waitForUserExit();
}
closeGraphics();
printf("Exited cleanly\n");
return 0;
Expand Down
4 changes: 4 additions & 0 deletions src/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,8 @@ GlobalSettings::GlobalSettings()
wantPrepass = true;
gi = false;
numPaths = 10;
numThreads = 0;
interactive = false;
}

void GlobalSettings::fillProperties(ParsedBlock& pb)
Expand All @@ -834,6 +836,8 @@ void GlobalSettings::fillProperties(ParsedBlock& pb)
pb.getBoolProp("wantPrepass", &wantPrepass);
pb.getBoolProp("gi", &gi);
pb.getIntProp("numPaths", &numPaths, 1);
pb.getIntProp("numThreads", &numThreads, 0, 64);
pb.getBoolProp("interactive", &interactive);
}

SceneElement* DefaultSceneParser::newSceneElement(const char* className)
Expand Down
3 changes: 3 additions & 0 deletions src/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ struct GlobalSettings: public SceneElement {

bool wantPrepass; //!< Coarse resolution pre-pass required (defaults to true)
int numPaths; //!< paths per pixel in path tracing

int numThreads; //!< # of threads for rendering; 0 = autodetect. 1 = single-threaded
bool interactive; //!< interactive render

GlobalSettings();
void fillProperties(ParsedBlock& pb);
Expand Down
6 changes: 4 additions & 2 deletions src/sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ volatile bool rendering = false;
bool render_async, wantToQuit = false;

/// try to create a frame window with the given dimensions
bool initGraphics(int frameWidth, int frameHeight)
bool initGraphics(int frameWidth, int frameHeight, bool fullscreen)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Cannot initialize SDL: %s\n", SDL_GetError());
return false;
}
screen = SDL_SetVideoMode(frameWidth, frameHeight, 32, 0);
int videoModeFlags = SDL_ASYNCBLIT;
if (fullscreen) videoModeFlags |= SDL_FULLSCREEN;
screen = SDL_SetVideoMode(frameWidth, frameHeight, 32, videoModeFlags );
if (!screen) {
printf("Cannot set video mode %dx%d - %s\n", frameWidth, frameHeight, SDL_GetError());
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/sdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

extern volatile bool rendering; // used in main/worker thread synchronization

bool initGraphics(int frameWidth, int frameHeight);
bool initGraphics(int frameWidth, int frameHeight, bool fullscreen = false);
void closeGraphics(void);
void displayVFB(Color vfb[VFB_MAX_SIZE][VFB_MAX_SIZE]); //!< displays the VFB (Virtual framebuffer) to the real one.
void waitForUserExit(void); //!< Pause. Wait until the user closes the application
Expand Down

0 comments on commit 9379177

Please sign in to comment.