Add image textures
This commit is contained in:
parent
fc35055466
commit
391aa6240e
@ -5,3 +5,4 @@ C implementation of the [*Ray tracing in one week-end*](https://raytracing.githu
|
|||||||
## Examples
|
## Examples
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|
|||||||
BIN
assets/earthmap.jpg
Normal file
BIN
assets/earthmap.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 158 KiB |
BIN
examples/earth.png
Normal file
BIN
examples/earth.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 320 KiB |
7897
external/stb_image.h
vendored
Normal file
7897
external/stb_image.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -192,7 +192,7 @@ bool hittable_list_bounding_box(const HittableList *list, double time_start,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void get_sphere_uv(Point3 p, double *u, double *v) {
|
static void get_sphere_uv(Point3 p, double *u, double *v) {
|
||||||
double theta = acos(-p.x);
|
double theta = acos(-p.y);
|
||||||
double phi = atan2(-p.z, p.x) + M_PI;
|
double phi = atan2(-p.z, p.x) + M_PI;
|
||||||
*u = phi / (2 * M_PI);
|
*u = phi / (2 * M_PI);
|
||||||
*v = theta / M_PI;
|
*v = theta / M_PI;
|
||||||
|
|||||||
25
main.c
25
main.c
@ -19,8 +19,9 @@
|
|||||||
#define SCENE_RANDOM 0
|
#define SCENE_RANDOM 0
|
||||||
#define SCENE_TWO_SPHERES 1
|
#define SCENE_TWO_SPHERES 1
|
||||||
#define SCENE_TWO_PERLIN_SPHERES 2
|
#define SCENE_TWO_PERLIN_SPHERES 2
|
||||||
|
#define SCENE_EARTH 3
|
||||||
|
|
||||||
#define SCENE_SELECT SCENE_TWO_PERLIN_SPHERES
|
#define SCENE_SELECT SCENE_EARTH
|
||||||
|
|
||||||
static Color ray_color(Ray r, const Hittable *world, int depth) {
|
static Color ray_color(Ray r, const Hittable *world, int depth) {
|
||||||
if (depth <= 0)
|
if (depth <= 0)
|
||||||
@ -143,6 +144,14 @@ static Hittable *two_perlin_spheres(Arena *arena) {
|
|||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Hittable *earth(Arena *arena) {
|
||||||
|
Texture *earth_texture = texture_create_image("assets/earthmap.jpg", arena);
|
||||||
|
Material *earth_surface = material_create_lambertian(earth_texture, arena);
|
||||||
|
Hittable *globe = hittable_create_sphere((Point3){0.0, 0.0, 0.0}, 2.0,
|
||||||
|
earth_surface, arena);
|
||||||
|
return globe;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
srand(42);
|
srand(42);
|
||||||
|
|
||||||
@ -158,14 +167,14 @@ int main(void) {
|
|||||||
/* Image parameters */
|
/* Image parameters */
|
||||||
|
|
||||||
const double aspect_ratio = 16.0 / 9.0;
|
const double aspect_ratio = 16.0 / 9.0;
|
||||||
const int image_width = 400;
|
const int image_width = 1200;
|
||||||
const int image_height = (int)(image_width / aspect_ratio);
|
const int image_height = (int)(image_width / aspect_ratio);
|
||||||
const int samples_per_pixel = 100;
|
const int samples_per_pixel = 500;
|
||||||
const int max_depth = 50;
|
const int max_depth = 50;
|
||||||
|
|
||||||
/* World */
|
/* World */
|
||||||
|
|
||||||
Point3 look_from = {13.0, 2.0, 3.0};
|
Point3 look_from = {0.0, 0.0, 1.0};
|
||||||
Point3 look_at = {0.0, 0.0, 0.0};
|
Point3 look_at = {0.0, 0.0, 0.0};
|
||||||
double vfov = 40.0;
|
double vfov = 40.0;
|
||||||
double aperture = 0.0;
|
double aperture = 0.0;
|
||||||
@ -189,6 +198,11 @@ int main(void) {
|
|||||||
look_from = (Point3){13.0, 2.0, 3.0};
|
look_from = (Point3){13.0, 2.0, 3.0};
|
||||||
look_at = (Point3){0.0, 0.0, 0.0};
|
look_at = (Point3){0.0, 0.0, 0.0};
|
||||||
vfov = 20.0;
|
vfov = 20.0;
|
||||||
|
#elif SCENE_SELECT == SCENE_EARTH
|
||||||
|
world = earth(&arena);
|
||||||
|
look_from = (Point3){13.0, 2.0, 3.0};
|
||||||
|
look_at = (Point3){0.0, 0.0, 0.0};
|
||||||
|
vfov = 20.0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Vec3 up = {0.0, 1.0, 0.0};
|
Vec3 up = {0.0, 1.0, 0.0};
|
||||||
@ -232,3 +246,6 @@ int main(void) {
|
|||||||
#include "texture.c"
|
#include "texture.c"
|
||||||
#include "utils.c"
|
#include "utils.c"
|
||||||
#include "vec3.c"
|
#include "vec3.c"
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "external/stb_image.h"
|
||||||
|
|||||||
108
texture.c
108
texture.c
@ -1,9 +1,17 @@
|
|||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "external/stb_image.h"
|
||||||
#include "perlin.h"
|
#include "perlin.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define DEBUG_COLOR \
|
||||||
|
(Color) { 1.0, 0.0, 1.0 }
|
||||||
|
|
||||||
|
static const int image_bytes_per_pixel = 3;
|
||||||
|
|
||||||
Texture *texture_create_solid_color(Color value, Arena *arena) {
|
Texture *texture_create_solid_color(Color value, Arena *arena) {
|
||||||
Texture *result = arena_alloc(arena, sizeof(Texture));
|
Texture *result = arena_alloc(arena, sizeof(Texture));
|
||||||
@ -22,6 +30,13 @@ Texture *texture_create_checker(const Texture *odd, const Texture *even,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture *texture_create_checker_solid_color(Color odd, Color even, double size,
|
||||||
|
Arena *arena) {
|
||||||
|
Texture *odd_texture = texture_create_solid_color(odd, arena);
|
||||||
|
Texture *even_texture = texture_create_solid_color(even, arena);
|
||||||
|
return texture_create_checker(odd_texture, even_texture, size, arena);
|
||||||
|
}
|
||||||
|
|
||||||
Texture *texture_create_perlin_noise(double scale, int point_count,
|
Texture *texture_create_perlin_noise(double scale, int point_count,
|
||||||
Arena *arena) {
|
Arena *arena) {
|
||||||
Texture *result = arena_alloc(arena, sizeof(Texture));
|
Texture *result = arena_alloc(arena, sizeof(Texture));
|
||||||
@ -31,11 +46,68 @@ Texture *texture_create_perlin_noise(double scale, int point_count,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture *texture_create_checker_solid_color(Color odd, Color even, double size,
|
Texture *texture_create_image(const char *filename, Arena *arena) {
|
||||||
Arena *arena) {
|
Texture *result = arena_alloc(arena, sizeof(Texture));
|
||||||
Texture *odd_texture = texture_create_solid_color(odd, arena);
|
result->type = TEXTURE_IMAGE;
|
||||||
Texture *even_texture = texture_create_solid_color(even, arena);
|
|
||||||
return texture_create_checker(odd_texture, even_texture, size, arena);
|
int components_per_pixel = image_bytes_per_pixel;
|
||||||
|
result->image.data =
|
||||||
|
stbi_load(filename, &result->image.width, &result->image.height,
|
||||||
|
&components_per_pixel, components_per_pixel);
|
||||||
|
if (!result->image.data) {
|
||||||
|
fprintf(stderr, "Failed to load texture from image file %s\n", filename);
|
||||||
|
result->image.width = result->image.height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->image.bytes_per_scanline =
|
||||||
|
image_bytes_per_pixel * result->image.width;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color image_value(const ImageTexture *image, double u, double v) {
|
||||||
|
if (!image->data)
|
||||||
|
return DEBUG_COLOR;
|
||||||
|
|
||||||
|
u = clamp(u, 0.0, 1.0);
|
||||||
|
v = 1.0 - clamp(v, 0.0, 1.0);
|
||||||
|
|
||||||
|
int i = u * image->width;
|
||||||
|
int j = v * image->height;
|
||||||
|
|
||||||
|
if (i >= image->width)
|
||||||
|
i = image->width - 1;
|
||||||
|
if (j >= image->height)
|
||||||
|
j = image->height - 1;
|
||||||
|
|
||||||
|
const double color_scale = 1.0 / 255.0;
|
||||||
|
const unsigned char *pixel =
|
||||||
|
image->data + j * image->bytes_per_scanline + i * image_bytes_per_pixel;
|
||||||
|
|
||||||
|
return (Color){color_scale * pixel[0], color_scale * pixel[1],
|
||||||
|
color_scale * pixel[2]};
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color solid_color_value(const SolidColor *solid_color) {
|
||||||
|
return solid_color->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color checker_value(const CheckerTexture *checker, double u, double v,
|
||||||
|
Point3 p) {
|
||||||
|
double sines = sin(checker->size * p.x) * sin(checker->size * p.y) *
|
||||||
|
sin(checker->size * p.z);
|
||||||
|
if (sines < 0.0)
|
||||||
|
return texture_value(checker->odd, u, v, p);
|
||||||
|
return texture_value(checker->even, u, v, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color perlin_value(const PerlinNoiseTexture *perlin, Point3 p) {
|
||||||
|
double noise_value =
|
||||||
|
0.5 *
|
||||||
|
(1.0 + sin(perlin->scale * p.z +
|
||||||
|
10 * perlin_turbulence(perlin->data, p,
|
||||||
|
PERLIN_DEFAULT_TURBULENCE_DEPTH)));
|
||||||
|
return color_mul_const(noise_value, (Color){1.0, 1.0, 1.0});
|
||||||
}
|
}
|
||||||
|
|
||||||
Color texture_value(const Texture *texture, double u, double v, Point3 p) {
|
Color texture_value(const Texture *texture, double u, double v, Point3 p) {
|
||||||
@ -46,28 +118,8 @@ Color texture_value(const Texture *texture, double u, double v, Point3 p) {
|
|||||||
return checker_value(&texture->checker, u, v, p);
|
return checker_value(&texture->checker, u, v, p);
|
||||||
case TEXTURE_PERLIN_NOISE:
|
case TEXTURE_PERLIN_NOISE:
|
||||||
return perlin_value(&texture->noise, p);
|
return perlin_value(&texture->noise, p);
|
||||||
|
case TEXTURE_IMAGE:
|
||||||
|
return image_value(&texture->image, u, v);
|
||||||
}
|
}
|
||||||
return (Color){0.0, 0.0, 0.0};
|
return DEBUG_COLOR;
|
||||||
}
|
|
||||||
|
|
||||||
Color solid_color_value(const SolidColor *solid_color) {
|
|
||||||
return solid_color->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color checker_value(const CheckerTexture *checker, double u, double v,
|
|
||||||
Point3 p) {
|
|
||||||
double sines = sin(checker->size * p.x) * sin(checker->size * p.y) *
|
|
||||||
sin(checker->size * p.z);
|
|
||||||
if (sines < 0.0)
|
|
||||||
return texture_value(checker->odd, u, v, p);
|
|
||||||
return texture_value(checker->even, u, v, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color perlin_value(const PerlinNoiseTexture *perlin, Point3 p) {
|
|
||||||
double noise_value =
|
|
||||||
0.5 *
|
|
||||||
(1.0 + sin(perlin->scale * p.z +
|
|
||||||
10 * perlin_turbulence(perlin->data, p,
|
|
||||||
PERLIN_DEFAULT_TURBULENCE_DEPTH)));
|
|
||||||
return color_mul_const(noise_value, (Color){1.0, 1.0, 1.0});
|
|
||||||
}
|
}
|
||||||
|
|||||||
16
texture.h
16
texture.h
@ -10,6 +10,7 @@ typedef enum TextureType {
|
|||||||
TEXTURE_SOLID_COLOR,
|
TEXTURE_SOLID_COLOR,
|
||||||
TEXTURE_CHECKER,
|
TEXTURE_CHECKER,
|
||||||
TEXTURE_PERLIN_NOISE,
|
TEXTURE_PERLIN_NOISE,
|
||||||
|
TEXTURE_IMAGE,
|
||||||
} TextureType;
|
} TextureType;
|
||||||
|
|
||||||
typedef struct Texture Texture;
|
typedef struct Texture Texture;
|
||||||
@ -29,12 +30,19 @@ typedef struct PerlinNoiseTexture {
|
|||||||
double scale;
|
double scale;
|
||||||
} PerlinNoiseTexture;
|
} PerlinNoiseTexture;
|
||||||
|
|
||||||
|
typedef struct ImageTexture {
|
||||||
|
unsigned char *data;
|
||||||
|
int width, height;
|
||||||
|
int bytes_per_scanline;
|
||||||
|
} ImageTexture;
|
||||||
|
|
||||||
struct Texture {
|
struct Texture {
|
||||||
TextureType type;
|
TextureType type;
|
||||||
union {
|
union {
|
||||||
SolidColor solid_color;
|
SolidColor solid_color;
|
||||||
CheckerTexture checker;
|
CheckerTexture checker;
|
||||||
PerlinNoiseTexture noise;
|
PerlinNoiseTexture noise;
|
||||||
|
ImageTexture image;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,14 +53,8 @@ Texture *texture_create_checker_solid_color(Color odd, Color even, double size,
|
|||||||
Arena *arena);
|
Arena *arena);
|
||||||
Texture *texture_create_perlin_noise(double scale, int point_count,
|
Texture *texture_create_perlin_noise(double scale, int point_count,
|
||||||
Arena *arena);
|
Arena *arena);
|
||||||
|
Texture *texture_create_image(const char *filename, Arena *arena);
|
||||||
|
|
||||||
Color texture_value(const Texture *texture, double u, double v, Point3 p);
|
Color texture_value(const Texture *texture, double u, double v, Point3 p);
|
||||||
|
|
||||||
Color solid_color_value(const SolidColor *solid_color);
|
|
||||||
|
|
||||||
Color checker_value(const CheckerTexture *checker, double u, double v,
|
|
||||||
Point3 p);
|
|
||||||
|
|
||||||
Color perlin_value(const PerlinNoiseTexture *perlin, Point3 p);
|
|
||||||
|
|
||||||
#endif /* INCLUDED_TEXTURE_H */
|
#endif /* INCLUDED_TEXTURE_H */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user