teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

4

分かっていない部分や怪しい部分を更新したのと太字にしました。

2019/11/02 04:31

投稿

littlestream
littlestream

スコア37

title CHANGED
File without changes
body CHANGED
@@ -4,7 +4,7 @@
4
4
  共有する頂点を全て足して平均を求めるか、ベクトルの長さを1.0にして
5
5
  収める正規化をすると良いみたいな事が書かれていました。
6
6
 
7
- この共有する頂点という意味がよく分からないです。
7
+ **この共有する頂点という意味がよく分からないです。**
8
8
 
9
9
 
10
10
  ちなみに法線べクトル自体は求める事が出来ます。 
@@ -56,14 +56,18 @@
56
56
  正規化すると、
57
57
  (100/len,-120/len,200/len)
58
58
  (0.394055203,-0.472866243,0.788110406)
59
+ 光源ベクトルと頂点ベクトルの内積は、
59
60
 
61
+ 頂点ベクトルが(Nx,Ny,Nz),光源ベクトルが(Lx,Ly,Lz)だとすると、
62
+ double DotProductResult=Nx*Lx+Ny*Ly+Nz*Lz;
63
+
60
64
  ちなみに、内積をこの法線ベクトルと視線ベクトル(カメラ?)と行う事で
61
65
  カメラの方を向いているかどうかわかるので、そのポリゴンの法線ベクトルが
62
66
  が0より小さければ描画して良いかどうかがカリングという法線ベクトル法
63
67
  という陰面消去で分かります。
64
68
 
65
- 3.あと内積で求めた頂点カラーをどういうループにすれば
69
+ **3.あと内積で求めた頂点カラーをどういうループにすれば
66
- 頂点カラーを適用できるのか分からないです。
70
+ 頂点カラーを適用できるのか分からないです。**
67
71
 
68
72
  4.最後に、グーローシェーディングの2次元版?はうまく行きました。
69
73
 
@@ -72,6 +76,12 @@
72
76
 
73
77
  一部のソースコードを公開します。
74
78
 
