$ ./config
$ make
$ make install
./sdltemplate.h:24:13: error: expected ';' at end of declaration
SDL_Color c{r,g,b,a};
오류나면 SDL_Color c = {r,g,b,a};
로 변경
덧셈 뺄셈 곱셈 나눗셈
연산을 지원. 더하여 dot product
, cross product
, unit vector
를 지원.한 벡터를 다른 벡터위로 정사영
시킨 길이와 그 다른 벡터의 길이
의 곱셈
이다.수직
인 벡터를 구하는 방법이다.origin
과 direction
으로 생성
direction
: (v1 - v0) / length (도착점 - 시작점) / 거리
https://gpgstudy.com/forum/viewtopic.php?t=15441
ray r(origin, lower_left_corner + u*horizontal + v*vertical - origin);
P(t) = A + tb
origin ray A
, direction b
, real number t
(0,0,0)
으로 잡고 오른손 좌표계 사용(z축 방향이 반대)카메라에서 픽셀까지의 광선
계산교차
하는 객체
를 정하기교차점의 색상
정하기auto origin = point3(0, 0, 0);
auto horizontal = vec3(viewport_width, 0, 0);
auto vertical = vec3(0, viewport_height, 0);
auto lower_left_corner = origin - horizontal/2 - vertical/2 - vec3(0, 0, focal_length);
카메라
에서 투영평면
까지의 거리
bool hit_sphere(const point3& center, double radius, const ray& r) {
vec3 oc = r.origin() - center; // (𝐀−𝐂)
auto a = dot(r.direction(), r.direction()); // 𝐛⋅𝐛
auto b = 2.0 * dot(oc, r.direction()); // 2𝐛⋅(𝐀−𝐂)
auto c = dot(oc, oc) - radius*radius; // (𝐀−𝐂)⋅(𝐀−𝐂)−𝑟^2
auto discriminant = b*b - 4*a*c;
return (discriminant > 0);
}
color ray_color(const ray& r) {
if (hit_sphere(point3(0,0,-1), 0.5, r)) // ray와 sphere이 교차하는 부분이라면
return color(1, 0, 0); // red 리턴
vec3 unit_direction = unit_vector(r.direction());
auto t = 0.5*(unit_direction.y() + 1.0);
return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}
Surface Normals
: 표면법선객체
에 수직인 선
, 광선 또는 벡터와 같은 객체P
에서의 outward normal
은 P - C(center)
direction에 놓여있다.double hit_sphere(const point3& center, double radius, const ray& r) {
vec3 oc = r.origin() - center;
auto a = dot(r.direction(), r.direction());
auto b = 2.0 * dot(oc, r.direction());
auto c = dot(oc, oc) - radius*radius;
auto discriminant = b*b - 4*a*c;
if (discriminant < 0) {
return -1.0;
} else {
return (-b - sqrt(discriminant) ) / (2.0*a); // 실제 근을 리턴 함
}
}
color ray_color(const ray& r) {
auto t = hit_sphere(point3(0,0,-1), 0.5, r);
if (t > 0.0) {
vec3 N = unit_vector(r.at(t) - vec3(0,0,-1)); // P - C direction
return 0.5*color(N.x()+1, N.y()+1, N.z()+1);
}
vec3 unit_direction = unit_vector(r.direction());
t = 0.5*(unit_direction.y() + 1.0);
return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}
double hit_sphere(const point3& center, double radius, const ray& r) {
vec3 oc = r.origin() - center;
auto a = r.direction().length_squared(); // dot 함수 말고 vec3 class의 length_squared 함수 사용
auto half_b = dot(oc, r.direction()); // 𝐛⋅(𝐀−𝐂)
auto c = oc.length_squared() - radius*radius; // dot 함수 말고 length_squared 사용
auto discriminant = half_b*half_b - a*c; // h^2 - ac
if (discriminant < 0) {
return -1.0;
} else {
return (-half_b - sqrt(discriminant) ) / a;
}
}
#ifndef HITTABLE_H
#define HITTABLE_H
#include "ray.h"
struct hit_record {
point3 p; // 표면 위 한 점 p
vec3 normal; // p에서의 법선
double t; // ray가 p에 닿을 때의 t?
};
class hittable {
public:
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const = 0;
// hit 함수를 순수 가상함수로 둬서 상속 받은 객체에서 각 방정식에 맞게 구현하게끔
};
#endif
struct hit_record {
point3 p;
vec3 normal;
double t;
bool front_face;
inline void set_face_normal(const ray& r, const vec3& outward_normal) {
front_face = dot(r.direction(), outward_normal) < 0;
normal = front_face ? outward_normal :-outward_normal;
}
};
bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
...
rec.t = root;
rec.p = r.at(rec.t);
vec3 outward_normal = (rec.p - center) / radius;
rec.set_face_normal(r, outward_normal);
return true;
}
bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
hit_record temp_rec;
bool hit_anything = false;
auto closest_so_far = t_max;
for (const auto& object : objects) {
if (object->hit(r, t_min, closest_so_far, temp_rec)) {
hit_anything = true;
closest_so_far = temp_rec.t;
rec = temp_rec;
}
}
return hit_anything;
}
We’ll start with diffuse (matte) materials.
흠 matte material 표현하는 방법을 설명하고 있는 것 같은데.. 뭐라는지 모르겠다
Really any algorithm that randomizes direction will produce surfaces that look matte.
🫠방향을 무작위로 하는 것이 왜 매트하게 보이게 할까..?
Figure 9: Generating a random diffuse bounce ray
sphere의 표면 위 한 점 P에 접한 unit radius sphere 두 개가 있음
P+n, P-n (n은 P에서의 normal) 을 중심으로 함.
P+n이 outside surface, P-n은 inside surface.
P에서 outside surface에 접한 구 안에 있는 random point S로 ray 쏜다면 이는 S-P (도착점 - 시작점)
We need a way to pick a random point in a unit radius sphere.
흠 랜덤 포인트 구하는 방법으로 rejection method 사용할 건데 x, y, z -1~1범위 중 하나 고르고 구 outside에 있는 거면 reject하고 try again 한다
color ray_color(const ray& r, const hittable& world) {
hit_record rec;
if (world.hit(r, 0, infinity, rec)) {
point3 target = rec.p + rec.normal + random_in_unit_sphere();
return 0.5 * ray_color(ray(rec.p, target - rec.p), world);
}
vec3 unit_direction = unit_vector(r.direction());
auto t = 0.5*(unit_direction.y() + 1.0);
return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}
--> 다시 이해해보기
color ray_color(const ray& r, const hittable& world, int depth) {
hit_record rec;
// If we've exceeded the ray bounce limit, no more light is gathered.
if (depth <= 0)
return color(0,0,0);
if (world.hit(r, 0, infinity, rec)) {
point3 target = rec.p + rec.normal + random_in_unit_sphere();
return 0.5 * ray_color(ray(rec.p, target - rec.p), world, depth-1); // depth 줄이면서 진행
}
vec3 unit_direction = unit_vector(r.direction());
auto t = 0.5*(unit_direction.y() + 1.0);
return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}
gamma corrected
감마보정: 빛의 강도 신호를 비선형적으로 변환하는 것.