質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。

Q&A

解決済

1回答

2874閲覧

GLSLで画面描画に使う行列でZ軸の値がおかしくなる原因が知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。

0グッド

0クリップ

投稿2020/09/16 06:35

編集2020/09/17 13:47

シェーダーで行う計算をCPUで普通に計算するテストコードを実装したいのですが予測通り最後で3次元目がよくわからない値に変わっているため画面に表示されない等の不具合が発生しているということを突き止めたのですがこれはなぜこんな値になっているのでしょうか?

追記 ロドリゲス回転行列がおかしいとの修正依頼を多数受けまして自分なりに修正しましたがもうどうしてもわかりません何をしたのか教えてくれますでしょうか?printf();でデバッグするとどうやらrotateの部分で値がおかしいためすべて狂ってるみたいです。

追記 
参考サイト: http://marupeke296.sakura.ne.jp/DXG_No58_RotQuaternionTrans.html
② クォータニオン→回転行列変換より回転行列を使いかました。

下記サイトの163ページの透視射形変換行列の数式を移しました。
参考サイト: https://tokoik.github.io/GLFWdraft.pdf

イメージ説明

GLSL

1#version 400 2//頂点シェーダー 3 4in vec3 position;//頂点座標 5 6uniform mat4 scale;//スケール行列 7uniform mat4 rotate;//回転行列 8uniform mat4 move;//平行移動行列 9 10uniform mat4 MP; 11 12out vec4 mt; 13 14void main() 15{ 16 vec4 t = vec4(position,1.0); 17 mat4 M = mat4(scale * rotate * move); 18 19 20 21 22 mt = vec4(MP * M * t); 23 24 25 26 27 gl_Position = MP * M * t; 28} 29 30

cpp