79
+ **なので、よく分かっていないのですが、面ごとの法線ベクトルを
80
+ 頂点ベクトルという変数をでっちあげて面ごとの法線ベクトルをその面ごとの頂点ベクトルに
81
+ 足すのと足した回数を調べておいて平均化したものに、RGB値のR値、G値、B値
82
+ それぞれに掛けてしまう方法なのかどうかすら分かってません。**
83
+
84
+
75
85
  ```c/c++言語
76
86
 
77
87
  void PSET(int x,int y,int col)

3

ソースの最新版です。

2019/11/02 04:31

投稿

littlestream
littlestream

スコア37

title CHANGED
File without changes
body CHANGED
@@ -72,7 +72,7 @@
72
72
 
73
73
  一部のソースコードを公開します。
74
74
 
75
- ```C言語
75
+ ```c/c++言語
76
76
 
77
77
  void PSET(int x,int y,int col)
78
78
  {
@@ -295,8 +295,27 @@
295
295
 
296
296
  ClearScreen();//画面を消す
297
297
 
298
+ //PSET(320,240,0x00ff0000);//点を打つ
299
+ //LINE(320,240,640,380,0x00ff0000);
300
+
301
+ int xy[4][2]={
302
+ 320,5,
303
+ 220,300,
304
+ 500,430,
305
+ 630,280
306
+ };
307
+ int Col[4]=
308
+ {
309
+ 0x00ff0000,
310
+ 0x0000ff00,
311
+ 0x000000ff,
312
+ 0x00ffffff
313
+ };
314
+
315
+
298
316
  Projection2DAxisFrom3DAxis(hdc);//透視投影
299
317
 
318
+ //PSET(320,240,0x00FFFFFF);
300
319
  XYZ vvv[12];//全ての頂点の法線をクリアする
301
320
 
302
321
  for(int i=0;i<12;i++)
@@ -304,9 +323,11 @@
304
323
  vvv[i].x=0.0f;//Clear
305
324
  vvv[i].y=0.0f;//Clear
306
325
  vvv[i].z=0.0f;//Clear
307
- //これが無いとどんどん加算されてしまう
308
326
  }
309
327
 
328
+ XYZ a[13];
329
+ XYZ b[13];
330
+ XYZ n[13];
310
331
 
311
332
  for(int i=0;i<12;i++)
312
333
  {
@@ -344,44 +365,60 @@
344
365
  }
345
366
  }
346
367
 
347
- //頂点ベクトルは求まった(はず...)から、頂点カラーを面にある全ての頂点で求める
368
+ //頂点ベクトルは求まった(はず...)から、頂点カラーを面にある全ての頂点で求める
348
369
  double ViewCos[12];
349
-
350
- int vpx=200,vpy=-120,vpz=100;
370
+ //XYZ vpx=200,vpy=-120,vpz=100;
351
-
352
371
  for(int i=0;i<12;i++)
353
372
  {
354
- double a=sqrt(vvv[i].x*vvv[i].x+vvv[i].y*vvv[i].y+vvv[i].z*vvv[i].z)+0.01f;
373
+ double a=sqrt(vvv[i].x*vvv[i].x+vvv[i].y*vvv[i].y+vvv[i].z*vvv[i].z)+0.01f;
374
+
375
+ int i1=Poly[i][0];
376
+ int i2=Poly[i][1];
377
+ int i3=Poly[i][2];
355
378
 
379
+ XYZ n=CalcNormal2(Pnt[i1],Pnt[i2],Pnt[i3]);
380
+
356
381
  vvv[i].x/=a;
357
382
  vvv[i].y/=a;
358
383
  vvv[i].z/=a;
384
+
385
+ XYZ light={100,-120,200};
386
+ double lenlight=sqrt((double)light.x*light.x+light.y*light.y+light.z*light.z);
359
387
 
388
+ light.x/=lenlight;
389
+ light.y/=lenlight;
390
+ light.z/=lenlight;
391
+
392
+ double spe1=vvv[i1].x*light.x+vvv[i1].y*light.y+vvv[i1].z*light.z;
393
+ double spe2=vvv[i2].x*light.x+vvv[i2].y*light.y+vvv[i2].z*light.z;
394
+ double spe3=vvv[i3].x*light.x+vvv[i3].y*light.y+vvv[i3].z*light.z;
395
+
360
- double vv=sqrt((vpx*vpx+vpy*vpy+vpz*vpz));//視線ベクトルの長さを求める
396
+ double vv=sqrt((vpx*vpx+vpy*vpy+vpz*vpz));//視線ベクトルの長さを求める
361
397
 
362
398
  double v1=vpx/(vv+0.01f);//視線ベクトルの正規化
363
399
  double v2=vpy/(vv+0.01f);//
364
400
  double v3=vpz/(vv+0.01f);//
365
401
 
366
- ViewCos[i]=(v1*vvv[i].x+v2*vvv[i].y+v3*vvv[i].z);
402
+ ViewCos[i]=(v1*n.x+v2*n.y+v3*n.z);
367
403
  //視線ベクトルと面ごとの法線ベクトルの内積
368
404
  if(ViewCos[i]<0)
369
405
  TRIANGLE2(Pnt2[Poly[i][0]].x,Pnt2[Poly[i][0]].y,
370
406
  Pnt2[Poly[i][1]].x,Pnt2[Poly[i][1]].y,
371
407
  Pnt2[Poly[i][2]].x,Pnt2[Poly[i][2]].y,
372
- RGB(255,255,255),
408
+ RGB(spe1*255,spe1*255,spe1*255),
373
- RGB(255,255,255),
409
+ RGB(spe2*255,spe2*255,spe2*255),
374
- RGB(255,255,255)
410
+ RGB(spe3*255,spe3*255,spe3*255)
375
411
  );
376
- //とりあえず真っ白にしたが、頂点カラーを求めた後にどうすれば
377
- //3点の色を指定する処理になるか分からないです。
378
412
 
379
413
  }
380
414
 
381
415
 
382
-
416
+ //反時計回りの座標軸
383
- CalcFPS(hdc);
417
+ //三角形を表示する
418
+ //DrawTextureMapping(320,0,0,480,640,0);
384
419
 
420
+ //FillGraRect(0,0,320,20,255,0,0,0,255,0);
421
+ CalcFPS(hdc);
385
422
  /* DIBSectionをDIBとして描画 */
386
423
  StretchDIBits(hdc, 0, 0, WIDTH, HEIGHT,
387
424
  0, 0, WIDTH, HEIGHT, lpPixel, &biInfo,
@@ -410,4 +447,5 @@
410
447
  return DefWindowProc(hwnd, iMsg, wParam, lParam);
411
448
 
412
449
  }
413
- ```
450
+ ```
451
+ ![イメージ説明](6af0066a11228dbaa3ab7964da8a4eb2.jpeg)

2

インデントが上手く行かなかったので<code>を使います。

2019/11/01 12:42

投稿

littlestream
littlestream

スコア37

title CHANGED
File without changes
body CHANGED
@@ -72,6 +72,7 @@
72
72
 
73
73
  一部のソースコードを公開します。
74
74
 
75
+ ```C言語
75
76
 
