2017-01-19 8 views
0

Blinn-Phong 알고리즘을 사용하여 장면의 조명을 계산했습니다. 아직 거리를 고려하지 않았습니다. 이 첫 번째 문제가 해결 될 때까지 내 HDR 및 Specular 계산을 사용하지 않도록 설정했습니다.왜 조명 계산이 잘못 되었습니까?

필자는 어딘가 95 %의 순서로 내 프래그먼트 쉐이더에서 실수를하고 있지만 다른 곳에서는 실수를 한 경우를 대비하여 전체 MCVE를 설정하고 있습니다.

단편 쉐이더 :

R"DATA(#version 430 
layout(location = 0) in vec3 vertex_color; 
layout(location = 1) in vec3 vertex_normal; 
layout(location = 2) in vec3 vertex_position; 

layout(location = 0) out vec4 fragment_color; 

uniform float ambient_factor = 0.05; 
uniform float diffuse_factor = 1; 
//Specular Lighting is disabled until I figure out where the mistake is. 
uniform float specular_factor = 0; 
uniform float specular_shininess = 15; 

uniform vec4 light_position = vec4(2, 0, 2, 1); 
uniform vec4 light_color = vec4(1, 1, 1, 1); 

uniform float exposure = 1; 

uniform vec4 eye; 

void main() { 
    vec3 texture_color = vertex_color; 
    vec3 normalized_fragment_normal = normalize(vertex_normal); 

    vec3 light_direction = normalize(light_position.xyz - vertex_position); 
    vec3 eye_direction = normalize(eye.xyz - vertex_position); 
    vec3 halfway_vector = normalize(light_direction + eye_direction); 

    float diffuse_strength = clamp(dot(normalized_fragment_normal, light_direction), 0, 1); 
    float blinn_phong_specular_strength = max(dot(normalized_fragment_normal, halfway_vector), 0); 

    vec3 working_color = vec3(
     texture_color * ambient_factor + 
     light_color.xyz * light_color.w * texture_color * diffuse_strength * diffuse_factor + 
     light_color.xyz * light_color.w * pow(blinn_phong_specular_strength, specular_shininess) * specular_factor 
    ); 

    //For handling HDR, but disabling for now so that the lighting differences/mistakes are more obvious. 
    //const float gamma = 2.2; 
    //vec3 mapped = vec3(1) - exp(-working_color * exposure); 

    //mapped = pow(mapped, vec3(1/gamma)); 

    //fragment_color = vec4(mapped, 1); 
    fragment_color = vec4(working_color, 1); 
})DATA" 

정점 셰이더 :

R"DATA(#version 430 
layout(location = 0) in vec3 position; 
layout(location = 1) in vec3 color; 
layout(location = 2) in vec3 normal; 

layout(location = 0) out vec3 vertex_color; 
layout(location = 1) out vec3 vertex_normal; 
layout(location = 2) out vec3 vertex_position; 

uniform mat4 projection; 
uniform mat4 view; 
uniform mat4 model_position; 
uniform mat4 model_normal; 

void main() { 
    gl_Position = projection * view * model_position * vec4(position, 1); 
    vertex_color = color; 
    vertex_normal = (model_normal * vec4(normal, 0)).xyz; 
    vertex_position = (model_position * vec4(position, 1)).xyz; 
})DATA" 

Shaders.h :

#pragma once 

#pragma warning(push) 
#pragma warning(once : 4251) 
#include<glbinding\gl\gl.h> 
#include<glbinding\Binding.h> 
#pragma warning(pop) 

const char * vert_src = "" 
#include "Cube.vert.glsl" 
; 

const char * frag_src = "" 
#include "Cube.frag.glsl" 
; 

//The two Light shaders are just pass-through shaders that make the cube look pure white. 
const char * light_vert_src = "" 
#include "Light.vert.glsl" 
; 

const char * light_frag_src = "" 
#include "Light.frag.glsl" 
; 

namespace shaders { 
    using namespace gl; 
    class failed_shader_compilation_exception : public std::runtime_error { 
     std::string error_log; 
    public: 
     failed_shader_compilation_exception(std::string const& why, std::string const& err) : 
      std::runtime_error(why), 
      error_log(err) {} 
     std::string get_log() const { 
      return error_log; 
     } 
    }; 

