Orthographic projection (정투영)
화면에서 모든 픽셀에서 모든 광선을 (0, 0, 1) 방향으로 쏘는 것
void Render(std::vector<glm::vec4>& pixels)
{
std::fill(pixels.begin(), pixels.end(), vec4{ 0.0f, 0.0f, 0.0f, 1.0f });
const vec3 eyePos(0.0f, 0.0f, -1.5f);
#pragma omp parallel for
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
const vec3 pixelPosWorld = TransformScreenToWorld(vec2(i, j));
// 광선의 방향 벡터
// 스크린에 수직인 z방향, 절대값 1.0인 유닉 벡터
// Orthographic projection (정투영) vs perspective projection (원근투영)
// 정투영
const auto rayDir = vec3(0.0f, 0.0f, 1.0f);
// 원근투영
// const auto rayDir = glm::normalize(pixelPosWorld - eyePos);
Ray pixelRay{ pixelPosWorld, rayDir };
pixels[i + width * j] = vec4(glm::clamp(traceRay(pixelRay), 0.0f, 1.0f), 1.0f);
}
}
vec3 TransformScreenToWorld(vec2 posScreen)
{
const float xScale = 2.0f / this->width;
const float yScale = 2.0f / this->height;
const float aspect = float(this->width) / this->height;
// 3차원 공간으로 확장 (z좌표는 0.0)
return vec3((posScreen.x * xScale - 1.0f) * aspect, -posScreen.y * yScale + 1.0f, 0.0f);
}
perspective projection (원근투영)
눈의 위치를 명확하게 먼저 정의.
눈의 위치에서 화면 픽셀 좌표쪽으로 ray를 쏨.
void Render(std::vector<glm::vec4>& pixels)
{
std::fill(pixels.begin(), pixels.end(), vec4{ 0.0f, 0.0f, 0.0f, 1.0f });
const vec3 eyePos(0.0f, 0.0f, -1.5f);
#pragma omp parallel for
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
const vec3 pixelPosWorld = TransformScreenToWorld(vec2(i, j));
// 광선의 방향 벡터
// 스크린에 수직인 z방향, 절대값 1.0인 유닉 벡터
// Orthographic projection (정투영) vs perspective projection (원근투영)
// 정투영
// const auto rayDir = vec3(0.0f, 0.0f, 1.0f);
// 원근투영
const auto rayDir = glm::normalize(pixelPosWorld - eyePos);
Ray pixelRay{ pixelPosWorld, rayDir };
pixels[i + width * j] = vec4(glm::clamp(traceRay(pixelRay), 0.0f, 1.0f), 1.0f);
}
}
vec3 TransformScreenToWorld(vec2 posScreen)
{
const float xScale = 2.0f / this->width;
const float yScale = 2.0f / this->height;
const float aspect = float(this->width) / this->height;
// 3차원 공간으로 확장 (z좌표는 0.0)
return vec3((posScreen.x * xScale - 1.0f) * aspect, -posScreen.y * yScale + 1.0f, 0.0f);
}
가까이 있는 물체를 먼저 그린다
Hit FindClosestCollision(Ray& ray)
{
float closest_d = std::numeric_limits<float>::max();
Hit closest_hit = Hit{ -1.0, dvec3(0.0), dvec3(0.0) };
for (int l = 0; l < objects.size(); l++)
{
auto hit = objects[l]->CheckRayCollision(ray);
if (hit.d >= 0.0f && closest_d > hit.d)
{
closest_d = hit.d;
closest_hit = hit;
closest_hit.obj = objects[l];
}
}
return closest_hit;
}