4. 三角形へのレンダリングとライティング パート1
此のチュートリアルシリーズを2025年7月22日午前2時から午前7時の間に始めた方へお知らせです。HomebrewがmacOSにデフォルトでインストールされていない事に気づき、インストールが非常に難しい場合がある為、libディレクトリにglfw.dylibを追加し、Xcodeプロジェクト設定を/usr/local/libのグローバルディレクトリではなくローカルディレクトリにリンクする様に変更しました。其の為、Macユーザー向けのGLFWインストール手順をGLSL 概要ページから削除しました。
Unixユーザーの場合、build_unix.shファイルに-lmフラグをリンカーに追加し、数学関数が動作する様に更新しました。
其の他の方には、includeディレクトリにvector.hファイルを追加しました。此れにより、色値を9つの異なるfloatで定義する代わりに、3つのVector3を作成出来る様になり、見た目がずっと良くなりました。其の為、グラデーションページも其れに合わせて調整しました。最後に、ページの最後で完全なソースコードを表示する代わりに、.diffファイルを共有し、その直下にプレビューを表示する様にしました。これにより、スクロール量が大幅に削減されます。
ZIP及びTARファイルも更新しました。こちらで入手出来ます。
4.1 三角形へのレンダリング
現在、シェーダーを画面全体にレンダリングしています。此れは見た目は良いですが、画面上に他に何をレンダリング出来るかという点で非常に制限があります。先ず其の問題を解決し、シェーダーを三角形にレンダリングしてみましょう。
// 頂点データ(フルスクリーンクアッド)を設定
float vertices[] = {
-0.5f, -0.5f, 0.0f, 0.0f, // 左下(位置、UV)
0.5f, -0.5f, 1.0f, 0.0f, // 右下
0.0f, 0.5f, 0.5f, 1.0f
};
GLuint indices[] = { 0, 1, 2 };
...
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
結果:

4.2 ライティングの説明
次に、ライティングについて説明します。重要でない様に思えるかもしんが、複雑なモデルを使用する場合、ライティングは非常に重要な概念です。一般的な光の種類は6つあり、此の章では其の内の最初の2つを、簡単なものから難しい物の順に説明します。
アンビエントライト
アンビエントライトは理解と実装が最も簡単です。方向性を持たない均一な光で、方向や距離などの複雑な計算は必要ありません。簡単に言えば、「アンビエントライト」は「背景光」とも呼ばれます。
ディレクショナルライト
ディレクショナルライトは、光の方向と表面の法線という、3Dライティングの基本的な概念を導入します。此れも比較的簡単です。太陽光に例える事が出来ます。
ポイントライト
ポイントライトは、ディレクショナルライトに位置と減衰を追加し、距離による光の減衰の概念を導入します。電球に例える事が出来ます。
光の方向の計算:(光の位置 - フラグメントの位置)
減衰を適用するには:1 / (定数 + 線形 * d + 二次体 * d²)
スポットライト
スポットライトは、ポイントライトに方向性と円錐角度を追加した物です。懐中電灯に例える事が出来ます。
ヘミスフィアライト
ヘミスフィアライトは、アンビエントライトの特殊な形態で、方向性(空と地面)の変化を追加します。エリアライトよりは複雑ではありませんが、環境に基づくライティングの概念を導入します。屋外のライティングをシミュレートする為に使用出来ます。
エリアライト
エリアライトは最も複雑で、表面全体の積分や近似(複数のポイントライトなど)が必要です。エリアライトは、窓やパネルの様な現実世界の表面をシミュレートします。
4.3 アンビエントライト
シェーダーディレクトリに新しいファイルfrag_ambient.glslを作成します。
#version 450 core
in vec2 uVu;
out vec4 out_color;
uniform vec3 materialColor;
uniform float ambientIntensity;
void main() {
vec3 ambient = materialColor * ambientIntensity;
out_color = vec4(ambient, 1.0);
}
簡単そうですね?Cコードではもっと多くの作業が必要です。
// シェーダーファイルを読み込む
#ifdef __APPLE__
char *vertexShaderSource = readShaderFile("shader/vertex.mac.glsl");
char *fragmentShaderSource = readShaderFile("shader/fragment.mac.glsl");
char *fragmentAmbientSource = readShaderFile("shader/frag_ambient.mac.glsl");
#else
char *vertexShaderSource = readShaderFile("shader/vertex.glsl");
char *fragmentShaderSource = readShaderFile("shader/fragment.glsl");
char *fragmentAmbientSource = readShaderFile("shader/frag_ambient.glsl");
#endif
if (!vertexShaderSource || !fragmentShaderSource || !fragmentAmbientSource) {
puts("シェーダーファイルの読み込みに失敗しました");
if (vertexShaderSource) free(vertexShaderSource);
if (fragmentShaderSource) free(fragmentShaderSource);
if (fragmentAmbientSource) free(fragmentAmbientSource);
glfwDestroyWindow(window);
glfwTerminate();
return -1;
}
// シェーダーをコンパイル
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, (const char **)&vertexShaderSource, NULL);
glCompileShader(vertexShader);
checkShaderCompile(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, (const char **)&fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
checkShaderCompile(fragmentShader);
GLuint fragmentAmbientShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentAmbientShader, 1, (const char **)&fragmentAmbientSource, NULL);
glCompileShader(fragmentAmbientShader);
checkShaderCompile(fragmentAmbientShader);
// 三角形のシェーダープログラムをリンク
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
checkProgramLink(shaderProgram);
// アンビエントシェーダープログラムをリンク
GLuint ambientShaderProgram = glCreateProgram();
glAttachShader(ambientShaderProgram, vertexShader);
glAttachShader(ambientShaderProgram, fragmentAmbientShader);
glLinkProgram(ambientShaderProgram);
checkProgramLink(ambientShaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(fragmentAmbientShader);
free(vertexShaderSource);
free(fragmentShaderSource);
free(fragmentAmbientSource);
// 頂点データ(三角形)を設定:三角形用(左にオフセット)
float vertices[] = {
-0.8f, -0.5f, 0.0f, 0.0f, // 左下(位置、UV)
-0.3f, -0.5f, 1.0f, 0.0f, // 右下
-0.55f, 0.5f, 0.5f, 1.0f // 上
};
GLuint indices[] = { 0, 1, 2 };
// 頂点データ(三角形)を設定:アンビエント用(右にオフセット)
float verticesAmbient[] = {
0.3f, -0.5f, 0.0f, 0.0f, // 左下(位置、UV)
0.8f, -0.5f, 1.0f, 0.0f, // 右下
0.55f, 0.5f, 0.5f, 1.0f // 上
};
// VAO、VBO、EBOを三角形用に設定
GLuint VAO, VBO, 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);
// 頂点属性:位置(location 0)、UV(location 1)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
size_t offset = 2 * sizeof(float);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)offset);
glEnableVertexAttribArray(1);
// VAO、VBO、EBOをアンビエント用に設定
GLuint VAOAmbient, VBOAmbient, EBOAmbient;
glGenVertexArrays(1, &VAOAmbient);
glGenBuffers(1, &VBOAmbient);
glGenBuffers(1, &EBOAmbient);
glBindVertexArray(VAOAmbient);
glBindBuffer(GL_ARRAY_BUFFER, VBOAmbient);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticesAmbient), verticesAmbient, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOAmbient);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)offset);
glEnableVertexAttribArray(1);
// メインレンダリングループ
while (!glfwWindowShouldClose(window)) {
// 画面をクリア
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// シェーダープログラムを使用
glUseProgram(shaderProgram);
// 時間に基づいて色をアニメーション
float time = (float)glfwGetTime();
float speed = 1.0f; // アニメーションの速度
float phase = 2.0f * 3.14159f / 3.0f; // // 120度の位相差(3色用)
// uColorA: 赤 -> 緑 -> 青
Vector3 colorA;
colorA.r = sin(time * speed + 0.0f) * 0.5f + 0.5f; // 0.0 to 1.0
colorA.g = sin(time * speed + phase) * 0.5f + 0.5f;
colorA.b = sin(time * speed + 2.0f * phase) * 0.5f + 0.5f;
// uColorB: 緑 -> 青 -> 赤
Vector3 colorB;
colorB.r = sin(time * speed + 2.0f * phase) * 0.5f + 0.5f;
colorB.g = sin(time * speed + 0.0f) * 0.5f + 0.5f;
colorB.b = sin(time * speed + phase) * 0.5f + 0.5f;
// uColorC: 青 -> 赤 -> 緑
Vector3 colorC;
colorC.r = sin(time * speed + phase) * 0.5f + 0.5f;
colorC.g = sin(time * speed + 2.0f * phase) * 0.5f + 0.5f;
colorC.b = sin(time * speed + 0.0f) * 0.5f + 0.5f;
// ユニフォームを設定
glUniform3f(glGetUniformLocation(shaderProgram, "uColorA"), colorA.r, colorA.g, colorA.b); // 赤
glUniform3f(glGetUniformLocation(shaderProgram, "uColorB"), colorB.r, colorB.g, colorB.b); // 緑
glUniform3f(glGetUniformLocation(shaderProgram, "uColorC"), colorC.r, colorC.g, colorC.b); // 青
// クアッドを描画
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
// アンビエントシェーダープログラムを使用(右の三角形)
glUseProgram(ambientShaderProgram);
// ユニフォームを設定(アンビエントシェーダー)
Vector3 materialColor = { 0.8f, 0.2f, 0.3f }; // 赤みがかった色
float ambientIntensity = 0.6f; // アンビエント光の強さ(0.0~1.0)
glUniform3f(glGetUniformLocation(ambientShaderProgram, "materialColor"), materialColor.r, materialColor.g, materialColor.b);
glUniform1f(glGetUniformLocation(ambientShaderProgram, "ambientIntensity"), ambientIntensity);
// 右の三角形を描画(アンビエントシェーダー)
glBindVertexArray(VAOAmbient);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
// バッファをスワップし、イベントを処理
glfwSwapBuffers(window);
glfwPollEvents();
}
// クリーンアップ
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteVertexArrays(1, &VAOAmbient);
glDeleteBuffers(1, &VBOAmbient);
glDeleteBuffers(1, &EBOAmbient);
glDeleteProgram(shaderProgram);
glDeleteProgram(ambientShaderProgram);
glfwDestroyWindow(window);
glfwTerminate();
結果は次の様になります:

