Some stuff
This commit is contained in:
commit
c4270d4a2e
22
LICENSE.txt
Normal file
22
LICENSE.txt
Normal file
@ -0,0 +1,22 @@
|
||||
LICENSE
|
||||
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
41
Makefile
Normal file
41
Makefile
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# smallptGPU & smallptCPU Makefile
|
||||
#
|
||||
|
||||
ATISTREAMSDKROOT=/home/david/src/ati-stream-sdk-v2.0-lnx64
|
||||
|
||||
CC=gcc
|
||||
CCFLAGS=-O3 -msse2 -mfpmath=sse -ftree-vectorize -funroll-loops -Wall \
|
||||
-I$(ATISTREAMSDKROOT)/include -L$(ATISTREAMSDKROOT)/lib/x86_64 -lglut -lOpenCL
|
||||
# Jens's patch for MacOS, comment the 2 lines above and un-comment the lines below
|
||||
#CCFLAGS=-O3 -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller \
|
||||
# -cl-fast-relaxed-math -cl-mad-enable -Wall -framework OpenCL -framework OpenGl -framework Glut
|
||||
|
||||
default: all
|
||||
|
||||
all: Makefile smallptCPU smallptGPU preprocessed_kernels
|
||||
|
||||
smallptCPU: smallptCPU.c displayfunc.c Makefile vec.h camera.h geom.h displayfunc.h simplernd.h scene.h geomfunc.h
|
||||
$(CC) $(CCFLAGS) -DSMALLPT_CPU -o smallptCPU smallptCPU.c displayfunc.c
|
||||
|
||||
smallptGPU: smallptGPU.c displayfunc.c Makefile vec.h camera.h geom.h displayfunc.h simplernd.h scene.h geomfunc.h
|
||||
$(CC) $(CCFLAGS) -DSMALLPT_GPU -o smallptGPU smallptGPU.c displayfunc.c
|
||||
|
||||
clean:
|
||||
rm -rf smallptCPU smallptGPU image.ppm SmallptGPU-v1.6 smallptgpu-v1.6.tgz preprocessed_rendering_kernel.cl
|
||||
|
||||
preprocessed_kernels:
|
||||
cpp <rendering_kernel.cl >preprocessed_rendering_kernel.cl
|
||||
cpp <rendering_kernel_dl.cl >preprocessed_rendering_kernel_dl.cl
|
||||
|
||||
tgz: clean all
|
||||
mkdir SmallptGPU-v1.6
|
||||
cp -r smallptCPU smallptGPU scenes LICENSE.txt Makefile README.txt \
|
||||
*.pl \
|
||||
*.c \
|
||||
*.h \
|
||||
*.cl \
|
||||
*.bat \
|
||||
SmallptGPU.exe glut32.dll SmallptGPU-v1.6
|
||||
tar zcvf smallptgpu-v1.6.tgz SmallptGPU-v1.6
|
||||
rm -rf SmallptGPU-v1.6
|
58
README.txt
Normal file
58
README.txt
Normal file
@ -0,0 +1,58 @@
|
||||
SmallptCPU vs. SmallptGPU
|
||||
=========================
|
||||
|
||||
SmallptGPU is a small and simple demo written in OpenCL in order to test the
|
||||
performance of this new standard. It is based on Kevin Beason's Smallpt available
|
||||
at http://www.kevinbeason.com/smallpt/
|
||||
SmallptGPU has been written using the ATI OpenCL SDK 2.0 on Linux but it
|
||||
should work on any platform/implementation.
|
||||
|
||||
glut32.dll has been downloaded from Nate Robins's http://www.xmission.com/~nate/glut.html
|
||||
|
||||
|
||||
How to compile
|
||||
==============
|
||||
|
||||
Just edit the Makefile and use an appropriate value for ATISTREAMSDKROOT.
|
||||
|
||||
|
||||
Key bindings
|
||||
============
|
||||
|
||||
'p' - save image.ppm
|
||||
ESC - exit
|
||||
Arrow keys - rotate camera left/right/up/down
|
||||
'a' and 'd' - move camera left and right
|
||||
'w' and 's' - move camera forward and backward
|
||||
'r' and 'f' - move camera up and down
|
||||
PageUp and PageDown - move camera target up and down
|
||||
' ' - refresh the window
|
||||
'+' and '-' - to select next/previous object
|
||||
'2', '3', '4', '5', '6', '8', '9' - to move selected object
|
||||
|
||||
History
|
||||
=======
|
||||
|
||||
V1.6 - Thanks to Jens and all the discussion at http://www.luxrender.net/forum/viewtopic.php?f=21&t=2947&start=240#p29397
|
||||
now SmallptGPU works fine with MacOS and NVIDIA cards. A bug in the Apple's OpenCL
|
||||
compiler has been found (http://www.khronos.org/message_boards/viewtopic.php?f=37&t=2148)
|
||||
and a workaround has been applied to SmallptGPU. Added a new kernel with
|
||||
direct lighting surface integrator (very fast indeed).
|
||||
|
||||
V1.5 - Thanks to discussion at http://forum.beyond3d.com/showthread.php?t=55913
|
||||
the perfomances on NVIDA GPUs have been improved. They are not yet where they should
|
||||
be but are lot better now.
|
||||
|
||||
V1.4 - Updated for ATI SDK 2.0, fixed a problem in object selection
|
||||
|
||||
V1.3 - Jens's patch for MacOS, added on-screen help, fixed performance
|
||||
estimation, removed movie recording, added on-screen help, added Windows binaries
|
||||
|
||||
V1.2 - Indirect diffuse path can be now disabled/enabled (available only
|
||||
on CPU version because a bug of ATI's compiler), optimized buffers
|
||||
reallocation, added keys to select/move objects
|
||||
|
||||
V1.1 - Fixed few portability problems, added support to save movie, fixed a
|
||||
problem in window resize code
|
||||
|
||||
V1.0 - First release
|
1
RUN_SCENE_CORNELL_128SIZE.bat
Normal file
1
RUN_SCENE_CORNELL_128SIZE.bat
Normal file
@ -0,0 +1 @@
|
||||
smallptGPU.exe 1 128 rendering_kernel.cl 640 480 scenes\cornell.scn
|
1
RUN_SCENE_CORNELL_32SIZE.bat
Normal file
1
RUN_SCENE_CORNELL_32SIZE.bat
Normal file
@ -0,0 +1 @@
|
||||
smallptGPU.exe 1 32 rendering_kernel.cl 640 480 scenes\cornell.scn
|
1
RUN_SCENE_CORNELL_64SIZE.bat
Normal file
1
RUN_SCENE_CORNELL_64SIZE.bat
Normal file
@ -0,0 +1 @@
|
||||
smallptGPU.exe 1 64 rendering_kernel.cl 640 480 scenes\cornell.scn
|
1
RUN_SCENE_CORNELL_64SIZE_DL.bat
Normal file
1
RUN_SCENE_CORNELL_64SIZE_DL.bat
Normal file
@ -0,0 +1 @@
|
||||
smallptGPU.exe 1 64 rendering_kernel_dl.cl 640 480 scenes\cornell.scn
|
1
RUN_SCENE_SIMPLE_64SIZE.bat
Normal file
1
RUN_SCENE_SIMPLE_64SIZE.bat
Normal file
@ -0,0 +1 @@
|
||||
smallptGPU.exe 1 64 rendering_kernel.cl 640 480 scenes\simple.scn
|
BIN
SmallptGPU.exe
Normal file
BIN
SmallptGPU.exe
Normal file
Binary file not shown.
37
camera.h
Normal file
37
camera.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CAMERA_H
|
||||
#define _CAMERA_H
|
||||
|
||||
#include "vec.h"
|
||||
|
||||
typedef struct {
|
||||
/* User defined values */
|
||||
Vec orig, target;
|
||||
/* Calculated values */
|
||||
Vec dir, x, y;
|
||||
} Camera;
|
||||
|
||||
#endif /* _CAMERA_H */
|
||||
|
431
displayfunc.c
Normal file
431
displayfunc.c
Normal file
@ -0,0 +1,431 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <sys/time.h>
|
||||
#elif defined (WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
Unsupported Platform !!!
|
||||
#endif
|
||||
|
||||
#include "camera.h"
|
||||
#include "geom.h"
|
||||
#include "displayfunc.h"
|
||||
|
||||
extern void ReInit(const int);
|
||||
extern void ReInitScene();
|
||||
extern void UpdateRendering();
|
||||
extern void UpdateCamera();
|
||||
|
||||
extern Camera camera;
|
||||
extern Sphere *spheres;
|
||||
extern unsigned int sphereCount;
|
||||
|
||||
int amiSmallptCPU;
|
||||
|
||||
int width = 640;
|
||||
int height = 480;
|
||||
unsigned int *pixels;
|
||||
char captionBuffer[256];
|
||||
|
||||
static int printHelp = 1;
|
||||
static int currentSphere;
|
||||
|
||||
double WallClockTime() {
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
|
||||
return t.tv_sec + t.tv_usec / 1000000.0;
|
||||
#elif defined (WIN32)
|
||||
return GetTickCount() / 1000.0;
|
||||
#else
|
||||
Unsupported Platform !!!
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PrintString(void *font, const char *string) {
|
||||
int len, i;
|
||||
|
||||
len = (int)strlen(string);
|
||||
for (i = 0; i < len; i++)
|
||||
glutBitmapCharacter(font, string[i]);
|
||||
}
|
||||
|
||||
static void PrintHelp() {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(0.f, 0.f, 0.5f, 0.5f);
|
||||
glRecti(40, 40, 600, 440);
|
||||
|
||||
glColor3f(1.f, 1.f, 1.f);
|
||||
glRasterPos2i(300, 420);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "Help");
|
||||
|
||||
glRasterPos2i(60, 390);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "h - toggle Help");
|
||||
glRasterPos2i(60, 360);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "arrow Keys - rotate camera left/right/up/down");
|
||||
glRasterPos2i(60, 330);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "a and d - move camera left and right");
|
||||
glRasterPos2i(60, 300);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "w and s - move camera forward and backward");
|
||||
glRasterPos2i(60, 270);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "r and f - move camera up and down");
|
||||
glRasterPos2i(60, 240);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "PageUp and PageDown - move camera target up and down");
|
||||
glRasterPos2i(60, 210);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "+ and - - to select next/previous object");
|
||||
glRasterPos2i(60, 180);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "2, 3, 4, 5, 6, 8, 9 - to move selected object");
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void ReadScene(char *fileName) {
|
||||
fprintf(stderr, "Reading scene: %s\n", fileName);
|
||||
|
||||
FILE *f = fopen(fileName, "r");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Failed to open file: %s\n", fileName);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Read the camera position */
|
||||
int c = fscanf(f,"camera %f %f %f %f %f %f\n",
|
||||
&camera.orig.x, &camera.orig.y, &camera.orig.z,
|
||||
&camera.target.x, &camera.target.y, &camera.target.z);
|
||||
if (c != 6) {
|
||||
fprintf(stderr, "Failed to read 6 camera parameters: %d\n", c);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Read the sphere count */
|
||||
c = fscanf(f,"size %u\n", &sphereCount);
|
||||
if (c != 1) {
|
||||
fprintf(stderr, "Failed to read sphere count: %d\n", c);
|
||||
exit(-1);
|
||||
}
|
||||
fprintf(stderr, "Scene size: %d\n", sphereCount);
|
||||
|
||||
/* Read all spheres */
|
||||
spheres = (Sphere *)malloc(sizeof(Sphere) * sphereCount);
|
||||
unsigned int i;
|
||||
for (i = 0; i < sphereCount; i++) {
|
||||
Sphere *s = &spheres[i];
|
||||
int mat;
|
||||
int c = fscanf(f,"sphere %f %f %f %f %f %f %f %f %f %f %d\n",
|
||||
&s->rad,
|
||||
&s->p.x, &s->p.y, &s->p.z,
|
||||
&s->e.x, &s->e.y, &s->e.z,
|
||||
&s->c.x, &s->c.y, &s->c.z,
|
||||
&mat);
|
||||
switch (mat) {
|
||||
case 0:
|
||||
s->refl = DIFF;
|
||||
break;
|
||||
case 1:
|
||||
s->refl = SPEC;
|
||||
break;
|
||||
case 2:
|
||||
s->refl = REFR;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Failed to read material type for sphere #%d: %d\n", i, mat);
|
||||
exit(-1);
|
||||
break;
|
||||
}
|
||||
if (c != 11) {
|
||||
fprintf(stderr, "Failed to read sphere #%d: %d\n", i, c);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void UpdateCamera() {
|
||||
vsub(camera.dir, camera.target, camera.orig);
|
||||
vnorm(camera.dir);
|
||||
|
||||
const Vec up = {0.f, 1.f, 0.f};
|
||||
const float fov = (M_PI / 180.f) * 45.f;
|
||||
vxcross(camera.x, camera.dir, up);
|
||||
vnorm(camera.x);
|
||||
vsmul(camera.x, width * fov / height, camera.x);
|
||||
|
||||
vxcross(camera.y, camera.x, camera.dir);
|
||||
vnorm(camera.y);
|
||||
vsmul(camera.y, fov, camera.y);
|
||||
}
|
||||
|
||||
void idleFunc(void) {
|
||||
UpdateRendering();
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
void displayFunc(void) {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glRasterPos2i(0, 0);
|
||||
glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Title
|
||||
glColor3f(1.f, 1.f, 1.f);
|
||||
glRasterPos2i(4, height - 16);
|
||||
if (amiSmallptCPU)
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "SmallptCPU v1.6 (Written by David Bucciarelli)");
|
||||
else
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, "SmallptGPU v1.6 (Written by David Bucciarelli)");
|
||||
|
||||
// Caption line 0
|
||||
glColor3f(1.f, 1.f, 1.f);
|
||||
glRasterPos2i(4, 10);
|
||||
PrintString(GLUT_BITMAP_HELVETICA_18, captionBuffer);
|
||||
|
||||
if (printHelp) {
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
|
||||
|
||||
PrintHelp();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
void reshapeFunc(int newWidth, int newHeight) {
|
||||
width = newWidth;
|
||||
height = newHeight;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.f, width - 1.f, 0.f, height - 1.f, -1.f, 1.f);
|
||||
|
||||
ReInit(1);
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
#define MOVE_STEP 10.0f
|
||||
#define ROTATE_STEP (2.f * M_PI / 180.f)
|
||||
void keyFunc(unsigned char key, int x, int y) {
|
||||
switch (key) {
|
||||
case 'p': {
|
||||
FILE *f = fopen("image.ppm", "w"); // Write image to PPM file.
|
||||
if (!f) {
|
||||
fprintf(stderr, "Failed to open image file: image.ppm\n");
|
||||
} else {
|
||||
fprintf(f, "P3\n%d %d\n%d\n", width, height, 255);
|
||||
|
||||
int x, y;
|
||||
for (y = height - 1; y >= 0; --y) {
|
||||
unsigned char *p = (unsigned char *)(&pixels[y * width]);
|
||||
for (x = 0; x < width; ++x, p += 4)
|
||||
fprintf(f, "%d %d %d ", p[0], p[1], p[2]);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 27: /* Escape key */
|
||||
fprintf(stderr, "Done.\n");
|
||||
exit(0);
|
||||
break;
|
||||
case ' ': /* Refresh display */
|
||||
ReInit(1);
|
||||
break;
|
||||
case 'a': {
|
||||
Vec dir = camera.x;
|
||||
vnorm(dir);
|
||||
vsmul(dir, -MOVE_STEP, dir);
|
||||
vadd(camera.orig, camera.orig, dir);
|
||||
vadd(camera.target, camera.target, dir);
|
||||
ReInit(0);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
Vec dir = camera.x;
|
||||
vnorm(dir);
|
||||
vsmul(dir, MOVE_STEP, dir);
|
||||
vadd(camera.orig, camera.orig, dir);
|
||||
vadd(camera.target, camera.target, dir);
|
||||
ReInit(0);
|
||||
break;
|
||||
}
|
||||
case 'w': {
|
||||
Vec dir = camera.dir;
|
||||
vsmul(dir, MOVE_STEP, dir);
|
||||
vadd(camera.orig, camera.orig, dir);
|
||||
vadd(camera.target, camera.target, dir);
|
||||
ReInit(0);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
Vec dir = camera.dir;
|
||||
vsmul(dir, -MOVE_STEP, dir);
|
||||
vadd(camera.orig, camera.orig, dir);
|
||||
vadd(camera.target, camera.target, dir);
|
||||
ReInit(0);
|
||||
break;
|
||||
}
|
||||
case 'r':
|
||||
camera.orig.y += MOVE_STEP;
|
||||
camera.target.y += MOVE_STEP;
|
||||
ReInit(0);
|
||||
break;
|
||||
case 'f':
|
||||
camera.orig.y -= MOVE_STEP;
|
||||
camera.target.y -= MOVE_STEP;
|
||||
ReInit(0);
|
||||
break;
|
||||
case '+':
|
||||
currentSphere = (currentSphere + 1) % sphereCount;
|
||||
fprintf(stderr, "Selected sphere %d (%f %f %f)\n", currentSphere,
|
||||
spheres[currentSphere].p.x, spheres[currentSphere].p.y, spheres[currentSphere].p.z);
|
||||
ReInitScene();
|
||||
break;
|
||||
case '-':
|
||||
currentSphere = (currentSphere + (sphereCount - 1)) % sphereCount;
|
||||
fprintf(stderr, "Selected sphere %d (%f %f %f)\n", currentSphere,
|
||||
spheres[currentSphere].p.x, spheres[currentSphere].p.y, spheres[currentSphere].p.z);
|
||||
ReInitScene();
|
||||
break;
|
||||
case '4':
|
||||
spheres[currentSphere].p.x -= 0.5f * MOVE_STEP;
|
||||
ReInitScene();
|
||||
break;
|
||||
case '6':
|
||||
spheres[currentSphere].p.x += 0.5f * MOVE_STEP;
|
||||
ReInitScene();
|
||||
break;
|
||||
case '8':
|
||||
spheres[currentSphere].p.z -= 0.5f * MOVE_STEP;
|
||||
ReInitScene();
|
||||
break;
|
||||
case '2':
|
||||
spheres[currentSphere].p.z += 0.5f * MOVE_STEP;
|
||||
ReInitScene();
|
||||
break;
|
||||
case '9':
|
||||
spheres[currentSphere].p.y += 0.5f * MOVE_STEP;
|
||||
ReInitScene();
|
||||
break;
|
||||
case '3':
|
||||
spheres[currentSphere].p.y -= 0.5f * MOVE_STEP;
|
||||
ReInitScene();
|
||||
break;
|
||||
case 'h':
|
||||
printHelp = (!printHelp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void specialFunc(int key, int x, int y) {
|
||||
switch (key) {
|
||||
case GLUT_KEY_UP: {
|
||||
Vec t = camera.target;
|
||||
vsub(t, t, camera.orig);
|
||||
t.y = t.y * cos(-ROTATE_STEP) + t.z * sin(-ROTATE_STEP);
|
||||
t.z = -t.y * sin(-ROTATE_STEP) + t.z * cos(-ROTATE_STEP);
|
||||
vadd(t, t, camera.orig);
|
||||
camera.target = t;
|
||||
ReInit(0);
|
||||
break;
|
||||
}
|
||||
case GLUT_KEY_DOWN: {
|
||||
Vec t = camera.target;
|
||||
vsub(t, t, camera.orig);
|
||||
t.y = t.y * cos(ROTATE_STEP) + t.z * sin(ROTATE_STEP);
|
||||
t.z = -t.y * sin(ROTATE_STEP) + t.z * cos(ROTATE_STEP);
|
||||
vadd(t, t, camera.orig);
|
||||
camera.target = t;
|
||||
ReInit(0);
|
||||
break;
|
||||
}
|
||||
case GLUT_KEY_LEFT: {
|
||||
Vec t = camera.target;
|
||||
vsub(t, t, camera.orig);
|
||||
t.x = t.x * cos(-ROTATE_STEP) - t.z * sin(-ROTATE_STEP);
|
||||
t.z = t.x * sin(-ROTATE_STEP) + t.z * cos(-ROTATE_STEP);
|
||||
vadd(t, t, camera.orig);
|
||||
camera.target = t;
|
||||
ReInit(0);
|
||||
break;
|
||||
}
|
||||
case GLUT_KEY_RIGHT: {
|
||||
Vec t = camera.target;
|
||||
vsub(t, t, camera.orig);
|
||||
t.x = t.x * cos(ROTATE_STEP) - t.z * sin(ROTATE_STEP);
|
||||
t.z = t.x * sin(ROTATE_STEP) + t.z * cos(ROTATE_STEP);
|
||||
vadd(t, t, camera.orig);
|
||||
camera.target = t;
|
||||
ReInit(0);
|
||||
break;
|
||||
}
|
||||
case GLUT_KEY_PAGE_UP:
|
||||
camera.target.y += MOVE_STEP;
|
||||
ReInit(0);
|
||||
break;
|
||||
case GLUT_KEY_PAGE_DOWN:
|
||||
camera.target.y -= MOVE_STEP;
|
||||
ReInit(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InitGlut(int argc, char *argv[], char *windowTittle) {
|
||||
glutInitWindowSize(width, height);
|
||||
glutInitWindowPosition(0,0);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||
glutInit(&argc, argv);
|
||||
|
||||
glutCreateWindow(windowTittle);
|
||||
|
||||
glutReshapeFunc(reshapeFunc);
|
||||
glutKeyboardFunc(keyFunc);
|
||||
glutSpecialFunc(specialFunc);
|
||||
glutDisplayFunc(displayFunc);
|
||||
glutIdleFunc(idleFunc);
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.f, width - 1.f, 0.f, height - 1.f, -1.f, 1.f);
|
||||
}
|
53
displayfunc.h
Normal file
53
displayfunc.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _DISPLAYFUNC_H
|
||||
#define _DISPLAYFUNC_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// Jens's patch for MacOS
|
||||
#ifdef __APPLE__
|
||||
#include <GLut/glut.h>
|
||||
#else
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include "vec.h"
|
||||
|
||||
extern int width;
|
||||
extern int height;
|
||||
extern unsigned int *pixels;
|
||||
extern unsigned int renderingFlags;
|
||||
extern char captionBuffer[256];
|
||||
|
||||
extern int amiSmallptCPU;
|
||||
|
||||
extern void InitGlut(int argc, char *argv[], char *windowTittle);
|
||||
extern double WallClockTime();
|
||||
|
||||
extern void ReadScene(char *);
|
||||
extern void UpdateCamera();
|
||||
|
||||
#endif /* _DISPLAYFUNC_H */
|
||||
|
50
geom.h
Normal file
50
geom.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _GEOM_H
|
||||
#define _GEOM_H
|
||||
|
||||
#include "vec.h"
|
||||
|
||||
#define EPSILON 0.01f
|
||||
#define FLOAT_PI 3.14159265358979323846f
|
||||
|
||||
typedef struct {
|
||||
Vec o, d;
|
||||
} Ray;
|
||||
|
||||
#define rinit(r, a, b) { vassign((r).o, a); vassign((r).d, b); }
|
||||
#define rassign(a, b) { vassign((a).o, (b).o); vassign((a).d, (b).d); }
|
||||
|
||||
enum Refl {
|
||||
DIFF, SPEC, REFR
|
||||
}; /* material types, used in radiance() */
|
||||
|
||||
typedef struct {
|
||||
float rad; /* radius */
|
||||
Vec p, e, c; /* position, emission, color */
|
||||
enum Refl refl; /* reflection type (DIFFuse, SPECular, REFRactive) */
|
||||
} Sphere;
|
||||
|
||||
#endif /* _GEOM_H */
|
||||
|
488
geomfunc.h
Normal file
488
geomfunc.h
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _GEOMFUNC_H
|
||||
#define _GEOMFUNC_H
|
||||
|
||||
#include "geom.h"
|
||||
#include "simplernd.h"
|
||||
|
||||
#ifndef SMALLPT_GPU
|
||||
|
||||
static float SphereIntersect(
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *s,
|
||||
const Ray *r) { /* returns distance, 0 if nohit */
|
||||
Vec op; /* Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0 */
|
||||
vsub(op, s->p, r->o);
|
||||
|
||||
float b = vdot(op, r->d);
|
||||
float det = b * b - vdot(op, op) + s->rad * s->rad;
|
||||
if (det < 0.f)
|
||||
return 0.f;
|
||||
else
|
||||
det = sqrt(det);
|
||||
|
||||
float t = b - det;
|
||||
if (t > EPSILON)
|
||||
return t;
|
||||
else {
|
||||
t = b + det;
|
||||
|
||||
if (t > EPSILON)
|
||||
return t;
|
||||
else
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
static void UniformSampleSphere(const float u1, const float u2, Vec *v) {
|
||||
const float zz = 1.f - 2.f * u1;
|
||||
const float r = sqrt(max(0.f, 1.f - zz * zz));
|
||||
const float phi = 2.f * FLOAT_PI * u2;
|
||||
const float xx = r * cos(phi);
|
||||
const float yy = r * sin(phi);
|
||||
|
||||
vinit(*v, xx, yy, zz);
|
||||
}
|
||||
|
||||
static int Intersect(
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *r,
|
||||
float *t,
|
||||
unsigned int *id) {
|
||||
float inf = (*t) = 1e20f;
|
||||
|
||||
unsigned int i = sphereCount;
|
||||
for (; i--;) {
|
||||
const float d = SphereIntersect(&spheres[i], r);
|
||||
if ((d != 0.f) && (d < *t)) {
|
||||
*t = d;
|
||||
*id = i;
|
||||
}
|
||||
}
|
||||
|
||||
return (*t < inf);
|
||||
}
|
||||
|
||||
static int IntersectP(
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *r,
|
||||
const float maxt) {
|
||||
unsigned int i = sphereCount;
|
||||
for (; i--;) {
|
||||
const float d = SphereIntersect(&spheres[i], r);
|
||||
if ((d != 0.f) && (d < maxt))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SampleLights(
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
const Vec *hitPoint,
|
||||
const Vec *normal,
|
||||
Vec *result) {
|
||||
vclr(*result);
|
||||
|
||||
/* For each light */
|
||||
unsigned int i;
|
||||
for (i = 0; i < sphereCount; i++) {
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *light = &spheres[i];
|
||||
if (!viszero(light->e)) {
|
||||
/* It is a light source */
|
||||
Ray shadowRay;
|
||||
shadowRay.o = *hitPoint;
|
||||
|
||||
/* Choose a point over the light source */
|
||||
Vec unitSpherePoint;
|
||||
UniformSampleSphere(GetRandom(seed0, seed1), GetRandom(seed0, seed1), &unitSpherePoint);
|
||||
Vec spherePoint;
|
||||
vsmul(spherePoint, light->rad, unitSpherePoint);
|
||||
vadd(spherePoint, spherePoint, light->p);
|
||||
|
||||
/* Build the shadow ray direction */
|
||||
vsub(shadowRay.d, spherePoint, *hitPoint);
|
||||
const float len = sqrt(vdot(shadowRay.d, shadowRay.d));
|
||||
vsmul(shadowRay.d, 1.f / len, shadowRay.d);
|
||||
|
||||
float wo = vdot(shadowRay.d, unitSpherePoint);
|
||||
if (wo > 0.f) {
|
||||
/* It is on the other half of the sphere */
|
||||
continue;
|
||||
} else
|
||||
wo = -wo;
|
||||
|
||||
/* Check if the light is visible */
|
||||
const float wi = vdot(shadowRay.d, *normal);
|
||||
if ((wi > 0.f) && (!IntersectP(spheres, sphereCount, &shadowRay, len - EPSILON))) {
|
||||
Vec c; vassign(c, light->e);
|
||||
const float s = (4.f * FLOAT_PI * light->rad * light->rad) * wi * wo / (len *len);
|
||||
vsmul(c, s, c);
|
||||
vadd(*result, *result, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RadiancePathTracing(
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *startRay,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
Vec *result) {
|
||||
Ray currentRay; rassign(currentRay, *startRay);
|
||||
Vec rad; vinit(rad, 0.f, 0.f, 0.f);
|
||||
Vec throughput; vinit(throughput, 1.f, 1.f, 1.f);
|
||||
|
||||
unsigned int depth = 0;
|
||||
int specularBounce = 1;
|
||||
for (;; ++depth) {
|
||||
// Removed Russian Roulette in order to improve execution on SIMT
|
||||
if (depth > 6) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
float t; /* distance to intersection */
|
||||
unsigned int id = 0; /* id of intersected object */
|
||||
if (!Intersect(spheres, sphereCount, ¤tRay, &t, &id)) {
|
||||
*result = rad; /* if miss, return */
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *obj = &spheres[id]; /* the hit object */
|
||||
|
||||
Vec hitPoint;
|
||||
vsmul(hitPoint, t, currentRay.d);
|
||||
vadd(hitPoint, currentRay.o, hitPoint);
|
||||
|
||||
Vec normal;
|
||||
vsub(normal, hitPoint, obj->p);
|
||||
vnorm(normal);
|
||||
|
||||
const float dp = vdot(normal, currentRay.d);
|
||||
|
||||
Vec nl;
|
||||
// SIMT optimization
|
||||
const float invSignDP = -1.f * sign(dp);
|
||||
vsmul(nl, invSignDP, normal);
|
||||
|
||||
/* Add emitted light */
|
||||
Vec eCol; vassign(eCol, obj->e);
|
||||
if (!viszero(eCol)) {
|
||||
if (specularBounce) {
|
||||
vsmul(eCol, fabs(dp), eCol);
|
||||
vmul(eCol, throughput, eCol);
|
||||
vadd(rad, rad, eCol);
|
||||
}
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->refl == DIFF) { /* Ideal DIFFUSE reflection */
|
||||
specularBounce = 0;
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
/* Direct lighting component */
|
||||
|
||||
Vec Ld;
|
||||
SampleLights(spheres, sphereCount, seed0, seed1, &hitPoint, &nl, &Ld);
|
||||
vmul(Ld, throughput, Ld);
|
||||
vadd(rad, rad, Ld);
|
||||
|
||||
/* Diffuse component */
|
||||
|
||||
float r1 = 2.f * FLOAT_PI * GetRandom(seed0, seed1);
|
||||
float r2 = GetRandom(seed0, seed1);
|
||||
float r2s = sqrt(r2);
|
||||
|
||||
Vec w; vassign(w, nl);
|
||||
|
||||
Vec u, a;
|
||||
if (fabs(w.x) > .1f) {
|
||||
vinit(a, 0.f, 1.f, 0.f);
|
||||
} else {
|
||||
vinit(a, 1.f, 0.f, 0.f);
|
||||
}
|
||||
vxcross(u, a, w);
|
||||
vnorm(u);
|
||||
|
||||
Vec v;
|
||||
vxcross(v, w, u);
|
||||
|
||||
Vec newDir;
|
||||
vsmul(u, cos(r1) * r2s, u);
|
||||
vsmul(v, sin(r1) * r2s, v);
|
||||
vadd(newDir, u, v);
|
||||
vsmul(w, sqrt(1 - r2), w);
|
||||
vadd(newDir, newDir, w);
|
||||
|
||||
currentRay.o = hitPoint;
|
||||
currentRay.d = newDir;
|
||||
continue;
|
||||
} else if (obj->refl == SPEC) { /* Ideal SPECULAR reflection */
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
vsmul(newDir, 2.f * vdot(normal, currentRay.d), normal);
|
||||
vsub(newDir, currentRay.d, newDir);
|
||||
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
rinit(currentRay, hitPoint, newDir);
|
||||
continue;
|
||||
} else {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
vsmul(newDir, 2.f * vdot(normal, currentRay.d), normal);
|
||||
vsub(newDir, currentRay.d, newDir);
|
||||
|
||||
Ray reflRay; rinit(reflRay, hitPoint, newDir); /* Ideal dielectric REFRACTION */
|
||||
int into = (vdot(normal, nl) > 0); /* Ray from outside going in? */
|
||||
|
||||
float nc = 1.f;
|
||||
float nt = 1.5f;
|
||||
float nnt = into ? nc / nt : nt / nc;
|
||||
float ddn = vdot(currentRay.d, nl);
|
||||
float cos2t = 1.f - nnt * nnt * (1.f - ddn * ddn);
|
||||
|
||||
if (cos2t < 0.f) { /* Total internal reflection */
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
rassign(currentRay, reflRay);
|
||||
continue;
|
||||
}
|
||||
|
||||
float kk = (into ? 1 : -1) * (ddn * nnt + sqrt(cos2t));
|
||||
Vec nkk;
|
||||
vsmul(nkk, kk, normal);
|
||||
Vec transDir;
|
||||
vsmul(transDir, nnt, currentRay.d);
|
||||
vsub(transDir, transDir, nkk);
|
||||
vnorm(transDir);
|
||||
|
||||
float a = nt - nc;
|
||||
float b = nt + nc;
|
||||
float R0 = a * a / (b * b);
|
||||
float c = 1 - (into ? -ddn : vdot(transDir, normal));
|
||||
|
||||
float Re = R0 + (1 - R0) * c * c * c * c*c;
|
||||
float Tr = 1.f - Re;
|
||||
float P = .25f + .5f * Re;
|
||||
float RP = Re / P;
|
||||
float TP = Tr / (1.f - P);
|
||||
|
||||
if (GetRandom(seed0, seed1) < P) { /* R.R. */
|
||||
vsmul(throughput, RP, throughput);
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
rassign(currentRay, reflRay);
|
||||
continue;
|
||||
} else {
|
||||
vsmul(throughput, TP, throughput);
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
rinit(currentRay, hitPoint, transDir);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RadianceDirectLighting(
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *startRay,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
Vec *result) {
|
||||
Ray currentRay; rassign(currentRay, *startRay);
|
||||
Vec rad; vinit(rad, 0.f, 0.f, 0.f);
|
||||
Vec throughput; vinit(throughput, 1.f, 1.f, 1.f);
|
||||
|
||||
unsigned int depth = 0;
|
||||
int specularBounce = 1;
|
||||
for (;; ++depth) {
|
||||
// Removed Russian Roulette in order to improve execution on SIMT
|
||||
if (depth > 6) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
float t; /* distance to intersection */
|
||||
unsigned int id = 0; /* id of intersected object */
|
||||
if (!Intersect(spheres, sphereCount, ¤tRay, &t, &id)) {
|
||||
*result = rad; /* if miss, return */
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef GPU_KERNEL
|
||||
OCL_CONSTANT_BUFFER
|
||||
#endif
|
||||
const Sphere *obj = &spheres[id]; /* the hit object */
|
||||
|
||||
Vec hitPoint;
|
||||
vsmul(hitPoint, t, currentRay.d);
|
||||
vadd(hitPoint, currentRay.o, hitPoint);
|
||||
|
||||
Vec normal;
|
||||
vsub(normal, hitPoint, obj->p);
|
||||
vnorm(normal);
|
||||
|
||||
const float dp = vdot(normal, currentRay.d);
|
||||
|
||||
Vec nl;
|
||||
// SIMT optimization
|
||||
const float invSignDP = -1.f * sign(dp);
|
||||
vsmul(nl, invSignDP, normal);
|
||||
|
||||
/* Add emitted light */
|
||||
Vec eCol; vassign(eCol, obj->e);
|
||||
if (!viszero(eCol)) {
|
||||
if (specularBounce) {
|
||||
vsmul(eCol, fabs(dp), eCol);
|
||||
vmul(eCol, throughput, eCol);
|
||||
vadd(rad, rad, eCol);
|
||||
}
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->refl == DIFF) { /* Ideal DIFFUSE reflection */
|
||||
specularBounce = 0;
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
/* Direct lighting component */
|
||||
|
||||
Vec Ld;
|
||||
SampleLights(spheres, sphereCount, seed0, seed1, &hitPoint, &nl, &Ld);
|
||||
vmul(Ld, throughput, Ld);
|
||||
vadd(rad, rad, Ld);
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
} else if (obj->refl == SPEC) { /* Ideal SPECULAR reflection */
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
vsmul(newDir, 2.f * vdot(normal, currentRay.d), normal);
|
||||
vsub(newDir, currentRay.d, newDir);
|
||||
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
rinit(currentRay, hitPoint, newDir);
|
||||
continue;
|
||||
} else {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
vsmul(newDir, 2.f * vdot(normal, currentRay.d), normal);
|
||||
vsub(newDir, currentRay.d, newDir);
|
||||
|
||||
Ray reflRay; rinit(reflRay, hitPoint, newDir); /* Ideal dielectric REFRACTION */
|
||||
int into = (vdot(normal, nl) > 0); /* Ray from outside going in? */
|
||||
|
||||
float nc = 1.f;
|
||||
float nt = 1.5f;
|
||||
float nnt = into ? nc / nt : nt / nc;
|
||||
float ddn = vdot(currentRay.d, nl);
|
||||
float cos2t = 1.f - nnt * nnt * (1.f - ddn * ddn);
|
||||
|
||||
if (cos2t < 0.f) { /* Total internal reflection */
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
rassign(currentRay, reflRay);
|
||||
continue;
|
||||
}
|
||||
|
||||
float kk = (into ? 1 : -1) * (ddn * nnt + sqrt(cos2t));
|
||||
Vec nkk;
|
||||
vsmul(nkk, kk, normal);
|
||||
Vec transDir;
|
||||
vsmul(transDir, nnt, currentRay.d);
|
||||
vsub(transDir, transDir, nkk);
|
||||
vnorm(transDir);
|
||||
|
||||
float a = nt - nc;
|
||||
float b = nt + nc;
|
||||
float R0 = a * a / (b * b);
|
||||
float c = 1 - (into ? -ddn : vdot(transDir, normal));
|
||||
|
||||
float Re = R0 + (1 - R0) * c * c * c * c*c;
|
||||
float Tr = 1.f - Re;
|
||||
float P = .25f + .5f * Re;
|
||||
float RP = Re / P;
|
||||
float TP = Tr / (1.f - P);
|
||||
|
||||
if (GetRandom(seed0, seed1) < P) { /* R.R. */
|
||||
vsmul(throughput, RP, throughput);
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
rassign(currentRay, reflRay);
|
||||
continue;
|
||||
} else {
|
||||
vsmul(throughput, TP, throughput);
|
||||
vmul(throughput, throughput, obj->c);
|
||||
|
||||
rinit(currentRay, hitPoint, transDir);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _GEOMFUNC_H */
|
||||
|
BIN
glut32.dll
Normal file
BIN
glut32.dll
Normal file
Binary file not shown.
586
preprocessed_rendering_kernel.cl
Normal file
586
preprocessed_rendering_kernel.cl
Normal file
@ -0,0 +1,586 @@
|
||||
# 1 "<stdin>"
|
||||
# 1 "<built-in>"
|
||||
# 1 "<command-line>"
|
||||
# 1 "<stdin>"
|
||||
# 26 "<stdin>"
|
||||
# 1 "camera.h" 1
|
||||
# 27 "camera.h"
|
||||
# 1 "vec.h" 1
|
||||
# 27 "vec.h"
|
||||
typedef struct {
|
||||
float x, y, z;
|
||||
} Vec;
|
||||
# 28 "camera.h" 2
|
||||
|
||||
typedef struct {
|
||||
|
||||
Vec orig, target;
|
||||
|
||||
Vec dir, x, y;
|
||||
} Camera;
|
||||
# 27 "<stdin>" 2
|
||||
# 1 "geomfunc.h" 1
|
||||
# 27 "geomfunc.h"
|
||||
# 1 "geom.h" 1
|
||||
# 32 "geom.h"
|
||||
typedef struct {
|
||||
Vec o, d;
|
||||
} Ray;
|
||||
|
||||
|
||||
|
||||
|
||||
enum Refl {
|
||||
DIFF, SPEC, REFR
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
float rad;
|
||||
Vec p, e, c;
|
||||
enum Refl refl;
|
||||
} Sphere;
|
||||
# 28 "geomfunc.h" 2
|
||||
# 1 "simplernd.h" 1
|
||||
# 34 "simplernd.h"
|
||||
static float GetRandom(unsigned int *seed0, unsigned int *seed1) {
|
||||
*seed0 = 36969 * ((*seed0) & 65535) + ((*seed0) >> 16);
|
||||
*seed1 = 18000 * ((*seed1) & 65535) + ((*seed1) >> 16);
|
||||
|
||||
unsigned int ires = ((*seed0) << 16) + (*seed1);
|
||||
|
||||
|
||||
union {
|
||||
float f;
|
||||
unsigned int ui;
|
||||
} res;
|
||||
res.ui = (ires & 0x007fffff) | 0x40000000;
|
||||
|
||||
return (res.f - 2.f) / 2.f;
|
||||
}
|
||||
# 29 "geomfunc.h" 2
|
||||
|
||||
|
||||
|
||||
static float SphereIntersect(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *s,
|
||||
const Ray *r) {
|
||||
Vec op;
|
||||
{ (op).x = (s->p).x - (r->o).x; (op).y = (s->p).y - (r->o).y; (op).z = (s->p).z - (r->o).z; };
|
||||
|
||||
float b = ((op).x * (r->d).x + (op).y * (r->d).y + (op).z * (r->d).z);
|
||||
float det = b * b - ((op).x * (op).x + (op).y * (op).y + (op).z * (op).z) + s->rad * s->rad;
|
||||
if (det < 0.f)
|
||||
return 0.f;
|
||||
else
|
||||
det = sqrt(det);
|
||||
|
||||
float t = b - det;
|
||||
if (t > 0.01f)
|
||||
return t;
|
||||
else {
|
||||
t = b + det;
|
||||
|
||||
if (t > 0.01f)
|
||||
return t;
|
||||
else
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
static void UniformSampleSphere(const float u1, const float u2, Vec *v) {
|
||||
const float zz = 1.f - 2.f * u1;
|
||||
const float r = sqrt(max(0.f, 1.f - zz * zz));
|
||||
const float phi = 2.f * 3.14159265358979323846f * u2;
|
||||
const float xx = r * cos(phi);
|
||||
const float yy = r * sin(phi);
|
||||
|
||||
{ (*v).x = xx; (*v).y = yy; (*v).z = zz; };
|
||||
}
|
||||
|
||||
static int Intersect(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *r,
|
||||
float *t,
|
||||
unsigned int *id) {
|
||||
float inf = (*t) = 1e20f;
|
||||
|
||||
unsigned int i = sphereCount;
|
||||
for (; i--;) {
|
||||
const float d = SphereIntersect(&spheres[i], r);
|
||||
if ((d != 0.f) && (d < *t)) {
|
||||
*t = d;
|
||||
*id = i;
|
||||
}
|
||||
}
|
||||
|
||||
return (*t < inf);
|
||||
}
|
||||
|
||||
static int IntersectP(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *r,
|
||||
const float maxt) {
|
||||
unsigned int i = sphereCount;
|
||||
for (; i--;) {
|
||||
const float d = SphereIntersect(&spheres[i], r);
|
||||
if ((d != 0.f) && (d < maxt))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SampleLights(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
const Vec *hitPoint,
|
||||
const Vec *normal,
|
||||
Vec *result) {
|
||||
{ (*result).x = 0.f; (*result).y = 0.f; (*result).z = 0.f; };
|
||||
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sphereCount; i++) {
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *light = &spheres[i];
|
||||
if (!(((light->e).x == 0.f) && ((light->e).x == 0.f) && ((light->e).z == 0.f))) {
|
||||
|
||||
Ray shadowRay;
|
||||
shadowRay.o = *hitPoint;
|
||||
|
||||
|
||||
Vec unitSpherePoint;
|
||||
UniformSampleSphere(GetRandom(seed0, seed1), GetRandom(seed0, seed1), &unitSpherePoint);
|
||||
Vec spherePoint;
|
||||
{ float k = (light->rad); { (spherePoint).x = k * (unitSpherePoint).x; (spherePoint).y = k * (unitSpherePoint).y; (spherePoint).z = k * (unitSpherePoint).z; } };
|
||||
{ (spherePoint).x = (spherePoint).x + (light->p).x; (spherePoint).y = (spherePoint).y + (light->p).y; (spherePoint).z = (spherePoint).z + (light->p).z; };
|
||||
|
||||
|
||||
{ (shadowRay.d).x = (spherePoint).x - (*hitPoint).x; (shadowRay.d).y = (spherePoint).y - (*hitPoint).y; (shadowRay.d).z = (spherePoint).z - (*hitPoint).z; };
|
||||
const float len = sqrt(((shadowRay.d).x * (shadowRay.d).x + (shadowRay.d).y * (shadowRay.d).y + (shadowRay.d).z * (shadowRay.d).z));
|
||||
{ float k = (1.f / len); { (shadowRay.d).x = k * (shadowRay.d).x; (shadowRay.d).y = k * (shadowRay.d).y; (shadowRay.d).z = k * (shadowRay.d).z; } };
|
||||
|
||||
float wo = ((shadowRay.d).x * (unitSpherePoint).x + (shadowRay.d).y * (unitSpherePoint).y + (shadowRay.d).z * (unitSpherePoint).z);
|
||||
if (wo > 0.f) {
|
||||
|
||||
continue;
|
||||
} else
|
||||
wo = -wo;
|
||||
|
||||
|
||||
const float wi = ((shadowRay.d).x * (*normal).x + (shadowRay.d).y * (*normal).y + (shadowRay.d).z * (*normal).z);
|
||||
if ((wi > 0.f) && (!IntersectP(spheres, sphereCount, &shadowRay, len - 0.01f))) {
|
||||
Vec c; { (c).x = (light->e).x; (c).y = (light->e).y; (c).z = (light->e).z; };
|
||||
const float s = (4.f * 3.14159265358979323846f * light->rad * light->rad) * wi * wo / (len *len);
|
||||
{ float k = (s); { (c).x = k * (c).x; (c).y = k * (c).y; (c).z = k * (c).z; } };
|
||||
{ (*result).x = (*result).x + (c).x; (*result).y = (*result).y + (c).y; (*result).z = (*result).z + (c).z; };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RadiancePathTracing(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *startRay,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
Vec *result) {
|
||||
Ray currentRay; { { ((currentRay).o).x = ((*startRay).o).x; ((currentRay).o).y = ((*startRay).o).y; ((currentRay).o).z = ((*startRay).o).z; }; { ((currentRay).d).x = ((*startRay).d).x; ((currentRay).d).y = ((*startRay).d).y; ((currentRay).d).z = ((*startRay).d).z; }; };
|
||||
Vec rad; { (rad).x = 0.f; (rad).y = 0.f; (rad).z = 0.f; };
|
||||
Vec throughput; { (throughput).x = 1.f; (throughput).y = 1.f; (throughput).z = 1.f; };
|
||||
|
||||
unsigned int depth = 0;
|
||||
int specularBounce = 1;
|
||||
for (;; ++depth) {
|
||||
|
||||
if (depth > 6) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
float t;
|
||||
unsigned int id = 0;
|
||||
if (!Intersect(spheres, sphereCount, ¤tRay, &t, &id)) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *obj = &spheres[id];
|
||||
|
||||
Vec hitPoint;
|
||||
{ float k = (t); { (hitPoint).x = k * (currentRay.d).x; (hitPoint).y = k * (currentRay.d).y; (hitPoint).z = k * (currentRay.d).z; } };
|
||||
{ (hitPoint).x = (currentRay.o).x + (hitPoint).x; (hitPoint).y = (currentRay.o).y + (hitPoint).y; (hitPoint).z = (currentRay.o).z + (hitPoint).z; };
|
||||
|
||||
Vec normal;
|
||||
{ (normal).x = (hitPoint).x - (obj->p).x; (normal).y = (hitPoint).y - (obj->p).y; (normal).z = (hitPoint).z - (obj->p).z; };
|
||||
{ float l = 1.f / sqrt(((normal).x * (normal).x + (normal).y * (normal).y + (normal).z * (normal).z)); { float k = (l); { (normal).x = k * (normal).x; (normal).y = k * (normal).y; (normal).z = k * (normal).z; } }; };
|
||||
|
||||
const float dp = ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z);
|
||||
|
||||
Vec nl;
|
||||
|
||||
const float invSignDP = -1.f * sign(dp);
|
||||
{ float k = (invSignDP); { (nl).x = k * (normal).x; (nl).y = k * (normal).y; (nl).z = k * (normal).z; } };
|
||||
|
||||
|
||||
Vec eCol; { (eCol).x = (obj->e).x; (eCol).y = (obj->e).y; (eCol).z = (obj->e).z; };
|
||||
if (!(((eCol).x == 0.f) && ((eCol).x == 0.f) && ((eCol).z == 0.f))) {
|
||||
if (specularBounce) {
|
||||
{ float k = (fabs(dp)); { (eCol).x = k * (eCol).x; (eCol).y = k * (eCol).y; (eCol).z = k * (eCol).z; } };
|
||||
{ (eCol).x = (throughput).x * (eCol).x; (eCol).y = (throughput).y * (eCol).y; (eCol).z = (throughput).z * (eCol).z; };
|
||||
{ (rad).x = (rad).x + (eCol).x; (rad).y = (rad).y + (eCol).y; (rad).z = (rad).z + (eCol).z; };
|
||||
}
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->refl == DIFF) {
|
||||
specularBounce = 0;
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
|
||||
|
||||
Vec Ld;
|
||||
SampleLights(spheres, sphereCount, seed0, seed1, &hitPoint, &nl, &Ld);
|
||||
{ (Ld).x = (throughput).x * (Ld).x; (Ld).y = (throughput).y * (Ld).y; (Ld).z = (throughput).z * (Ld).z; };
|
||||
{ (rad).x = (rad).x + (Ld).x; (rad).y = (rad).y + (Ld).y; (rad).z = (rad).z + (Ld).z; };
|
||||
|
||||
|
||||
|
||||
float r1 = 2.f * 3.14159265358979323846f * GetRandom(seed0, seed1);
|
||||
float r2 = GetRandom(seed0, seed1);
|
||||
float r2s = sqrt(r2);
|
||||
|
||||
Vec w; { (w).x = (nl).x; (w).y = (nl).y; (w).z = (nl).z; };
|
||||
|
||||
Vec u, a;
|
||||
if (fabs(w.x) > .1f) {
|
||||
{ (a).x = 0.f; (a).y = 1.f; (a).z = 0.f; };
|
||||
} else {
|
||||
{ (a).x = 1.f; (a).y = 0.f; (a).z = 0.f; };
|
||||
}
|
||||
{ (u).x = (a).y * (w).z - (a).z * (w).y; (u).y = (a).z * (w).x - (a).x * (w).z; (u).z = (a).x * (w).y - (a).y * (w).x; };
|
||||
{ float l = 1.f / sqrt(((u).x * (u).x + (u).y * (u).y + (u).z * (u).z)); { float k = (l); { (u).x = k * (u).x; (u).y = k * (u).y; (u).z = k * (u).z; } }; };
|
||||
|
||||
Vec v;
|
||||
{ (v).x = (w).y * (u).z - (w).z * (u).y; (v).y = (w).z * (u).x - (w).x * (u).z; (v).z = (w).x * (u).y - (w).y * (u).x; };
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (cos(r1) * r2s); { (u).x = k * (u).x; (u).y = k * (u).y; (u).z = k * (u).z; } };
|
||||
{ float k = (sin(r1) * r2s); { (v).x = k * (v).x; (v).y = k * (v).y; (v).z = k * (v).z; } };
|
||||
{ (newDir).x = (u).x + (v).x; (newDir).y = (u).y + (v).y; (newDir).z = (u).z + (v).z; };
|
||||
{ float k = (sqrt(1 - r2)); { (w).x = k * (w).x; (w).y = k * (w).y; (w).z = k * (w).z; } };
|
||||
{ (newDir).x = (newDir).x + (w).x; (newDir).y = (newDir).y + (w).y; (newDir).z = (newDir).z + (w).z; };
|
||||
|
||||
currentRay.o = hitPoint;
|
||||
currentRay.d = newDir;
|
||||
continue;
|
||||
} else if (obj->refl == SPEC) {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (2.f * ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z)); { (newDir).x = k * (normal).x; (newDir).y = k * (normal).y; (newDir).z = k * (normal).z; } };
|
||||
{ (newDir).x = (currentRay.d).x - (newDir).x; (newDir).y = (currentRay.d).y - (newDir).y; (newDir).z = (currentRay.d).z - (newDir).z; };
|
||||
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = (hitPoint).x; ((currentRay).o).y = (hitPoint).y; ((currentRay).o).z = (hitPoint).z; }; { ((currentRay).d).x = (newDir).x; ((currentRay).d).y = (newDir).y; ((currentRay).d).z = (newDir).z; }; };
|
||||
continue;
|
||||
} else {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (2.f * ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z)); { (newDir).x = k * (normal).x; (newDir).y = k * (normal).y; (newDir).z = k * (normal).z; } };
|
||||
{ (newDir).x = (currentRay.d).x - (newDir).x; (newDir).y = (currentRay.d).y - (newDir).y; (newDir).z = (currentRay.d).z - (newDir).z; };
|
||||
|
||||
Ray reflRay; { { ((reflRay).o).x = (hitPoint).x; ((reflRay).o).y = (hitPoint).y; ((reflRay).o).z = (hitPoint).z; }; { ((reflRay).d).x = (newDir).x; ((reflRay).d).y = (newDir).y; ((reflRay).d).z = (newDir).z; }; };
|
||||
int into = (((normal).x * (nl).x + (normal).y * (nl).y + (normal).z * (nl).z) > 0);
|
||||
|
||||
float nc = 1.f;
|
||||
float nt = 1.5f;
|
||||
float nnt = into ? nc / nt : nt / nc;
|
||||
float ddn = ((currentRay.d).x * (nl).x + (currentRay.d).y * (nl).y + (currentRay.d).z * (nl).z);
|
||||
float cos2t = 1.f - nnt * nnt * (1.f - ddn * ddn);
|
||||
|
||||
if (cos2t < 0.f) {
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = ((reflRay).o).x; ((currentRay).o).y = ((reflRay).o).y; ((currentRay).o).z = ((reflRay).o).z; }; { ((currentRay).d).x = ((reflRay).d).x; ((currentRay).d).y = ((reflRay).d).y; ((currentRay).d).z = ((reflRay).d).z; }; };
|
||||
continue;
|
||||
}
|
||||
|
||||
float kk = (into ? 1 : -1) * (ddn * nnt + sqrt(cos2t));
|
||||
Vec nkk;
|
||||
{ float k = (kk); { (nkk).x = k * (normal).x; (nkk).y = k * (normal).y; (nkk).z = k * (normal).z; } };
|
||||
Vec transDir;
|
||||
{ float k = (nnt); { (transDir).x = k * (currentRay.d).x; (transDir).y = k * (currentRay.d).y; (transDir).z = k * (currentRay.d).z; } };
|
||||
{ (transDir).x = (transDir).x - (nkk).x; (transDir).y = (transDir).y - (nkk).y; (transDir).z = (transDir).z - (nkk).z; };
|
||||
{ float l = 1.f / sqrt(((transDir).x * (transDir).x + (transDir).y * (transDir).y + (transDir).z * (transDir).z)); { float k = (l); { (transDir).x = k * (transDir).x; (transDir).y = k * (transDir).y; (transDir).z = k * (transDir).z; } }; };
|
||||
|
||||
float a = nt - nc;
|
||||
float b = nt + nc;
|
||||
float R0 = a * a / (b * b);
|
||||
float c = 1 - (into ? -ddn : ((transDir).x * (normal).x + (transDir).y * (normal).y + (transDir).z * (normal).z));
|
||||
|
||||
float Re = R0 + (1 - R0) * c * c * c * c*c;
|
||||
float Tr = 1.f - Re;
|
||||
float P = .25f + .5f * Re;
|
||||
float RP = Re / P;
|
||||
float TP = Tr / (1.f - P);
|
||||
|
||||
if (GetRandom(seed0, seed1) < P) {
|
||||
{ float k = (RP); { (throughput).x = k * (throughput).x; (throughput).y = k * (throughput).y; (throughput).z = k * (throughput).z; } };
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = ((reflRay).o).x; ((currentRay).o).y = ((reflRay).o).y; ((currentRay).o).z = ((reflRay).o).z; }; { ((currentRay).d).x = ((reflRay).d).x; ((currentRay).d).y = ((reflRay).d).y; ((currentRay).d).z = ((reflRay).d).z; }; };
|
||||
continue;
|
||||
} else {
|
||||
{ float k = (TP); { (throughput).x = k * (throughput).x; (throughput).y = k * (throughput).y; (throughput).z = k * (throughput).z; } };
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = (hitPoint).x; ((currentRay).o).y = (hitPoint).y; ((currentRay).o).z = (hitPoint).z; }; { ((currentRay).d).x = (transDir).x; ((currentRay).d).y = (transDir).y; ((currentRay).d).z = (transDir).z; }; };
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RadianceDirectLighting(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *startRay,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
Vec *result) {
|
||||
Ray currentRay; { { ((currentRay).o).x = ((*startRay).o).x; ((currentRay).o).y = ((*startRay).o).y; ((currentRay).o).z = ((*startRay).o).z; }; { ((currentRay).d).x = ((*startRay).d).x; ((currentRay).d).y = ((*startRay).d).y; ((currentRay).d).z = ((*startRay).d).z; }; };
|
||||
Vec rad; { (rad).x = 0.f; (rad).y = 0.f; (rad).z = 0.f; };
|
||||
Vec throughput; { (throughput).x = 1.f; (throughput).y = 1.f; (throughput).z = 1.f; };
|
||||
|
||||
unsigned int depth = 0;
|
||||
int specularBounce = 1;
|
||||
for (;; ++depth) {
|
||||
|
||||
if (depth > 6) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
float t;
|
||||
unsigned int id = 0;
|
||||
if (!Intersect(spheres, sphereCount, ¤tRay, &t, &id)) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *obj = &spheres[id];
|
||||
|
||||
Vec hitPoint;
|
||||
{ float k = (t); { (hitPoint).x = k * (currentRay.d).x; (hitPoint).y = k * (currentRay.d).y; (hitPoint).z = k * (currentRay.d).z; } };
|
||||
{ (hitPoint).x = (currentRay.o).x + (hitPoint).x; (hitPoint).y = (currentRay.o).y + (hitPoint).y; (hitPoint).z = (currentRay.o).z + (hitPoint).z; };
|
||||
|
||||
Vec normal;
|
||||
{ (normal).x = (hitPoint).x - (obj->p).x; (normal).y = (hitPoint).y - (obj->p).y; (normal).z = (hitPoint).z - (obj->p).z; };
|
||||
{ float l = 1.f / sqrt(((normal).x * (normal).x + (normal).y * (normal).y + (normal).z * (normal).z)); { float k = (l); { (normal).x = k * (normal).x; (normal).y = k * (normal).y; (normal).z = k * (normal).z; } }; };
|
||||
|
||||
const float dp = ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z);
|
||||
|
||||
Vec nl;
|
||||
|
||||
const float invSignDP = -1.f * sign(dp);
|
||||
{ float k = (invSignDP); { (nl).x = k * (normal).x; (nl).y = k * (normal).y; (nl).z = k * (normal).z; } };
|
||||
|
||||
|
||||
Vec eCol; { (eCol).x = (obj->e).x; (eCol).y = (obj->e).y; (eCol).z = (obj->e).z; };
|
||||
if (!(((eCol).x == 0.f) && ((eCol).x == 0.f) && ((eCol).z == 0.f))) {
|
||||
if (specularBounce) {
|
||||
{ float k = (fabs(dp)); { (eCol).x = k * (eCol).x; (eCol).y = k * (eCol).y; (eCol).z = k * (eCol).z; } };
|
||||
{ (eCol).x = (throughput).x * (eCol).x; (eCol).y = (throughput).y * (eCol).y; (eCol).z = (throughput).z * (eCol).z; };
|
||||
{ (rad).x = (rad).x + (eCol).x; (rad).y = (rad).y + (eCol).y; (rad).z = (rad).z + (eCol).z; };
|
||||
}
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->refl == DIFF) {
|
||||
specularBounce = 0;
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
|
||||
|
||||
Vec Ld;
|
||||
SampleLights(spheres, sphereCount, seed0, seed1, &hitPoint, &nl, &Ld);
|
||||
{ (Ld).x = (throughput).x * (Ld).x; (Ld).y = (throughput).y * (Ld).y; (Ld).z = (throughput).z * (Ld).z; };
|
||||
{ (rad).x = (rad).x + (Ld).x; (rad).y = (rad).y + (Ld).y; (rad).z = (rad).z + (Ld).z; };
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
} else if (obj->refl == SPEC) {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (2.f * ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z)); { (newDir).x = k * (normal).x; (newDir).y = k * (normal).y; (newDir).z = k * (normal).z; } };
|
||||
{ (newDir).x = (currentRay.d).x - (newDir).x; (newDir).y = (currentRay.d).y - (newDir).y; (newDir).z = (currentRay.d).z - (newDir).z; };
|
||||
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = (hitPoint).x; ((currentRay).o).y = (hitPoint).y; ((currentRay).o).z = (hitPoint).z; }; { ((currentRay).d).x = (newDir).x; ((currentRay).d).y = (newDir).y; ((currentRay).d).z = (newDir).z; }; };
|
||||
continue;
|
||||
} else {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (2.f * ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z)); { (newDir).x = k * (normal).x; (newDir).y = k * (normal).y; (newDir).z = k * (normal).z; } };
|
||||
{ (newDir).x = (currentRay.d).x - (newDir).x; (newDir).y = (currentRay.d).y - (newDir).y; (newDir).z = (currentRay.d).z - (newDir).z; };
|
||||
|
||||
Ray reflRay; { { ((reflRay).o).x = (hitPoint).x; ((reflRay).o).y = (hitPoint).y; ((reflRay).o).z = (hitPoint).z; }; { ((reflRay).d).x = (newDir).x; ((reflRay).d).y = (newDir).y; ((reflRay).d).z = (newDir).z; }; };
|
||||
int into = (((normal).x * (nl).x + (normal).y * (nl).y + (normal).z * (nl).z) > 0);
|
||||
|
||||
float nc = 1.f;
|
||||
float nt = 1.5f;
|
||||
float nnt = into ? nc / nt : nt / nc;
|
||||
float ddn = ((currentRay.d).x * (nl).x + (currentRay.d).y * (nl).y + (currentRay.d).z * (nl).z);
|
||||
float cos2t = 1.f - nnt * nnt * (1.f - ddn * ddn);
|
||||
|
||||
if (cos2t < 0.f) {
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = ((reflRay).o).x; ((currentRay).o).y = ((reflRay).o).y; ((currentRay).o).z = ((reflRay).o).z; }; { ((currentRay).d).x = ((reflRay).d).x; ((currentRay).d).y = ((reflRay).d).y; ((currentRay).d).z = ((reflRay).d).z; }; };
|
||||
continue;
|
||||
}
|
||||
|
||||
float kk = (into ? 1 : -1) * (ddn * nnt + sqrt(cos2t));
|
||||
Vec nkk;
|
||||
{ float k = (kk); { (nkk).x = k * (normal).x; (nkk).y = k * (normal).y; (nkk).z = k * (normal).z; } };
|
||||
Vec transDir;
|
||||
{ float k = (nnt); { (transDir).x = k * (currentRay.d).x; (transDir).y = k * (currentRay.d).y; (transDir).z = k * (currentRay.d).z; } };
|
||||
{ (transDir).x = (transDir).x - (nkk).x; (transDir).y = (transDir).y - (nkk).y; (transDir).z = (transDir).z - (nkk).z; };
|
||||
{ float l = 1.f / sqrt(((transDir).x * (transDir).x + (transDir).y * (transDir).y + (transDir).z * (transDir).z)); { float k = (l); { (transDir).x = k * (transDir).x; (transDir).y = k * (transDir).y; (transDir).z = k * (transDir).z; } }; };
|
||||
|
||||
float a = nt - nc;
|
||||
float b = nt + nc;
|
||||
float R0 = a * a / (b * b);
|
||||
float c = 1 - (into ? -ddn : ((transDir).x * (normal).x + (transDir).y * (normal).y + (transDir).z * (normal).z));
|
||||
|
||||
float Re = R0 + (1 - R0) * c * c * c * c*c;
|
||||
float Tr = 1.f - Re;
|
||||
float P = .25f + .5f * Re;
|
||||
float RP = Re / P;
|
||||
float TP = Tr / (1.f - P);
|
||||
|
||||
if (GetRandom(seed0, seed1) < P) {
|
||||
{ float k = (RP); { (throughput).x = k * (throughput).x; (throughput).y = k * (throughput).y; (throughput).z = k * (throughput).z; } };
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = ((reflRay).o).x; ((currentRay).o).y = ((reflRay).o).y; ((currentRay).o).z = ((reflRay).o).z; }; { ((currentRay).d).x = ((reflRay).d).x; ((currentRay).d).y = ((reflRay).d).y; ((currentRay).d).z = ((reflRay).d).z; }; };
|
||||
continue;
|
||||
} else {
|
||||
{ float k = (TP); { (throughput).x = k * (throughput).x; (throughput).y = k * (throughput).y; (throughput).z = k * (throughput).z; } };
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = (hitPoint).x; ((currentRay).o).y = (hitPoint).y; ((currentRay).o).z = (hitPoint).z; }; { ((currentRay).d).x = (transDir).x; ((currentRay).d).y = (transDir).y; ((currentRay).d).z = (transDir).z; }; };
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# 28 "<stdin>" 2
|
||||
|
||||
static void GenerateCameraRay(__constant Camera *camera,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
const int width, const int height, const int x, const int y, Ray *ray) {
|
||||
const float invWidth = 1.f / width;
|
||||
const float invHeight = 1.f / height;
|
||||
const float r1 = GetRandom(seed0, seed1) - .5f;
|
||||
const float r2 = GetRandom(seed0, seed1) - .5f;
|
||||
const float kcx = (x + r1) * invWidth - .5f;
|
||||
const float kcy = (y + r2) * invHeight - .5f;
|
||||
|
||||
Vec rdir;
|
||||
{ (rdir).x = camera->x.x * kcx + camera->y.x * kcy + camera->dir.x; (rdir).y = camera->x.y * kcx + camera->y.y * kcy + camera->dir.y; (rdir).z = camera->x.z * kcx + camera->y.z * kcy + camera->dir.z; };
|
||||
|
||||
|
||||
|
||||
|
||||
Vec rorig;
|
||||
{ float k = (0.1f); { (rorig).x = k * (rdir).x; (rorig).y = k * (rdir).y; (rorig).z = k * (rdir).z; } };
|
||||
{ (rorig).x = (rorig).x + (camera->orig).x; (rorig).y = (rorig).y + (camera->orig).y; (rorig).z = (rorig).z + (camera->orig).z; }
|
||||
|
||||
{ float l = 1.f / sqrt(((rdir).x * (rdir).x + (rdir).y * (rdir).y + (rdir).z * (rdir).z)); { float k = (l); { (rdir).x = k * (rdir).x; (rdir).y = k * (rdir).y; (rdir).z = k * (rdir).z; } }; };
|
||||
{ { ((*ray).o).x = (rorig).x; ((*ray).o).y = (rorig).y; ((*ray).o).z = (rorig).z; }; { ((*ray).d).x = (rdir).x; ((*ray).d).y = (rdir).y; ((*ray).d).z = (rdir).z; }; };
|
||||
}
|
||||
|
||||
__kernel void RadianceGPU(
|
||||
__global Vec *colors, __global unsigned int *seedsInput,
|
||||
__constant Sphere *sphere, __constant Camera *camera,
|
||||
const unsigned int sphereCount,
|
||||
const int width, const int height,
|
||||
const int currentSample,
|
||||
__global int *pixels) {
|
||||
const int gid = get_global_id(0);
|
||||
const int gid2 = 2 * gid;
|
||||
const int x = gid % width;
|
||||
const int y = gid / width;
|
||||
|
||||
|
||||
if (y >= height)
|
||||
return;
|
||||
|
||||
|
||||
unsigned int seed0 = seedsInput[gid2];
|
||||
unsigned int seed1 = seedsInput[gid2 + 1];
|
||||
|
||||
Ray ray;
|
||||
GenerateCameraRay(camera, &seed0, &seed1, width, height, x, y, &ray);
|
||||
|
||||
Vec r;
|
||||
RadiancePathTracing(sphere, sphereCount, &ray, &seed0, &seed1, &r);
|
||||
|
||||
const int i = (height - y - 1) * width + x;
|
||||
if (currentSample == 0) {
|
||||
|
||||
{ (colors[i]).x = (r).x; (colors[i]).y = (r).y; (colors[i]).z = (r).z; };
|
||||
} else {
|
||||
const float k1 = currentSample;
|
||||
const float k2 = 1.f / (currentSample + 1.f);
|
||||
colors[i].x = (colors[i].x * k1 + r.x) * k2;
|
||||
colors[i].y = (colors[i].y * k1 + r.y) * k2;
|
||||
colors[i].z = (colors[i].z * k1 + r.z) * k2;
|
||||
}
|
||||
|
||||
pixels[y * width + x] = ((int)(pow(clamp(colors[i].x, 0.f, 1.f), 1.f / 2.2f) * 255.f + .5f)) |
|
||||
(((int)(pow(clamp(colors[i].y, 0.f, 1.f), 1.f / 2.2f) * 255.f + .5f)) << 8) |
|
||||
(((int)(pow(clamp(colors[i].z, 0.f, 1.f), 1.f / 2.2f) * 255.f + .5f)) << 16);
|
||||
|
||||
seedsInput[gid2] = seed0;
|
||||
seedsInput[gid2 + 1] = seed1;
|
||||
}
|
586
preprocessed_rendering_kernel_dl.cl
Normal file
586
preprocessed_rendering_kernel_dl.cl
Normal file
@ -0,0 +1,586 @@
|
||||
# 1 "<stdin>"
|
||||
# 1 "<built-in>"
|
||||
# 1 "<command-line>"
|
||||
# 1 "<stdin>"
|
||||
# 26 "<stdin>"
|
||||
# 1 "camera.h" 1
|
||||
# 27 "camera.h"
|
||||
# 1 "vec.h" 1
|
||||
# 27 "vec.h"
|
||||
typedef struct {
|
||||
float x, y, z;
|
||||
} Vec;
|
||||
# 28 "camera.h" 2
|
||||
|
||||
typedef struct {
|
||||
|
||||
Vec orig, target;
|
||||
|
||||
Vec dir, x, y;
|
||||
} Camera;
|
||||
# 27 "<stdin>" 2
|
||||
# 1 "geomfunc.h" 1
|
||||
# 27 "geomfunc.h"
|
||||
# 1 "geom.h" 1
|
||||
# 32 "geom.h"
|
||||
typedef struct {
|
||||
Vec o, d;
|
||||
} Ray;
|
||||
|
||||
|
||||
|
||||
|
||||
enum Refl {
|
||||
DIFF, SPEC, REFR
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
float rad;
|
||||
Vec p, e, c;
|
||||
enum Refl refl;
|
||||
} Sphere;
|
||||
# 28 "geomfunc.h" 2
|
||||
# 1 "simplernd.h" 1
|
||||
# 34 "simplernd.h"
|
||||
static float GetRandom(unsigned int *seed0, unsigned int *seed1) {
|
||||
*seed0 = 36969 * ((*seed0) & 65535) + ((*seed0) >> 16);
|
||||
*seed1 = 18000 * ((*seed1) & 65535) + ((*seed1) >> 16);
|
||||
|
||||
unsigned int ires = ((*seed0) << 16) + (*seed1);
|
||||
|
||||
|
||||
union {
|
||||
float f;
|
||||
unsigned int ui;
|
||||
} res;
|
||||
res.ui = (ires & 0x007fffff) | 0x40000000;
|
||||
|
||||
return (res.f - 2.f) / 2.f;
|
||||
}
|
||||
# 29 "geomfunc.h" 2
|
||||
|
||||
|
||||
|
||||
static float SphereIntersect(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *s,
|
||||
const Ray *r) {
|
||||
Vec op;
|
||||
{ (op).x = (s->p).x - (r->o).x; (op).y = (s->p).y - (r->o).y; (op).z = (s->p).z - (r->o).z; };
|
||||
|
||||
float b = ((op).x * (r->d).x + (op).y * (r->d).y + (op).z * (r->d).z);
|
||||
float det = b * b - ((op).x * (op).x + (op).y * (op).y + (op).z * (op).z) + s->rad * s->rad;
|
||||
if (det < 0.f)
|
||||
return 0.f;
|
||||
else
|
||||
det = sqrt(det);
|
||||
|
||||
float t = b - det;
|
||||
if (t > 0.01f)
|
||||
return t;
|
||||
else {
|
||||
t = b + det;
|
||||
|
||||
if (t > 0.01f)
|
||||
return t;
|
||||
else
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
static void UniformSampleSphere(const float u1, const float u2, Vec *v) {
|
||||
const float zz = 1.f - 2.f * u1;
|
||||
const float r = sqrt(max(0.f, 1.f - zz * zz));
|
||||
const float phi = 2.f * 3.14159265358979323846f * u2;
|
||||
const float xx = r * cos(phi);
|
||||
const float yy = r * sin(phi);
|
||||
|
||||
{ (*v).x = xx; (*v).y = yy; (*v).z = zz; };
|
||||
}
|
||||
|
||||
static int Intersect(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *r,
|
||||
float *t,
|
||||
unsigned int *id) {
|
||||
float inf = (*t) = 1e20f;
|
||||
|
||||
unsigned int i = sphereCount;
|
||||
for (; i--;) {
|
||||
const float d = SphereIntersect(&spheres[i], r);
|
||||
if ((d != 0.f) && (d < *t)) {
|
||||
*t = d;
|
||||
*id = i;
|
||||
}
|
||||
}
|
||||
|
||||
return (*t < inf);
|
||||
}
|
||||
|
||||
static int IntersectP(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *r,
|
||||
const float maxt) {
|
||||
unsigned int i = sphereCount;
|
||||
for (; i--;) {
|
||||
const float d = SphereIntersect(&spheres[i], r);
|
||||
if ((d != 0.f) && (d < maxt))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SampleLights(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
const Vec *hitPoint,
|
||||
const Vec *normal,
|
||||
Vec *result) {
|
||||
{ (*result).x = 0.f; (*result).y = 0.f; (*result).z = 0.f; };
|
||||
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sphereCount; i++) {
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *light = &spheres[i];
|
||||
if (!(((light->e).x == 0.f) && ((light->e).x == 0.f) && ((light->e).z == 0.f))) {
|
||||
|
||||
Ray shadowRay;
|
||||
shadowRay.o = *hitPoint;
|
||||
|
||||
|
||||
Vec unitSpherePoint;
|
||||
UniformSampleSphere(GetRandom(seed0, seed1), GetRandom(seed0, seed1), &unitSpherePoint);
|
||||
Vec spherePoint;
|
||||
{ float k = (light->rad); { (spherePoint).x = k * (unitSpherePoint).x; (spherePoint).y = k * (unitSpherePoint).y; (spherePoint).z = k * (unitSpherePoint).z; } };
|
||||
{ (spherePoint).x = (spherePoint).x + (light->p).x; (spherePoint).y = (spherePoint).y + (light->p).y; (spherePoint).z = (spherePoint).z + (light->p).z; };
|
||||
|
||||
|
||||
{ (shadowRay.d).x = (spherePoint).x - (*hitPoint).x; (shadowRay.d).y = (spherePoint).y - (*hitPoint).y; (shadowRay.d).z = (spherePoint).z - (*hitPoint).z; };
|
||||
const float len = sqrt(((shadowRay.d).x * (shadowRay.d).x + (shadowRay.d).y * (shadowRay.d).y + (shadowRay.d).z * (shadowRay.d).z));
|
||||
{ float k = (1.f / len); { (shadowRay.d).x = k * (shadowRay.d).x; (shadowRay.d).y = k * (shadowRay.d).y; (shadowRay.d).z = k * (shadowRay.d).z; } };
|
||||
|
||||
float wo = ((shadowRay.d).x * (unitSpherePoint).x + (shadowRay.d).y * (unitSpherePoint).y + (shadowRay.d).z * (unitSpherePoint).z);
|
||||
if (wo > 0.f) {
|
||||
|
||||
continue;
|
||||
} else
|
||||
wo = -wo;
|
||||
|
||||
|
||||
const float wi = ((shadowRay.d).x * (*normal).x + (shadowRay.d).y * (*normal).y + (shadowRay.d).z * (*normal).z);
|
||||
if ((wi > 0.f) && (!IntersectP(spheres, sphereCount, &shadowRay, len - 0.01f))) {
|
||||
Vec c; { (c).x = (light->e).x; (c).y = (light->e).y; (c).z = (light->e).z; };
|
||||
const float s = (4.f * 3.14159265358979323846f * light->rad * light->rad) * wi * wo / (len *len);
|
||||
{ float k = (s); { (c).x = k * (c).x; (c).y = k * (c).y; (c).z = k * (c).z; } };
|
||||
{ (*result).x = (*result).x + (c).x; (*result).y = (*result).y + (c).y; (*result).z = (*result).z + (c).z; };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RadiancePathTracing(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *startRay,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
Vec *result) {
|
||||
Ray currentRay; { { ((currentRay).o).x = ((*startRay).o).x; ((currentRay).o).y = ((*startRay).o).y; ((currentRay).o).z = ((*startRay).o).z; }; { ((currentRay).d).x = ((*startRay).d).x; ((currentRay).d).y = ((*startRay).d).y; ((currentRay).d).z = ((*startRay).d).z; }; };
|
||||
Vec rad; { (rad).x = 0.f; (rad).y = 0.f; (rad).z = 0.f; };
|
||||
Vec throughput; { (throughput).x = 1.f; (throughput).y = 1.f; (throughput).z = 1.f; };
|
||||
|
||||
unsigned int depth = 0;
|
||||
int specularBounce = 1;
|
||||
for (;; ++depth) {
|
||||
|
||||
if (depth > 6) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
float t;
|
||||
unsigned int id = 0;
|
||||
if (!Intersect(spheres, sphereCount, ¤tRay, &t, &id)) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *obj = &spheres[id];
|
||||
|
||||
Vec hitPoint;
|
||||
{ float k = (t); { (hitPoint).x = k * (currentRay.d).x; (hitPoint).y = k * (currentRay.d).y; (hitPoint).z = k * (currentRay.d).z; } };
|
||||
{ (hitPoint).x = (currentRay.o).x + (hitPoint).x; (hitPoint).y = (currentRay.o).y + (hitPoint).y; (hitPoint).z = (currentRay.o).z + (hitPoint).z; };
|
||||
|
||||
Vec normal;
|
||||
{ (normal).x = (hitPoint).x - (obj->p).x; (normal).y = (hitPoint).y - (obj->p).y; (normal).z = (hitPoint).z - (obj->p).z; };
|
||||
{ float l = 1.f / sqrt(((normal).x * (normal).x + (normal).y * (normal).y + (normal).z * (normal).z)); { float k = (l); { (normal).x = k * (normal).x; (normal).y = k * (normal).y; (normal).z = k * (normal).z; } }; };
|
||||
|
||||
const float dp = ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z);
|
||||
|
||||
Vec nl;
|
||||
|
||||
const float invSignDP = -1.f * sign(dp);
|
||||
{ float k = (invSignDP); { (nl).x = k * (normal).x; (nl).y = k * (normal).y; (nl).z = k * (normal).z; } };
|
||||
|
||||
|
||||
Vec eCol; { (eCol).x = (obj->e).x; (eCol).y = (obj->e).y; (eCol).z = (obj->e).z; };
|
||||
if (!(((eCol).x == 0.f) && ((eCol).x == 0.f) && ((eCol).z == 0.f))) {
|
||||
if (specularBounce) {
|
||||
{ float k = (fabs(dp)); { (eCol).x = k * (eCol).x; (eCol).y = k * (eCol).y; (eCol).z = k * (eCol).z; } };
|
||||
{ (eCol).x = (throughput).x * (eCol).x; (eCol).y = (throughput).y * (eCol).y; (eCol).z = (throughput).z * (eCol).z; };
|
||||
{ (rad).x = (rad).x + (eCol).x; (rad).y = (rad).y + (eCol).y; (rad).z = (rad).z + (eCol).z; };
|
||||
}
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->refl == DIFF) {
|
||||
specularBounce = 0;
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
|
||||
|
||||
Vec Ld;
|
||||
SampleLights(spheres, sphereCount, seed0, seed1, &hitPoint, &nl, &Ld);
|
||||
{ (Ld).x = (throughput).x * (Ld).x; (Ld).y = (throughput).y * (Ld).y; (Ld).z = (throughput).z * (Ld).z; };
|
||||
{ (rad).x = (rad).x + (Ld).x; (rad).y = (rad).y + (Ld).y; (rad).z = (rad).z + (Ld).z; };
|
||||
|
||||
|
||||
|
||||
float r1 = 2.f * 3.14159265358979323846f * GetRandom(seed0, seed1);
|
||||
float r2 = GetRandom(seed0, seed1);
|
||||
float r2s = sqrt(r2);
|
||||
|
||||
Vec w; { (w).x = (nl).x; (w).y = (nl).y; (w).z = (nl).z; };
|
||||
|
||||
Vec u, a;
|
||||
if (fabs(w.x) > .1f) {
|
||||
{ (a).x = 0.f; (a).y = 1.f; (a).z = 0.f; };
|
||||
} else {
|
||||
{ (a).x = 1.f; (a).y = 0.f; (a).z = 0.f; };
|
||||
}
|
||||
{ (u).x = (a).y * (w).z - (a).z * (w).y; (u).y = (a).z * (w).x - (a).x * (w).z; (u).z = (a).x * (w).y - (a).y * (w).x; };
|
||||
{ float l = 1.f / sqrt(((u).x * (u).x + (u).y * (u).y + (u).z * (u).z)); { float k = (l); { (u).x = k * (u).x; (u).y = k * (u).y; (u).z = k * (u).z; } }; };
|
||||
|
||||
Vec v;
|
||||
{ (v).x = (w).y * (u).z - (w).z * (u).y; (v).y = (w).z * (u).x - (w).x * (u).z; (v).z = (w).x * (u).y - (w).y * (u).x; };
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (cos(r1) * r2s); { (u).x = k * (u).x; (u).y = k * (u).y; (u).z = k * (u).z; } };
|
||||
{ float k = (sin(r1) * r2s); { (v).x = k * (v).x; (v).y = k * (v).y; (v).z = k * (v).z; } };
|
||||
{ (newDir).x = (u).x + (v).x; (newDir).y = (u).y + (v).y; (newDir).z = (u).z + (v).z; };
|
||||
{ float k = (sqrt(1 - r2)); { (w).x = k * (w).x; (w).y = k * (w).y; (w).z = k * (w).z; } };
|
||||
{ (newDir).x = (newDir).x + (w).x; (newDir).y = (newDir).y + (w).y; (newDir).z = (newDir).z + (w).z; };
|
||||
|
||||
currentRay.o = hitPoint;
|
||||
currentRay.d = newDir;
|
||||
continue;
|
||||
} else if (obj->refl == SPEC) {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (2.f * ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z)); { (newDir).x = k * (normal).x; (newDir).y = k * (normal).y; (newDir).z = k * (normal).z; } };
|
||||
{ (newDir).x = (currentRay.d).x - (newDir).x; (newDir).y = (currentRay.d).y - (newDir).y; (newDir).z = (currentRay.d).z - (newDir).z; };
|
||||
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = (hitPoint).x; ((currentRay).o).y = (hitPoint).y; ((currentRay).o).z = (hitPoint).z; }; { ((currentRay).d).x = (newDir).x; ((currentRay).d).y = (newDir).y; ((currentRay).d).z = (newDir).z; }; };
|
||||
continue;
|
||||
} else {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (2.f * ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z)); { (newDir).x = k * (normal).x; (newDir).y = k * (normal).y; (newDir).z = k * (normal).z; } };
|
||||
{ (newDir).x = (currentRay.d).x - (newDir).x; (newDir).y = (currentRay.d).y - (newDir).y; (newDir).z = (currentRay.d).z - (newDir).z; };
|
||||
|
||||
Ray reflRay; { { ((reflRay).o).x = (hitPoint).x; ((reflRay).o).y = (hitPoint).y; ((reflRay).o).z = (hitPoint).z; }; { ((reflRay).d).x = (newDir).x; ((reflRay).d).y = (newDir).y; ((reflRay).d).z = (newDir).z; }; };
|
||||
int into = (((normal).x * (nl).x + (normal).y * (nl).y + (normal).z * (nl).z) > 0);
|
||||
|
||||
float nc = 1.f;
|
||||
float nt = 1.5f;
|
||||
float nnt = into ? nc / nt : nt / nc;
|
||||
float ddn = ((currentRay.d).x * (nl).x + (currentRay.d).y * (nl).y + (currentRay.d).z * (nl).z);
|
||||
float cos2t = 1.f - nnt * nnt * (1.f - ddn * ddn);
|
||||
|
||||
if (cos2t < 0.f) {
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = ((reflRay).o).x; ((currentRay).o).y = ((reflRay).o).y; ((currentRay).o).z = ((reflRay).o).z; }; { ((currentRay).d).x = ((reflRay).d).x; ((currentRay).d).y = ((reflRay).d).y; ((currentRay).d).z = ((reflRay).d).z; }; };
|
||||
continue;
|
||||
}
|
||||
|
||||
float kk = (into ? 1 : -1) * (ddn * nnt + sqrt(cos2t));
|
||||
Vec nkk;
|
||||
{ float k = (kk); { (nkk).x = k * (normal).x; (nkk).y = k * (normal).y; (nkk).z = k * (normal).z; } };
|
||||
Vec transDir;
|
||||
{ float k = (nnt); { (transDir).x = k * (currentRay.d).x; (transDir).y = k * (currentRay.d).y; (transDir).z = k * (currentRay.d).z; } };
|
||||
{ (transDir).x = (transDir).x - (nkk).x; (transDir).y = (transDir).y - (nkk).y; (transDir).z = (transDir).z - (nkk).z; };
|
||||
{ float l = 1.f / sqrt(((transDir).x * (transDir).x + (transDir).y * (transDir).y + (transDir).z * (transDir).z)); { float k = (l); { (transDir).x = k * (transDir).x; (transDir).y = k * (transDir).y; (transDir).z = k * (transDir).z; } }; };
|
||||
|
||||
float a = nt - nc;
|
||||
float b = nt + nc;
|
||||
float R0 = a * a / (b * b);
|
||||
float c = 1 - (into ? -ddn : ((transDir).x * (normal).x + (transDir).y * (normal).y + (transDir).z * (normal).z));
|
||||
|
||||
float Re = R0 + (1 - R0) * c * c * c * c*c;
|
||||
float Tr = 1.f - Re;
|
||||
float P = .25f + .5f * Re;
|
||||
float RP = Re / P;
|
||||
float TP = Tr / (1.f - P);
|
||||
|
||||
if (GetRandom(seed0, seed1) < P) {
|
||||
{ float k = (RP); { (throughput).x = k * (throughput).x; (throughput).y = k * (throughput).y; (throughput).z = k * (throughput).z; } };
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = ((reflRay).o).x; ((currentRay).o).y = ((reflRay).o).y; ((currentRay).o).z = ((reflRay).o).z; }; { ((currentRay).d).x = ((reflRay).d).x; ((currentRay).d).y = ((reflRay).d).y; ((currentRay).d).z = ((reflRay).d).z; }; };
|
||||
continue;
|
||||
} else {
|
||||
{ float k = (TP); { (throughput).x = k * (throughput).x; (throughput).y = k * (throughput).y; (throughput).z = k * (throughput).z; } };
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = (hitPoint).x; ((currentRay).o).y = (hitPoint).y; ((currentRay).o).z = (hitPoint).z; }; { ((currentRay).d).x = (transDir).x; ((currentRay).d).y = (transDir).y; ((currentRay).d).z = (transDir).z; }; };
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RadianceDirectLighting(
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *spheres,
|
||||
const unsigned int sphereCount,
|
||||
const Ray *startRay,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
Vec *result) {
|
||||
Ray currentRay; { { ((currentRay).o).x = ((*startRay).o).x; ((currentRay).o).y = ((*startRay).o).y; ((currentRay).o).z = ((*startRay).o).z; }; { ((currentRay).d).x = ((*startRay).d).x; ((currentRay).d).y = ((*startRay).d).y; ((currentRay).d).z = ((*startRay).d).z; }; };
|
||||
Vec rad; { (rad).x = 0.f; (rad).y = 0.f; (rad).z = 0.f; };
|
||||
Vec throughput; { (throughput).x = 1.f; (throughput).y = 1.f; (throughput).z = 1.f; };
|
||||
|
||||
unsigned int depth = 0;
|
||||
int specularBounce = 1;
|
||||
for (;; ++depth) {
|
||||
|
||||
if (depth > 6) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
float t;
|
||||
unsigned int id = 0;
|
||||
if (!Intersect(spheres, sphereCount, ¤tRay, &t, &id)) {
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
__constant
|
||||
|
||||
const Sphere *obj = &spheres[id];
|
||||
|
||||
Vec hitPoint;
|
||||
{ float k = (t); { (hitPoint).x = k * (currentRay.d).x; (hitPoint).y = k * (currentRay.d).y; (hitPoint).z = k * (currentRay.d).z; } };
|
||||
{ (hitPoint).x = (currentRay.o).x + (hitPoint).x; (hitPoint).y = (currentRay.o).y + (hitPoint).y; (hitPoint).z = (currentRay.o).z + (hitPoint).z; };
|
||||
|
||||
Vec normal;
|
||||
{ (normal).x = (hitPoint).x - (obj->p).x; (normal).y = (hitPoint).y - (obj->p).y; (normal).z = (hitPoint).z - (obj->p).z; };
|
||||
{ float l = 1.f / sqrt(((normal).x * (normal).x + (normal).y * (normal).y + (normal).z * (normal).z)); { float k = (l); { (normal).x = k * (normal).x; (normal).y = k * (normal).y; (normal).z = k * (normal).z; } }; };
|
||||
|
||||
const float dp = ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z);
|
||||
|
||||
Vec nl;
|
||||
|
||||
const float invSignDP = -1.f * sign(dp);
|
||||
{ float k = (invSignDP); { (nl).x = k * (normal).x; (nl).y = k * (normal).y; (nl).z = k * (normal).z; } };
|
||||
|
||||
|
||||
Vec eCol; { (eCol).x = (obj->e).x; (eCol).y = (obj->e).y; (eCol).z = (obj->e).z; };
|
||||
if (!(((eCol).x == 0.f) && ((eCol).x == 0.f) && ((eCol).z == 0.f))) {
|
||||
if (specularBounce) {
|
||||
{ float k = (fabs(dp)); { (eCol).x = k * (eCol).x; (eCol).y = k * (eCol).y; (eCol).z = k * (eCol).z; } };
|
||||
{ (eCol).x = (throughput).x * (eCol).x; (eCol).y = (throughput).y * (eCol).y; (eCol).z = (throughput).z * (eCol).z; };
|
||||
{ (rad).x = (rad).x + (eCol).x; (rad).y = (rad).y + (eCol).y; (rad).z = (rad).z + (eCol).z; };
|
||||
}
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->refl == DIFF) {
|
||||
specularBounce = 0;
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
|
||||
|
||||
Vec Ld;
|
||||
SampleLights(spheres, sphereCount, seed0, seed1, &hitPoint, &nl, &Ld);
|
||||
{ (Ld).x = (throughput).x * (Ld).x; (Ld).y = (throughput).y * (Ld).y; (Ld).z = (throughput).z * (Ld).z; };
|
||||
{ (rad).x = (rad).x + (Ld).x; (rad).y = (rad).y + (Ld).y; (rad).z = (rad).z + (Ld).z; };
|
||||
|
||||
*result = rad;
|
||||
return;
|
||||
} else if (obj->refl == SPEC) {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (2.f * ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z)); { (newDir).x = k * (normal).x; (newDir).y = k * (normal).y; (newDir).z = k * (normal).z; } };
|
||||
{ (newDir).x = (currentRay.d).x - (newDir).x; (newDir).y = (currentRay.d).y - (newDir).y; (newDir).z = (currentRay.d).z - (newDir).z; };
|
||||
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = (hitPoint).x; ((currentRay).o).y = (hitPoint).y; ((currentRay).o).z = (hitPoint).z; }; { ((currentRay).d).x = (newDir).x; ((currentRay).d).y = (newDir).y; ((currentRay).d).z = (newDir).z; }; };
|
||||
continue;
|
||||
} else {
|
||||
specularBounce = 1;
|
||||
|
||||
Vec newDir;
|
||||
{ float k = (2.f * ((normal).x * (currentRay.d).x + (normal).y * (currentRay.d).y + (normal).z * (currentRay.d).z)); { (newDir).x = k * (normal).x; (newDir).y = k * (normal).y; (newDir).z = k * (normal).z; } };
|
||||
{ (newDir).x = (currentRay.d).x - (newDir).x; (newDir).y = (currentRay.d).y - (newDir).y; (newDir).z = (currentRay.d).z - (newDir).z; };
|
||||
|
||||
Ray reflRay; { { ((reflRay).o).x = (hitPoint).x; ((reflRay).o).y = (hitPoint).y; ((reflRay).o).z = (hitPoint).z; }; { ((reflRay).d).x = (newDir).x; ((reflRay).d).y = (newDir).y; ((reflRay).d).z = (newDir).z; }; };
|
||||
int into = (((normal).x * (nl).x + (normal).y * (nl).y + (normal).z * (nl).z) > 0);
|
||||
|
||||
float nc = 1.f;
|
||||
float nt = 1.5f;
|
||||
float nnt = into ? nc / nt : nt / nc;
|
||||
float ddn = ((currentRay.d).x * (nl).x + (currentRay.d).y * (nl).y + (currentRay.d).z * (nl).z);
|
||||
float cos2t = 1.f - nnt * nnt * (1.f - ddn * ddn);
|
||||
|
||||
if (cos2t < 0.f) {
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = ((reflRay).o).x; ((currentRay).o).y = ((reflRay).o).y; ((currentRay).o).z = ((reflRay).o).z; }; { ((currentRay).d).x = ((reflRay).d).x; ((currentRay).d).y = ((reflRay).d).y; ((currentRay).d).z = ((reflRay).d).z; }; };
|
||||
continue;
|
||||
}
|
||||
|
||||
float kk = (into ? 1 : -1) * (ddn * nnt + sqrt(cos2t));
|
||||
Vec nkk;
|
||||
{ float k = (kk); { (nkk).x = k * (normal).x; (nkk).y = k * (normal).y; (nkk).z = k * (normal).z; } };
|
||||
Vec transDir;
|
||||
{ float k = (nnt); { (transDir).x = k * (currentRay.d).x; (transDir).y = k * (currentRay.d).y; (transDir).z = k * (currentRay.d).z; } };
|
||||
{ (transDir).x = (transDir).x - (nkk).x; (transDir).y = (transDir).y - (nkk).y; (transDir).z = (transDir).z - (nkk).z; };
|
||||
{ float l = 1.f / sqrt(((transDir).x * (transDir).x + (transDir).y * (transDir).y + (transDir).z * (transDir).z)); { float k = (l); { (transDir).x = k * (transDir).x; (transDir).y = k * (transDir).y; (transDir).z = k * (transDir).z; } }; };
|
||||
|
||||
float a = nt - nc;
|
||||
float b = nt + nc;
|
||||
float R0 = a * a / (b * b);
|
||||
float c = 1 - (into ? -ddn : ((transDir).x * (normal).x + (transDir).y * (normal).y + (transDir).z * (normal).z));
|
||||
|
||||
float Re = R0 + (1 - R0) * c * c * c * c*c;
|
||||
float Tr = 1.f - Re;
|
||||
float P = .25f + .5f * Re;
|
||||
float RP = Re / P;
|
||||
float TP = Tr / (1.f - P);
|
||||
|
||||
if (GetRandom(seed0, seed1) < P) {
|
||||
{ float k = (RP); { (throughput).x = k * (throughput).x; (throughput).y = k * (throughput).y; (throughput).z = k * (throughput).z; } };
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = ((reflRay).o).x; ((currentRay).o).y = ((reflRay).o).y; ((currentRay).o).z = ((reflRay).o).z; }; { ((currentRay).d).x = ((reflRay).d).x; ((currentRay).d).y = ((reflRay).d).y; ((currentRay).d).z = ((reflRay).d).z; }; };
|
||||
continue;
|
||||
} else {
|
||||
{ float k = (TP); { (throughput).x = k * (throughput).x; (throughput).y = k * (throughput).y; (throughput).z = k * (throughput).z; } };
|
||||
{ (throughput).x = (throughput).x * (obj->c).x; (throughput).y = (throughput).y * (obj->c).y; (throughput).z = (throughput).z * (obj->c).z; };
|
||||
|
||||
{ { ((currentRay).o).x = (hitPoint).x; ((currentRay).o).y = (hitPoint).y; ((currentRay).o).z = (hitPoint).z; }; { ((currentRay).d).x = (transDir).x; ((currentRay).d).y = (transDir).y; ((currentRay).d).z = (transDir).z; }; };
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# 28 "<stdin>" 2
|
||||
|
||||
static void GenerateCameraRay(__constant Camera *camera,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
const int width, const int height, const int x, const int y, Ray *ray) {
|
||||
const float invWidth = 1.f / width;
|
||||
const float invHeight = 1.f / height;
|
||||
const float r1 = GetRandom(seed0, seed1) - .5f;
|
||||
const float r2 = GetRandom(seed0, seed1) - .5f;
|
||||
const float kcx = (x + r1) * invWidth - .5f;
|
||||
const float kcy = (y + r2) * invHeight - .5f;
|
||||
|
||||
Vec rdir;
|
||||
{ (rdir).x = camera->x.x * kcx + camera->y.x * kcy + camera->dir.x; (rdir).y = camera->x.y * kcx + camera->y.y * kcy + camera->dir.y; (rdir).z = camera->x.z * kcx + camera->y.z * kcy + camera->dir.z; };
|
||||
|
||||
|
||||
|
||||
|
||||
Vec rorig;
|
||||
{ float k = (0.1f); { (rorig).x = k * (rdir).x; (rorig).y = k * (rdir).y; (rorig).z = k * (rdir).z; } };
|
||||
{ (rorig).x = (rorig).x + (camera->orig).x; (rorig).y = (rorig).y + (camera->orig).y; (rorig).z = (rorig).z + (camera->orig).z; }
|
||||
|
||||
{ float l = 1.f / sqrt(((rdir).x * (rdir).x + (rdir).y * (rdir).y + (rdir).z * (rdir).z)); { float k = (l); { (rdir).x = k * (rdir).x; (rdir).y = k * (rdir).y; (rdir).z = k * (rdir).z; } }; };
|
||||
{ { ((*ray).o).x = (rorig).x; ((*ray).o).y = (rorig).y; ((*ray).o).z = (rorig).z; }; { ((*ray).d).x = (rdir).x; ((*ray).d).y = (rdir).y; ((*ray).d).z = (rdir).z; }; };
|
||||
}
|
||||
|
||||
__kernel void RadianceGPU(
|
||||
__global Vec *colors, __global unsigned int *seedsInput,
|
||||
__constant Sphere *sphere, __constant Camera *camera,
|
||||
const unsigned int sphereCount,
|
||||
const int width, const int height,
|
||||
const int currentSample,
|
||||
__global int *pixels) {
|
||||
const int gid = get_global_id(0);
|
||||
const int gid2 = 2 * gid;
|
||||
const int x = gid % width;
|
||||
const int y = gid / width;
|
||||
|
||||
|
||||
if (y >= height)
|
||||
return;
|
||||
|
||||
|
||||
unsigned int seed0 = seedsInput[gid2];
|
||||
unsigned int seed1 = seedsInput[gid2 + 1];
|
||||
|
||||
Ray ray;
|
||||
GenerateCameraRay(camera, &seed0, &seed1, width, height, x, y, &ray);
|
||||
|
||||
Vec r;
|
||||
RadianceDirectLighting(sphere, sphereCount, &ray, &seed0, &seed1, &r);
|
||||
|
||||
const int i = (height - y - 1) * width + x;
|
||||
if (currentSample == 0) {
|
||||
|
||||
{ (colors[i]).x = (r).x; (colors[i]).y = (r).y; (colors[i]).z = (r).z; };
|
||||
} else {
|
||||
const float k1 = currentSample;
|
||||
const float k2 = 1.f / (currentSample + 1.f);
|
||||
colors[i].x = (colors[i].x * k1 + r.x) * k2;
|
||||
colors[i].y = (colors[i].y * k1 + r.y) * k2;
|
||||
colors[i].z = (colors[i].z * k1 + r.z) * k2;
|
||||
}
|
||||
|
||||
pixels[y * width + x] = ((int)(pow(clamp(colors[i].x, 0.f, 1.f), 1.f / 2.2f) * 255.f + .5f)) |
|
||||
(((int)(pow(clamp(colors[i].y, 0.f, 1.f), 1.f / 2.2f) * 255.f + .5f)) << 8) |
|
||||
(((int)(pow(clamp(colors[i].z, 0.f, 1.f), 1.f / 2.2f) * 255.f + .5f)) << 16);
|
||||
|
||||
seedsInput[gid2] = seed0;
|
||||
seedsInput[gid2 + 1] = seed1;
|
||||
}
|
97
rendering_kernel.cl
Normal file
97
rendering_kernel.cl
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define GPU_KERNEL
|
||||
|
||||
#include "camera.h"
|
||||
#include "geomfunc.h"
|
||||
|
||||
static void GenerateCameraRay(OCL_CONSTANT_BUFFER Camera *camera,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
const int width, const int height, const int x, const int y, Ray *ray) {
|
||||
const float invWidth = 1.f / width;
|
||||
const float invHeight = 1.f / height;
|
||||
const float r1 = GetRandom(seed0, seed1) - .5f;
|
||||
const float r2 = GetRandom(seed0, seed1) - .5f;
|
||||
const float kcx = (x + r1) * invWidth - .5f;
|
||||
const float kcy = (y + r2) * invHeight - .5f;
|
||||
|
||||
Vec rdir;
|
||||
vinit(rdir,
|
||||
camera->x.x * kcx + camera->y.x * kcy + camera->dir.x,
|
||||
camera->x.y * kcx + camera->y.y * kcy + camera->dir.y,
|
||||
camera->x.z * kcx + camera->y.z * kcy + camera->dir.z);
|
||||
|
||||
Vec rorig;
|
||||
vsmul(rorig, 0.1f, rdir);
|
||||
vadd(rorig, rorig, camera->orig)
|
||||
|
||||
vnorm(rdir);
|
||||
rinit(*ray, rorig, rdir);
|
||||
}
|
||||
|
||||
__kernel void RadianceGPU(
|
||||
__global Vec *colors, __global unsigned int *seedsInput,
|
||||
OCL_CONSTANT_BUFFER Sphere *sphere, OCL_CONSTANT_BUFFER Camera *camera,
|
||||
const unsigned int sphereCount,
|
||||
const int width, const int height,
|
||||
const int currentSample,
|
||||
__global int *pixels) {
|
||||
const int gid = get_global_id(0);
|
||||
const int gid2 = 2 * gid;
|
||||
const int x = gid % width;
|
||||
const int y = gid / width;
|
||||
|
||||
/* Check if we have to do something */
|
||||
if (y >= height)
|
||||
return;
|
||||
|
||||
/* LordCRC: move seed to local store */
|
||||
unsigned int seed0 = seedsInput[gid2];
|
||||
unsigned int seed1 = seedsInput[gid2 + 1];
|
||||
|
||||
Ray ray;
|
||||
GenerateCameraRay(camera, &seed0, &seed1, width, height, x, y, &ray);
|
||||
|
||||
Vec r;
|
||||
RadiancePathTracing(sphere, sphereCount, &ray, &seed0, &seed1, &r);
|
||||
|
||||
const int i = (height - y - 1) * width + x;
|
||||
if (currentSample == 0) {
|
||||
// Jens's patch for MacOS
|
||||
vassign(colors[i], r);
|
||||
} else {
|
||||
const float k1 = currentSample;
|
||||
const float k2 = 1.f / (currentSample + 1.f);
|
||||
colors[i].x = (colors[i].x * k1 + r.x) * k2;
|
||||
colors[i].y = (colors[i].y * k1 + r.y) * k2;
|
||||
colors[i].z = (colors[i].z * k1 + r.z) * k2;
|
||||
}
|
||||
|
||||
pixels[y * width + x] = toInt(colors[i].x) |
|
||||
(toInt(colors[i].y) << 8) |
|
||||
(toInt(colors[i].z) << 16);
|
||||
|
||||
seedsInput[gid2] = seed0;
|
||||
seedsInput[gid2 + 1] = seed1;
|
||||
}
|
97
rendering_kernel_dl.cl
Normal file
97
rendering_kernel_dl.cl
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define GPU_KERNEL
|
||||
|
||||
#include "camera.h"
|
||||
#include "geomfunc.h"
|
||||
|
||||
static void GenerateCameraRay(OCL_CONSTANT_BUFFER Camera *camera,
|
||||
unsigned int *seed0, unsigned int *seed1,
|
||||
const int width, const int height, const int x, const int y, Ray *ray) {
|
||||
const float invWidth = 1.f / width;
|
||||
const float invHeight = 1.f / height;
|
||||
const float r1 = GetRandom(seed0, seed1) - .5f;
|
||||
const float r2 = GetRandom(seed0, seed1) - .5f;
|
||||
const float kcx = (x + r1) * invWidth - .5f;
|
||||
const float kcy = (y + r2) * invHeight - .5f;
|
||||
|
||||
Vec rdir;
|
||||
vinit(rdir,
|
||||
camera->x.x * kcx + camera->y.x * kcy + camera->dir.x,
|
||||
camera->x.y * kcx + camera->y.y * kcy + camera->dir.y,
|
||||
camera->x.z * kcx + camera->y.z * kcy + camera->dir.z);
|
||||
|
||||
Vec rorig;
|
||||
vsmul(rorig, 0.1f, rdir);
|
||||
vadd(rorig, rorig, camera->orig)
|
||||
|
||||
vnorm(rdir);
|
||||
rinit(*ray, rorig, rdir);
|
||||
}
|
||||
|
||||
__kernel void RadianceGPU(
|
||||
__global Vec *colors, __global unsigned int *seedsInput,
|
||||
OCL_CONSTANT_BUFFER Sphere *sphere, OCL_CONSTANT_BUFFER Camera *camera,
|
||||
const unsigned int sphereCount,
|
||||
const int width, const int height,
|
||||
const int currentSample,
|
||||
__global int *pixels) {
|
||||
const int gid = get_global_id(0);
|
||||
const int gid2 = 2 * gid;
|
||||
const int x = gid % width;
|
||||
const int y = gid / width;
|
||||
|
||||
/* Check if we have to do something */
|
||||
if (y >= height)
|
||||
return;
|
||||
|
||||
/* LordCRC: move seed to local store */
|
||||
unsigned int seed0 = seedsInput[gid2];
|
||||
unsigned int seed1 = seedsInput[gid2 + 1];
|
||||
|
||||
Ray ray;
|
||||
GenerateCameraRay(camera, &seed0, &seed1, width, height, x, y, &ray);
|
||||
|
||||
Vec r;
|
||||
RadianceDirectLighting(sphere, sphereCount, &ray, &seed0, &seed1, &r);
|
||||
|
||||
const int i = (height - y - 1) * width + x;
|
||||
if (currentSample == 0) {
|
||||
// Jens's patch for MacOS
|
||||
vassign(colors[i], r);
|
||||
} else {
|
||||
const float k1 = currentSample;
|
||||
const float k2 = 1.f / (currentSample + 1.f);
|
||||
colors[i].x = (colors[i].x * k1 + r.x) * k2;
|
||||
colors[i].y = (colors[i].y * k1 + r.y) * k2;
|
||||
colors[i].z = (colors[i].z * k1 + r.z) * k2;
|
||||
}
|
||||
|
||||
pixels[y * width + x] = toInt(colors[i].x) |
|
||||
(toInt(colors[i].y) << 8) |
|
||||
(toInt(colors[i].z) << 16);
|
||||
|
||||
seedsInput[gid2] = seed0;
|
||||
seedsInput[gid2 + 1] = seed1;
|
||||
}
|
53
scene.h
Normal file
53
scene.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _SCENE_H
|
||||
#define _SCENE_H
|
||||
|
||||
#include "geomfunc.h"
|
||||
|
||||
#define WALL_RAD 1e4f
|
||||
static Sphere CornellSpheres[] = { /* Scene: radius, position, emission, color, material */
|
||||
{ WALL_RAD, {WALL_RAD + 1.f, 40.8f, 81.6f}, {0.f, 0.f, 0.f}, {.75f, .25f, .25f}, DIFF }, /* Left */
|
||||
{ WALL_RAD, {-WALL_RAD + 99.f, 40.8f, 81.6f}, {0.f, 0.f, 0.f}, {.25f, .25f, .75f}, DIFF }, /* Rght */
|
||||
{ WALL_RAD, {50.f, 40.8f, WALL_RAD}, {0.f, 0.f, 0.f}, {.75f, .75f, .75f}, DIFF }, /* Back */
|
||||
{ WALL_RAD, {50.f, 40.8f, -WALL_RAD + 270.f}, {0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}, DIFF }, /* Frnt */
|
||||
{ WALL_RAD, {50.f, WALL_RAD, 81.6f}, {0.f, 0.f, 0.f}, {.75f, .75f, .75f}, DIFF }, /* Botm */
|
||||
{ WALL_RAD, {50.f, -WALL_RAD + 81.6f, 81.6f}, {0.f, 0.f, 0.f}, {.75f, .75f, .75f}, DIFF }, /* Top */
|
||||
{ 16.5f, {27.f, 16.5f, 47.f}, {0.f, 0.f, 0.f}, {.9f, .9f, .9f}, SPEC }, /* Mirr */
|
||||
{ 16.5f, {73.f, 16.5f, 78.f}, {0.f, 0.f, 0.f}, {.9f, .9f, .9f}, REFR }, /* Glas */
|
||||
{ 7.f, {50.f, 81.6f - 15.f, 81.6f}, {12.f, 12.f, 12.f}, {0.f, 0.f, 0.f}, DIFF } /* Lite */
|
||||
};
|
||||
|
||||
#ifdef SCENE_TEST
|
||||
static const Sphere spheres[] = { /* Scene: radius, position, emission, color, material */
|
||||
{ 1000.f, {0.f, -1000.f, 0.f}, {0.f, 0.f, 0.f}, {.75f, .75f, .75f}, DIFF }, /* Ground */
|
||||
{ 15.f, {10.f, 15.f, 0.0f}, {0.f, 0.f, 0.f}, {.75f, 0.f, 0.f}, DIFF }, /* Red */
|
||||
{ 20.f, {-40.f, 20.f, 0.0f}, {0.f, 0.f, 0.f}, {0.f, 0.f, .75f}, DIFF }, /* Blue */
|
||||
{ 10.f, {-5.f, 10.f, 20.0f}, {0.f, 0.f, 0.f}, {0.f, .75f, .0f}, DIFF }, /* Blue */
|
||||
{ 10.f, {-30.f, 100.0f, 20.f}, {12.f, 12.f, 12.f}, {0.f, 0.f, 0.f}, DIFF } /* Lite */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _SCENE_H */
|
||||
|
60
scene_build_complex.pl
Normal file
60
scene_build_complex.pl
Normal file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
$maxDepth = 4.0;
|
||||
|
||||
sub PrintSphere {
|
||||
my $depth = shift;
|
||||
my $posx = shift;
|
||||
my $posy = shift;
|
||||
my $posz = shift;
|
||||
my $rad = shift;
|
||||
|
||||
my $k = $depth / $maxDepth;
|
||||
my $col1 = 0.75 * $k;
|
||||
my $col2 = 0.75 * (1.0 - $k);
|
||||
|
||||
print "sphere $rad $posx $posy $posz 0 0 0 $col2 0 $col1 0\n";
|
||||
}
|
||||
|
||||
sub HyperSphere {
|
||||
my $depth = shift;
|
||||
if ($depth <= $maxDepth) {
|
||||
my $posx = shift;
|
||||
my $posy = shift;
|
||||
my $posz = shift;
|
||||
my $rad = shift;
|
||||
my $direction = shift;
|
||||
|
||||
PrintSphere($depth, $posx, $posy, $posz, $rad);
|
||||
|
||||
my $newRad = $rad / 2.0;
|
||||
if ($direction != 0) {
|
||||
HyperSphere($depth + 1.0, $posx - $rad - $newRad, $posy, $posz, $newRad, 1);
|
||||
}
|
||||
if ($direction != 1) {
|
||||
HyperSphere($depth + 1.0, $posx + $rad + $newRad, $posy, $posz, $newRad, 0);
|
||||
}
|
||||
if ($direction != 2) {
|
||||
HyperSphere($depth + 1.0, $posx, $posy - $rad - $newRad, $posz, $newRad, 3);
|
||||
}
|
||||
if ($direction != 3) {
|
||||
HyperSphere($depth + 1.0, $posx, $posy + $rad + $newRad, $posz, $newRad, 2);
|
||||
}
|
||||
if ($direction != 4) {
|
||||
HyperSphere($depth + 1.0, $posx, $posy, $posz - $rad - $newRad, $newRad, 5);
|
||||
}
|
||||
if ($direction != 5) {
|
||||
HyperSphere($depth + 1.0, $posx, $posy, $posz + $rad + $newRad, $newRad, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Directions:
|
||||
# 0 - from -x
|
||||
# 1 - from +x
|
||||
# 2 - from -y
|
||||
# 3 - from +y
|
||||
# 4 - from -z
|
||||
# 5 - from +z
|
||||
|
||||
HyperSphere(0.0, 0.0, 0.0, 0.0, 15.0, 2);
|
5
scenes/caustic.scn
Normal file
5
scenes/caustic.scn
Normal file
@ -0,0 +1,5 @@
|
||||
camera 20 80 300 0 40 0
|
||||
size 3
|
||||
sphere 1000 0 -1000 0 0 0 0 0.75 0.75 0.75 0
|
||||
sphere 15 0 30 0 0 0 0 0.9 0.9 0.9 2
|
||||
sphere 15 0 100 0 15 15 15 0 0 0 0
|
7
scenes/caustic3.scn
Normal file
7
scenes/caustic3.scn
Normal file
@ -0,0 +1,7 @@
|
||||
camera 20 100 300 0 25 0
|
||||
size 5
|
||||
sphere 1000 0 -1000 0 0 0 0 0.75 0.75 0.75 0
|
||||
sphere 10 35 15 0 0 0 0 0.9 0 0 2
|
||||
sphere 15 -35 20 0 0 0 0 0 0.9 0 2
|
||||
sphere 20 0 25 -35 0 0 0 0 0 0.9 2
|
||||
sphere 8 0 60 0 15 15 15 0 0 0 0
|
785
scenes/complex.scn
Normal file
785
scenes/complex.scn
Normal file
@ -0,0 +1,785 @@
|
||||
camera 20 80 150 0 15 0
|
||||
size 783
|
||||
sphere 8 50 80 90 25 25 25 0 0 0 0
|
||||
sphere 10000 0 -10050 0 0 0 0 0.75 0.75 0.75 0
|
||||
sphere 15 0 0 0 0 0 0 0.75 0 0 0
|
||||
sphere 7.5 -22.5 0 0 0 0 0 0.5625 0 0.1875 0
|
||||
sphere 3.75 -33.75 0 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -39.375 0 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -42.1875 0 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -39.375 -2.8125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -39.375 2.8125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -39.375 0 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -39.375 0 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -33.75 -5.625 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -36.5625 -5.625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -30.9375 -5.625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 -8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 -5.625 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 -5.625 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -33.75 5.625 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -36.5625 5.625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -30.9375 5.625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 5.625 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 5.625 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -33.75 0 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -36.5625 0 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -30.9375 0 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 -2.8125 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 2.8125 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 0 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -33.75 0 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -36.5625 0 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -30.9375 0 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 -2.8125 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 2.8125 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -33.75 0 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 -22.5 -11.25 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -28.125 -11.25 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -30.9375 -11.25 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 -14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 -8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 -11.25 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 -11.25 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -16.875 -11.25 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 -11.25 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 -14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 -8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 -11.25 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 -11.25 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 -16.875 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 -16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 -16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -19.6875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -16.875 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -16.875 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 -11.25 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 -11.25 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 -11.25 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -14.0625 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -8.4375 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -11.25 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 -11.25 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 -11.25 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 -11.25 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -14.0625 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -8.4375 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -11.25 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 -22.5 11.25 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -28.125 11.25 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -30.9375 11.25 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 11.25 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 11.25 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -16.875 11.25 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 11.25 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 11.25 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 11.25 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 16.875 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 19.6875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 16.875 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 16.875 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 11.25 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 11.25 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 11.25 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 8.4375 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 14.0625 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 11.25 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 11.25 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 11.25 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 11.25 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 8.4375 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 14.0625 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 11.25 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 -22.5 0 -11.25 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -28.125 0 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -30.9375 0 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 -2.8125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 2.8125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 0 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 0 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -16.875 0 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 0 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 -2.8125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 2.8125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 0 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 0 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 -5.625 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 -5.625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 -5.625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -8.4375 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -5.625 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -5.625 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 5.625 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 5.625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 5.625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 8.4375 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 5.625 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 5.625 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 0 -16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 0 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 0 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -2.8125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 2.8125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 0 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 -22.5 0 11.25 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -28.125 0 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -30.9375 0 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 -2.8125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 2.8125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 0 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -28.125 0 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -16.875 0 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 0 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 -2.8125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 2.8125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 0 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 0 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 -5.625 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 -5.625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 -5.625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -8.4375 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -5.625 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -5.625 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 5.625 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 5.625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 5.625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 8.4375 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 5.625 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 5.625 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -22.5 0 16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -25.3125 0 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -19.6875 0 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 -2.8125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 2.8125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -22.5 0 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 7.5 22.5 0 0 0 0 0 0.5625 0 0.1875 0
|
||||
sphere 3.75 33.75 0 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 39.375 0 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 42.1875 0 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 39.375 -2.8125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 39.375 2.8125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 39.375 0 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 39.375 0 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 33.75 -5.625 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 30.9375 -5.625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 36.5625 -5.625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 -8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 -5.625 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 -5.625 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 33.75 5.625 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 30.9375 5.625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 36.5625 5.625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 5.625 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 5.625 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 33.75 0 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 30.9375 0 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 36.5625 0 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 -2.8125 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 2.8125 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 0 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 33.75 0 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 30.9375 0 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 36.5625 0 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 -2.8125 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 2.8125 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 33.75 0 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 22.5 -11.25 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 16.875 -11.25 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 14.0625 -11.25 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 -14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 -8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 -11.25 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 -11.25 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 28.125 -11.25 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 30.9375 -11.25 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 -14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 -8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 -11.25 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 -11.25 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 -16.875 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 -16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 -16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -19.6875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -16.875 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -16.875 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 -11.25 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 -11.25 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 -11.25 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -14.0625 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -8.4375 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -11.25 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 -11.25 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 -11.25 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 -11.25 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -14.0625 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -8.4375 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -11.25 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 22.5 11.25 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 16.875 11.25 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 14.0625 11.25 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 11.25 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 11.25 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 28.125 11.25 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 30.9375 11.25 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 8.4375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 11.25 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 11.25 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 16.875 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 19.6875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 16.875 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 16.875 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 11.25 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 11.25 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 11.25 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 8.4375 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 14.0625 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 11.25 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 11.25 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 11.25 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 11.25 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 8.4375 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 14.0625 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 11.25 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 22.5 0 -11.25 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 16.875 0 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 14.0625 0 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 -2.8125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 2.8125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 0 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 0 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 28.125 0 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 30.9375 0 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 -2.8125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 2.8125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 0 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 0 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 -5.625 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 -5.625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 -5.625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -8.4375 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -5.625 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -5.625 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 5.625 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 5.625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 5.625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 8.4375 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 5.625 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 5.625 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 0 -16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 0 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 0 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -2.8125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 2.8125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 0 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 22.5 0 11.25 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 16.875 0 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 14.0625 0 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 -2.8125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 2.8125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 0 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 0 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 28.125 0 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 30.9375 0 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 -2.8125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 2.8125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 0 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 28.125 0 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 -5.625 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 -5.625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 -5.625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -8.4375 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -5.625 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -5.625 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 5.625 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 5.625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 5.625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 8.4375 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 5.625 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 5.625 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 22.5 0 16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 0 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 25.3125 0 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 -2.8125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 2.8125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 22.5 0 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 7.5 0 22.5 0 0 0 0 0.5625 0 0.1875 0
|
||||
sphere 3.75 -11.25 22.5 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -16.875 22.5 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -19.6875 22.5 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 19.6875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 25.3125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 22.5 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 22.5 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 16.875 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 16.875 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 16.875 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 28.125 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 28.125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 28.125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 30.9375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 28.125 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 28.125 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 22.5 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 22.5 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 22.5 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 19.6875 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 25.3125 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 22.5 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 22.5 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 22.5 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 22.5 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 19.6875 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 25.3125 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 22.5 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 11.25 22.5 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 16.875 22.5 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 22.5 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 19.6875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 25.3125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 22.5 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 22.5 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 16.875 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 16.875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 14.0625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 16.875 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 16.875 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 28.125 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 28.125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 28.125 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 30.9375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 28.125 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 28.125 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 22.5 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 22.5 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 22.5 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 19.6875 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 25.3125 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 22.5 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 22.5 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 22.5 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 22.5 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 19.6875 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 25.3125 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 22.5 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 33.75 0 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 33.75 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 33.75 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 30.9375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 36.5625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 33.75 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 33.75 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 33.75 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 33.75 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 30.9375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 36.5625 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 33.75 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 33.75 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 39.375 0 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 39.375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 39.375 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 42.1875 0 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 39.375 -2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 39.375 2.8125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 33.75 -5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 33.75 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 33.75 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 30.9375 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 36.5625 -5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 33.75 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 33.75 5.625 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 33.75 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 33.75 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 30.9375 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 36.5625 5.625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 33.75 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 22.5 -11.25 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 22.5 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 22.5 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 19.6875 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 25.3125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 22.5 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 22.5 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 22.5 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 22.5 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 19.6875 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 25.3125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 22.5 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 22.5 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 16.875 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 16.875 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 16.875 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 14.0625 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 16.875 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 16.875 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 28.125 -11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 28.125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 28.125 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 30.9375 -11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 28.125 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 28.125 -8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 22.5 -16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 22.5 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 22.5 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 19.6875 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 25.3125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 22.5 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 22.5 11.25 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 22.5 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 22.5 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 19.6875 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 25.3125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 22.5 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 22.5 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 22.5 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 22.5 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 19.6875 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 25.3125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 22.5 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 22.5 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 16.875 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 16.875 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 16.875 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 14.0625 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 16.875 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 16.875 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 28.125 11.25 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 28.125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 28.125 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 30.9375 11.25 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 28.125 8.4375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 28.125 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 22.5 16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 22.5 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 22.5 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 19.6875 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 25.3125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 22.5 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 7.5 0 0 -22.5 0 0 0 0.5625 0 0.1875 0
|
||||
sphere 3.75 -11.25 0 -22.5 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -16.875 0 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -19.6875 0 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 -2.8125 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 2.8125 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 0 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 0 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 -5.625 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 -5.625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 -5.625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -8.4375 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -5.625 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -5.625 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 5.625 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 5.625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 5.625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 8.4375 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 5.625 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 5.625 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 0 -28.125 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 0 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 0 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -2.8125 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 2.8125 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 0 -30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 0 -16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 0 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 0 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -2.8125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 2.8125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 0 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 11.25 0 -22.5 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 16.875 0 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 0 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 -2.8125 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 2.8125 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 0 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 0 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 -5.625 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 -5.625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 -5.625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -8.4375 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -5.625 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -5.625 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 5.625 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 5.625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 5.625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 8.4375 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 5.625 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 5.625 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 0 -28.125 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 0 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 0 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -2.8125 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 2.8125 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 0 -30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 0 -16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 0 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 0 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -2.8125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 2.8125 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 0 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 -11.25 -22.5 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 -11.25 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 -11.25 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -14.0625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -8.4375 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -11.25 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -11.25 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 -11.25 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 -11.25 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -14.0625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -8.4375 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -11.25 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -11.25 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 -16.875 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 -16.875 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 -16.875 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -19.6875 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -16.875 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -16.875 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 -11.25 -28.125 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 -11.25 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 -11.25 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -14.0625 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -8.4375 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -11.25 -30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 -11.25 -16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 -11.25 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 -11.25 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -14.0625 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -8.4375 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -11.25 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 11.25 -22.5 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 11.25 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 11.25 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 8.4375 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 14.0625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 11.25 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 11.25 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 11.25 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 11.25 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 8.4375 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 14.0625 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 11.25 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 11.25 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 16.875 -22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 16.875 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 16.875 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 19.6875 -22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 16.875 -25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 16.875 -19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 11.25 -28.125 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 11.25 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 11.25 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 8.4375 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 14.0625 -28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 11.25 -30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 11.25 -16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 11.25 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 11.25 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 8.4375 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 14.0625 -16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 11.25 -14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 0 -33.75 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 0 -33.75 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 0 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -2.8125 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 2.8125 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 0 -36.5625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 0 -30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 0 -33.75 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 0 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -2.8125 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 2.8125 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 0 -36.5625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 0 -30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 -5.625 -33.75 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 -5.625 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 -5.625 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -8.4375 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -5.625 -36.5625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -5.625 -30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 5.625 -33.75 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 5.625 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 5.625 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 8.4375 -33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 5.625 -36.5625 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 5.625 -30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 0 -39.375 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 0 -39.375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 0 -39.375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -2.8125 -39.375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 2.8125 -39.375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 0 -42.1875 0 0 0 0 0 0.75 0
|
||||
sphere 7.5 0 0 22.5 0 0 0 0.5625 0 0.1875 0
|
||||
sphere 3.75 -11.25 0 22.5 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -16.875 0 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -19.6875 0 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 -2.8125 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 2.8125 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 0 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -16.875 0 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 -5.625 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 -5.625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 -5.625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -8.4375 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -5.625 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -5.625 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 5.625 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 5.625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 5.625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 8.4375 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 5.625 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 5.625 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 0 16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 0 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 0 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -2.8125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 2.8125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 0 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 -11.25 0 28.125 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -14.0625 0 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -8.4375 0 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 -2.8125 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 2.8125 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -11.25 0 30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 11.25 0 22.5 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 16.875 0 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 19.6875 0 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 -2.8125 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 2.8125 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 0 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 16.875 0 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 -5.625 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 -5.625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 -5.625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -8.4375 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -5.625 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -5.625 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 5.625 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 5.625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 5.625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 8.4375 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 5.625 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 5.625 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 0 16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 0 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 0 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -2.8125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 2.8125 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 0 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 11.25 0 28.125 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 0 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 14.0625 0 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 -2.8125 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 2.8125 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 11.25 0 30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 -11.25 22.5 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 -11.25 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 -11.25 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -14.0625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -8.4375 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -11.25 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -11.25 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 -11.25 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 -11.25 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -14.0625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -8.4375 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -11.25 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -11.25 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 -16.875 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 -16.875 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 -16.875 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -19.6875 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -16.875 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -16.875 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 -11.25 16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 -11.25 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 -11.25 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -14.0625 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -8.4375 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -11.25 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 -11.25 28.125 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 -11.25 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 -11.25 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -14.0625 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -8.4375 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -11.25 30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 11.25 22.5 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 11.25 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 11.25 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 8.4375 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 14.0625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 11.25 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 11.25 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 11.25 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 11.25 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 8.4375 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 14.0625 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 11.25 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 11.25 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 16.875 22.5 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 16.875 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 16.875 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 19.6875 22.5 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 16.875 19.6875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 16.875 25.3125 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 11.25 16.875 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 11.25 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 11.25 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 8.4375 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 14.0625 16.875 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 11.25 14.0625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 11.25 28.125 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 11.25 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 11.25 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 8.4375 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 14.0625 28.125 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 11.25 30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 3.75 0 0 33.75 0 0 0 0.375 0 0.375 0
|
||||
sphere 1.875 -5.625 0 33.75 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -8.4375 0 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 -2.8125 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 2.8125 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 0 30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 -5.625 0 36.5625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 5.625 0 33.75 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 8.4375 0 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 -2.8125 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 2.8125 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 0 30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 5.625 0 36.5625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 -5.625 33.75 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 -5.625 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 -5.625 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -8.4375 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -5.625 30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -5.625 36.5625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 5.625 33.75 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 5.625 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 5.625 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 8.4375 33.75 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 5.625 30.9375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 5.625 36.5625 0 0 0 0 0 0.75 0
|
||||
sphere 1.875 0 0 39.375 0 0 0 0.1875 0 0.5625 0
|
||||
sphere 0.9375 -2.8125 0 39.375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 2.8125 0 39.375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 -2.8125 39.375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 2.8125 39.375 0 0 0 0 0 0.75 0
|
||||
sphere 0.9375 0 0 42.1875 0 0 0 0 0 0.75 0
|
11
scenes/cornell.scn
Normal file
11
scenes/cornell.scn
Normal file
@ -0,0 +1,11 @@
|
||||
camera 50 45 205.6 50 44.957388 204.6
|
||||
size 9
|
||||
sphere 10000 10001 40.8 81.6 0 0 0 0.75 .25 0.25 0
|
||||
sphere 10000 -9901 40.8 81.6 0 0 0 0.25 .25 0.75 0
|
||||
sphere 10000 50 40.8 10000 0 0 0 0.75 .75 0.75 0
|
||||
sphere 10000 50 40.8 -9730 0 0 0 0 0 0 0
|
||||
sphere 10000 50 10000 81.6 0 0 0 0.75 .75 0.75 0
|
||||
sphere 10000 50 -9918.4 81.6 0 0 0 0.75 .75 0.75 0
|
||||
sphere 16.5 27 16.5 47 0 0 0 0.9 0.9 0.9 1
|
||||
sphere 16.5 73 16.5 78 0 0 0 0.9 0.9 0.9 2
|
||||
sphere 7 50 66.6 81.6 12 12 12 0 0 0 0
|
11
scenes/cornell_large.scn
Normal file
11
scenes/cornell_large.scn
Normal file
@ -0,0 +1,11 @@
|
||||
camera 50 45 295.6 50 44.957388 294.6
|
||||
size 9
|
||||
sphere 10000 10001 40.8 81.6 0 0 0 0.75 .25 0.25 0
|
||||
sphere 10000 -9801 40.8 81.6 0 0 0 0.25 .25 0.75 0
|
||||
sphere 10000 50 40.8 10000 0 0 0 0.75 .75 0.75 0
|
||||
sphere 10000 50 40.8 -9530 0 0 0 0.75 .75 0.75 0
|
||||
sphere 10000 50 10000 81.6 0 0 0 0.75 .75 0.75 0
|
||||
sphere 10000 50 -9818.4 81.6 0 0 0 0.75 .75 0.75 0
|
||||
sphere 16.5 27 16.5 47 0 0 0 0.9 0.9 0.9 1
|
||||
sphere 16.5 73 16.5 78 0 0 0 0.9 0.9 0.9 2
|
||||
sphere 7 50 66.6 81.6 12 12 12 0 0 0 0
|
7
scenes/simple.scn
Normal file
7
scenes/simple.scn
Normal file
@ -0,0 +1,7 @@
|
||||
camera 20 80 300 0 15 0
|
||||
size 5
|
||||
sphere 1000 0 -1000 0 0 0 0 0.75 0.75 0.75 0
|
||||
sphere 10 35 10 0 0 0 0 0.75 0 0 0
|
||||
sphere 15 -35 15 0 0 0 0 0 0.75 0 0
|
||||
sphere 20 0 20 -35 0 0 0 0 0 0.75 0
|
||||
sphere 8 0 60 0 15 15 15 0 0 0 0
|
53
simplernd.h
Normal file
53
simplernd.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _SIMPLERND_H
|
||||
#define _SIMPLERND_H
|
||||
|
||||
/*
|
||||
* A Simple Random number generator
|
||||
* from http://en.wikipedia.org/wiki/Random_number_generator
|
||||
*/
|
||||
|
||||
#ifndef SMALLPT_GPU
|
||||
|
||||
static float GetRandom(unsigned int *seed0, unsigned int *seed1) {
|
||||
*seed0 = 36969 * ((*seed0) & 65535) + ((*seed0) >> 16);
|
||||
*seed1 = 18000 * ((*seed1) & 65535) + ((*seed1) >> 16);
|
||||
|
||||
unsigned int ires = ((*seed0) << 16) + (*seed1);
|
||||
|
||||
/* Convert to float */
|
||||
union {
|
||||
float f;
|
||||
unsigned int ui;
|
||||
} res;
|
||||
res.ui = (ires & 0x007fffff) | 0x40000000;
|
||||
|
||||
return (res.f - 2.f) / 2.f;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SIMPLERND_H */
|
||||
|
BIN
smallptCPU
Normal file
BIN
smallptCPU
Normal file
Binary file not shown.
175
smallptCPU.c
Normal file
175
smallptCPU.c
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on smallpt, a Path Tracer by Kevin Beason, 2008
|
||||
* Modified by David Bucciarelli to show the output via OpenGL/GLUT, ported
|
||||
* to C, work with float, fixed RR, ported to OpenCL, etc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "camera.h"
|
||||
#include "scene.h"
|
||||
#include "displayfunc.h"
|
||||
|
||||
int workGroupSize = 1;
|
||||
|
||||
static Vec *colors;
|
||||
static unsigned int *seeds;
|
||||
Camera camera;
|
||||
static int currentSample = 0;
|
||||
Sphere *spheres;
|
||||
unsigned int sphereCount;
|
||||
|
||||
void FreeBuffers() {
|
||||
free(seeds);
|
||||
free(colors);
|
||||
free(pixels);
|
||||
}
|
||||
|
||||
void AllocateBuffers() {
|
||||
const int pixelCount = height * width ;
|
||||
int i;
|
||||
colors = malloc(sizeof(Vec[pixelCount]));
|
||||
|
||||
seeds = malloc(sizeof(unsigned int[pixelCount * 2]));
|
||||
for (i = 0; i < pixelCount * 2; i++) {
|
||||
seeds[i] = rand();
|
||||
if (seeds[i] < 2)
|
||||
seeds[i] = 2;
|
||||
}
|
||||
|
||||
pixels = malloc(sizeof(unsigned int[pixelCount]));
|
||||
}
|
||||
|
||||
void UpdateRendering(void) {
|
||||
double startTime = WallClockTime();
|
||||
|
||||
const float invWidth = 1.f / width;
|
||||
const float invHeight = 1.f / height;
|
||||
|
||||
int x, y;
|
||||
for (y = 0; y < height; y++) { /* Loop over image rows */
|
||||
for (x = 0; x < width; x++) { /* Loop cols */
|
||||
const int i = (height - y - 1) * width + x;
|
||||
const int i2 = 2 * i;
|
||||
|
||||
const float r1 = GetRandom(&seeds[i2], &seeds[i2 + 1]) - .5f;
|
||||
const float r2 = GetRandom(&seeds[i2], &seeds[i2 + 1]) - .5f;
|
||||
const float kcx = (x + r1) * invWidth - .5f;
|
||||
const float kcy = (y + r2) * invHeight - .5f;
|
||||
|
||||
Vec rdir;
|
||||
vinit(rdir,
|
||||
camera.x.x * kcx + camera.y.x * kcy + camera.dir.x,
|
||||
camera.x.y * kcx + camera.y.y * kcy + camera.dir.y,
|
||||
camera.x.z * kcx + camera.y.z * kcy + camera.dir.z);
|
||||
|
||||
Vec rorig;
|
||||
vsmul(rorig, 0.1f, rdir);
|
||||
vadd(rorig, rorig, camera.orig)
|
||||
|
||||
vnorm(rdir);
|
||||
const Ray ray = {rorig, rdir};
|
||||
Vec r;
|
||||
RadiancePathTracing(spheres, sphereCount, &ray,
|
||||
&seeds[i2], &seeds[i2 + 1], &r);
|
||||
|
||||
if (currentSample == 0)
|
||||
colors[i] = r;
|
||||
else {
|
||||
const float k1 = currentSample;
|
||||
const float k2 = 1.f / (k1 + 1.f);
|
||||
colors[i].x = (colors[i].x * k1 + r.x) * k2;
|
||||
colors[i].y = (colors[i].y * k1 + r.y) * k2;
|
||||
colors[i].z = (colors[i].z * k1 + r.z) * k2;
|
||||
}
|
||||
|
||||
pixels[y * width + x] = toInt(colors[i].x) |
|
||||
(toInt(colors[i].y) << 8) |
|
||||
(toInt(colors[i].z) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
const float elapsedTime = WallClockTime() - startTime;
|
||||
const float sampleSec = height * width / elapsedTime;
|
||||
sprintf(captionBuffer, "Rendering time %.3f sec (pass %d) Sample/sec %.1fK\n",
|
||||
elapsedTime, currentSample, sampleSec / 1000.f);
|
||||
|
||||
currentSample++;
|
||||
}
|
||||
|
||||
void ReInitScene() {
|
||||
currentSample = 0;
|
||||
}
|
||||
|
||||
void ReInit(const int reallocBuffers) {
|
||||
// Check if I have to reallocate buffers
|
||||
if (reallocBuffers) {
|
||||
FreeBuffers();
|
||||
AllocateBuffers();
|
||||
}
|
||||
|
||||
UpdateCamera();
|
||||
currentSample = 0;
|
||||
UpdateRendering();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
amiSmallptCPU = 1;
|
||||
|
||||
fprintf(stderr, "Usage: %s\n", argv[0]);
|
||||
fprintf(stderr, "Usage: %s <window width> <window height> <scene file>\n", argv[0]);
|
||||
|
||||
if (argc == 4) {
|
||||
width = atoi(argv[1]);
|
||||
height = atoi(argv[2]);
|
||||
ReadScene(argv[3]);
|
||||
} else if (argc == 1) {
|
||||
spheres = CornellSpheres;
|
||||
sphereCount = sizeof(CornellSpheres) / sizeof(Sphere);
|
||||
|
||||
vinit(camera.orig, 50.f, 45.f, 205.6f);
|
||||
vinit(camera.target, 50.f, 45 - 0.042612f, 204.6);
|
||||
} else
|
||||
exit(-1);
|
||||
|
||||
UpdateCamera();
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
AllocateBuffers();
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
InitGlut(argc, argv, "SmallPT CPU V1.6 (Written by David Bucciarelli)");
|
||||
|
||||
glutMainLoop( );
|
||||
|
||||
return 0;
|
||||
}
|
BIN
smallptGPU
Normal file
BIN
smallptGPU
Normal file
Binary file not shown.
862
smallptGPU.c
Normal file
862
smallptGPU.c
Normal file
@ -0,0 +1,862 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on smallpt, a Path Tracer by Kevin Beason, 2008
|
||||
* Modified by David Bucciarelli to show the output via OpenGL/GLUT, ported
|
||||
* to C, work with float, fixed RR, ported to OpenCL, etc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
// Jens's patch for MacOS
|
||||
#ifdef __APPLE__
|
||||
#include <OpenCL/opencl.h>
|
||||
#else
|
||||
#include <CL/cl.h>
|
||||
#endif
|
||||
|
||||
#include "camera.h"
|
||||
#include "scene.h"
|
||||
#include "displayfunc.h"
|
||||
|
||||
/* Options */
|
||||
static int useGPU = 1;
|
||||
static int forceWorkSize = 0;
|
||||
|
||||
/* OpenCL variables */
|
||||
static cl_context context;
|
||||
static cl_mem colorBuffer;
|
||||
static cl_mem pixelBuffer;
|
||||
static cl_mem seedBuffer;
|
||||
static cl_mem sphereBuffer;
|
||||
static cl_mem cameraBuffer;
|
||||
static cl_command_queue commandQueue;
|
||||
static cl_program program;
|
||||
static cl_kernel kernel;
|
||||
static unsigned int workGroupSize = 1;
|
||||
static char *kernelFileName = "rendering_kernel.cl";
|
||||
|
||||
static Vec *colors;
|
||||
static unsigned int *seeds;
|
||||
Camera camera;
|
||||
static int currentSample = 0;
|
||||
Sphere *spheres;
|
||||
unsigned int sphereCount;
|
||||
|
||||
static void FreeBuffers() {
|
||||
cl_int status = clReleaseMemObject(colorBuffer);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to release OpenCL color buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clReleaseMemObject(pixelBuffer);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to release OpenCL pixel buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clReleaseMemObject(seedBuffer);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to release OpenCL seed buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
free(seeds);
|
||||
free(colors);
|
||||
free(pixels);
|
||||
}
|
||||
|
||||
static void AllocateBuffers() {
|
||||
const int pixelCount = width * height;
|
||||
int i;
|
||||
colors = (Vec *)malloc(sizeof(Vec) * pixelCount);
|
||||
|
||||
seeds = (unsigned int *)malloc(sizeof(unsigned int) * pixelCount * 2);
|
||||
for (i = 0; i < pixelCount * 2; i++) {
|
||||
seeds[i] = rand();
|
||||
if (seeds[i] < 2)
|
||||
seeds[i] = 2;
|
||||
}
|
||||
|
||||
pixels = (unsigned int *)malloc(sizeof(unsigned int) * pixelCount);
|
||||
// Test colors
|
||||
for(i = 0; i < pixelCount; ++i)
|
||||
pixels[i] = i;
|
||||
|
||||
cl_int status;
|
||||
cl_uint sizeBytes = sizeof(Vec) * width * height;
|
||||
colorBuffer = clCreateBuffer(
|
||||
context,
|
||||
CL_MEM_READ_WRITE,
|
||||
sizeBytes,
|
||||
NULL,
|
||||
&status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create OpenCL output buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sizeBytes = sizeof(unsigned int) * width * height;
|
||||
pixelBuffer = clCreateBuffer(
|
||||
context,
|
||||
CL_MEM_WRITE_ONLY,
|
||||
sizeBytes,
|
||||
NULL,
|
||||
&status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create OpenCL pixel buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sizeBytes = sizeof(unsigned int) * width * height * 2;
|
||||
seedBuffer = clCreateBuffer(
|
||||
context,
|
||||
CL_MEM_READ_WRITE,
|
||||
sizeBytes,
|
||||
NULL,
|
||||
&status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create OpenCL seed buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
status = clEnqueueWriteBuffer(
|
||||
commandQueue,
|
||||
seedBuffer,
|
||||
CL_TRUE,
|
||||
0,
|
||||
sizeBytes,
|
||||
seeds,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to write the OpenCL seeds buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static char *ReadSources(const char *fileName) {
|
||||
FILE *file = fopen(fileName, "r");
|
||||
if (!file) {
|
||||
fprintf(stderr, "Failed to open file '%s'\n", fileName);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (fseek(file, 0, SEEK_END)) {
|
||||
fprintf(stderr, "Failed to seek file '%s'\n", fileName);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
long size = ftell(file);
|
||||
if (size == 0) {
|
||||
fprintf(stderr, "Failed to check position on file '%s'\n", fileName);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
rewind(file);
|
||||
|
||||
char *src = (char *)malloc(sizeof(char) * size + 1);
|
||||
if (!src) {
|
||||
fprintf(stderr, "Failed to allocate memory for file '%s'\n", fileName);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Reading file '%s' (size %ld bytes)\n", fileName, size);
|
||||
size_t res = fread(src, 1, sizeof(char) * size, file);
|
||||
if (res != sizeof(char) * size) {
|
||||
fprintf(stderr, "Failed to read file '%s' (read %ld)\n", fileName, res);
|
||||
exit(-1);
|
||||
}
|
||||
src[size] = '\0'; /* NULL terminated */
|
||||
|
||||
fclose(file);
|
||||
|
||||
return src;
|
||||
|
||||
}
|
||||
|
||||
static void SetUpOpenCL() {
|
||||
cl_device_type dType;
|
||||
|
||||
if (useGPU)
|
||||
dType = CL_DEVICE_TYPE_GPU;
|
||||
else
|
||||
dType = CL_DEVICE_TYPE_CPU;
|
||||
|
||||
// Select the platform
|
||||
|
||||
cl_uint numPlatforms;
|
||||
cl_platform_id platform = NULL;
|
||||
cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL platforms\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (numPlatforms > 0) {
|
||||
cl_platform_id *platforms = (cl_platform_id *)malloc(sizeof(cl_platform_id) * numPlatforms);
|
||||
status = clGetPlatformIDs(numPlatforms, platforms, NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL platform IDs\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < numPlatforms; ++i) {
|
||||
char pbuf[100];
|
||||
status = clGetPlatformInfo(platforms[i],
|
||||
CL_PLATFORM_VENDOR,
|
||||
sizeof(pbuf),
|
||||
pbuf,
|
||||
NULL);
|
||||
|
||||
status = clGetPlatformIDs(numPlatforms, platforms, NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL platform IDs\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "OpenCL Platform %d: %s\n", i, pbuf);
|
||||
}
|
||||
|
||||
platform = platforms[0];
|
||||
free(platforms);
|
||||
}
|
||||
|
||||
// Select the device
|
||||
|
||||
cl_device_id devices[32];
|
||||
cl_uint deviceCount;
|
||||
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 32, devices, &deviceCount);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device IDs\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int deviceFound = 0;
|
||||
cl_device_id selectedDevice;
|
||||
unsigned int i;
|
||||
for (i = 0; i < deviceCount; ++i) {
|
||||
cl_device_type type = 0;
|
||||
status = clGetDeviceInfo(devices[i],
|
||||
CL_DEVICE_TYPE,
|
||||
sizeof(cl_device_type),
|
||||
&type,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char *stype;
|
||||
switch (type) {
|
||||
case CL_DEVICE_TYPE_ALL:
|
||||
stype = "TYPE_ALL";
|
||||
break;
|
||||
case CL_DEVICE_TYPE_DEFAULT:
|
||||
stype = "TYPE_DEFAULT";
|
||||
break;
|
||||
case CL_DEVICE_TYPE_CPU:
|
||||
stype = "TYPE_CPU";
|
||||
if (!useGPU && !deviceFound) {
|
||||
selectedDevice = devices[i];
|
||||
deviceFound = 1;
|
||||
}
|
||||
break;
|
||||
case CL_DEVICE_TYPE_GPU:
|
||||
stype = "TYPE_GPU";
|
||||
if (useGPU && !deviceFound) {
|
||||
selectedDevice = devices[i];
|
||||
deviceFound = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
stype = "TYPE_UNKNOWN";
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "OpenCL Device %d: Type = %s\n", i, stype);
|
||||
|
||||
char buf[256];
|
||||
status = clGetDeviceInfo(devices[i],
|
||||
CL_DEVICE_NAME,
|
||||
sizeof(char[256]),
|
||||
&buf,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "OpenCL Device %d: Name = %s\n", i, buf);
|
||||
|
||||
cl_uint units = 0;
|
||||
status = clGetDeviceInfo(devices[i],
|
||||
CL_DEVICE_MAX_COMPUTE_UNITS,
|
||||
sizeof(cl_uint),
|
||||
&units,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "OpenCL Device %d: Compute units = %u\n", i, units);
|
||||
|
||||
size_t gsize = 0;
|
||||
status = clGetDeviceInfo(devices[i],
|
||||
CL_DEVICE_MAX_WORK_GROUP_SIZE,
|
||||
sizeof(size_t),
|
||||
&gsize,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "OpenCL Device %d: Max. work group size = %d\n", i, (unsigned int)gsize);
|
||||
}
|
||||
|
||||
if (!deviceFound) {
|
||||
fprintf(stderr, "Unable to select an appropriate device\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Create the context
|
||||
|
||||
cl_context_properties cps[3] = {
|
||||
CL_CONTEXT_PLATFORM,
|
||||
(cl_context_properties) platform,
|
||||
0
|
||||
};
|
||||
|
||||
cl_context_properties *cprops = (NULL == platform) ? NULL : cps;
|
||||
context = clCreateContext(
|
||||
cprops,
|
||||
1,
|
||||
&selectedDevice,
|
||||
NULL,
|
||||
NULL,
|
||||
&status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to open OpenCL context\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Get the device list data */
|
||||
size_t deviceListSize;
|
||||
status = clGetContextInfo(
|
||||
context,
|
||||
CL_CONTEXT_DEVICES,
|
||||
32,
|
||||
devices,
|
||||
&deviceListSize);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL context info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Print devices list */
|
||||
for (i = 0; i < deviceListSize / sizeof(cl_device_id); ++i) {
|
||||
cl_device_type type = 0;
|
||||
status = clGetDeviceInfo(devices[i],
|
||||
CL_DEVICE_TYPE,
|
||||
sizeof(cl_device_type),
|
||||
&type,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char *stype;
|
||||
switch (type) {
|
||||
case CL_DEVICE_TYPE_ALL:
|
||||
stype = "TYPE_ALL";
|
||||
break;
|
||||
case CL_DEVICE_TYPE_DEFAULT:
|
||||
stype = "TYPE_DEFAULT";
|
||||
break;
|
||||
case CL_DEVICE_TYPE_CPU:
|
||||
stype = "TYPE_CPU";
|
||||
break;
|
||||
case CL_DEVICE_TYPE_GPU:
|
||||
stype = "TYPE_GPU";
|
||||
break;
|
||||
default:
|
||||
stype = "TYPE_UNKNOWN";
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "[SELECTED] OpenCL Device %d: Type = %s\n", i, stype);
|
||||
|
||||
char buf[256];
|
||||
status = clGetDeviceInfo(devices[i],
|
||||
CL_DEVICE_NAME,
|
||||
sizeof(char[256]),
|
||||
&buf,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "[SELECTED] OpenCL Device %d: Name = %s\n", i, buf);
|
||||
|
||||
cl_uint units = 0;
|
||||
status = clGetDeviceInfo(devices[i],
|
||||
CL_DEVICE_MAX_COMPUTE_UNITS,
|
||||
sizeof(cl_uint),
|
||||
&units,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "[SELECTED] OpenCL Device %d: Compute units = %u\n", i, units);
|
||||
|
||||
size_t gsize = 0;
|
||||
status = clGetDeviceInfo(devices[i],
|
||||
CL_DEVICE_MAX_WORK_GROUP_SIZE,
|
||||
sizeof(size_t),
|
||||
&gsize,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL device info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "[SELECTED] OpenCL Device %d: Max. work group size = %d\n", i, (unsigned int)gsize);
|
||||
}
|
||||
|
||||
cl_command_queue_properties prop = 0;
|
||||
commandQueue = clCreateCommandQueue(
|
||||
context,
|
||||
devices[0],
|
||||
prop,
|
||||
&status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create OpenCL command queue: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
sphereBuffer = clCreateBuffer(
|
||||
context,
|
||||
#ifdef __APPLE__
|
||||
CL_MEM_READ_WRITE, // NOTE: not READ_ONLY because of Apple's OpenCL bug
|
||||
#else
|
||||
CL_MEM_READ_ONLY,
|
||||
#endif
|
||||
sizeof(Sphere) * sphereCount,
|
||||
NULL,
|
||||
&status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create OpenCL scene buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
status = clEnqueueWriteBuffer(
|
||||
commandQueue,
|
||||
sphereBuffer,
|
||||
CL_TRUE,
|
||||
0,
|
||||
sizeof(Sphere) * sphereCount,
|
||||
spheres,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to write the OpenCL scene buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
cameraBuffer = clCreateBuffer(
|
||||
context,
|
||||
#ifdef __APPLE__
|
||||
CL_MEM_READ_WRITE, // NOTE: not READ_ONLY because of Apple's OpenCL bug
|
||||
#else
|
||||
CL_MEM_READ_ONLY,
|
||||
#endif
|
||||
sizeof(Camera),
|
||||
NULL,
|
||||
&status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create OpenCL camera buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
status = clEnqueueWriteBuffer(
|
||||
commandQueue,
|
||||
cameraBuffer,
|
||||
CL_TRUE,
|
||||
0,
|
||||
sizeof(Camera),
|
||||
&camera,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to write the OpenCL camera buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
AllocateBuffers();
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/* Create the kernel program */
|
||||
const char *sources = ReadSources(kernelFileName);
|
||||
program = clCreateProgramWithSource(
|
||||
context,
|
||||
1,
|
||||
&sources,
|
||||
NULL,
|
||||
&status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to open OpenCL kernel sources: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
status = clBuildProgram(program, 1, devices, "-I. -D__APPLE__", NULL, NULL);
|
||||
#else
|
||||
status = clBuildProgram(program, 1, devices, "-I. ", NULL, NULL);
|
||||
#endif
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to build OpenCL kernel: %d\n", status);
|
||||
|
||||
size_t retValSize;
|
||||
status = clGetProgramBuildInfo(
|
||||
program,
|
||||
devices[0],
|
||||
CL_PROGRAM_BUILD_LOG,
|
||||
0,
|
||||
NULL,
|
||||
&retValSize);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL kernel info size: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char *buildLog = (char *)malloc(retValSize + 1);
|
||||
status = clGetProgramBuildInfo(
|
||||
program,
|
||||
devices[0],
|
||||
CL_PROGRAM_BUILD_LOG,
|
||||
retValSize,
|
||||
buildLog,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL kernel info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
buildLog[retValSize] = '\0';
|
||||
|
||||
fprintf(stderr, "OpenCL Programm Build Log: %s\n", buildLog);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
kernel = clCreateKernel(program, "RadianceGPU", &status);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create OpenCL kernel: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// LordCRC's patch for better workGroupSize
|
||||
size_t gsize = 0;
|
||||
status = clGetKernelWorkGroupInfo(kernel,
|
||||
devices[0],
|
||||
CL_KERNEL_WORK_GROUP_SIZE,
|
||||
sizeof(size_t),
|
||||
&gsize,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to get OpenCL kernel work group size info: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
workGroupSize = (unsigned int) gsize;
|
||||
fprintf(stderr, "OpenCL Device 0: kernel work group size = %d\n", workGroupSize);
|
||||
|
||||
if (forceWorkSize > 0) {
|
||||
fprintf(stderr, "OpenCL Device 0: forced kernel work group size = %d\n", forceWorkSize);
|
||||
workGroupSize = forceWorkSize;
|
||||
}
|
||||
}
|
||||
|
||||
static void ExecuteKernel() {
|
||||
/* Enqueue a kernel run call */
|
||||
size_t globalThreads[1];
|
||||
globalThreads[0] = width * height;
|
||||
if (globalThreads[0] % workGroupSize != 0)
|
||||
globalThreads[0] = (globalThreads[0] / workGroupSize + 1) * workGroupSize;
|
||||
size_t localThreads[1];
|
||||
localThreads[0] = workGroupSize;
|
||||
|
||||
cl_int status = clEnqueueNDRangeKernel(
|
||||
commandQueue,
|
||||
kernel,
|
||||
1,
|
||||
NULL,
|
||||
globalThreads,
|
||||
localThreads,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to enqueue OpenCL work: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateRendering() {
|
||||
double startTime = WallClockTime();
|
||||
int startSampleCount = currentSample;
|
||||
|
||||
/* Set kernel arguments */
|
||||
cl_int status = clSetKernelArg(
|
||||
kernel,
|
||||
0,
|
||||
sizeof(cl_mem),
|
||||
(void *)&colorBuffer);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #1: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clSetKernelArg(
|
||||
kernel,
|
||||
1,
|
||||
sizeof(cl_mem),
|
||||
(void *)&seedBuffer);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #2: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clSetKernelArg(
|
||||
kernel,
|
||||
2,
|
||||
sizeof(cl_mem),
|
||||
(void *)&sphereBuffer);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #3: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clSetKernelArg(
|
||||
kernel,
|
||||
3,
|
||||
sizeof(cl_mem),
|
||||
(void *)&cameraBuffer);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #4: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clSetKernelArg(
|
||||
kernel,
|
||||
4,
|
||||
sizeof(unsigned int),
|
||||
(void *)&sphereCount);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #5: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clSetKernelArg(
|
||||
kernel,
|
||||
5,
|
||||
sizeof(int),
|
||||
(void *)&width);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #6: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clSetKernelArg(
|
||||
kernel,
|
||||
6,
|
||||
sizeof(int),
|
||||
(void *)&height);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #7: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clSetKernelArg(
|
||||
kernel,
|
||||
7,
|
||||
sizeof(int),
|
||||
(void *)¤tSample);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #8: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = clSetKernelArg(
|
||||
kernel,
|
||||
8,
|
||||
sizeof(cl_mem),
|
||||
(void *)&pixelBuffer);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to set OpenCL arg. #9: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
if (currentSample < 20) {
|
||||
ExecuteKernel();
|
||||
currentSample++;
|
||||
} else {
|
||||
/* After first 20 samples, continue to execute kernels for more and more time */
|
||||
const float k = min(currentSample - 20, 100) / 100.f;
|
||||
const float tresholdTime = 0.5f * k;
|
||||
for (;;) {
|
||||
ExecuteKernel();
|
||||
clFinish(commandQueue);
|
||||
currentSample++;
|
||||
|
||||
const float elapsedTime = WallClockTime() - startTime;
|
||||
if (elapsedTime > tresholdTime)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/* Enqueue readBuffer */
|
||||
status = clEnqueueReadBuffer(
|
||||
commandQueue,
|
||||
pixelBuffer,
|
||||
CL_TRUE,
|
||||
0,
|
||||
width * height * sizeof(unsigned int),
|
||||
pixels,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to read the OpenCL pixel buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
const double elapsedTime = WallClockTime() - startTime;
|
||||
const int samples = currentSample - startSampleCount;
|
||||
const double sampleSec = samples * height * width / elapsedTime;
|
||||
sprintf(captionBuffer, "Rendering time %.3f sec (pass %d) Sample/sec %.1fK\n",
|
||||
elapsedTime, currentSample, sampleSec / 1000.f);
|
||||
}
|
||||
|
||||
void ReInitScene() {
|
||||
currentSample = 0;
|
||||
|
||||
// Redownload the scene
|
||||
|
||||
cl_int status = clEnqueueWriteBuffer(
|
||||
commandQueue,
|
||||
sphereBuffer,
|
||||
CL_TRUE,
|
||||
0,
|
||||
sizeof(Sphere) * sphereCount,
|
||||
spheres,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to write the OpenCL scene buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void ReInit(const int reallocBuffers) {
|
||||
// Check if I have to reallocate buffers
|
||||
if (reallocBuffers) {
|
||||
FreeBuffers();
|
||||
UpdateCamera();
|
||||
AllocateBuffers();
|
||||
} else
|
||||
UpdateCamera();
|
||||
|
||||
cl_int status = clEnqueueWriteBuffer(
|
||||
commandQueue,
|
||||
cameraBuffer,
|
||||
CL_TRUE,
|
||||
0,
|
||||
sizeof(Camera),
|
||||
&camera,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (status != CL_SUCCESS) {
|
||||
fprintf(stderr, "Failed to write the OpenCL camera buffer: %d\n", status);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
currentSample = 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
amiSmallptCPU = 0;
|
||||
|
||||
fprintf(stderr, "Usage: %s\n", argv[0]);
|
||||
fprintf(stderr, "Usage: %s <use CPU/GPU device (0=CPU or 1=GPU)> <workgroup size (0=default value or anything > 0 and power of 2)> <kernel file name> <window width> <window height> <scene file>\n", argv[0]);
|
||||
|
||||
if (argc == 7) {
|
||||
useGPU = atoi(argv[1]);
|
||||
forceWorkSize = atoi(argv[2]);
|
||||
kernelFileName = argv[3];
|
||||
width = atoi(argv[4]);
|
||||
height = atoi(argv[5]);
|
||||
ReadScene(argv[6]);
|
||||
} else if (argc == 1) {
|
||||
spheres = CornellSpheres;
|
||||
sphereCount = sizeof(CornellSpheres) / sizeof(Sphere);
|
||||
|
||||
vinit(camera.orig, 50.f, 45.f, 205.6f);
|
||||
vinit(camera.target, 50.f, 45 - 0.042612f, 204.6);
|
||||
} else
|
||||
exit(-1);
|
||||
|
||||
UpdateCamera();
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
SetUpOpenCL();
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
InitGlut(argc, argv, "SmallPT GPU V1.6 (Written by David Bucciarelli)");
|
||||
|
||||
glutMainLoop();
|
||||
|
||||
return 0;
|
||||
}
|
66
vec.h
Normal file
66
vec.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright (c) 2009 David Bucciarelli (davibu@interfree.it)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _VEC_H
|
||||
#define _VEC_H
|
||||
|
||||
typedef struct {
|
||||
float x, y, z; // position, also color (r,g,b)
|
||||
} Vec;
|
||||
|
||||
#define vinit(v, a, b, c) { (v).x = a; (v).y = b; (v).z = c; }
|
||||
#define vassign(a, b) vinit(a, (b).x, (b).y, (b).z)
|
||||
#define vclr(v) vinit(v, 0.f, 0.f, 0.f)
|
||||
#define vadd(v, a, b) vinit(v, (a).x + (b).x, (a).y + (b).y, (a).z + (b).z)
|
||||
#define vsub(v, a, b) vinit(v, (a).x - (b).x, (a).y - (b).y, (a).z - (b).z)
|
||||
#define vsadd(v, a, b) { float k = (a); vinit(v, (b).x + k, (b).y + k, (b).z + k) }
|
||||
#define vssub(v, a, b) { float k = (a); vinit(v, (b).x - k, (b).y - k, (b).z - k) }
|
||||
#define vmul(v, a, b) vinit(v, (a).x * (b).x, (a).y * (b).y, (a).z * (b).z)
|
||||
#define vsmul(v, a, b) { float k = (a); vinit(v, k * (b).x, k * (b).y, k * (b).z) }
|
||||
#define vdot(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z)
|
||||
#define vnorm(v) { float l = 1.f / sqrt(vdot(v, v)); vsmul(v, l, v); }
|
||||
#define vxcross(v, a, b) vinit(v, (a).y * (b).z - (a).z * (b).y, (a).z * (b).x - (a).x * (b).z, (a).x * (b).y - (a).y * (b).x)
|
||||
#define vfilter(v) ((v).x > (v).y && (v).x > (v).z ? (v).x : (v).y > (v).z ? (v).y : (v).z)
|
||||
#define viszero(v) (((v).x == 0.f) && ((v).x == 0.f) && ((v).z == 0.f))
|
||||
|
||||
#ifndef GPU_KERNEL
|
||||
#define clamp(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
|
||||
#define max(x, y) ( (x) > (y) ? (x) : (y))
|
||||
#define min(x, y) ( (x) < (y) ? (x) : (y))
|
||||
#define sign(x) ((x) > 0 ? 1 : -1)
|
||||
#endif
|
||||
|
||||
#define toInt(x) ((int)(pow(clamp(x, 0.f, 1.f), 1.f / 2.2f) * 255.f + .5f))
|
||||
|
||||
// Rendering flags
|
||||
#define RFLAGS_DISABLE_DIFFUSE_PATH 1
|
||||
|
||||
// NOTE: workaround for an Apple OpenCL compiler bug
|
||||
#ifdef __APPLE__
|
||||
#define OCL_CONSTANT_BUFFER __global
|
||||
#else
|
||||
#define OCL_CONSTANT_BUFFER __constant
|
||||
#endif
|
||||
|
||||
#endif /* _VEC_H */
|
||||
|
Loading…
Reference in New Issue
Block a user