    void handle_shader_error(GLuint shader, std::string const& type, bool is_shader = true) { 
     int log_length; 
     if (is_shader) 
      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); 
     else 
      glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &log_length); 
     std::string errlog; 
     errlog.resize(log_length); 
     if (is_shader) 
      glGetShaderInfoLog(shader, log_length, nullptr, &errlog[0]); 
     else 
      glGetProgramInfoLog(shader, log_length, nullptr, &errlog[0]); 
     if (is_shader) 
      glDeleteShader(shader); 
     else 
      glDeleteProgram(shader); 
     throw failed_shader_compilation_exception("The " + type + " failed to Compile", errlog); 
    } 

    GLuint get_program(const char * vsrc, const char * fsrc) { 
     GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); 
     int ret; 

     glShaderSource(vertex_shader, 1, &vsrc, nullptr); 
     glCompileShader(vertex_shader); 
     glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &ret); 
     if (!ret) { 
      handle_shader_error(vertex_shader, "Vertex Shader"); 
     } 

     GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 

     glShaderSource(fragment_shader, 1, &fsrc, nullptr); 
     glCompileShader(fragment_shader); 
     glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &ret); 
     if (!ret) { 
      glDeleteShader(vertex_shader); 
      handle_shader_error(fragment_shader, "Fragment Shader"); 
     } 

     GLuint program = glCreateProgram(); 
     glAttachShader(program, vertex_shader); 
     glAttachShader(program, fragment_shader); 
     glLinkProgram(program); 
     glDeleteShader(vertex_shader); 
     glDeleteShader(fragment_shader); 

     glGetProgramiv(program, GL_LINK_STATUS, &ret); 
     if (!ret) { 
      handle_shader_error(program, "Program", false); 
     } 
     return program; 
    } 
} 

하여 Main.cpp :

#define GLFW_INCLUDE_NONE 
#include<GLFW\glfw3.h> 

#pragma warning(push) 
#pragma warning(once : 4251) 
#include<glbinding\gl43core\gl.h> 
#include<glbinding\Binding.h> 
#pragma warning(pop) 

#include<iostream> 

#include<glm/glm.hpp> 
#include<glm/gtc/matrix_transform.hpp> 
#include<glm/gtc/type_ptr.hpp> 

#include "Shaders.h" 

float vertex_data[] { 
    0, 0, 0, 1, 0, 0, 0, 0, 1, 
    1, 0, 0, 1, 0, 0, 0, 0, 1, 
    1, 1, 0, 1, 0, 0, 0, 0, 1, 
    0, 0, 0, 1, 0, 0, 0, 0, 1, 
    1, 1, 0, 1, 0, 0, 0, 0, 1, 
    0, 1, 0, 1, 0, 0, 0, 0, 1, 

    1, 0, 0, 0, 1, 0, 1, 0, 0, 
    1, 0, -1, 0, 1, 0, 1, 0, 0, 
    1, 1, -1, 0, 1, 0, 1, 0, 0, 
    1, 0, 0, 0, 1, 0, 1, 0, 0, 
    1, 1, -1, 0, 1, 0, 1, 0, 0, 
    1, 1, 0, 0, 1, 0, 1, 0, 0, 

    1, 0, -1, 0, 1, 1, 0, 0, -1, 
    0, 0, -1, 0, 1, 1, 0, 0, -1, 
    0, 1, -1, 0, 1, 1, 0, 0, -1, 
    1, 0, -1, 0, 1, 1, 0, 0, -1, 
    0, 1, -1, 0, 1, 1, 0, 0, -1, 
    1, 1, -1, 0, 1, 1, 0, 0, -1, 

    0, 0, -1, 1, 0, 1, -1, 0, 0, 
    0, 0, 0, 1, 0, 1, -1, 0, 0, 
    0, 1, 0, 1, 0, 1, -1, 0, 0, 
    0, 0, -1, 1, 0, 1, -1, 0, 0, 
    0, 1, 0, 1, 0, 1, -1, 0, 0, 
    0, 1, -1, 1, 0, 1, -1, 0, 0, 

    0, 1, 0, 0, 0, 1, 0, 1, 0, 
    1, 1, 0, 0, 0, 1, 0, 1, 0, 
    1, 1, -1, 0, 0, 1, 0, 1, 0, 
    0, 1, 0, 0, 0, 1, 0, 1, 0, 
    1, 1, -1, 0, 0, 1, 0, 1, 0, 
    0, 1, -1, 0, 0, 1, 0, 1, 0, 

    0, 0, 0, 1, 1, 0, 0, -1, 0, 
    0, 0, -1, 1, 1, 0, 0, -1, 0, 
    1, 0, -1, 1, 1, 0, 0, -1, 0, 
    0, 0, 0, 1, 1, 0, 0, -1, 0, 
    1, 0, -1, 1, 1, 0, 0, -1, 0, 
    1, 0, 0, 1, 1, 0, 0, -1, 0, 
}; 