1#include "stdio.h" 2#include <iostream> 3 4//透視射形行列 5float mp[16]; 6 7//座標構造体 8struct position 9{ 10public: 11 float x; 12 float y; 13 float z; 14 15 float w; 16}; 17 18 19//頂点バッファー 20float Vertex[6][4] = 21{ 22 {-0.5, 0.5, 1.0,1.0}, 23 {-0.5, -0.5, 1.0,1.0}, 24 {0.5, -0.5, 1.0,1.0}, 25 26 {-0.5, 0.5, 1.0,1.0}, 27 {0.5, 0.5, 1.0,1.0 }, 28 {0.5, -0.5, 1.0,1.0} 29}; 30 31 32 33//透視投影変換行列を作る 34void create_matri_mp(float top, float bottom, float left, float right, 35 float near, float far, float result[16]) 36{ 37 result[0] = (2 * near) / (right - left); 38 result[5] = (2 * near) / (top - bottom); 39 40 result[8] = (right + left) / (right - left); 41 42 result[9] = (top + bottom) / (top - bottom); 43 44 result[10] = (far + near) / (far - near); 45 46 result[11] = -1; 47 result[14] = (2 * far * near) / (far - near); 48 49 50} 51 52//行列を表示 53void print_matrix(const char* str, float mp[4][4]) 54{ 55 printf("name: %s\n", str); 56 for (int i = 0; i < 4; i++) 57 { 58 for (int j = 0; j < 4; j++) 59 { 60 printf("[ %.2f ] , ", mp[i][j]); 61 } 62 printf("\n"); 63 } 64} 65 66 67//行列掛け算 68//void mul(float a[4][4], float b[4][4]) 69void mul(float a[16], float b[16], float result[16]) 70{ 71 result[0] = (a[0] * b[0]) + (a[4] * b[1]) + (a[8] * b[2]) + (a[12] * b[3]); 72 73 result[1] = (a[1] * b[0]) + (a[5] * b[1]) + (a[9] * b[2]) + (a[13] * b[3]); 74 75 result[2] = (a[2] * b[0]) + (a[6] * b[1]) + (a[10] * b[2]) + (a[14] * b[3]); 76 77 result[3] = (a[3] * b[0]) + (a[7] * b[1]) + (a[11] * b[2]) + (a[15] * b[3]); 78 79 ///////// 80 81 result[4] = (a[0] * b[4]) + (a[4] * b[5]) + (a[8] * b[6]) + (a[12] * b[7]); 82 83 result[5] = (a[1] * b[4]) + (a[5] * b[5]) + (a[9] * b[6]) + (a[13] * b[7]); 84 85 result[6] = (a[2] * b[4]) + (a[6] * b[5]) + (a[10] * b[6]) + (a[14] * b[7]); 86 87 result[7] = (a[3] * b[4]) + (a[7] * b[5]) + (a[11] * b[6]) + (a[15] * b[7]); 88 89 ///////// 90 result[8] = (a[0] * b[8]) + (a[4] * b[9]) + (a[8] * b[10]) + (a[12] * b[11]); 91 92 result[9] = (a[1] * b[8]) + (a[5] * b[9]) + (a[9] * b[10]) + (a[13] * b[11]); 93 94 result[10] = (a[2] * b[8]) + (a[6] * b[9]) + (a[10] * b[10]) + (a[14] * b[11]); 95 96 result[11] = (a[3] * b[8]) + (a[7] * b[9]) + (a[11] * b[10]) + (a[15] * b[11]); 97 98 ///////// 99 100 result[12] = (a[0] * b[12]) + (a[4] * b[13]) + (a[8] * b[14]) + (a[12] * b[15]); 101 102 result[13] = (a[1] * b[12]) + (a[5] * b[13]) + (a[9] * b[14]) + (a[13] * b[15]); 103 104 result[14] = (a[2] * b[12]) + (a[6] * b[13]) + (a[10] * b[14]) + (a[14] * b[15]); 105 106 result[15] = (a[3] * b[12]) + (a[7] * b[13]) + (a[11] * b[14]) + (a[15] * b[15]); 107 108 109} 110 111//行列計算 a x b 112void mul_A_B(float a[16], float b[16], float result[16]) 113{ 114 result[0] = (a[0] * b[0]) + (a[1] * b[4]) + (a[2] * b[8] ) + (a[3] * b[12]); 115 result[1] = (a[0] * b[1]) + (a[1] * b[5]) + (a[2] * b[9] ) + (a[3] * b[13]); 116 result[2] = (a[0] * b[2]) + (a[1] * b[6]) + (a[2] * b[10]) + (a[3] * b[14]); 117 result[3] = (a[0] * b[3]) + (a[1] * b[7]) + (a[2] * b[11]) + (a[3] * b[15]); 118 119 result[4] = (a[4] * b[0]) + (a[5] * b[4]) + (a[6] * b[8]) + (a[7] * b[12]); 120 result[5] = (a[4] * b[1]) + (a[5] * b[5]) + (a[6] * b[9]) + (a[7] * b[13]); 121 result[6] = (a[4] * b[2]) + (a[5] * b[6]) + (a[6] * b[10]) + (a[7] * b[14]); 122 result[7] = (a[4] * b[3]) + (a[5] * b[7]) + (a[6] * b[11]) + (a[7] * b[15]); 123 124 125 result[8] = (a[8] * b[0]) + (a[9] * b[4]) + (a[10] * b[8]) + (a[11] * b[12]); 126 result[9] = (a[8] * b[1]) + (a[9] * b[5]) + (a[10] * b[9]) + (a[11] * b[13]); 127 result[10] = (a[8] * b[2]) + (a[9] * b[6]) + (a[10] * b[10]) + (a[11] * b[14]); 128 result[11] = (a[8] * b[3]) + (a[9] * b[7]) + (a[10] * b[11]) + (a[11] * b[15]); 129 130 result[12] = (a[12] * b[0]) + (a[13] * b[4]) + (a[14] * b[8]) + (a[15] * b[12]); 131 result[13] = (a[12] * b[1]) + (a[13] * b[5]) + (a[14] * b[9]) + (a[15] * b[13]); 132 result[14] = (a[12] * b[2]) + (a[13] * b[6]) + (a[14] * b[10]) + (a[15] * b[14]); 133 result[15] = (a[12] * b[3]) + (a[13] * b[7]) + (a[14] * b[11]) + (a[15] * b[15]); 134} 135 136 137 138//ベクトルと行列の掛け算 139void mul_vec3_matrix(float m[16], float v[3], float r[3]) 140{ 141 printf("\n\n"); 142 for (int j = 0; j < 3; j++) 143 { 144 printf("[ %.2f ] ", r[j]); 145 } 146 printf("\n"); 147} 148 149 150//画面表示 151void print_(float tmp[16]) 152{ 153 for (int i = 0; i < 16; i++) 154 { 155 if (i % 4 == 0) 156 { 157 printf("\n"); 158 } 159 160 printf(" [ %.2f ] ", tmp[i]); 161 } 162 163 printf("\n\n"); 164 165} 166 167 168int main() 169{ 170 create_matri_mp(1.0f, -1.0f, -1.0f, 1.0f, 1.0, 10.f, mp);//透視射形変換行列mp 171 172 173 //回転行列 174 struct position pos; 175 176 pos.x = 1.0f; 177 pos.y = 0; 178 pos.z = 0; 179 180 pos.w = 1.0f; 181 float r = 1.0f; 182 183 float rotate[16] = { 184 (pos.x * pos.x * (1 - cos(r)) + cos(r)), 185 (pos.x * pos.y * (1 - cos(r)) - (pos.z * sin(r))), 186 (pos.x * pos.z * (1 - cos(r)) + (pos.y * sin(r))), 187 0, 188 189 (pos.x * pos.y * (1 - cos(r)) + (pos.z * sin(r))), 190 (pos.y * pos.y * (1 - cos(r)) + cos(r)), 191 (pos.y * pos.z * (1 - cos(r)) - (pos.x * sin(r))), 192 0, 193 194 (pos.x * pos.z * (1 - cos(r)) - (pos.y * sin(r))), 195 (pos.y * pos.z * (1 - cos(r)) + (pos.x * sin(r))), 196 (pos.z * pos.z * (1 - cos(r)) + cos(r)), 197 0, 198 199 0,0,0,1 200 }; 201 202 // print_(rotate); 203 204 //平行移動 205 struct position p; 206 p.x = 0; 207 p.y = 0; 208 p.z = 0; 209 p.w = 1; 210 211 float move[16] = 212 { 213 1,0,0,0, 214 0,1,0,0, 215 0,0,1,0, 216 p.x,p.y,p.z,1, 217 }; 218 219 // print_(move); 220 221 float t[16]; 222 mul(rotate, move, t); 223 // print_(t); 224 225 //スケール行列 226 float scale[16] = { 227 1,0,0,0, 228 0,1,0,0, 229 0,0,1,0, 230 0,0,0,1 231 }; 232 233 print_(scale); 234 235 float t2[16]; 236 mul(scale, t, t2); 237 print_(t); 238 239 240 241 242 243 for (int i = 0; i < 6; i++) 244 { 245 float t3[16]; 246 mul(Vertex[i], t2, t3); 247// print_(t2); 248 249 250 float t4[16]; 251 mul(mp, t2, t4); 252 // print_(t4); 253 } 254 255 256 float a[16] = 257 { 258 0,3,2,5, 259 0,2,2,1, 260 261 0,7,4,3, 262 0,3,3,7, 263 264 }; 265 266 267 float b[16] = 268 { 269 0,3,5,5, 270 0,5,8,6, 271 272 8,7,3,3, 273 5,8,3,8, 274 275 }; 276 277 278 float c[16] = { 0 }; 279 280 //mul_A_B(a,b,c); 281 282// print_(c); 283 284 285 286 return 0; 287}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/09/16 06:56

