-
Notifications
You must be signed in to change notification settings - Fork 0
/
ColorOnly.cl
107 lines (91 loc) · 2.65 KB
/
ColorOnly.cl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
__constant float EPS = 1e-3;
typedef struct Ray {
float3 pos;
float3 dir;
} Ray;
typedef struct Cam {
float theta;
float width;
float height;
float3 pos;
float3 up;
float3 lookAt;
} Cam;
typedef struct Material {
float refraction;
float reflection;
float diffuse;
float3 color;
} Material;
typedef struct Sphere {
float radius;
float3 pos;
Material mat;
} Sphere;
Ray getPixelRay(__constant Cam* cam, int x, int y) {
Ray ret;
float3 w = -normalize(cam->lookAt);
float3 v = normalize(cam->up);
float3 u = cross(v, w);
float halfHeight = cam->height / 2;
float halfWidth = cam->width / 2;
float distance = halfHeight / tan(cam->theta / 2);
float3 eyePos = cam->pos + w * distance;
float3 leftBottomPos = cam->pos - v * halfHeight - u * halfWidth;
float tu = (float)x / get_global_size(0);
float tv = 1.0 - (float)y / get_global_size(1);
ret.pos = leftBottomPos + tu * cam->width * u + tv * cam->height * v;
ret.dir = normalize(ret.pos - eyePos);
return ret;
}
float getFirstCollideWithSphere(const Ray* ray, const Sphere* sphere) {
float a = pow(ray->dir.x, 2) + pow(ray->dir.y, 2) + pow(ray->dir.z, 2);
float b = 2 * (ray->dir.x * (ray->pos.x - sphere->pos.x)
+ ray->dir.y * (ray->pos.y - sphere->pos.y)
+ ray->dir.z * (ray->pos.z - sphere->pos.z));
float c = pow(ray->pos.x - sphere->pos.x, 2)
+ pow(ray->pos.y - sphere->pos.y, 2)
+ pow(ray->pos.z - sphere->pos.z, 2)
- pow(sphere->radius, 2);
float delta = b * b - 4 * a * c;
if (delta <= 0) return -1;
delta = sqrt(delta);
float t = (-b - delta) / (2 * a);
if (t > EPS) return t;
t = (-b + delta) / (2 * a);
if (t > EPS) return t;
return -1;
}
float3 getFirstCollide(const Ray* ray, __constant Sphere* sphere, const int sphereSize, int* id) {
*id = -1;
float mm = 0;
for (int i = 0; i < sphereSize; i++)
{
Sphere nows = sphere[i];
float t = getFirstCollideWithSphere(ray, &nows);
if (t == -1) continue;
if (mm == 0 || t < mm) {
mm = t;
*id = i;
}
}
return ray->pos + mm * ray->dir;
}
float3 emitRay(Ray ray, __constant Sphere* sphere, const int sphereSize) {
int id;
float3 pos = getFirstCollide(&ray, sphere, sphereSize, &id);
if (id == -1)
return (float3)(0, 0, 0);
float3 color = (float3)(0, 0, 0);
color += sphere[id].mat.color;
return color;
}
__kernel void kernelMain(__global uchar3* pixels, __constant Sphere* sphere, const int sphereSize, __constant Cam* cam) {
int2 coord = (int2)(get_global_id(0), get_global_id(1));
uint idx = coord.y * get_global_size(0) + coord.x;
Ray startRay = getPixelRay(cam, coord.x, coord.y);
float3 color = emitRay(startRay, sphere, sphereSize);
pixels[idx].x = color.x;
pixels[idx].y = color.y;
pixels[idx].z = color.z;
}