4.4 ディレクショナルライト
此のチュートリアルではディレクショナルライトは似た様に見えるかもしんが、実際の複雑な環境では全く異なる物です。同じ様に見える理由は、影を落とす3Dオブジェクトがない為です。
新しいファイルvertex_directional.glslを作成し、以下を挿入します:
#version 450 core
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aUv;
layout(location = 2) in vec3 aNormal;
out vec2 vUv;
out vec3 vNormal;
void main() {
vUv = aUv;
vNormal = aNormal;
gl_Position = vec4(aPosition, 0.0, 1.0);
}
layout(location = 2) in vec3 aNormal; は、頂点の法線のための3Dベクトル入力を定義し、属性2に割り当てます。法線は頂点が「向いている」方向を示し、光が各頂点にどの様に当たるかを決定します。vNormal = aNormal; で此の値を変更せずにフラグメントシェーダーに渡します。
新しいファイルfrag_directional.glslを作成し、以下を挿入します:
#version 450 core
in vec2 vUv;
out vec4 out_color;
uniform vec3 materialColor;
uniform vec3 lightDirection;
uniform float lightIntensity;
void main() {
vec3 normal = vec3(0.0, 0.0, 1.0);
float diffuseFactor = max(dot(normal, -normalize(lightDirection)), 0.0);
vec3 diffuse = materialColor * diffuseFactor * lightIntensity;
out_color = vec4(diffuse, 1.0);
}
in vec3 vNormal;は、頂点シェーダーから受け取った法線ベクトルを追加します。uniform vec3 materialColor;は、三角形の基本色(RGB)を保持します。此れはuniformであり、Cプログラムから設定され、全てのピクセルで同じままです。uniform vec3 lightDirection;は、光が来る方向の座標(XYZ)を保持します。此れは、太陽の様に直線的な光の方向をシェーダーに伝えます。uniform float lightIntensity;は、光の明るさを保持し、0.0が最も暗く(光なし)、1.0が最も明るいです。
vec3 normal = normalize(vNormal);は、補間された法線(vNormal)を取り、長さを1にスケールします(normalize)。此れにより、正確なライティング計算が保証されます。normalize(lightDirection)は、lightDirectionベクトルを長さ1にスケールし、一貫した計算を保証します。-normalize(lightDirection)は、光の方向を反転させ、表面に向かって光が来る様にします。dot(normal, -normalize(lightDirections))は、法線と反転した光の方向の間の角度のコサインを計算します。max(..., 0.0)は、結果が負にならない様にし(負の値は表面の裏から来る光を意味し、それを無視します)。
main.cで:
// 頂点データ(三角形)を設定:ディレクショナル用(右にオフセット)
float verticesDirectional[] = {
0.3f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.707f, // 左下(位置、UV、形動ノーマル)
0.8f, -0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.707f, // 右下
0.55f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.707f // 上
};
...
// VAO、VBO、EBOをディレクショナル用に設定
GLuint VAODirectional, VBODirectional, EBODirectional;
glGenVertexArrays(1, &VAODirectional);
glGenBuffers(1, &VBODirectional);
glGenBuffers(1, &EBODirectional);
glBindVertexArray(VAODirectional);
glBindBuffer(GL_ARRAY_BUFFER, VBODirectional);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticesDirectional), verticesDirectional, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBODirectional);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void *)(2 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void *)(4 * sizeof(float)));
glEnableVertexAttribArray(2);
...
// ディレクショナルシェーダープログラムを使用(右の三角形)
glUseProgram(directionalShaderProgram);
// ユニフォームを設定(アンビエントシェーダー)
Vector3 materialColor = { 0.8f, 0.2f, 0.3f }; // 赤みがかった色
Vector3 lightDirection = { 0.0f, 0.0f, -1.0f }; // ライトの方向(正規化不要、シェーダーで処理)
float lightIntensity = 1.0f; // ライトの強さ(0.0~1.0)
glUniform3f(glGetUniformLocation(directionalShaderProgram, "materialColor"), materialColor.r, materialColor.g, materialColor.b);
glUniform3f(glGetUniformLocation(directionalShaderProgram, "lightDirection"), lightDirection.x, lightDirection.y, lightDirection.z);
glUniform1f(glGetUniformLocation(directionalShaderProgram, "lightIntensity"), lightIntensity);