デバッグのための行いなのですから,そこは頑張りましょうよ. ・行列の乗算処理が間違っていないか? → これが疑わしいのならば,乗算処理を単体でテストして,まともなことを確認しましょう.真っ先に. 「適当に要素値を決めた行列2個と,手計算なりで求めたその積」をテストパターンとして何個か用意すれば確認できるでしょう. ・create_matri_mp()がおかしいのか?  → これで計算された行列には「(これこれこういう作用だ,という)意味」があるハズ. つまり,「ある座標に乗じたならばその結果はこうなるハズだ」というINとOUTのセットを,その意味から,前述の行列の積と同じようにテストパターンとして用意して確認することができるハズ.
退会済みユーザー

退会済みユーザー

2020/09/16 06:59

なるほど。しかしなにか間違えているというのは事実でしょうか?
fana

2020/09/16 07:07

それを調べるのですよね? やっている計算は 最終結果 = MP * scale * rotate * move * v なわけですが, 例えば,vに何か適当な値を定めたときに, move * v は期待通りの値になっているか? を確認する. ここが大丈夫そうならば,次は, rotate * (move * v ) までが期待通りの値になっているか? を同様に確認する. ここまでが大丈夫ならば…… として,見ていけばよいのでは. どこかで「期待と異なる結果」に遭遇したならば,怪しいのはそこです. 各段階での「期待される結果」をあなたが把握していることが必要です.(それが無いと確認のしようがないので)
退会済みユーザー

退会済みユーザー

2020/09/16 08:54

わかりました。質問ですがこの手のバグはどうやったらいいのでしょうか?
stdio

2020/09/16 08:58 編集

create_matri_mpの result[3][3]の値が0になっているのか気になります。記憶は曖昧ですが、1.0だったような気がします。
退会済みユーザー

退会済みユーザー

2020/09/16 08:59

result[3][3] = 1.0;としましたがやはり値が同じくマイナスですw
退会済みユーザー

退会済みユーザー

2020/09/16 09:02

質問内容を編集しましたので再度御覧ください
1T2R3M4

2020/09/16 10:23

デバッグについてはfanaさんが書いているように 入力に対して各関数の出力が期待値通りか確認して 違ったら関数内で引数は正しくわたっているか、 計算結果は正しいかとかを確認していけばいいのではないでしょうか。
退会済みユーザー

