OpenGLでobjをBlinn-Phongシェーダで表示してみる
はじめに
この記事はシリーズ記事です。目次はこちら。
この記事ではobjファイルを読み込み、鏡面反射項にBlinn-Phongを利用して表示するところまでを行います。
プログラムの変更点
次に前回からのプログラムの変更点を示します。
シェーダの変更点
フラグメントシェーダを次のように書き換えます。
shader.frag
#version 460
in vec3 vWorldPosition;
in vec3 vWorldNormal;
layout (location = 0) out vec4 fragment;
uniform vec3 worldCameraPosition;
const vec3 worldLightPosition = vec3(0.0, 5.0, 2.0);
const vec3 lightColor = vec3(1.0);
const vec3 Kdiff = vec3(0.8, 0.5, 0.2);
const vec3 Kspec = vec3(1.0);
const float shininess = 50;
void main() {
vec3 L = normalize(worldLightPosition - vWorldPosition);
vec3 V = normalize(worldCameraPosition - vWorldPosition);
vec3 N = normalize(vWorldNormal);
vec3 H = normalize(L + V);
// Lambert
vec3 diffuse = max(dot(L, N), 0) * Kdiff * lightColor;
// Blinn-phong
vec3 specular = pow(max(dot(N, H), 0), shininess) * Kspec * lightColor;
vec3 color = diffuse + specular;
fragment = vec4(color, 1.0);
}
Uniform変数でカメラのワールド座標系での位置を取得しています。
Kspec
は鏡面反射係数で、shininess
は輝き係数です。
ViewベクトルV
とライトベクトルL
から中間ベクトルH
を計算しています。
N
とH
の内積をshininess
乗して鏡面反射成分を計算しています。
拡散反射について反射係数を前回から変更して色を変えています。
Applicationクラスの変更点
worldCameraPosition
用のメンバ変数を追加します。
application.h
GLFWwindow* window_;
GLuint program_;
GLuint model_loc_;
GLuint model_it_loc_;
GLuint view_projection_loc_;
+ GLuint world_camera_position_loc_;
std::vector<MeshEntity> mesh_entities_;
std::unique_ptr<Camera> camera_;
Application::Init
の中のUniform変数のlocationの取得の部分に追記します。
application.cpp
// Uniform変数の位置を取得
model_loc_ = glGetUniformLocation(program_, "Model");
model_it_loc_ = glGetUniformLocation(program_, "ModelIT");
view_projection_loc_ = glGetUniformLocation(program_, "ViewProjection");
+ world_camera_position_loc_ =
+ glGetUniformLocation(program_, "worldCameraPosition");
Application::Update
を次のように書き換えます。
application.cpp
void Application::Update(const double delta_time) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program_);
auto view_projection = camera_->GetViewProjectionMatrix();
+ auto camera_position = camera_->GetPosition();
glUniformMatrix4fv(view_projection_loc_, 1, GL_FALSE, &view_projection[0][0]);
+ glUniform3fv(world_camera_position_loc_, 1, &camera_position[0]);
for (auto&& mesh_entity : mesh_entities_) {
auto model = mesh_entity.GetModelMatrix();
auto model_it = glm::inverseTranspose(model);
glUniformMatrix4fv(model_loc_, 1, GL_FALSE, &model[0][0]);
glUniformMatrix4fv(model_it_loc_, 1, GL_FALSE, &model_it[0][0]);
mesh_entity.mesh_->Draw();
}
}
実行結果
実行結果は次のようになります。
プログラム全文
プログラム全文はGitHubにアップロードしてあります。