PandA-2024.02
simple_raytrace.c
Go to the documentation of this file.
1 #include <math.h>
2 
3 // Print data at the exit point
4 void print(int x);
5 void print2(int arg0, int arg1);
6 // Used to simulate set_pixel x,y,color
7 void print3(int arg0, int arg1, int arg2);
8 
9 typedef float float3 __attribute__((vector_size(16)));
10 typedef float float4 __attribute__((vector_size(16)));
11 
12 float dot3f(float3 a, float3 b)
13 {
14  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
15 }
16 
17 // Similar to OpenCL, there are
18 // built-in vector types float1,...,float4
19 // and functions like dot3f for dot-product
20 struct Node;
21 struct Intersection;
22 
23 // Stores one object of the scene
24 struct Node
25 {
26  // position
27  float4 pos;
28 
29  // intersection function
30  struct Intersection (*intersect)(struct Node *node, float3 start, float3 dir);
31 
32  // left child node
33  int left;
34 
35  // right child node
36  int right;
37 
38  // color rgb
39  float3 color;
40 };
41 
42 // Represents an intersection between a
43 // ray and the scene
45 {
46  float dist; // distance from the start
47  float3 color; // color at this position
48 };
49 
50 // intersection functions for all three types
52 (struct Node *node, float3 start, float3 dir);
54 (struct Node *node, float3 start, float3 dir);
56 (struct Node *node, float3 start, float3 dir);
57 
58 // raytracing function
59 float3 raytrace_color(float3 start, float3 dir);
60 
61 // Array containing scene objects
62 struct Node nodes[7] =
63 {
64  { (float4){0,1,0,0}, plane_intersect,
65  0, 0, (float3){1,0,0} },
66  { (float4){0,1,2,1}, sphere_intersect,
67  0, 0, (float3){0,0,1} },
68  { (float4){1,0,0,1}, node_intersect,
69  0, 1, (float3){1,1,1} },
70  { (float4){-2,1,2,1}, sphere_intersect,
71  0, 0, (float3){0,1,0} },
72  { (float4){1,0,0,1}, node_intersect,
73  3, 2, (float3){1,1,1} },
74  { (float4){2,1,2,1}, sphere_intersect,
75  0, 0, (float3){0,1,1} },
76  { (float4){1,0,0,1}, node_intersect,
77  4, 5, (float3){1,1,1} }
78 };
79 
80 // Helper function to construct an
81 // intersection structure
82 struct Intersection intersection
83 (float dist, float3 color)
84 {
85  struct Intersection result;
86  result.dist = dist;
87  result.color = color;
88  return result;
89 }
90 
91 // Generates a checkerboard pattern mapped
92 // onto the XY plane
93 float3 get_color(float3 pos)
94 {
95  int ix = fabs(pos[0]);
96  int iy = fabs(pos[1]);
97  int iz = fabs(pos[2]);
98  return ((ix ^ iz) & 1) ?
99  (float3){1,0,0} :
100  (float3){0.25,0,0};
101 }
102 
103 // Calculates intersection between a
104 // plane and the ray start + t * dir
105 struct Intersection plane_intersect
106 (struct Node *node, float3 start, float3 dir)
107 {
108  // Solves the following system:
109  // ray(t) = start + t * dir
110  // plane: dot(plane.xyz, x) + plane.w = 0
111 
112  float4 plane = node->pos;
113  float n_dot_dir = dot3f(plane, dir);
114  float n_dot_start = dot3f(plane, start);
115 
116  // Solve for parameter t of the ray
117  // We ignore the case n_dot_dir==0
118  float t = (-plane[3] - n_dot_start)
119  / n_dot_dir;
120  // p is the intersection point
121  float3 p = start + t * dir;
122  // Calculate color at position p
123  float3 c = get_color(p);
124 
125  return intersection(t, c);
126 }
127 
128 // Calculates intersection between a
129 // sphere and the ray start + t * dir
130 struct Intersection sphere_intersect
131 (struct Node *node, float3 start, float3 dir)
132 {
133  float4 pos = node->pos;
134 
135  // The position vector contains the center
136  // the sphere and the squared radius in w
137  float3 center = pos;
138  float squared_radius = pos[3];
139 
140  // Solves the following system
141  // ray(t) = start + t * dir
142  // sphere: (p-center)^2 == squared_radius
143  float3 v = start - center;
144 
145  float a = dot3f(dir, dir);
146  float b = 2 * dot3f(v, dir);
147  float c = dot3f(v,v) - squared_radius;
148  // Determinant of the quadratic equation
149  float det = b * b - 4 * a * c;
150  // There is not intersection point
151  if (det < 0)
152  {
153  return intersection(det, (float3){0,0,0});
154  }
155 
156  // One or two intersection points exists
157  float s = sqrt(det);
158 
159  // Calculate parameter t of both points
160  float t0 = (-b + s) / (2 * a);
161  float t1 = (-b - s) / (2 * a);
162 
163  // Choose nearest intersection point
164  float dist = t0 < t1 ? t0 : t1;
165 
166  // Calculate actual position
167  float3 n = v + dist * dir;
168  // Perform simple lighting
169  float diffuse = fabs(n[0] - n[1] + n[2]);
170 
171  // Clamp diffuse to [0..1]
172  diffuse = diffuse < 0 ? 0 : diffuse;
173  diffuse = diffuse > 1.0 ? 1.0 : diffuse;
174 
175  // Multiply diffuse light with sphere color
176  return intersection(dist,
177  diffuse * node->color);
178 }
179 
180 // Intersection function for scene node
181 // Invokes intersection function of it childs
182 // and returns the nearest intersection point
183 struct Intersection node_intersect
184 (struct Node *node, float3 start, float3 dir)
185 {
186  struct Intersection a, b;
187  int left = node->left;
188  int right = node->right;
189 
190  // Call intersect on child nodes
191  a = nodes[left].
192  intersect(&nodes[left], start, dir);
193  b = nodes[right].
194  intersect(&nodes[right], start, dir);
195 
196  if (a.dist < 0)
197  return b;
198 
199  if (b.dist < 0)
200  return a;
201 
202  return (a.dist < b.dist) ? a : b;
203 }
204 
205 // Calculates the direction of the ray
206 // at screen position (x,y)
207 float3 view_vec(int x, int y)
208 {
209  float vx = (2.0/31.0) * x - 1.0;
210  float vy = (-2.0/31.0) * y + 1.0;
211  return (float3){vx, vy, 1};
212 }
213 
214 // Packs floating point RGB color
215 // into integer value
216 int rgb(float r, float g, float b)
217 {
218  return (int)(r * 255)
219  + ((int)(g * 255) << 8)
220  + ((int)(b * 255) << 16);
221 }
222 
223 // Sends a ray into the scene and returns
224 // the color of the nearest intersection
225 // or black if no intersection was found
226 float3 raytrace_color
227 (float3 start, float3 dir)
228 {
229  struct Intersection i, i0, i1;
230  i = nodes[6].intersect
231  (&nodes[6], start, dir);
232  return i.dist < 0.0
233  ? (float3){0,0,0}
234  : i.color;
235 }
236 
237 // entry function invoked by the test bench
238 // Calculates the color for pixel (x,y)
239 void raytrace(int x, int y)
240 {
241  // Get ray direction for pixel (x,y)
242  float3 v = view_vec(x,y);
243 
244  // Camera position is (0,1,0)
245  float3 start = (float3){0,1,0};
246 
247  float3 color = raytrace_color(start, v);
248 
249  // Convert color into packed integer
250  int c = rgb(color[0], color[1], color[2]);
251 
252  // Set color of pixel (x,y) to c
253  print3(x,y, c);
254 }
struct Node nodes[7]
int left
struct Intersection sphere_intersect(struct Node *node, float3 start, float3 dir)
void raytrace(int x, int y)
struct Intersection(* intersect)(struct Node *node, float3 start, float3 dir)
struct Intersection intersection(float dist, float3 color)
int right
float3 get_color(float3 pos)
struct Intersection plane_intersect(struct Node *node, float3 start, float3 dir)
void print(int x)
float float3 __attribute__((vector_size(16)))
int result[SIZE]
Definition: adpcm.c:800
float3 view_vec(int x, int y)
float dot3f(float3 a, float3 b)
struct Intersection node_intersect(struct Node *node, float3 start, float3 dir)
float3 raytrace_color(float3 start, float3 dir)
void print3(int arg0, int arg1, int arg2)
x
Return the smallest n such that 2^n >= _x.
float4 pos
float3 color
int rgb(float r, float g, float b)
void print2(int arg0, int arg1)

Generated on Mon Feb 12 2024 13:02:49 for PandA-2024.02 by doxygen 1.8.13