float light_cube_data[]{ 
    0, 0, 0, 1, 0, 0, 1, 1, 0, 
    0, 0, 0, 1, 1, 0, 0, 1, 0, 

    1, 0, 0, 1, 0, -1, 1, 1, -1, 
    1, 0, 0, 1, 1, -1, 1, 1, 0, 

    1, 0, -1, 0, 0, -1, 0, 1, -1, 
    1, 0, -1, 0, 1, -1, 1, 1, -1, 

    0, 0, -1, 0, 0, 0, 0, 1, 0, 
    0, 0, -1, 0, 1, 0, 0, 1, -1, 

    0, 1, 0, 1, 1, 0, 1, 1, -1, 
    0, 1, 0, 1, 1, -1, 0, 1, -1, 

    0, 0, 0, 0, 0, -1, 1, 0, -1, 
    0, 0, 0, 1, 0, -1, 1, 0, 0, 
}; 

int main() { 
    glfwInit(); 
    GLFWwindow * window = glfwCreateWindow(300, 300, "bluh", nullptr, nullptr); 
    glfwMakeContextCurrent(window); 
    glbinding::Binding::initialize(); 
    using namespace gl43core; 
    GLuint program = 0, light_program = 0; 
    try { 
     program = shaders::get_program(vert_src, frag_src); 
     light_program = shaders::get_program(light_vert_src, light_frag_src); 
    } 
    catch (shaders::failed_shader_compilation_exception const& e) { 
     std::cerr << e.what() << std::endl; 
     std::cerr << e.get_log() << std::endl; 
     system("pause"); 
     return 1; 
    } 
    glUseProgram(program); 
    GLuint vao, vbo; 
    GLuint light_vao, light_vbo; 

    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); 
    glEnableVertexAttribArray(0); 
    glEnableVertexAttribArray(1); 
    glEnableVertexAttribArray(2); 
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)0); 
    glVertexAttribPointer(1, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); 
    glVertexAttribPointer(2, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); 

    glGenVertexArrays(1, &light_vao); 
    glBindVertexArray(light_vao); 
    glGenBuffers(1, &light_vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, light_vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(light_cube_data), light_cube_data, GL_STATIC_DRAW); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(GLfloat), (void*)0); 

    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_CULL_FACE); 

    glm::mat4 view = glm::lookAt(glm::vec3(2, 3, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); 
    struct manip_data { 
     glm::quat view_quat; 
     glm::vec3 view_position; 
     glm::vec4 light_position{ 3, 0, 3, 1 }; 
     glm::vec4 light_color{ 1, 1, 1, 1 }; 
     double prior_time; 
     double current_time; 
    }; 

    manip_data data; 
    data.view_quat = glm::quat(view); 
    data.view_position = glm::vec3(glm::inverse(view)[3]); 
    data.prior_time = data.current_time = glfwGetTime(); 

    glfwSetWindowUserPointer(window, &data); 
    glfwSetKeyCallback(window, [](GLFWwindow * window, int key, int code, int action, int modifier) { 
     manip_data & data = *(reinterpret_cast<manip_data *>(glfwGetWindowUserPointer(window))); 
     data.current_time = glfwGetTime(); 
     double dt = data.current_time - data.prior_time; 
     if (action == GLFW_PRESS || action == GLFW_REPEAT) { 
      switch (key) { 
      case GLFW_KEY_W: data.view_position += glm::inverse(data.view_quat) * glm::vec3(0, 0, -1) * float(dt) * 50.f; break; 
      case GLFW_KEY_S: data.view_position += glm::inverse(data.view_quat) * glm::vec3(0, 0, 1) * float(dt) * 50.f; break; 
      case GLFW_KEY_A: data.view_position += glm::inverse(data.view_quat) * glm::vec3(-1, 0, 0) * float(dt) * 50.f; break; 
      case GLFW_KEY_D: data.view_position += glm::inverse(data.view_quat) * glm::vec3(1, 0, 0) * float(dt) * 50.f; break; 
      case GLFW_KEY_LEFT_SHIFT: data.view_position += glm::inverse(data.view_quat) * glm::vec3(0, 1, 0) * float(dt) * 50.f; break; 
      case GLFW_KEY_LEFT_CONTROL: data.view_position += glm::inverse(data.view_quat) * glm::vec3(0, -1, 0) * float(dt) * 50.f; break; 

      case GLFW_KEY_KP_8: data.view_quat = glm::angleAxis(-float(dt) * 50, glm::vec3(1, 0, 0)) * data.view_quat; break; 
      case GLFW_KEY_KP_2: data.view_quat = glm::angleAxis(float(dt) * 50, glm::vec3(1, 0, 0)) * data.view_quat; break; 
      case GLFW_KEY_KP_4: data.view_quat = glm::angleAxis(-float(dt) * 50, glm::vec3(0, 1, 0)) * data.view_quat; break; 
      case GLFW_KEY_KP_6: data.view_quat = glm::angleAxis(float(dt) * 50, glm::vec3(0, 1, 0)) * data.view_quat; break; 
      case GLFW_KEY_KP_9: data.view_quat = glm::angleAxis(-float(dt) * 50, glm::vec3(0, 0, -1)) * data.view_quat; break; 
      case GLFW_KEY_KP_7: data.view_quat = glm::angleAxis(float(dt) * 50, glm::vec3(0, 0, -1)) * data.view_quat; break; 
      } 
     } 
     data.prior_time = data.current_time; 
    }); 

    while (!glfwWindowShouldClose(window)) { 
     glfwPollEvents(); 
     data.prior_time = glfwGetTime(); 
     int width, height; 
     glfwGetFramebufferSize(window, &width, &height); 
     glViewport(0, 0, width, height); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     glm::mat4 projection = glm::perspective(glm::radians(60.f), float(width)/height, 0.1f, 100.f); 
     glm::mat4 model; 
     glm::mat4 normal_model; 

     view = glm::translate(glm::mat4_cast(data.view_quat), -data.view_position); 
     glm::vec4 eye = glm::inverse(view)[3]; 
     glm::vec4 light_position{ 1.25, 0.5, 1.25, 1 }; 

     glUseProgram(program); 
     glBindVertexArray(vao); 
     glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, false, glm::value_ptr(projection)); 
     glUniformMatrix4fv(glGetUniformLocation(program, "view"), 1, false, glm::value_ptr(view)); 
     glUniformMatrix4fv(glGetUniformLocation(program, "model_position"), 1, false, glm::value_ptr(model)); 
     glUniformMatrix4fv(glGetUniformLocation(program, "model_normal"), 1, false, glm::value_ptr(normal_model)); 
     glUniform4fv(glGetUniformLocation(program, "eye"), 1, glm::value_ptr(eye)); 
     glUniform4fv(glGetUniformLocation(program, "light_position"), 1, glm::value_ptr(light_position)); 

     glDrawArrays(GL_TRIANGLES, 0, sizeof(vertex_data)/sizeof(GLfloat)/9); 

     model = glm::translate(model, glm::vec3(light_position)); 
     model = glm::scale(model, glm::vec3(0.25, 0.25, 0.25)); 

     glUseProgram(light_program); 
     glBindVertexArray(light_vao); 

     glUniformMatrix4fv(glGetUniformLocation(light_program, "projection"), 1, false, glm::value_ptr(projection)); 
     glUniformMatrix4fv(glGetUniformLocation(light_program, "view"), 1, false, glm::value_ptr(view)); 
     glUniformMatrix4fv(glGetUniformLocation(light_program, "model_position"), 1, false, glm::value_ptr(model)); 

     glDrawArrays(GL_TRIANGLES, 0, sizeof(light_cube_data)/sizeof(GLfloat)/3); 

     glfwSwapBuffers(window); 
    } 

    return 0; 
} 
,536,

이것은 조명이 잘못되었다는 것을 알아 내기 위해 추가 된 몇 가지 주석이있는 기본 렌더링 위치의 그림입니다.

Picture of Incorrect Lighting

내가 GLFW를 사용하여 내의 OpenGL API 액세스 glbinding하지만 glbinding 대신 그것을 사용하는 경우 GLEW 거의 동일한 코드가 있어요. 또한 수학 함수에 GLM을 사용하고 있습니다.

답변

3

당신이 법선으로 정점 색상을 다시 사용하고 배열의 실제 법선을 사용하지 않을 :

glVertexAttribPointer(1, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); 
glVertexAttribPointer(2, 3, GL_FLOAT, false, 9 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); 
+0

* 한숨 *. 네, 그게 바보 같아야한다는 것을 알았습니다. 조각 쉐이더가 문제라고 생각하지 않는다면. 어쨌든, 고마워. 그것은 좋은 잡기입니다. – Xirema

관련 문제