2017-01-19 6 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; 
} 

これはデフォルトのレンダリング位置の写真で、照明が間違っていることをどのように知っているかを識別するためにいくつかの注釈を付け加えています。

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

関連する問題