OpenGL

[OpenGL] Light Sources 종류 및 예제

usingsystem 2024. 7. 1. 16:28
728x90

 

Simple Light 

 

  • Ambient Light (앰비언트 광원)
    • 설명: 앰비언트 라이트는 어디에나 있는 빛으로, 난반사를 통해 모든 방향에서 같은 정도의 낮은 밝기를 가진다. 특별한 광원이 없더라도 간접 조명으로 공간을 채운다.
    • 사용 예: 기본적인 환경 조명.
  • Point Light Sources (점 광원)
    • 설명: 중심점 P0에서 모든 방향으로 동일하게 빛을 방출하는 광원으로, 특정 지점에서 빛을 방출하여 전구와 유사하다.
    • 사용
  • Parallel Light Sources (평행 광원)
    • 설명: 광원이 매우 멀리 있어서 빛이 평행하게 들어오는 것을 가정하는 광원으로, 태양광을 모델링할 때 사용된다.
    • 사용 예: 태양광.

 

Real Light

 

  • Spot Lights (스팟 광원)
    • 설명: 특정 지점에서 원추형으로 빛을 방출하는 조명으로, 무대 조명과 유사하다.
    • 사용 예: 무대 조명, 차량 전조등.
  • Area Light Sources (면 광원)
    • 설명:
      • 좁은 의미의 Area Light: Parallel Light의 빛의 진행 방향을 제한하여 특정 구역만 빛을 받도록 설정.
      • 넓은 의미의 Area Light: 기하학적 형상 전체에서 빛이 나오는 광원으로, 현실적으로 여러 개의 점 광원이 한 곳에서 나오는 것과 비슷하다.
    • 사용 예: 천장의 형광등, 창문을 통한 태양광.

Vertex Shader (vertex_shader.glsl)

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

out vec3 FragPos;
out vec3 Normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

 

Fragment Shader (fragment_shader.glsl)

#version 330 core
out vec4 FragColor;

in vec3 FragPos;
in vec3 Normal;

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};

struct Light {
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;

    vec3 direction;
    float cutOff;
    float outerCutOff;
};

uniform Material material;
uniform Light light;
uniform vec3 viewPos;

void main()
{
    // Ambient
    vec3 ambient = light.ambient * material.ambient;

    // Diffuse
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(light.position - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = light.diffuse * (diff * material.diffuse);

    // Specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = light.specular * (spec * material.specular);

    // Result
    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0);
}

Ambient Light 예제 (main_ambient.cpp)

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "shader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

// 함수 프로토타입
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// 설정
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{
    // GLFW 초기화 및 설정
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // GLFW 창 생성
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Ambient Light Example", NULL, NULL);
    if (window == NULL)
    {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    // GLAD 초기화: 모든 OpenGL 함수 포인터 로드
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        return -1;
    }

    // 셰이더 프로그램 빌드 및 컴파일
    Shader lightingShader("vertex_shader.glsl", "fragment_shader.glsl");

    // 정점 데이터 및 버퍼 설정, 정점 속성 구성
    float vertices[] = {
        // positions          // normals
         0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
         0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
        // ... (다른 정점 데이터)
    };
    unsigned int indices[] = {
        0, 1, 3, // 첫 번째 삼각형
        1, 2, 3, // 두 번째 삼각형
        // ... (다른 인덱스 데이터)
    };
    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // 조명 정보 설정
    lightingShader.use();
    lightingShader.setVec3("light.ambient", glm::vec3(0.2f, 0.2f, 0.2f)); // 앰비언트 색상 설정
    lightingShader.setVec3("light.diffuse", glm::vec3(0.0f, 0.0f, 0.0f)); // 디퓨즈 색상 설정
    lightingShader.setVec3("light.specular", glm::vec3(0.0f, 0.0f, 0.0f)); // 스펙큘러 색상 설정

    lightingShader.setVec3("material.ambient", glm::vec3(1.0f, 0.5f, 0.31f)); // 재질의 앰비언트 색상 설정
    lightingShader.setVec3("material.diffuse", glm::vec3(1.0f, 0.5f, 0.31f)); // 재질의 디퓨즈 색상 설정
    lightingShader.setVec3("material.specular", glm::vec3(0.5f, 0.5f, 0.5f)); // 재질의 스펙큘러 색상 설정
    lightingShader.setFloat("material.shininess", 32.0f); // 재질의 광택도 설정

    // 렌더링 루프
    while (!glfwWindowShouldClose(window))
    {
        // 입력 처리
        processInput(window);

        // 렌더링
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // VAO 바인딩 및 렌더링
        lightingShader.use();
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        // 버퍼 스와핑 및 이벤트 폴링
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // 자원 해제
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);

    // GLFW 종료
    glfwTerminate();
    return 0;
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

Point Light 예제 (main_point.cpp)

// 이전 코드와 동일한 부분은 생략하고, 조명 정보 설정 부분만 수정

// 조명 정보 설정
lightingShader.use();
lightingShader.setVec3("light.position", glm::vec3(1.2f, 1.0f, 2.0f)); // 광원 위치 설정
lightingShader.setVec3("light.ambient", glm::vec3(0.2f, 0.2f, 0.2f)); // 앰비언트 색상 설정
lightingShader.setVec3("light.diffuse", glm::vec3(0.5f, 0.5f, 0.5f)); // 디퓨즈 색상 설정
lightingShader.setVec3("light.specular", glm::vec3(1.0f, 1.0f, 1.0f)); // 스펙큘러 색상 설정
lightingShader.setVec3("light.direction", glm::vec3(0.0f, 0.0f, 0.0f)); // 방향 초기화
728x90