Normalise indentation (spaces vs tabs)
This commit is contained in:
parent
c02be0fa2f
commit
e00649fc05
1 changed files with 253 additions and 253 deletions
506
tinyray.c
506
tinyray.c
|
@ -18,61 +18,61 @@ typedef unsigned char byte;
|
||||||
|
|
||||||
/* Minimal Floating Point Vector Maths - Author: Matthew Jakeman */
|
/* Minimal Floating Point Vector Maths - Author: Matthew Jakeman */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
} Vec3;
|
} Vec3;
|
||||||
|
|
||||||
Vec3 vec3_new(float x, float y, float z) {
|
Vec3 vec3_new(float x, float y, float z) {
|
||||||
Vec3 vec;
|
Vec3 vec;
|
||||||
vec.x = x;
|
vec.x = x;
|
||||||
vec.y = y;
|
vec.y = y;
|
||||||
vec.z = z;
|
vec.z = z;
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 vec3_add(Vec3 a, Vec3 b) {
|
Vec3 vec3_add(Vec3 a, Vec3 b) {
|
||||||
return vec3_new(a.x + b.x, a.y + b.y, a.z + b.z);
|
return vec3_new(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 vec3_subtract(Vec3 a, Vec3 b) {
|
Vec3 vec3_subtract(Vec3 a, Vec3 b) {
|
||||||
return vec3_new(a.x - b.x, a.y - b.y, a.z - b.z);
|
return vec3_new(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 vec3_subtract_scalar(Vec3 a, float b) {
|
Vec3 vec3_subtract_scalar(Vec3 a, float b) {
|
||||||
return vec3_new(a.x - b, a.y - b, a.z - b);
|
return vec3_new(a.x - b, a.y - b, a.z - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 vec3_divide_scalar(Vec3 a, float b) {
|
Vec3 vec3_divide_scalar(Vec3 a, float b) {
|
||||||
return vec3_new(a.x/b, a.y/b, a.z/b);
|
return vec3_new(a.x/b, a.y/b, a.z/b);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 vec3_multiply(Vec3 a, Vec3 b) {
|
Vec3 vec3_multiply(Vec3 a, Vec3 b) {
|
||||||
return vec3_new(a.x*b.x, a.y*b.y, a.z*b.z);
|
return vec3_new(a.x*b.x, a.y*b.y, a.z*b.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 vec3_multiply_scalar(Vec3 a, float b) {
|
Vec3 vec3_multiply_scalar(Vec3 a, float b) {
|
||||||
return vec3_new(a.x*b, a.y*b, a.z*b);
|
return vec3_new(a.x*b, a.y*b, a.z*b);
|
||||||
}
|
}
|
||||||
|
|
||||||
float vec3_dot(Vec3 a, Vec3 b) {
|
float vec3_dot(Vec3 a, Vec3 b) {
|
||||||
return a.x*b.x + a.y*b.y + a.z*b.z;
|
return a.x*b.x + a.y*b.y + a.z*b.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
float vec3_len(Vec3 v) {
|
float vec3_len(Vec3 v) {
|
||||||
return (float)sqrtf((v.x * v.x) + (v.y * v.y) + (v.z * v.z));
|
return (float)sqrtf((v.x * v.x) + (v.y * v.y) + (v.z * v.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 vec3_normalise(Vec3 v) {
|
Vec3 vec3_normalise(Vec3 v) {
|
||||||
return vec3_divide_scalar(v, vec3_len(v)); // Calculate unit vector
|
return vec3_divide_scalar(v, vec3_len(v)); // Calculate unit vector
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 vec3_clamp(Vec3 v, float min_value, float max_value) {
|
Vec3 vec3_clamp(Vec3 v, float min_value, float max_value) {
|
||||||
return vec3_new(
|
return vec3_new(
|
||||||
fmin(fmax(v.x, min_value), max_value),
|
fmin(fmax(v.x, min_value), max_value),
|
||||||
fmin(fmax(v.y, min_value), max_value),
|
fmin(fmax(v.y, min_value), max_value),
|
||||||
fmin(fmax(v.z, min_value), max_value)
|
fmin(fmax(v.z, min_value), max_value)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// END - vectors
|
// END - vectors
|
||||||
|
|
||||||
|
@ -80,32 +80,32 @@ Vec3 vec3_clamp(Vec3 v, float min_value, float max_value) {
|
||||||
typedef Vec3 RgbColour;
|
typedef Vec3 RgbColour;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
RgbColour diffuse;
|
RgbColour diffuse;
|
||||||
float specular;
|
float specular;
|
||||||
} Material;
|
} Material;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Vec3 centre;
|
Vec3 centre;
|
||||||
float radius;
|
float radius;
|
||||||
Material material;
|
Material material;
|
||||||
} Sphere;
|
} Sphere;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Vec3 origin;
|
Vec3 origin;
|
||||||
Vec3 direction;
|
Vec3 direction;
|
||||||
} Ray;
|
} Ray;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PointLight,
|
PointLight,
|
||||||
DirectionalLight,
|
DirectionalLight,
|
||||||
AmbientLight
|
AmbientLight
|
||||||
} LightType;
|
} LightType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LightType type;
|
LightType type;
|
||||||
Vec3 position; // point only
|
Vec3 position; // point only
|
||||||
Vec3 direction; // directional only
|
Vec3 direction; // directional only
|
||||||
float intensity;
|
float intensity;
|
||||||
} Light;
|
} Light;
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
|
@ -118,48 +118,48 @@ const static unsigned int HEIGHT = 600;
|
||||||
|
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
Sphere sphere_new(Vec3 centre, float radius, Material material) {
|
Sphere sphere_new(Vec3 centre, float radius, Material material) {
|
||||||
Sphere sphere = {0};
|
Sphere sphere = {0};
|
||||||
sphere.centre = centre;
|
sphere.centre = centre;
|
||||||
sphere.radius = radius;
|
sphere.radius = radius;
|
||||||
sphere.material = material;
|
sphere.material = material;
|
||||||
return sphere;
|
return sphere;
|
||||||
}
|
}
|
||||||
|
|
||||||
Light light_point_new(float intensity, Vec3 position) {
|
Light light_point_new(float intensity, Vec3 position) {
|
||||||
Light light = {0};
|
Light light = {0};
|
||||||
light.type = PointLight;
|
light.type = PointLight;
|
||||||
light.position = position;
|
light.position = position;
|
||||||
light.intensity = intensity;
|
light.intensity = intensity;
|
||||||
return light;
|
return light;
|
||||||
}
|
}
|
||||||
|
|
||||||
Light light_ambient_new(float intensity) {
|
Light light_ambient_new(float intensity) {
|
||||||
Light light = {0};
|
Light light = {0};
|
||||||
light.type = AmbientLight;
|
light.type = AmbientLight;
|
||||||
light.intensity = intensity;
|
light.intensity = intensity;
|
||||||
return light;
|
return light;
|
||||||
}
|
}
|
||||||
|
|
||||||
Light light_directional_new(float intensity, Vec3 direction) {
|
Light light_directional_new(float intensity, Vec3 direction) {
|
||||||
Light light = {0};
|
Light light = {0};
|
||||||
light.type = DirectionalLight;
|
light.type = DirectionalLight;
|
||||||
light.direction = direction;
|
light.direction = direction;
|
||||||
light.intensity = intensity;
|
light.intensity = intensity;
|
||||||
return light;
|
return light;
|
||||||
}
|
}
|
||||||
|
|
||||||
Material material_new(Vec3 diffuse, float specular) {
|
Material material_new(Vec3 diffuse, float specular) {
|
||||||
Material material = {0};
|
Material material = {0};
|
||||||
material.diffuse = diffuse;
|
material.diffuse = diffuse;
|
||||||
material.specular = specular;
|
material.specular = specular;
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ray ray_new(Vec3 origin, Vec3 direction) {
|
Ray ray_new(Vec3 origin, Vec3 direction) {
|
||||||
Ray ray;
|
Ray ray;
|
||||||
ray.origin = origin;
|
ray.origin = origin;
|
||||||
ray.direction = direction;
|
ray.direction = direction;
|
||||||
return ray;
|
return ray;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lighting Compute Algorithm
|
// Lighting Compute Algorithm
|
||||||
|
@ -171,50 +171,50 @@ Ray ray_new(Vec3 origin, Vec3 direction) {
|
||||||
// RETURNS:
|
// RETURNS:
|
||||||
// - intensity of light
|
// - intensity of light
|
||||||
float lighting_compute(Vec3 point, Vec3 normal,
|
float lighting_compute(Vec3 point, Vec3 normal,
|
||||||
Vec3 view, float specular,
|
Vec3 view, float specular,
|
||||||
Light *lights, int num_lights) {
|
Light *lights, int num_lights) {
|
||||||
|
|
||||||
// Intensity of light for the given pixel
|
// Intensity of light for the given pixel
|
||||||
float intensity = 0.0f;
|
float intensity = 0.0f;
|
||||||
|
|
||||||
// Iterate over lights
|
// Iterate over lights
|
||||||
for (int i = 0; i < num_lights; i++)
|
for (int i = 0; i < num_lights; i++)
|
||||||
{
|
{
|
||||||
Light *light = &lights[i];
|
Light *light = &lights[i];
|
||||||
if (light->type == AmbientLight)
|
if (light->type == AmbientLight)
|
||||||
{
|
{
|
||||||
// Simply add ambient light to total
|
// Simply add ambient light to total
|
||||||
intensity += light->intensity;
|
intensity += light->intensity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Vec3 light_ray;
|
Vec3 light_ray;
|
||||||
if (light->type == PointLight)
|
if (light->type == PointLight)
|
||||||
// Point Light: Direction of ray from light to point
|
// Point Light: Direction of ray from light to point
|
||||||
light_ray = vec3_subtract(light->position, point);
|
light_ray = vec3_subtract(light->position, point);
|
||||||
else
|
else
|
||||||
// Directional Light: Direction
|
// Directional Light: Direction
|
||||||
light_ray = light->direction;
|
light_ray = light->direction;
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
float reflect = vec3_dot(normal, light_ray);
|
float reflect = vec3_dot(normal, light_ray);
|
||||||
intensity += (light->intensity * reflect)/(vec3_len(normal) * vec3_len(light_ray));
|
intensity += (light->intensity * reflect)/(vec3_len(normal) * vec3_len(light_ray));
|
||||||
|
|
||||||
// Specular
|
// Specular
|
||||||
if (specular != -1)
|
if (specular != -1)
|
||||||
{
|
{
|
||||||
Vec3 r = vec3_subtract(vec3_multiply_scalar(normal, 2 * vec3_dot(normal, light_ray)), light_ray);
|
Vec3 r = vec3_subtract(vec3_multiply_scalar(normal, 2 * vec3_dot(normal, light_ray)), light_ray);
|
||||||
float reflect_view_proj = vec3_dot(r, view);
|
float reflect_view_proj = vec3_dot(r, view);
|
||||||
if (reflect_view_proj > 0)
|
if (reflect_view_proj > 0)
|
||||||
{
|
{
|
||||||
float cosine = reflect_view_proj/(vec3_len(r) * vec3_len(view));
|
float cosine = reflect_view_proj/(vec3_len(r) * vec3_len(view));
|
||||||
intensity += light->intensity * powf(cosine, specular);
|
intensity += light->intensity * powf(cosine, specular);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return intensity;
|
return intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sphere-Ray Intersection
|
// Sphere-Ray Intersection
|
||||||
|
@ -227,40 +227,40 @@ float lighting_compute(Vec3 point, Vec3 normal,
|
||||||
// - boolean of whether ray intersected a sphere
|
// - boolean of whether ray intersected a sphere
|
||||||
// - [out] dist0, dist 1 = perpendicular distances to points of intersection
|
// - [out] dist0, dist 1 = perpendicular distances to points of intersection
|
||||||
int do_sphere_raycast(Sphere sphere, Ray ray, float *dist0, float *dist1) {
|
int do_sphere_raycast(Sphere sphere, Ray ray, float *dist0, float *dist1) {
|
||||||
|
|
||||||
// Please see sphere_ray_intersection.bmp
|
// Please see sphere_ray_intersection.bmp
|
||||||
*dist0 = 0;
|
*dist0 = 0;
|
||||||
*dist1 = 0;
|
*dist1 = 0;
|
||||||
|
|
||||||
// Find L and tca
|
// Find L and tca
|
||||||
Vec3 L = vec3_subtract(sphere.centre, ray.origin);
|
Vec3 L = vec3_subtract(sphere.centre, ray.origin);
|
||||||
float tca = vec3_dot(L, ray.direction);
|
float tca = vec3_dot(L, ray.direction);
|
||||||
|
|
||||||
// Discard if intersection is behind origin
|
// Discard if intersection is behind origin
|
||||||
if (tca < 0)
|
if (tca < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Find d
|
// Find d
|
||||||
float d = sqrtf(vec3_dot(L, L) - tca * tca);
|
float d = sqrtf(vec3_dot(L, L) - tca * tca);
|
||||||
if (d > sphere.radius)
|
if (d > sphere.radius)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Calculate thc using pythagoras
|
// Calculate thc using pythagoras
|
||||||
float thc = sqrtf(sphere.radius * sphere.radius - d * d);
|
float thc = sqrtf(sphere.radius * sphere.radius - d * d);
|
||||||
|
|
||||||
// Calculate t0 and t1 (perpendicular distance to
|
// Calculate t0 and t1 (perpendicular distance to
|
||||||
// the 0th and 1st intersection)
|
// the 0th and 1st intersection)
|
||||||
float t0 = tca - thc;
|
float t0 = tca - thc;
|
||||||
float t1 = tca + thc;
|
float t1 = tca + thc;
|
||||||
|
|
||||||
// Ensure at least one of t0 and t1 is greater than zero
|
// Ensure at least one of t0 and t1 is greater than zero
|
||||||
if (t0 < 0 && t1 < 0)
|
if (t0 < 0 && t1 < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*dist0 = t0;
|
*dist0 = t0;
|
||||||
*dist1 = t1;
|
*dist1 = t1;
|
||||||
|
|
||||||
return 1; // Intersection found
|
return 1; // Intersection found
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raytrace Scene at Point
|
// Raytrace Scene at Point
|
||||||
|
@ -274,64 +274,64 @@ int do_sphere_raycast(Sphere sphere, Ray ray, float *dist0, float *dist1) {
|
||||||
// RETURNS:
|
// RETURNS:
|
||||||
// - rgb colour of pixel being raytraced
|
// - rgb colour of pixel being raytraced
|
||||||
RgbColour raytrace(Vec3 origin, Vec3 dir, float min_t, float max_t,
|
RgbColour raytrace(Vec3 origin, Vec3 dir, float min_t, float max_t,
|
||||||
Sphere *spheres, int num_spheres,
|
Sphere *spheres, int num_spheres,
|
||||||
Light *lights, int num_lights) {
|
Light *lights, int num_lights) {
|
||||||
|
|
||||||
// Closest sphere to screen (for depth-testing)
|
// Closest sphere to screen (for depth-testing)
|
||||||
Sphere *closest = 0;
|
Sphere *closest = 0;
|
||||||
|
|
||||||
// We use t_comp to store the t-depth of the closest
|
// We use t_comp to store the t-depth of the closest
|
||||||
// sphere and compare it with other spheres to perform
|
// sphere and compare it with other spheres to perform
|
||||||
// primitive depth testing (where 't' is perpendicular
|
// primitive depth testing (where 't' is perpendicular
|
||||||
// distance to the point of intersection)
|
// distance to the point of intersection)
|
||||||
float t_comp = (float)MAX_DIST;
|
float t_comp = (float)MAX_DIST;
|
||||||
|
|
||||||
// Ray to test
|
// Ray to test
|
||||||
Ray ray = ray_new(origin, dir);
|
Ray ray = ray_new(origin, dir);
|
||||||
|
|
||||||
// Cycle through all spheres and depth-test
|
// Cycle through all spheres and depth-test
|
||||||
for (int i = 0; i < num_spheres; i++)
|
for (int i = 0; i < num_spheres; i++)
|
||||||
{
|
{
|
||||||
float dist0, dist1;
|
float dist0, dist1;
|
||||||
if (do_sphere_raycast(spheres[i], ray, &dist0, &dist1))
|
if (do_sphere_raycast(spheres[i], ray, &dist0, &dist1))
|
||||||
{
|
{
|
||||||
// Check dist0
|
// Check dist0
|
||||||
if ((min_t < dist0 && dist0 < max_t) &&
|
if ((min_t < dist0 && dist0 < max_t) &&
|
||||||
dist0 < t_comp)
|
dist0 < t_comp)
|
||||||
{
|
{
|
||||||
t_comp = dist0;
|
t_comp = dist0;
|
||||||
closest = &spheres[i];
|
closest = &spheres[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now check dist1
|
// Now check dist1
|
||||||
if ((min_t < dist1 && dist1 < max_t) &&
|
if ((min_t < dist1 && dist1 < max_t) &&
|
||||||
dist1 < t_comp)
|
dist1 < t_comp)
|
||||||
{
|
{
|
||||||
t_comp = dist1;
|
t_comp = dist1;
|
||||||
closest = &spheres[i];
|
closest = &spheres[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!closest)
|
if (!closest)
|
||||||
return Invalid;
|
return Invalid;
|
||||||
|
|
||||||
Vec3 point = vec3_add(origin, vec3_multiply_scalar(dir, t_comp));
|
Vec3 point = vec3_add(origin, vec3_multiply_scalar(dir, t_comp));
|
||||||
Vec3 normal = vec3_normalise(vec3_subtract(point, closest->centre));
|
Vec3 normal = vec3_normalise(vec3_subtract(point, closest->centre));
|
||||||
Material material = closest->material;
|
Material material = closest->material;
|
||||||
|
|
||||||
return vec3_clamp(
|
return vec3_clamp(
|
||||||
vec3_multiply_scalar(
|
vec3_multiply_scalar(
|
||||||
material.diffuse,
|
material.diffuse,
|
||||||
lighting_compute(
|
lighting_compute(
|
||||||
point, normal,
|
point, normal,
|
||||||
vec3_multiply_scalar(dir, -1),
|
vec3_multiply_scalar(dir, -1),
|
||||||
material.specular,
|
material.specular,
|
||||||
lights, num_lights
|
lights, num_lights
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
0.0f, 255.0f // Clamp between 0 and 255
|
0.0f, 255.0f // Clamp between 0 and 255
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watermark: Says "MATT J"
|
// Watermark: Says "MATT J"
|
||||||
|
@ -339,12 +339,12 @@ RgbColour raytrace(Vec3 origin, Vec3 dir, float min_t, float max_t,
|
||||||
#define MARK_ROWS 7
|
#define MARK_ROWS 7
|
||||||
int mark[MARK_ROWS][MARK_COLS] = {
|
int mark[MARK_ROWS][MARK_COLS] = {
|
||||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
{0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0},
|
{0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0},
|
||||||
{0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
|
{0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
|
||||||
{0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
|
{0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
|
||||||
{0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
|
{0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
|
||||||
{0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0},
|
{0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0},
|
||||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Draws a watermark on the screen using the above array
|
// Draws a watermark on the screen using the above array
|
||||||
|
@ -357,94 +357,94 @@ void DrawWatermark(byte *data) {
|
||||||
|
|
||||||
for (int i = 0; i < MARK_COLS; i++) {
|
for (int i = 0; i < MARK_COLS; i++) {
|
||||||
for (int j = 0; j < MARK_ROWS; j++) {
|
for (int j = 0; j < MARK_ROWS; j++) {
|
||||||
int y_corner = start_y + j*(size*2 + stride);
|
int y_corner = start_y + j*(size*2 + stride);
|
||||||
int x_corner = start_x + i*(size*2 + stride);
|
int x_corner = start_x + i*(size*2 + stride);
|
||||||
|
|
||||||
// Draw Square
|
// Draw Square
|
||||||
for (int x = x_corner; x < (x_corner + size); x++) {
|
for (int x = x_corner; x < (x_corner + size); x++) {
|
||||||
for (int y = y_corner; y < (y_corner + size); y++) {
|
for (int y = y_corner; y < (y_corner + size); y++) {
|
||||||
if (mark[j][i] == 0) {
|
if (mark[j][i] == 0) {
|
||||||
data[(y*WIDTH + x) * 3 + 0] = (byte)(i/(float)MARK_COLS * 255) % 180;
|
data[(y*WIDTH + x) * 3 + 0] = (byte)(i/(float)MARK_COLS * 255) % 180;
|
||||||
data[(y*WIDTH + x) * 3 + 1] = (byte)(j/(float)MARK_ROWS * 255) % 180;
|
data[(y*WIDTH + x) * 3 + 1] = (byte)(j/(float)MARK_ROWS * 255) % 180;
|
||||||
data[(y*WIDTH + x) * 3 + 2] = (byte)240;
|
data[(y*WIDTH + x) * 3 + 2] = (byte)240;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data[(y*WIDTH + x) * 3 + 0] = (byte)255;
|
data[(y*WIDTH + x) * 3 + 0] = (byte)255;
|
||||||
data[(y*WIDTH + x) * 3 + 1] = (byte)255;
|
data[(y*WIDTH + x) * 3 + 1] = (byte)255;
|
||||||
data[(y*WIDTH + x) * 3 + 2] = (byte)255;
|
data[(y*WIDTH + x) * 3 + 2] = (byte)255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
byte *data = malloc(sizeof(byte) * 3 * WIDTH * HEIGHT);
|
byte *data = malloc(sizeof(byte) * 3 * WIDTH * HEIGHT);
|
||||||
|
|
||||||
// Materials
|
// Materials
|
||||||
Material blue = material_new(vec3_new(69, 161, 255), 500);
|
Material blue = material_new(vec3_new(69, 161, 255), 500);
|
||||||
Material white = material_new(vec3_new(240, 240, 240), 180);
|
Material white = material_new(vec3_new(240, 240, 240), 180);
|
||||||
Material red = material_new(vec3_new(255, 0, 57), 10);
|
Material red = material_new(vec3_new(255, 0, 57), 10);
|
||||||
Material ground = material_new(vec3_new(0, 57, 89), 1000);
|
Material ground = material_new(vec3_new(0, 57, 89), 1000);
|
||||||
|
|
||||||
// Scene
|
// Scene
|
||||||
#define NUM_SPHERES 4
|
#define NUM_SPHERES 4
|
||||||
Sphere spheres[NUM_SPHERES];
|
Sphere spheres[NUM_SPHERES];
|
||||||
spheres[0] = sphere_new(vec3_new(-0.75f, -0.2f, 6.5f), 1.5f, red);
|
spheres[0] = sphere_new(vec3_new(-0.75f, -0.2f, 6.5f), 1.5f, red);
|
||||||
spheres[1] = sphere_new(vec3_new(0, -1, 5), 1.0f, blue);
|
spheres[1] = sphere_new(vec3_new(0, -1, 5), 1.0f, blue);
|
||||||
spheres[2] = sphere_new(vec3_new(2, -0.5, 8), 3.0f, white);
|
spheres[2] = sphere_new(vec3_new(2, -0.5, 8), 3.0f, white);
|
||||||
spheres[3] = sphere_new(vec3_new(0, -4001, 0), 4000, ground);
|
spheres[3] = sphere_new(vec3_new(0, -4001, 0), 4000, ground);
|
||||||
|
|
||||||
// Lights
|
// Lights
|
||||||
#define NUM_LIGHTS 3
|
#define NUM_LIGHTS 3
|
||||||
Light lights[NUM_LIGHTS];
|
Light lights[NUM_LIGHTS];
|
||||||
lights[0] = light_ambient_new(0.2f);
|
lights[0] = light_ambient_new(0.2f);
|
||||||
lights[1] = light_point_new(0.6f, vec3_new(-8, 1, 0));
|
lights[1] = light_point_new(0.6f, vec3_new(-8, 1, 0));
|
||||||
lights[2] = light_directional_new(0.2f, vec3_new(1, 4, -8));
|
lights[2] = light_directional_new(0.2f, vec3_new(1, 4, -8));
|
||||||
|
|
||||||
// For non-square images (future-proofing?)
|
// For non-square images (future-proofing?)
|
||||||
float aspect_ratio = (float)WIDTH/(float)HEIGHT;
|
float aspect_ratio = (float)WIDTH/(float)HEIGHT;
|
||||||
float screen_dim = tanf(FOV / (float)2);
|
float screen_dim = tanf(FOV / (float)2);
|
||||||
|
|
||||||
Vec3 origin = Zero;
|
Vec3 origin = Zero;
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
for (int x = 0; x < WIDTH; x++) {
|
for (int x = 0; x < WIDTH; x++) {
|
||||||
for (int y = 0; y < HEIGHT; y++) {
|
for (int y = 0; y < HEIGHT; y++) {
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
data[(y*WIDTH + x) * 3 + 0] = (byte)(y/(float)WIDTH * 255);
|
data[(y*WIDTH + x) * 3 + 0] = (byte)(y/(float)WIDTH * 255);
|
||||||
data[(y*WIDTH + x) * 3 + 1] = (byte)(x/(float)HEIGHT * 255);
|
data[(y*WIDTH + x) * 3 + 1] = (byte)(x/(float)HEIGHT * 255);
|
||||||
data[(y*WIDTH + x) * 3 + 2] = (byte)160;
|
data[(y*WIDTH + x) * 3 + 2] = (byte)160;
|
||||||
|
|
||||||
// Get Pixel in World Coords
|
// Get Pixel in World Coords
|
||||||
float x_world_coord = (2*(x + 0.5f)/(float)HEIGHT - 1) * screen_dim * aspect_ratio;
|
float x_world_coord = (2*(x + 0.5f)/(float)HEIGHT - 1) * screen_dim * aspect_ratio;
|
||||||
float y_world_coord = -(2*(y + 0.5f)/(float)WIDTH - 1) * screen_dim;
|
float y_world_coord = -(2*(y + 0.5f)/(float)WIDTH - 1) * screen_dim;
|
||||||
Vec3 dir = vec3_normalise(vec3_new(x_world_coord, y_world_coord, 1));
|
Vec3 dir = vec3_normalise(vec3_new(x_world_coord, y_world_coord, 1));
|
||||||
|
|
||||||
// Raytrace Pixel
|
// Raytrace Pixel
|
||||||
RgbColour colour = raytrace(origin, dir, 1.0f, (float)MAX_DIST,
|
RgbColour colour = raytrace(origin, dir, 1.0f, (float)MAX_DIST,
|
||||||
spheres, NUM_SPHERES,
|
spheres, NUM_SPHERES,
|
||||||
lights, NUM_LIGHTS);
|
lights, NUM_LIGHTS);
|
||||||
|
|
||||||
// Draw Geometry
|
// Draw Geometry
|
||||||
if (colour.x != -1) {
|
if (colour.x != -1) {
|
||||||
data[(y*WIDTH + x) * 3 + 0] = (byte)colour.x;
|
data[(y*WIDTH + x) * 3 + 0] = (byte)colour.x;
|
||||||
data[(y*WIDTH + x) * 3 + 1] = (byte)colour.y;
|
data[(y*WIDTH + x) * 3 + 1] = (byte)colour.y;
|
||||||
data[(y*WIDTH + x) * 3 + 2] = (byte)colour.z;
|
data[(y*WIDTH + x) * 3 + 2] = (byte)colour.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
DrawWatermark(data);
|
DrawWatermark(data);
|
||||||
|
|
||||||
// Write to file
|
// Write to file
|
||||||
printf("tinyray: writing to file!");
|
printf("tinyray: writing to file!");
|
||||||
if (!stbi_write_bmp("output.bmp", WIDTH, HEIGHT, 3, data))
|
if (!stbi_write_bmp("output.bmp", WIDTH, HEIGHT, 3, data))
|
||||||
printf("tinyray: failed to write image!");
|
printf("tinyray: failed to write image!");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue