새소식

인기 검색어

게임 개발/그래픽스

[그래픽스] Orthographic projection (정투영) vs perspective projection (원근투영)

  • -

정투영 vs 원근투영

Orthographic projection (정투영)

화면에서 모든 픽셀에서 모든 광선을 (0, 0, 1) 방향으로 쏘는 것

Orthographic projection (정투영)

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를 쏨.

perspective projection (원근투영)

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;
}
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.