76
77
  void PSET(int x,int y,int col)
77
78
  {
@@ -408,4 +409,5 @@
408
409
 
409
410
  return DefWindowProc(hwnd, iMsg, wParam, lParam);
410
411
 
411
- }
412
+ }
413
+ ```

1

ソースを公開します。

2019/11/01 12:16

投稿

littlestream
littlestream

スコア37

title CHANGED
File without changes
body CHANGED
@@ -68,4 +68,344 @@
68
68
  4.最後に、グーローシェーディングの2次元版?はうまく行きました。
69
69
 
70
70
  5.うまく行かないので、困っています。どうすれば求まるのか
71
- 誰か教えてください。
71
+ 誰か教えてください。
72
+
73
+ 一部のソースコードを公開します。
74
+
75
+
76
+ void PSET(int x,int y,int col)
77
+ {
78
+ //点を打つ
79
+ if(x<0 || x>WIDTH) return;
80
+ if(y<0 || y>HEIGHT) return;
81
+
82
+ lpPixel[x+(y*WIDTH)]=col;
83
+ }
84
+
85
+ inline void ScanEdge(int x1,int y1,int x2,int y2,int c1,int c2)
86
+ {
87
+
88
+ int b1=(c1>>16) & 0xFF;
89
+ int g1=(c1>>8) & 0xFF;
90
+ int r1=c1 & 0xFF;
91
+
92
+ int b2=(c2>>16) & 0xFF;
93
+ int g2=(c2>>8) & 0xFF;
94
+ int r2=c2 & 0xFF;
95
+
96
+ for(double i=0.0f;i<=1.00f;i+=0.0001f)//0.0~1.0を、0~1024に直す
97
+ {
98
+ int ax=x1*(1.0-i)+x2*i;//線形補間の固定小数点処理化(X成分
99
+ int ay=y1*(1.0-i)+y2*i;//(固定小数点(Y成分
100
+ double k=(ay-y1)/(double)(y2-y1);//0.0~1.0を0~256に直す
101
+
102
+ if(ay<0 || ay>=HEIGHT) continue;
103
+ if(minX2[ay]>ax)//minなX(左側の線分)
104
+ {
105
+ minX2[ay]=ax;
106
+ int b=(1.0-k)*b1+k*b2;
107
+ int g=(1.0-k)*g1+k*g2;
108
+ int r=(1.0-k)*r1+k*r2;
109
+
110
+ if(r<0) r=0; if(r>255) r=255;
111
+ if(g<0) g=0; if(g>255) g=255;
112
+ if(b<0) b=0; if(b>255) b=255;
113
+
114
+ cmin[ay]=RGB(b,g,r);
115
+ PSET(ax,ay,cmin[ay]);
116
+ }
117
+ if(maxX2[ay]<ax)//maxなX(右側の線分)
118
+ {
119
+ maxX2[ay]=ax;
120
+
121
+ int b=(1.0-k)*b1+k*b2;
122
+ int g=(1.0-k)*g1+k*g2;
123
+ int r=(1.0-k)*r1+k*r2;
124
+
125
+ if(r<0) r=0; if(r>255) r=255;
126
+ if(g<0) g=0; if(g>255) g=255;
127
+ if(b<0) b=0; if(b>255) b=255;
128
+
129
+
130
+
131
+ cmax[ay]=RGB(b,g,r);
132
+
133
+ PSET(ax,ay,cmax[ay]);
134
+ }
135
+
136
+ }
137
+ }
138
+
139
+ inline void TRIANGLE2(int x1,int y1,int x2,int y2,int x3,int y3,int c1,int c2,int c3)
140
+ {
141
+
142
+ for(int i=0;i<HEIGHT;i++)
143
+ {
144
+ minX2[i]=65536;
145
+ maxX2[i]=-65536;
146
+ cmin[i]=RGB(0,0,0);
147
+ cmax[i]=RGB(0,0,0);
148
+ }
149
+
150
+
151
+ ScanEdge(x1,y1,x2,y2,c1,c2);
152
+ ScanEdge(x2,y2,x3,y3,c2,c3);
153
+ ScanEdge(x3,y3,x1,y1,c3,c1);
154
+
155
+ for(int y=0;y<HEIGHT;y++)
156
+ {
157
+ if(minX2[y]==65536 || maxX2[y]==-65536) continue;
158
+
159
+ for(int x=minX2[y];x<=maxX2[y];x++)
160
+ {
161
+ int r1=cmin[y] & 0xFF;
162
+ int g1=cmin[y]>>8 & 0xFF;
163
+ int b1=cmin[y]>>16 & 0xFF;
164
+
165
+ int r2=cmax[y] & 0xFF;
166
+ int g2=cmax[y]>>8 & 0xFF;
167
+ int b2=cmax[y]>>16 & 0xFF;
168
+
169
+ int j=((x-minX2[y])<<8)/(maxX2[y]-minX2[y]+1);
170
+
171
+ int r=r1*((1<<8)-j)+(r2)*j>>8;
172
+ int g=g1*((1<<8)-j)+(g2)*j>>8;
173
+ int b=b1*((1<<8)-j)+(b2)*j>>8;
174
+
175
+ int NewR=r;
176
+ int NewG=g;
177
+ int NewB=b;
178
+
179
+ if(NewR<0) NewR=0; if(NewR>255) NewR=255;
180
+ if(NewG<0) NewG=0; if(NewG>255) NewG=255;
181
+ if(NewB<0) NewB=0; if(NewB>255) NewB=255;
182
+
183
+
184
+ PSET(x,y,RGB(NewB,NewG,NewR));
185
+ }
186
+ }
187
+ }
188
+
189
+ XYZ CalcNormal2(XYZ a,XYZ b,XYZ c)
190
+ {
191
+ XYZ d={0.0f};
192
+ XYZ a2,b2;
193
+
194
+ a2.x=a.x-b.x;
195
+ a2.y=a.y-b.y;
196
+ a2.z=a.z-b.z;
197
+
198
+ b2.x=a.x-c.x;
199
+ b2.y=a.y-c.y;
200
+ b2.z=a.z-c.z;
201
+
202
+ double len=sqrt(a2.x*a2.x+a2.y*a2.y+a2.z*a2.z);
203
+ a2.x/=len;
204
+ a2.y/=len;
205
+ a2.z/=len;
206
+
207
+ double len2=sqrt(b2.x*b2.x+b2.y*b2.y+b2.z*b2.z);
208
+ b2.x/=len2;
209
+ b2.y/=len2;
210
+ b2.z/=len2;
211
+
212
+
213
+ //23-32 31-13 12-21
214
+ //aY*bZ-aZ*bY aZ*bX-aX*bZ aX*bY-aY*bX
215
+ d.x=a2.y*b2.z-a2.z*b2.y;
216
+ d.y=a2.z*b2.x-a2.x*b2.z;
217
+ d.z=a2.x*b2.y-a2.y*b2.x;
218
+
219
+ return d;
220
+ }
221
+
222
+
223
+ LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
224
+
225
+
226
+
227
+ HDC hdc;
228
+ PAINTSTRUCT ps;
229
+
230
+ switch (iMsg) {
231
+
232
+ case WM_TIMER:
233
+ {
234
+ if(GetAsyncKeyState(VK_ESCAPE)<0)
235
+ SendMessage(hwnd,WM_DESTROY,NULL,NULL);
236
+ double X=0.0f;
237
+ double Y=0.0f;
238
+ double Z=0.0f;
239
+
240
+ //Z+=0.1f;
241
+ //Y+=0.1f;
242
+ if(GetAsyncKeyState(VK_RIGHT)<0) Y=-2.5f;
243
+ else if(GetAsyncKeyState(VK_LEFT)<0) Y=2.5f;
244
+ else Y=0.0f;
245
+
246
+ if(GetAsyncKeyState(VK_DOWN)<0) X=-2.5f;
247
+ else if(GetAsyncKeyState(VK_UP)<0) X=2.5f;
248
+ else X=0.0f;
249
+
250
+ Rotate(X,Y,0);
251
+ static int X1=0,X2=0;
252
+ int n=8;
253
+
254
+
255
+
256
+ InvalidateRect(hwnd,NULL,NULL);
257
+ }
258
+ return 0;
259
+ case WM_CREATE:
260
+ MyOutputDebugString("起動しました。");
261
+ Init();//3次元座標を代入
262
+
263
+ SetTimer(hwnd,100,5,NULL);
264
+ /* BITMAPINFOをゼロクリア */
265
+ ZeroMemory(&biInfo, sizeof(BITMAPINFO));
266
+
267
+ /* BITMAPINFO設定 */
268
+ biInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
269
+ biInfo.bmiHeader.biWidth = WIDTH;
270
+ biInfo.bmiHeader.biHeight = -HEIGHT;
271
+ biInfo.bmiHeader.biPlanes = 1;
272
+ biInfo.bmiHeader.biBitCount = 32;
273
+ biInfo.bmiHeader.biCompression = BI_RGB;
274
+
275
+ /* ウインドウのDCを取得 */
276
+ hdc = GetDC(hwnd);
277
+
278
+ /* biInfoの形式でDIBSectionを作成 */
279
+ hBMP =CreateDIBSection(hdc, &biInfo, DIB_RGB_COLORS, (LPVOID*)(&lpPixel), NULL, 0);
280
+
281
+ /* DIBSection用のメモリDCを作成 */
282
+ hdcBMP = CreateCompatibleDC(hdc);
283
+
284
+ /* メモリDCにDIBSectionを選択 */
285
+ hBMPOLD = (HBITMAP)SelectObject(hdcBMP, hBMP);
286
+
287
+ /* 不要になったウインドウのDCを解放 */
288
+ ReleaseDC(hwnd, hdc);
289
+
290
+ return 0;
291
+ case WM_PAINT:
292
+ {
293
+ hdc = BeginPaint(hwnd, &ps);
294
+
295
+ ClearScreen();//画面を消す
296
+
297
+ Projection2DAxisFrom3DAxis(hdc);//透視投影
298
+
299
+ XYZ vvv[12];//全ての頂点の法線をクリアする
300
+
301
+ for(int i=0;i<12;i++)
302
+ {
303
+ vvv[i].x=0.0f;//Clear
304
+ vvv[i].y=0.0f;//Clear
305
+ vvv[i].z=0.0f;//Clear
306
+ //これが無いとどんどん加算されてしまう
307
+ }
308
+
309
+
310
+ for(int i=0;i<12;i++)
311
+ {
312
+ int i1=Poly[i][0];
313
+ int i2=Poly[i][1];
314
+ int i3=Poly[i][2];
315
+
316
+ XYZ n=CalcNormal2(Pnt[i1],Pnt[i2],Pnt[i3]);
317
+ vvv[i1].x+=n.x;
318
+ vvv[i1].y+=n.y;
319
+ vvv[i1].z+=n.z;
320
+
321
+ vvv[i2].x+=n.x;
322
+ vvv[i2].y+=n.y;
323
+ vvv[i2].z+=n.z;
324
+
325
+ vvv[i3].x+=n.x;
326
+ vvv[i3].y+=n.y;
327
+ vvv[i3].z+=n.z;
328
+
329
+ vvv[i1].count++;
330
+ vvv[i2].count++;
331
+ vvv[i3].count++;
332
+ //全ての頂点毎に、全ての面の頂点座標と比較して、
333
+
334
+ }
335
+
336
+ for(int i=0;i<8;i++)
337
+ {
338
+ if(vvv[i].count>0)
339
+ {
340
+ vvv[i].x/=vvv[i].count ;
341
+ vvv[i].y/=vvv[i].count ;
342
+ vvv[i].z/=vvv[i].count ;
343
+ }
344
+ }
345
+
346
+ //頂点ベクトルは求まった(はず...)から、頂点カラーを面にある全ての頂点で求める
347
+ double ViewCos[12];
348
+
349
+ int vpx=200,vpy=-120,vpz=100;
350
+
351
+ for(int i=0;i<12;i++)
352
+ {
353
+ double a=sqrt(vvv[i].x*vvv[i].x+vvv[i].y*vvv[i].y+vvv[i].z*vvv[i].z)+0.01f;
354
+
355
+ vvv[i].x/=a;
356
+ vvv[i].y/=a;
357
+ vvv[i].z/=a;
358
+
359
+ double vv=sqrt((vpx*vpx+vpy*vpy+vpz*vpz));//視線ベクトルの長さを求める
360
+
361
+ double v1=vpx/(vv+0.01f);//視線ベクトルの正規化
362
+ double v2=vpy/(vv+0.01f);//
363
+ double v3=vpz/(vv+0.01f);//
364
+
365
+ ViewCos[i]=(v1*vvv[i].x+v2*vvv[i].y+v3*vvv[i].z);
366
+ //視線ベクトルと面ごとの法線ベクトルの内積
367
+ if(ViewCos[i]<0)
368
+ TRIANGLE2(Pnt2[Poly[i][0]].x,Pnt2[Poly[i][0]].y,
369
+ Pnt2[Poly[i][1]].x,Pnt2[Poly[i][1]].y,
370
+ Pnt2[Poly[i][2]].x,Pnt2[Poly[i][2]].y,
371
+ RGB(255,255,255),
372
+ RGB(255,255,255),
373
+ RGB(255,255,255)
374
+ );
375
+ //とりあえず真っ白にしたが、頂点カラーを求めた後にどうすれば
376
+ //3点の色を指定する処理になるか分からないです。
377
+
378
+ }
379
+
380
+
381
+
382
+ CalcFPS(hdc);
383
+
384
+ /* DIBSectionをDIBとして描画 */
385
+ StretchDIBits(hdc, 0, 0, WIDTH, HEIGHT,
386
+ 0, 0, WIDTH, HEIGHT, lpPixel, &biInfo,
387
+ DIB_RGB_COLORS,SRCCOPY);
388
+
389
+
390
+ EndPaint(hwnd, &ps);
391
+
392
+ DeleteObject(SelectObject(hdc , GetStockObject(WHITE_BRUSH)));
393
+ }
394
+ return 0;
395
+
396
+ case WM_DESTROY: /* ウインドウ破棄時 */
397
+
398
+ SelectObject(hdcBMP, hBMPOLD);
399
+
400
+ DeleteObject(hdcBMP);
401
+ DeleteObject(hBMP);
402
+
403
+ PostQuitMessage(0);
404
+
405
+ return 0;
406
+
407
+ }
408
+
409
+ return DefWindowProc(hwnd, iMsg, wParam, lParam);
410
+
411
+ }