退会済みユーザー

2020/09/16 13:26 編集

質問内容を大幅に変更しましたので御覧ください。
Soei

2020/09/16 17:59 編集

検証などはしていないので確かなことは言えませんが、 回転行列がおかしくないですか? 12個しか初期化要素がないため(4,4)成分にあたるrot[15]が0になってしまっています。 また、ロドリゲスの回転公式を表現したいのでしょうが、そうであれば回転軸posは単位ベクトル(大きさが1のベクトル)でなければいけません。 ※追記 ロドリゲスの回転公式としてもおかしいですね。 (1 - cos(r))は足すのではなく掛けないといけませんし、ほかにもいくつか間違いがあるみたいです。
stdio

2020/09/16 23:57

それともう一つ。 rotateの初期化部分で、16個初期化しないといけないにも関わらず、最初の12個しか初期化されていないのは何故でしょうか?
退会済みユーザー

退会済みユーザー

2020/09/17 09:53 編集

提示コードを編集しましたので御覧ください
退会済みユーザー

退会済みユーザー

2020/09/17 09:58

以前にも貴方に言いましたが、ここは他人にデバッグをしてもらうサイトではないですよ?
退会済みユーザー

退会済みユーザー

2020/09/17 10:05 編集

そう見えてしまうのですが。デバッグ依頼をするつもりは一切ないのですが自分の知らない範囲で何かやっているものがあるのかと思い質問しました。削除したほうがよろしいのでしょうか?
退会済みユーザー

退会済みユーザー

2020/09/17 10:35

別に後ろめたいことが無いなら消さなくてもいいと思いますが、Soeiさん、stdioさんにコメントで指摘されてる事くらいまともに返信したらどうでしょう。
退会済みユーザー

退会済みユーザー

2020/09/17 10:55 編集

わかりました。 Soeiさん、stdioさん 修正したのですが治りませんでした。また追記の文章を御覧ください。実装を変えましたがだめでした。 rotateの最後の4つの数値に0,0,0,1というコードを忘れていたので追加しました。が結果が変わりません
Soei

2020/09/17 11:16 編集

指摘した部分が直っていませんよ。 ・回転軸posは単位ベクトル(大きさが1のベクトル)でなければいけません。 ・(1 - cos(r))は足すのではなく掛けないといけません。 ・ほかにもいくつか間違いがあります。細かく指摘しないので自分で探してください。
退会済みユーザー

退会済みユーザー

2020/09/17 14:47 編集

様々な場所のコードを編集しました。演算子のミスなどの間違えを修正しましたので御覧ください。
退会済みユーザー

退会済みユーザー

2020/09/18 00:43 編集

何故私が他人にデバッグをして貰ってるように見えるかというと、コンピュータは外部から入力されるランダムなデータなど不確定要素が入らない限りは数式通りの答えしか出しません。 デバッグでステップ実行したり、変数値を出力しながら少しづつ入力値と計算結果、数式を照合しながら調べていけば、通常は自分で間違いに気づく筈なのです。 なので、きちんとデバッグをしている人が、 > 3次元目がよくわからない値に変わっているため などという事を言うのがおかしいのです。これは、つまり自分で計算結果を何も検証していないということです。 fana さんが指摘されている、 > 各段階での「期待される結果」をあなたが把握していることが必要です.(それが無いと確認のしようがないので) これが全てだと思います。
guest

回答1

0

ベストアンサー

イメージ説明

**自己解決しました。
**

まずは構造体のstruct poisition pos;を初期化していないことで変な値が入っているということも原因のうちでした。提示コードは修正してありますが

シェーダーの掛け算の順番もおかしいためそれを修正

cpp

1mat4 M = mat4(move * rotate * scale);

各行列は数学上では左上から右上に進みますがOpenGLの場合は左上から左下に進みむのでまずその数式とプログラム数式の違いを修正しました。

また編集と修正にも多数コメントが有る通り値の設定の忘れていつ要素への数値の設定と演算子や符号のつけ忘れや間違いなどを修正。rotate行列

自分はなぜ行うのか不明ですが最後にある

cpp

1 2 float r2[4]; 3 mul_vec4_matrix(t4, Vertex[i], r2);

コードはツイッターで回答をもらいましたて「 透視投影行列を掛けた結果のvec4はwが1ではない値になると思います。その場合はxyzをwで割った値が求めたい頂点座標 」というのがあるみたいでその数式になりますがシェーダーで本番する場合はこれは必要ないですがCPU計算による数式を作る場合は必要みたいです。

投稿2020/09/18 00:46

編集2020/09/18 00:48
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問