파이썬으로 3D 렌더링을 위한 광심도 효과 구현하기

개요

광심도(Phong shading)는 3D 렌더링의 중요한 효과 중 하나로, 물체의 표면에 따라 빛의 반사 정도를 조절하여 현실적인 느낌을 내는 기술입니다. 이번 포스트에서는 파이썬을 사용하여 광심도 효과를 구현하는 방법에 대해 알아보겠습니다.

필요한 라이브러리 설치

먼저, 광심도 효과를 구현하기 위해 필요한 라이브러리를 설치해야 합니다. 파이썬에서는 PyOpenGL이라는 라이브러리를 이용하여 OpenGL을 사용할 수 있습니다. 아래의 명령어를 사용하여 PyOpenGL을 설치합니다.

pip install PyOpenGL

물체의 정점 데이터 생성

광심도 효과를 적용하기 위해서는 먼저 물체의 정점 데이터를 생성해야 합니다. 정점 데이터는 3차원 공간에서 물체의 모양을 나타내기 위한 정보로, 정점의 위치와 법선 벡터의 정보가 필요합니다. 법선 벡터는 물체 표면의 방향성을 나타내며, 광원에서의 빛의 반사를 결정하는데 중요한 역할을 합니다.

import numpy as np

# 물체의 정점 데이터 생성
vertices = np.array([
    [1, 1, 1],  # 정점 1의 위치
    [1, -1, 1],  # 정점 2의 위치
    [-1, -1, 1],  # 정점 3의 위치
    [-1, 1, 1]  # 정점 4의 위치
])

normals = np.array([
    [0, 0, 1],  # 정점 1의 법선 벡터
    [0, 0, 1],  # 정점 2의 법선 벡터
    [0, 0, 1],  # 정점 3의 법선 벡터
    [0, 0, 1],  # 정점 4의 법선 벡터
])

광심도 계산하기

광심도 효과를 구현하기 위해서는 물체의 법선 벡터와 빛의 위치 및 강도를 이용해 광심도 값을 계산해야 합니다. 아래의 코드는 광심도 계산을 위한 함수입니다.

def calculate_phong_shading(vertices, normals, light_position, light_intensity, viewer_position, ambient_intensity, specular_intensity, specular_power):
    # 빛의 방향 벡터 계산
    light_direction = light_position - vertices

    # 빛과 법선 벡터의 내적 계산
    dot_product = np.sum(normals * light_direction, axis=1)

    # 빛의 반사 방향 계산
    reflection_direction = 2 * dot_product[:, np.newaxis] * normals - light_direction
    reflection_direction /= np.linalg.norm(reflection_direction, axis=1)[:, np.newaxis]

    # 빛의 반사와 보는 방향 벡터의 내적 계산
    dot_product_viewer = np.sum(reflection_direction * (-viewer_position), axis=1)

    # 광심도 값 계산
    ambient_component = ambient_intensity
    diffuse_component = np.clip(dot_product, 0, 1) * light_intensity
    specular_component = specular_intensity * np.power(np.clip(dot_product_viewer, 0, 1), specular_power)

    phong_shading = ambient_component + diffuse_component + specular_component
    return phong_shading

효과 적용하기

마지막으로, 물체에 광심도를 적용하여 렌더링하는 방법입니다. 아래의 코드는 광심도 값을 구하고, 이를 이용해 물체를 그리는 예시입니다.

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from PIL import Image

def render_scene():
    # 광원 위치 및 강도 설정
    light_position = np.array([0, 0, 3])
    light_intensity = 1.0

    # 관찰자 위치 설정
    viewer_position = np.array([0, 0, 5])

    # 환경 광원과 반사광 강도 설정
    ambient_intensity = 0.2
    specular_intensity = 0.5
    specular_power = 32

    # 물체의 광심도 효과 계산
    phong_shading = calculate_phong_shading(vertices, normals, light_position, light_intensity, viewer_position,
                                            ambient_intensity, specular_intensity, specular_power)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glBegin(GL_QUADS)
    for i in range(len(vertices)):
        # 광심도 값을 이용해 물체를 그림
        glColor3f(phong_shading[i], phong_shading[i], phong_shading[i])
        glVertex3f(vertices[i][0], vertices[i][1], vertices[i][2])
    glEnd()
    glFlush()

# OpenGL 초기화 함수
def init():
    glutInit()
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH)
    glutInitWindowSize(400, 400)
    glutCreateWindow(b"Phong Shading")

    glEnable(GL_DEPTH_TEST)
    glClearColor(0, 0, 0, 1)

    gluPerspective(45, 1, 0.1, 10)
    glTranslatef(0, 0, -5)

    glutDisplayFunc(render_scene)
    glutMainLoop()

init()

결론

이렇게 파이썬을 사용하여 3D 렌더링에서 광심도 효과를 구현하는 방법을 살펴보았습니다. 광심도를 이용하면 물체의 표면을 현실적으로 표현할 수 있고, 시각적인 렌더링에 더욱 실감 나는 효과를 줄 수 있습니다.