rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@2
|
2 #include <string.h>
|
nuclear@2
|
3 #include <math.h>
|
nuclear@2
|
4 #include <errno.h>
|
nuclear@0
|
5 #include <assert.h>
|
nuclear@0
|
6 #include "ocl.h"
|
nuclear@0
|
7
|
nuclear@2
|
8 struct RendInfo {
|
nuclear@2
|
9 int xsz, ysz;
|
nuclear@2
|
10 int num_sph;
|
nuclear@2
|
11 int max_iter;
|
nuclear@2
|
12 } __attribute__((packed));
|
nuclear@2
|
13
|
nuclear@1
|
14 struct Sphere {
|
nuclear@1
|
15 cl_float4 pos;
|
nuclear@1
|
16 cl_float radius;
|
nuclear@1
|
17
|
nuclear@1
|
18 cl_float4 color;
|
nuclear@1
|
19 } __attribute__((packed));
|
nuclear@1
|
20
|
nuclear@1
|
21 struct Ray {
|
nuclear@1
|
22 cl_float4 origin, dir;
|
nuclear@1
|
23 } __attribute__((packed));
|
nuclear@1
|
24
|
nuclear@1
|
25
|
nuclear@2
|
26 Ray get_primary_ray(int x, int y, int w, int h, float vfov_deg);
|
nuclear@2
|
27 bool write_ppm(const char *fname, float *fb, int xsz, int ysz);
|
nuclear@2
|
28
|
nuclear@0
|
29 int main()
|
nuclear@0
|
30 {
|
nuclear@2
|
31 const int xsz = 800;
|
nuclear@2
|
32 const int ysz = 600;
|
nuclear@0
|
33
|
nuclear@2
|
34 Sphere sphlist[] = {
|
nuclear@2
|
35 {{0, 0, 10, 1}, 1.0, {1, 0, 0, 1}}
|
nuclear@2
|
36 };
|
nuclear@2
|
37 RendInfo rinf = {xsz, ysz, sizeof sphlist / sizeof *sphlist, 6};
|
nuclear@2
|
38 Ray *prim_rays = new Ray[xsz * ysz];
|
nuclear@2
|
39 float *fb = new float[xsz * ysz * 4];
|
nuclear@2
|
40
|
nuclear@2
|
41 /* calculate primary rays */
|
nuclear@2
|
42 for(int i=0; i<ysz; i++) {
|
nuclear@2
|
43 for(int j=0; j<xsz; j++) {
|
nuclear@2
|
44 prim_rays[i * xsz + j] = get_primary_ray(j, i, xsz, ysz, 45.0);
|
nuclear@2
|
45 }
|
nuclear@0
|
46 }
|
nuclear@0
|
47
|
nuclear@2
|
48 /* setup opencl */
|
nuclear@2
|
49 CLProgram prog("render");
|
nuclear@2
|
50 if(!prog.load("rt.cl")) {
|
nuclear@0
|
51 return 1;
|
nuclear@0
|
52 }
|
nuclear@0
|
53
|
nuclear@2
|
54 prog.set_arg_buffer(0, ARG_WR, xsz * ysz * 4 * sizeof(float), fb);
|
nuclear@2
|
55 prog.set_arg_buffer(1, ARG_RD, sizeof rinf, &rinf);
|
nuclear@2
|
56 prog.set_arg_buffer(2, ARG_RD, sizeof sphlist, sphlist);
|
nuclear@2
|
57 prog.set_arg_buffer(3, ARG_RD, xsz * ysz * sizeof *prim_rays, prim_rays);
|
nuclear@2
|
58
|
nuclear@2
|
59 if(!prog.run(1, xsz * ysz)) {
|
nuclear@0
|
60 return 1;
|
nuclear@0
|
61 }
|
nuclear@0
|
62
|
nuclear@2
|
63 CLMemBuffer *mbuf = prog.get_arg_buffer(0);
|
nuclear@0
|
64 map_mem_buffer(mbuf, MAP_RD);
|
nuclear@2
|
65 if(!write_ppm("out.ppm", fb, xsz, ysz)) {
|
nuclear@2
|
66 return 1;
|
nuclear@2
|
67 }
|
nuclear@2
|
68 unmap_mem_buffer(mbuf);
|
nuclear@0
|
69
|
nuclear@2
|
70 delete [] fb;
|
nuclear@2
|
71 delete [] prim_rays;
|
nuclear@0
|
72
|
nuclear@0
|
73 return 0;
|
nuclear@0
|
74 }
|
nuclear@2
|
75
|
nuclear@2
|
76 Ray get_primary_ray(int x, int y, int w, int h, float vfov_deg)
|
nuclear@2
|
77 {
|
nuclear@2
|
78 float vfov = M_PI * vfov_deg / 180.0;
|
nuclear@2
|
79 float aspect = (float)w / (float)h;
|
nuclear@2
|
80
|
nuclear@2
|
81 float ysz = 2.0;
|
nuclear@2
|
82 float xsz = aspect * ysz;
|
nuclear@2
|
83
|
nuclear@2
|
84 float px = ((float)x / (float)w) * xsz - xsz / 2.0;
|
nuclear@2
|
85 float py = 1.0 - ((float)y / (float)h) * ysz;
|
nuclear@2
|
86 float pz = 1.0 / tan(0.5 * vfov);
|
nuclear@2
|
87
|
nuclear@2
|
88 pz *= 1000.0;
|
nuclear@2
|
89
|
nuclear@2
|
90 Ray ray = {{0, 0, 0, 1}, {px, py, pz, 1}};
|
nuclear@2
|
91 return ray;
|
nuclear@2
|
92 }
|
nuclear@2
|
93
|
nuclear@2
|
94 bool write_ppm(const char *fname, float *fb, int xsz, int ysz)
|
nuclear@2
|
95 {
|
nuclear@2
|
96 FILE *fp;
|
nuclear@2
|
97
|
nuclear@2
|
98 if(!(fp = fopen(fname, "wb"))) {
|
nuclear@2
|
99 fprintf(stderr, "write_ppm: failed to open file %s for writing: %s\n", fname, strerror(errno));
|
nuclear@2
|
100 return false;
|
nuclear@2
|
101 }
|
nuclear@2
|
102 fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
|
nuclear@2
|
103
|
nuclear@2
|
104 for(int i=0; i<xsz * ysz * 4; i++) {
|
nuclear@2
|
105 if(i % 4 == 3) continue;
|
nuclear@2
|
106
|
nuclear@2
|
107 unsigned char c = (unsigned char)(fb[i] * 255.0);
|
nuclear@2
|
108 fputc(c, fp);
|
nuclear@2
|
109 }
|
nuclear@2
|
110 fclose(fp);
|
nuclear@2
|
111 return true;
|
nuclear@2
|
112 }
|