最終的な変更: DIFFをダウンロード
ファイル: a/main-ambient.c
| 前 | 新 | ||
|---|---|---|---|
| 151 | // シェーダーファイルを読み込む | 151 | // シェーダーファイルを読み込む |
| 152 | #ifdef __APPLE__ | 152 | #ifdef __APPLE__ |
| 153 | char *vertexShaderSource = readShaderFile("shader/vertex.mac.glsl"); | 153 | char *vertexShaderSource = readShaderFile("shader/vertex.mac.glsl"); |
| 154 | char *fragmentShaderSource = readShaderFile("shader/fragment.mac.glsl"); | 154 | char *fragmentShaderSource = readShaderFile("shader/fragment.mac.glsl"); |
| 155 | 155 | char *fragmentAmbientSource = readShaderFile("shader/frag_ambient.mac.glsl"); | |
| 156 | #else | 156 | #else |
| 157 | char *vertexShaderSource = readShaderFile("shader/vertex.glsl"); | 157 | char *vertexShaderSource = readShaderFile("shader/vertex.glsl"); |
| 158 | char *fragmentShaderSource = readShaderFile("shader/fragment.glsl"); | 158 | char *fragmentShaderSource = readShaderFile("shader/fragment.glsl"); |
| 159 | 159 | char *fragmentAmbientSource = readShaderFile("shader/frag_ambient.glsl"); | |
| 160 | #endif | 160 | #endif |
| 161 | if (!vertexShaderSource || !fragmentShaderSource) { | 161 | if (!vertexShaderSource || !vertexDirectionalSource || !fragmentShaderSource || !fragmentAmbientSource) { |
| 162 | puts("シェーダーファイルの読み込みに失敗しました"); | 162 | puts("シェーダーファイルの読み込みに失敗しました"); |
| 163 | if (vertexShaderSource) free(vertexShaderSource); | 163 | if (vertexShaderSource) free(vertexShaderSource); |
| 164 | if (fragmentShaderSource) free(fragmentShaderSource); | 164 | if (fragmentShaderSource) free(fragmentShaderSource); |
| 165 | 165 | if (fragmentAmbientSource) free(fragmentAmbientSource); | |
| 166 | glfwDestroyWindow(window); | 166 | glfwDestroyWindow(window); |
| 167 | glfwTerminate(); | 167 | glfwTerminate(); |
| 168 | return -1; | 168 | return -1; |
| 171 | 181 | glCompileShader(vertexShader); | |
| 172 | 182 | checkShaderCompile(vertexShader); | |
| 173 | 183 | ||
| 174 | 184 | GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); | |
| 175 | 185 | glShaderSource(fragmentShader, 1, (const char **)&fragmentShaderSource, NULL); | |
| 176 | 186 | glCompileShader(fragmentShader); | |
| 177 | 187 | checkShaderCompile(fragmentShader); | |
| 178 | 188 | ||
| 179 | 189 | GLuint fragmentAmbientShader = glCreateShader(GL_FRAGMENT_SHADER); | |
| 180 | 190 | glShaderSource(fragmentAmbientShader, 1, (const char **)&fragmentAmbientSource, NULL); | |
| 181 | glCompileShader(vertexShader); | 191 | glCompileShader(fragmentAmbientShader); |
| 182 | checkShaderCompile(vertexShader); | 192 | checkShaderCompile(fragmentAmbientShader); |
| 183 | 193 | ||
| 184 | GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); | 194 | // 三角形のシェーダープログラムをリンク |
| 185 | glShaderSource(fragmentShader, 1, (const char **)&fragmentShaderSource, NULL); | 195 | GLuint shaderProgram = glCreateProgram(); |
| 186 | glCompileShader(fragmentShader); | 196 | glAttachShader(shaderProgram, vertexShader); |
| 187 | checkShaderCompile(fragmentShader); | 197 | glAttachShader(shaderProgram, fragmentShader); |
| 188 | 198 | glLinkProgram(shaderProgram); | |
| 189 | // シェーダープログラムをリンク | 199 | checkProgramLink(shaderProgram); |
| 190 | 200 | ||
| 191 | 201 | // アンビエントシェーダープログラムをリンク | |
| 192 | 202 | GLuint ambientShaderProgram = glCreateProgram(); | |
| 193 | 203 | glAttachShader(ambientShaderProgram, vertexShader); | |
| 194 | 204 | glAttachShader(ambientShaderProgram, fragmentAmbientShader); | |
| 195 | GLuint shaderProgram = glCreateProgram(); | 205 | glLinkProgram(ambientShaderProgram); |
| 196 | glAttachShader(shaderProgram, vertexShader); | 206 | checkProgramLink(ambientShaderProgram); |
| 197 | glAttachShader(shaderProgram, fragmentShader); | 207 | |
| 198 | glLinkProgram(shaderProgram); | 208 | glDeleteShader(vertexShader); |
| 199 | checkProgramLink(shaderProgram); | 209 | glDeleteShader(fragmentShader); |
| 200 | 210 | glDeleteShader(fragmentAmbientShader); | |
| 201 | 211 | free(vertexShaderSource); | |
| 202 | 212 | free(vertexDirectionalSource); | |
| 203 | 213 | free(fragmentShaderSource); | |
| 204 | 214 | free(fragmentAmbientSource); | |
| 205 | 215 | ||
| 206 | 216 | // 頂点データ(三角形)を設定:三角形用(左にオフセット) | |
| 207 | 217 | float vertices[] = { | |
| 208 | glDeleteShader(vertexShader); | 218 | -0.8f, -0.5f, 0.0f, 0.0f, // 左下(位置、UV) |
| 209 | glDeleteShader(fragmentShader); | 219 | -0.3f, -0.5f, 1.0f, 0.0f, // 右下 |
| 210 | 220 | -0.55f, 0.5f, 0.5f, 1.0f // 上 | |
| 211 | free(vertexShaderSource); | 221 | }; |
| 212 | 222 | GLuint indices[] = { 0, 1, 2 }; | |
| 213 | free(fragmentShaderSource); | 223 | |
| 214 | 224 | // 頂点データ(三角形)を設定:アンビエント用(右にオフセット) | |
| 215 | 225 | float verticesAmbient[] = { | |
| 216 | // 頂点データ(フルスクリーンクアッド)を設定 | 226 | 0.3f, -0.5f, 0.0f, 0.0f, // 左下(位置、UV) |
| 217 | float vertices[] = { | 227 | 0.8f, -0.5f, 1.0f, 0.0f, // 右下 |
| 218 | -1.0f, -1.0f, 0.0f, 0.0f, // 左下(位置、UV) | 228 | 0.55f, 0.5f, 0.5f, 1.0f // 上 |
| 219 | 1.0f, -1.0f, 1.0f, 0.0f, // 右下 | 229 | }; |
| 220 | 1.0f, 1.0f, 1.0f, 1.0f, // 右上 | 230 | |
| 221 | -1.0f, 1.0f, 0.0f, 1.0f // 左上 | 231 | // VAO、VBO、EBOを三角形用に設定 |
| 222 | GLuint indices[] = { 0, 1, 2, 2, 3, 0 }; | 232 | GLuint VAO, VBO, EBO; |
| 223 | 233 | glGenVertexArrays(1, &VAO); | |
| 224 | 234 | glGenBuffers(1, &VBO); | |
| 225 | 267 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); | |
| 226 | 268 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); | |
| 227 | 269 | ||
| 228 | 270 | ||
| 229 | 271 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); | |
| 230 | 272 | glEnableVertexAttribArray(0); | |
| 231 | 273 | size_t offset = 2 * sizeof(float); | |
| 232 | GLuint VAO, VBO, EBO; | 274 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)offset); |
| 233 | glGenVertexArrays(1, &VAO); | 275 | glEnableVertexAttribArray(1); |
| 234 | glGenBuffers(1, &VBO); | 276 | |
| 208 | 277 | // VAO、VBO、EBOをアンビエント用に設定 | |
| 209 | 278 | GLuint VAOAmbient, VBOAmbient, EBOAmbient; | |
| 210 | 279 | glGenVertexArrays(1, &VAOAmbient); | |
| 211 | 280 | glGenBuffers(1, &VBOAmbient); | |
| 212 | 281 | glGenBuffers(1, &EBOAmbient); | |
| 213 | 282 | ||
| 214 | 283 | glBindVertexArray(VAOAmbient); | |
| 215 | 284 | glBindBuffer(GL_ARRAY_BUFFER, VBOAmbient); | |
| 216 | 285 | glBufferData(GL_ARRAY_BUFFER, sizeof(verticesAmbient), verticesAmbient, GL_STATIC_DRAW); | |
| 217 | 286 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOAmbient); | |
| 218 | 287 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); | |
| 219 | 288 | ||
| 220 | 289 | // メインレンダリングループ | |
| 221 | 290 | while (!glfwWindowShouldClose(window)) { | |
| 222 | 291 | // 画面をクリア | |
| 223 | 344 | ||
| 224 | 345 | // クアッドを描画 | |
| 225 | 346 | glBindVertexArray(VAO); | |
| 226 | 347 | glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); | |
| 227 | 348 | ||
| 228 | 349 | // アンビエントシェーダープログラムを使用(右の三角形) | |
| 229 | 350 | glUseProgram(ambientShaderProgram); | |
| 230 | 351 | ||
| 231 | 352 | // ユニフォームを設定(アンビエントシェーダー) | |
| 232 | 353 | Vector3 materialColor = { 0.8f, 0.2f, 0.3f }; // 赤みがかった色 | |
| 233 | 354 | Vector3 lightDirection = { -0.5f, -0.5f, -0.707f }; // ライトの方向(正規化不要、シェーダーで処理) | |
| 234 | 355 | float ambientIntensity = 0.6f; // アンビエント光の強さ(0.0~1.0) | |
| 235 | 356 | ||
| 236 | 357 | glUniform3f(glGetUniformLocation(directionalShaderProgram, "materialColor"), materialColor.r, materialColor.g, materialColor.b); | |
| 237 | 358 | glUniform3f(glGetUniformLocation(directionalShaderProgram, "lightDirection"), lightDirection.x, lightDirection.y, lightDirection.z); | |
| 238 | 359 | glUniform1f(glGetUniformLocation(ambientShaderProgram, "ambientIntensity"), ambientIntensity); | |
| 239 | 360 | ||
| 240 | 361 | // 右の三角形を描画(アンビエントシェーダー) | |
| 241 | 362 | glBindVertexArray(VAOAmbient); | |
| 242 | 363 | glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); | |
| 243 | 364 | ||
| 244 | 365 | // バッファをスワップし、イベントを処理 | |
| 245 | 366 | glfwSwapBuffers(window); | |
| 246 | 377 | glDeleteVertexArrays(1, &VAO); | |
| 247 | 378 | glDeleteBuffers(1, &VBO); | |
| 248 | 379 | glDeleteBuffers(1, &EBO); | |
| 249 | 380 | glDeleteVertexArrays(1, &VAOAmbient); | |
| 250 | 381 | glDeleteBuffers(1, &VBOAmbient); | |
| 251 | 382 | glDeleteBuffers(1, &EBOAmbient); | |
| 252 | 383 | glDeleteProgram(shaderProgram); | |
| 253 | 384 | glDeleteProgram(ambientShaderProgram); | |
| 254 | 385 | glfwDestroyWindow(window); | |
| 255 | 386 | glfwTerminate(); | |
| 256 | 387 | ||
| 257 | 388 | return 0; | |
| 258 | 389 | } | |
| 259 | |||
| 260 | |||
| 261 | |||
| 262 | |||
| 263 | |||
| 264 | |||
| 265 | |||
| 266 | |||
| 267 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); | ||
| 268 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); | ||
| 269 | |||
| 270 | 頂点属性:位置(location 0)、UV(location 1) | ||
| 271 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); | ||
| 272 | glEnableVertexAttribArray(0); | ||
| 273 | size_t offset = 2 * sizeof(float); | ||
| 274 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)offset); | ||
| 275 | glEnableVertexAttribArray(1); | ||
| 276 | |||
| 277 | |||
| 278 | |||
| 279 | |||
| 280 | |||
| 281 | |||
| 282 | |||
| 283 | |||
| 284 | |||
| 285 | |||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | // メインレンダリングループ | ||
| 290 | while (!glfwWindowShouldClose(window)) { | ||
| 291 | // 画面をクリア | ||
| 254 | |||
| 255 | |||
| 256 | |||
| 257 | |||
| 258 | |||
| 259 | |||
| 260 | |||
| 261 | |||
| 262 | |||
| 263 | |||
| 264 | |||
| 265 | |||
| 266 | |||
| 267 | |||
| 268 | |||
| 269 | |||
| 270 | |||
| 271 | |||
| 272 | |||
| 273 | |||
| 274 | |||
| 275 | |||
| 276 | |||
| 277 | |||
| 278 | |||
| 279 | |||
| 280 | |||
| 281 | |||
| 282 | |||
| 283 | |||
| 284 | |||
| 285 | |||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | |||
| 291 | |||
| 292 | |||
| 293 | |||
| 294 | |||
| 295 | |||
| 296 | |||
| 297 | |||
| 298 | |||
| 299 | |||
| 300 | |||
| 301 | |||
| 302 | |||
| 303 | |||
| 304 | |||
| 305 | |||
| 306 | |||
| 307 | |||
| 308 | |||
| 309 | |||
| 310 | |||
| 311 | |||
| 312 | |||
| 313 | |||
| 314 | |||
| 315 | |||
| 316 | |||
| 317 | |||
| 318 | |||
| 319 | |||
| 320 | |||
| 321 | |||
| 322 | |||
| 323 | |||
| 324 | |||
| 325 | |||
| 326 | |||
| 327 | |||
| 328 | |||
| 329 | |||
| 330 | |||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | |||
| 335 | |||
| 336 | |||
| 337 | |||
| 338 | |||
| 339 | |||
| 340 | |||
| 341 | |||
| 342 | |||
| 343 | |||
| 344 | |||
| 345 | // クアッドを描画 | ||
| 346 | glBindVertexArray(VAO); | ||
| 347 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); | ||
| 348 | |||
| 349 | |||
| 350 | |||
| 351 | |||
| 352 | |||
| 353 | |||
| 354 | |||
| 355 | |||
| 356 | |||
| 357 | |||
| 358 | |||
| 359 | |||
| 360 | |||
| 361 | |||
| 362 | |||
| 363 | |||
| 364 | |||
| 365 | // バッファをスワップし、イベントを処理 | ||
| 366 | glfwSwapBuffers(window); | ||
| 265 | |||
| 266 | |||
| 267 | |||
| 268 | |||
| 269 | |||
| 270 | |||
| 271 | |||
| 272 | |||
| 273 | |||
| 274 | |||
| 275 | |||
| 276 | |||
| 277 | |||
| 278 | |||
| 279 | |||
| 280 | |||
| 281 | |||
| 282 | |||
| 283 | |||
| 284 | |||
| 285 | |||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | |||
| 291 | |||
| 292 | |||
| 293 | |||
| 294 | |||
| 295 | |||
| 296 | |||
| 297 | |||
| 298 | |||
| 299 | |||
| 300 | |||
| 301 | |||
| 302 | |||
| 303 | |||
| 304 | |||
| 305 | |||
| 306 | |||
| 307 | |||
| 308 | |||
| 309 | |||
| 310 | |||
| 311 | |||
| 312 | |||
| 313 | |||
| 314 | |||
| 315 | |||
| 316 | |||
| 317 | |||
| 318 | |||
| 319 | |||
| 320 | |||
| 321 | |||
| 322 | |||
| 323 | |||
| 324 | |||
| 325 | |||
| 326 | |||
| 327 | |||
| 328 | |||
| 329 | |||
| 330 | |||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | |||
| 335 | |||
| 336 | |||
| 337 | |||
| 338 | |||
| 339 | |||
| 340 | |||
| 341 | |||
| 342 | |||
| 343 | |||
| 344 | |||
| 345 | |||
| 346 | |||
| 347 | |||
| 348 | |||
| 349 | |||
| 350 | |||
| 351 | |||
| 352 | |||
| 353 | |||
| 354 | |||
| 355 | |||
| 356 | |||
| 357 | |||
| 358 | |||
| 359 | |||
| 360 | |||
| 361 | |||
| 362 | |||
| 363 | |||
| 364 | |||
| 365 | |||
| 366 | |||
| 367 | |||
| 368 | |||
| 369 | |||
| 370 | |||
| 371 | |||
| 372 | |||
| 373 | |||
| 374 | |||
| 375 | |||
| 376 | |||
| 377 | glDeleteVertexArrays(1, &VAO); | ||
| 378 | glDeleteBuffers(1, &VBO); | ||
| 379 | glDeleteBuffers(1, &EBO); | ||
| 380 | |||
| 381 | |||
| 382 | |||
| 383 | glDeleteProgram(shaderProgram); | ||
| 384 | |||
| 385 | glfwDestroyWindow(window); | ||
| 386 | glfwTerminate(); | ||
| 387 | |||
| 388 | return 0; | ||
| 389 | } | ||
ファイル: a/main-directional.c
| 前 | 新 | ||
|---|---|---|---|
| 151 | // シェーダーファイルを読み込む | 151 | // シェーダーファイルを読み込む |
| 152 | #ifdef __APPLE__ | 152 | #ifdef __APPLE__ |
| 153 | char *vertexShaderSource = readShaderFile("shader/vertex.mac.glsl"); | 153 | char *vertexShaderSource = readShaderFile("shader/vertex.mac.glsl"); |
| 154 | 154 | char *vertexDirectionalSource = readShaderFile("shader/vertex_directional.mac.glsl"); | |
| 155 | char *fragmentShaderSource = readShaderFile("shader/fragment.mac.glsl"); | 155 | char *fragmentShaderSource = readShaderFile("shader/fragment.mac.glsl"); |
| 156 | 156 | char *fragmentDirectionalSource = readShaderFile("shader/frag_directional.mac.glsl"); | |
| 157 | #else | 157 | #else |
| 158 | char *vertexShaderSource = readShaderFile("shader/vertex.glsl"); | 158 | char *vertexShaderSource = readShaderFile("shader/vertex.glsl"); |
| 159 | 159 | char *vertexDirectionalSource = readShaderFile("shader/vertex_directional.glsl"); | |
| 160 | char *fragmentShaderSource = readShaderFile("shader/fragment.glsl"); | 160 | char *fragmentShaderSource = readShaderFile("shader/fragment.glsl"); |
| 161 | 161 | char *fragmentDirectionalSource = readShaderFile("shader/frag_directional.glsl"); | |
| 162 | #endif | 162 | #endif |
| 163 | if (!vertexShaderSource || !fragmentShaderSource) { | 163 | if (!vertexShaderSource || !vertexDirectionalSource || !fragmentShaderSource || !fragmentDirectionalSource) { |
| 164 | puts("シェーダーファイルの読み込みに失敗しました"); | 164 | puts("シェーダーファイルの読み込みに失敗しました"); |
| 165 | if (vertexShaderSource) free(vertexShaderSource); | 165 | if (vertexShaderSource) free(vertexShaderSource); |
| 166 | 166 | if (vertexDirectionalSource) free(vertexDirectionalSource); | |
| 167 | if (fragmentShaderSource) free(fragmentShaderSource); | 167 | if (fragmentShaderSource) free(fragmentShaderSource); |
| 168 | 168 | if (fragmentDirectionalSource) free(fragmentDirectionalSource); | |
| 169 | glfwDestroyWindow(window); | 169 | glfwDestroyWindow(window); |
| 170 | glfwTerminate(); | 170 | glfwTerminate(); |
| 171 | return -1; | 171 | return -1; |
| 171 | 181 | glCompileShader(vertexShader); | |
| 172 | 182 | checkShaderCompile(vertexShader); | |
| 173 | 183 | ||
| 174 | 184 | GLuint vertexDirectionalShader = glCreateShader(GL_VERTEX_SHADER); | |
| 175 | 185 | glShaderSource(vertexDirectionalShader, 1, (const char **)&vertexDirectionalSource, NULL); | |
| 176 | 186 | glCompileShader(vertexDirectionalShader); | |
| 177 | 187 | checkShaderCompile(vertexDirectionalShader); | |
| 178 | 188 | ||
| 179 | 189 | GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); | |
| 180 | 190 | glShaderSource(fragmentShader, 1, (const char **)&fragmentShaderSource, NULL); | |
| 181 | glCompileShader(vertexShader); | 191 | glCompileShader(fragmentShader); |
| 182 | checkShaderCompile(vertexShader); | 192 | checkShaderCompile(fragmentShader); |
| 183 | 193 | ||
| 184 | 194 | GLuint fragmentDirectionalShader = glCreateShader(GL_FRAGMENT_SHADER); | |
| 185 | 195 | glShaderSource(fragmentDirectionalShader, 1, (const char **)&fragmentDirectionalSource, NULL); | |
| 186 | 196 | glCompileShader(fragmentDirectionalShader); | |
| 187 | 197 | checkShaderCompile(fragmentDirectionalShader); | |
| 188 | 198 | ||
| 189 | GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); | 199 | // 三角形のシェーダープログラムをリンク |
| 190 | glShaderSource(fragmentShader, 1, (const char **)&fragmentShaderSource, NULL); | 200 | GLuint shaderProgram = glCreateProgram(); |
| 191 | glCompileShader(fragmentShader); | 201 | glAttachShader(shaderProgram, vertexShader); |
| 192 | checkShaderCompile(fragmentShader); | 202 | glAttachShader(shaderProgram, fragmentShader); |
| 193 | 203 | glLinkProgram(shaderProgram); | |
| 194 | 204 | checkProgramLink(shaderProgram); | |
| 195 | 205 | ||
| 196 | 206 | // ディレクショナルシェーダープログラムをリンク | |
| 197 | 207 | GLuint directionalShaderProgram = glCreateProgram(); | |
| 198 | 208 | glAttachShader(directionalShaderProgram, vertexDirectionalShader); | |
| 199 | 209 | glAttachShader(directionalShaderProgram, fragmentDirectionalShader); | |
| 200 | GLuint shaderProgram = glCreateProgram(); | 210 | glLinkProgram(directionalShaderProgram); |
| 201 | glAttachShader(shaderProgram, vertexShader); | 211 | checkProgramLink(directionalShaderProgram); |
| 202 | glAttachShader(shaderProgram, fragmentShader); | 212 | |
| 203 | glLinkProgram(shaderProgram); | 213 | glDeleteShader(vertexShader); |
| 204 | checkProgramLink(shaderProgram); | 214 | glDeleteShader(vertexDirectionalShader); |
| 205 | 215 | glDeleteShader(fragmentShader); | |
| 206 | 216 | glDeleteShader(fragmentDirectionalShader); | |
| 207 | 217 | free(vertexShaderSource); | |
| 208 | 218 | free(vertexDirectionalSource); | |
| 209 | 219 | free(fragmentShaderSource); | |
| 210 | 220 | free(fragmentDirectionalSource); | |
| 211 | 221 | ||
| 212 | 222 | // 頂点データ(三角形)を設定:三角形用(左にオフセット) | |
| 213 | glDeleteShader(vertexShader); | 223 | float vertices[] = { |
| 214 | 224 | -0.8f, -0.5f, 0.0f, 0.0f, // 左下(位置、UV) | |
| 215 | glDeleteShader(fragmentShader); | 225 | -0.3f, -0.5f, 1.0f, 0.0f, // 右下 |
| 216 | 226 | -0.55f, 0.5f, 0.5f, 1.0f // 上 | |
| 217 | free(vertexShaderSource); | 227 | }; |
| 218 | 228 | GLuint indices[] = { 0, 1, 2 }; | |
| 219 | free(fragmentShaderSource); | 229 | |
| 220 | 230 | // 頂点データ(三角形)を設定:ディレクショナル用(右にオフセット) | |
| 221 | 231 | float verticesDirectional[] = { | |
| 222 | // 頂点データ(フルスクリーンクアッド)を設定 | 232 | 0.3f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.707f, // 左下(位置、UV、形動ノーマル) |
| 223 | float vertices[] = { | 233 | 0.8f, -0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.707f, // 右下 |
| 224 | -1.0f, -1.0f, 0.0f, 0.0f, // 左下(位置、UV) | 234 | 0.55f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.707f // 上 |
| 225 | 1.0f, -1.0f, 1.0f, 0.0f, // 右下 | 235 | }; |
| 226 | 1.0f, 1.0f, 1.0f, 1.0f, // 右上 | 236 | |
| 227 | -1.0f, 1.0f, 0.0f, 1.0f // 左上 | 237 | |
| 228 | 238 | // VAO、VBO、EBOを三角形用に設定 | |
| 229 | 239 | GLuint VAO, VBO, EBO; | |
| 230 | 240 | glGenVertexArrays(1, &VAO); | |
| 231 | 241 | glGenBuffers(1, &VBO); | |
| 232 | 267 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); | |
| 233 | 268 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); | |
| 234 | 269 | ||
| 235 | }; | 270 | // 頂点属性:位置(location 0)、UV(location 1)、ノーマル (2) |
| 236 | GLuint indices[] = { 0, 1, 2, 2, 3, 0 }; | 271 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); |
| 237 | 272 | glEnableVertexAttribArray(0); | |
| 238 | 273 | size_t offset = 2 * sizeof(float); | |
| 239 | GLuint VAO, VBO, EBO; | 274 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)offset); |
| 240 | glGenVertexArrays(1, &VAO); | 275 | glEnableVertexAttribArray(1); |
| 241 | glGenBuffers(1, &VBO); | 276 | |
| 208 | 277 | // VAO、VBO、EBOをディレクショナル用に設定 | |
| 209 | 278 | GLuint VAODirectional, VBODirectional, EBODirectional; | |
| 210 | 279 | glGenVertexArrays(1, &VAODirectional); | |
| 211 | 280 | glGenBuffers(1, &VBODirectional); | |
| 212 | 281 | glGenBuffers(1, &EBODirectional); | |
| 213 | 282 | ||
| 214 | 283 | glBindVertexArray(VAODirectional); | |
| 215 | 284 | glBindBuffer(GL_ARRAY_BUFFER, VBODirectional); | |
| 216 | 285 | glBufferData(GL_ARRAY_BUFFER, sizeof(verticesDirectional), verticesDirectional, GL_STATIC_DRAW); | |
| 217 | 286 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBODirectional); | |
| 218 | 287 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); | |
| 219 | 288 | ||
| 220 | 289 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void *)0); | |
| 221 | 290 | glEnableVertexAttribArray(0); | |
| 222 | 291 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void *)(2 * sizeof(float))); | |
| 223 | 292 | glEnableVertexAttribArray(1); | |
| 224 | 293 | glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void *)(4 * sizeof(float))); | |
| 225 | 294 | glEnableVertexAttribArray(2); | |
| 226 | 295 | ||
| 227 | 296 | // メインレンダリングループ | |
| 228 | 297 | while (!glfwWindowShouldClose(window)) { | |
| 229 | 298 | // 画面をクリア | |
| 230 | 344 | ||
| 231 | 345 | // クアッドを描画 | |
| 232 | 346 | glBindVertexArray(VAO); | |
| 233 | 347 | glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); | |
| 234 | 348 | ||
| 235 | 349 | // ディレクショナルシェーダープログラムを使用(右の三角形) | |
| 236 | 350 | glUseProgram(directionalShaderProgram); | |
| 237 | 351 | ||
| 238 | 352 | // ユニフォームを設定(アンビエントシェーダー) | |
| 239 | 353 | Vector3 materialColor = { 0.8f, 0.2f, 0.3f }; // 赤みがかった色 | |
| 240 | 354 | Vector3 lightDirection = { -0.5f, -0.5f, -0.707f }; // ライトの方向(正規化不要、シェーダーで処理) | |
| 241 | 355 | float lightIntensity = 1.0f; // ライトの強さ(0.0~1.0) | |
| 242 | 356 | ||
| 243 | 357 | glUniform3f(glGetUniformLocation(directionalShaderProgram, "materialColor"), materialColor.r, materialColor.g, materialColor.b); | |
| 244 | 358 | glUniform3f(glGetUniformLocation(directionalShaderProgram, "lightDirection"), lightDirection.x, lightDirection.y, lightDirection.z); | |
| 245 | 359 | glUniform1f(glGetUniformLocation(directionalShaderProgram, "lightIntensity"), lightIntensity); | |
| 246 | 360 | ||
| 247 | 361 | // 右の三角形を描画(ディレクショナルシェーダー) | |
| 248 | 362 | glBindVertexArray(VAODirectional); | |
| 249 | 363 | glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); | |
| 250 | 364 | ||
| 251 | 365 | // バッファをスワップし、イベントを処理 | |
| 252 | 366 | glfwSwapBuffers(window); | |
| 253 | 377 | glDeleteVertexArrays(1, &VAO); | |
| 254 | 378 | glDeleteBuffers(1, &VBO); | |
| 255 | 379 | glDeleteBuffers(1, &EBO); | |
| 256 | 380 | glDeleteVertexArrays(1, &VAODirectional); | |
| 257 | 381 | glDeleteBuffers(1, &VBODirectional); | |
| 258 | 382 | glDeleteBuffers(1, &EBODirectional); | |
| 259 | 383 | glDeleteProgram(shaderProgram); | |
| 260 | 384 | glDeleteProgram(directionalShaderProgram); | |
| 261 | 385 | glfwDestroyWindow(window); | |
| 262 | 386 | glfwTerminate(); | |
| 263 | 387 | ||
| 264 | 388 | return 0; | |
| 265 | 389 | } | |
| 266 | |||
| 267 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); | ||
| 268 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); | ||
| 269 | |||
| 270 | // 頂点属性:位置(location 0)、UV(location 1) | ||
| 271 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); | ||
| 272 | glEnableVertexAttribArray(0); | ||
| 273 | size_t offset = 2 * sizeof(float); | ||
| 274 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)offset); | ||
| 275 | glEnableVertexAttribArray(1); | ||
| 276 | |||
| 277 | |||
| 278 | |||
| 279 | |||
| 280 | |||
| 281 | |||
| 282 | |||
| 283 | |||
| 284 | |||
| 285 | |||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | |||
| 291 | |||
| 292 | |||
| 293 | |||
| 294 | |||
| 295 | |||
| 296 | // メインレンダリングループ | ||
| 297 | while (!glfwWindowShouldClose(window)) { | ||
| 298 | // 画面をクリア | ||
| 254 | |||
| 255 | |||
| 256 | |||
| 257 | |||
| 258 | |||
| 259 | |||
| 260 | |||
| 261 | |||
| 262 | |||
| 263 | |||
| 264 | |||
| 265 | |||
| 266 | |||
| 267 | |||
| 268 | |||
| 269 | |||
| 270 | |||
| 271 | |||
| 272 | |||
| 273 | |||
| 274 | |||
| 275 | |||
| 276 | |||
| 277 | |||
| 278 | |||
| 279 | |||
| 280 | |||
| 281 | |||
| 282 | |||
| 283 | |||
| 284 | |||
| 285 | |||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | |||
| 291 | |||
| 292 | |||
| 293 | |||
| 294 | |||
| 295 | |||
| 296 | |||
| 297 | |||
| 298 | |||
| 299 | |||
| 300 | |||
| 301 | |||
| 302 | |||
| 303 | |||
| 304 | |||
| 305 | |||
| 306 | |||
| 307 | |||
| 308 | |||
| 309 | |||
| 310 | |||
| 311 | |||
| 312 | |||
| 313 | |||
| 314 | |||
| 315 | |||
| 316 | |||
| 317 | |||
| 318 | |||
| 319 | |||
| 320 | |||
| 321 | |||
| 322 | |||
| 323 | |||
| 324 | |||
| 325 | |||
| 326 | |||
| 327 | |||
| 328 | |||
| 329 | |||
| 330 | |||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | |||
| 335 | |||
| 336 | |||
| 337 | |||
| 338 | |||
| 339 | |||
| 340 | |||
| 341 | |||
| 342 | |||
| 343 | |||
| 344 | |||
| 345 | // クアッドを描画 | ||
| 346 | glBindVertexArray(VAO); | ||
| 347 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); | ||
| 348 | |||
| 349 | |||
| 350 | |||
| 351 | |||
| 352 | |||
| 353 | |||
| 354 | |||
| 355 | |||
| 356 | |||
| 357 | |||
| 358 | |||
| 359 | |||
| 360 | |||
| 361 | |||
| 362 | |||
| 363 | |||
| 364 | |||
| 365 | // バッファをスワップし、イベントを処理 | ||
| 366 | glfwSwapBuffers(window); | ||
| 265 | |||
| 266 | |||
| 267 | |||
| 268 | |||
| 269 | |||
| 270 | |||
| 271 | |||
| 272 | |||
| 273 | |||
| 274 | |||
| 275 | |||
| 276 | |||
| 277 | |||
| 278 | |||
| 279 | |||
| 280 | |||
| 281 | |||
| 282 | |||
| 283 | |||
| 284 | |||
| 285 | |||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | |||
| 291 | |||
| 292 | |||
| 293 | |||
| 294 | |||
| 295 | |||
| 296 | |||
| 297 | |||
| 298 | |||
| 299 | |||
| 300 | |||
| 301 | |||
| 302 | |||
| 303 | |||
| 304 | |||
| 305 | |||
| 306 | |||
| 307 | |||
| 308 | |||
| 309 | |||
| 310 | |||
| 311 | |||
| 312 | |||
| 313 | |||
| 314 | |||
| 315 | |||
| 316 | |||
| 317 | |||
| 318 | |||
| 319 | |||
| 320 | |||
| 321 | |||
| 322 | |||
| 323 | |||
| 324 | |||
| 325 | |||
| 326 | |||
| 327 | |||
| 328 | |||
| 329 | |||
| 330 | |||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | |||
| 335 | |||
| 336 | |||
| 337 | |||
| 338 | |||
| 339 | |||
| 340 | |||
| 341 | |||
| 342 | |||
| 343 | |||
| 344 | |||
| 345 | |||
| 346 | |||
| 347 | |||
| 348 | |||
| 349 | |||
| 350 | |||
| 351 | |||
| 352 | |||
| 353 | |||
| 354 | |||
| 355 | |||
| 356 | |||
| 357 | |||
| 358 | |||
| 359 | |||
| 360 | |||
| 361 | |||
| 362 | |||
| 363 | |||
| 364 | |||
| 365 | |||
| 366 | |||
| 367 | |||
| 368 | |||
| 369 | |||
| 370 | |||
| 371 | |||
| 372 | |||
| 373 | |||
| 374 | |||
| 375 | |||
| 376 | |||
| 377 | glDeleteVertexArrays(1, &VAO); | ||
| 378 | glDeleteBuffers(1, &VBO); | ||
| 379 | glDeleteBuffers(1, &EBO); | ||
| 380 | |||
| 381 | |||
| 382 | |||
| 383 | glDeleteProgram(shaderProgram); | ||
| 384 | |||
| 385 | glfwDestroyWindow(window); | ||
| 386 | glfwTerminate(); | ||
| 387 | |||
| 388 | return 0; | ||
| 389 | } | ||
ファイル: a/shader/frag_ambient.glsl
| 前 | 新 | ||
|---|---|---|---|
| 1 | #version 450 core | ||
| 2 | |||
| 3 | in vec2 uVu; | ||
| 4 | out vec4 out_color; | ||
| 5 | |||
| 6 | uniform vec3 materialColor; | ||
| 7 | uniform float ambientIntensity; | ||
| 8 | |||
| 9 | void main() { | ||
| 10 | vec3 ambient = materialColor * ambientIntensity; | ||
| 11 | out_color = vec4(ambient, 1.0); | ||
| 12 | } | ||
ファイル: a/shader/frag_directional.glsl
| 前 | 新 | ||
|---|---|---|---|
| 1 | #version 450 core | ||
| 2 | |||
| 3 | in vec2 vUv; | ||
| 4 | in vec3 vNormal; | ||
| 5 | out vec4 out_color; | ||
| 6 | |||
| 7 | uniform vec3 materialColor; | ||
| 8 | uniform vec3 lightDirection; | ||
| 9 | uniform float lightIntensity; | ||
| 10 | |||
| 11 | void main() { | ||
| 12 | vec3 normal = normalize(vNormal); | ||
| 13 | |||
| 14 | float diffuseFactor = max(dot(normal, -normalize(lightDirection)), 0.0); | ||
| 15 | vec3 diffuse = materialColor * diffuseFactor * lightIntensity; | ||
| 16 | out_color = vec4(diffuse, 1.0); | ||
| 17 | } | ||
ファイル: a/shader/vertex_directional.glsl
| 前 | 新 | ||
|---|---|---|---|
| 1 | #version 450 core | ||
| 2 | |||
| 3 | layout(location = 0) in vec2 aPosition; | ||
| 4 | layout(location = 1) in vec2 aUv; | ||
| 5 | layout(location = 2) in vec3 aNormal; | ||
| 6 | |||
| 7 | out vec2 vUv; | ||
| 8 | out vec3 vNormal; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | vUv = aUv; | ||
| 12 | vNormal = aNormal; | ||
| 13 | gl_Position = vec4(aPosition, 0.0, 1.0); | ||
| 14 | } | ||