Vec3.h
그래픽스에서 기본적으로 사용되는 Vector3 클래스를 구현한다.
뒤에 나오게 될 [색상, 위치, 방향] 모두 벡터를 이용해 연산하기 때문에, using을 이용하여 별칭으로 만들 것이다.
이 방법은 색상에서 위치를 빼는 것 같은 연산에 대해 방어할 수는 없지만, 조금이나마 가독성을 좋게 하기 위함이다.
#include <cmath>
#include <iostream>
class Vector3
{
public:
Vector3() : E{ 0,0,0 } {}
Vector3(double e0, double e1, double e2) : E{ e0, e1, e2 } {}
double X() const { return E[0]; }
double Y() const { return E[1]; }
double Z() const { return E[2]; }
Vector3 operator-() const { return Vector3(-E[0], -E[1], -E[2]); }
double operator[](int i) const { return E[i]; }
double& operator[](int i) { return E[i]; }
Vector3& operator+=(const Vector3& v)
{
E[0] += v.E[0];
E[1] += v.E[1];
E[2] += v.E[2];
return *this;
}
Vector3& operator*=(double t)
{
E[0] *= t;
E[1] *= t;
E[2] *= t;
return *this;
}
Vector3& operator/=(double t)
{
return *this *= 1 / t;
}
double Length() const
{
return std::sqrt(LengthSquared());
}
double LengthSquared() const
{
return E[0] * E[0] + E[1] * E[1] + E[2] * E[2];
}
public:
// 벡터3의 각 원소를 배열로 관리
double E[3];
};
// 별칭 정의
using Vector3 = Vec3;
using Point3 = Vector3;
이어서 아래는 연산자 오버라이딩을 포함한 벡터의 유틸리티 함수다.
inline std::ostream& operator<<(std::ostream& out, const Vector3& v)
{
return out << v.E[0] << ' ' << v.E[1] << ' ' << v.E[2];
}
inline Vector3 operator+(const Vector3& u, const Vector3& v)
{
return Vector3(u.E[0] + v.E[0], u.E[1] + v.E[1], u.E[2] + v.E[2]);
}
inline Vector3 operator-(const Vector3& u, const Vector3& v)
{
return Vector3(u.E[0] - v.E[0], u.E[1] - v.E[1], u.E[2] - v.E[2]);
}
inline Vector3 operator*(const Vector3& u, const Vector3& v)
{
return Vector3(u.E[0] * v.E[0], u.E[1] * v.E[1], u.E[2] * v.E[2]);
}
inline Vector3 operator*(double t, const Vector3& v)
{
return Vector3(t * v.E[0], t * v.E[1], t * v.E[2]);
}
inline Vector3 operator*(const Vector3& v, double t)
{
return t * v;
}
inline Vector3 operator/(const Vector3& v, double t)
{
return (1 / t) * v;
}
inline double Dot(const Vector3& u, const Vector3& v)
{
return u.E[0] * v.E[0]
+ u.E[1] * v.E[1]
+ u.E[2] * v.E[2];
}
inline Vector3 Cross(const Vector3& u, const Vector3& v)
{
return Vector3(u.E[1] * v.E[2] - u.E[2] * v.E[1],
u.E[2] * v.E[0] - u.E[0] * v.E[2],
u.E[0] * v.E[1] - u.E[1] * v.E[0]);
}
inline Vector3 UnitVector(const Vector3& v)
{
return v / v.Length();
}
Color.h
vector클래스를 이용한 단일 픽셀 색상을 출력하는 함수를 정의하는 헤더파일이다.
기존 main에 있던 render영역을 가져와 분리한 것이다.
#include "Vec3.h"
#include <iostream>
// 가독성을 위한 별칭
using Color = Vec3;
// 들어온 색상을 출력
void WriteColor(std::ostream& out, const Color& pixelColor)
{
double r = pixelColor.X();
double g = pixelColor.Y();
double b = pixelColor.Z();
// [0,1] 범위의 컴포넌트 값을 바이트 범위 [0,255]로 변환
int rByte = int(255.999 * r);
int gByte = int(255.999 * g);
int bByte = int(255.999 * b);
// 픽셀 색상을 출력
out << rByte << ' ' << gByte << ' ' << bByte << '\n';
}
main.cpp
vector, color 클래스를 사용하여 렌더 로직을 수정한다.
#include "Color.h"
#include "Vec3.h"
#include <iostream>
int main()
{
// Image
int ImageWidth = 256;
int ImageHeight = 256;
// Render
std::cout << "P3\n" << ImageWidth << ' ' << ImageHeight << "\n255\n";
for (int j = 0; j < ImageHeight; j++)
{
std::clog << "\rScanlines remaining: " << (ImageHeight - j) << ' ' << std::flush;
for (int i = 0; i < ImageWidth; i++)
{
auto PixelColor = Color(double(i)/(ImageWidth-1), double(j)/(ImageHeight-1), 0);
WriteColor(std::cout, PixelColor);
}
}
std::clog << "\rDone.\n";
}
Result
아직까지는 렌더 부분이 바뀐 게 없기 때문에 이전과 같은 이미지가 출력된다.

'C++ > Ray Tracing' 카테고리의 다른 글
| [03] Adding a Sphere (0) | 2026.03.03 |
|---|---|
| [02]Rays & Simple Camera & Background (0) | 2026.02.26 |
| [00] Output an Image (0) | 2026.02.20 |
