3

OpenGLを学びたいので、非常に簡単な例から始めることにしました。スターダスト宇宙船からの測定値から推測されるように、ワイルド2彗星の形状をレンダリングします(データの詳細:http://nssdc.gsfc.nasa.gov/ nmc / masterCatalog.do?ds = PSSB-00133)。私はOpenGLについてまったく何も知らないことを覚えておいてください。いくつかのGoogle-fuは、以下に示すコードまで到達するのに役立ちました。私の最善の努力にもかかわらず、私の彗星は最悪です:

ワイルド2彗星のOpenGLレンダリング

見栄えを良くしたいのですが、どうすればいいのかわかりません(レッドブックなどを読む以外に)。例えば:

  • 形状の非常に基本的な「ワイヤーフレーム」レンダリングを作成するにはどうすればよいですか?
  • 太陽が「下」方向に沿っている(つまり、-Yに沿っている)とすると、光を追加して反対側の影を見るにはどうすればよいですか?
  • 「マウスイベント」を追加して、ビューを回転させたり、ズームイン/ズームアウトしたりするにはどうすればよいですか?

どうすればこのモンスターをより美しく見せることができますか?オンラインチュートリアルやコード例への参照はありますか?

ソースコード、データ、およびmakefile(OS Xの場合)をbitbucketに配置しました。

hg clone https://arrieta@bitbucket.org/arrieta/learning-opengl

データは、8,761個のトリプレット(ボディ固定フレーム内の頂点)と17,518個の三角形(各三角形は、8,761個の頂点トリプレットの1つを参照する整数のトリプレット)で構成されています。

#include<stdio.h>
#include<stdlib.h>

#include<OpenGL/gl.h>
#include<OpenGL/glu.h> 
// I added this in case you want to "copy/paste" the program into a
// non-Mac computer
#ifdef __APPLE__
#  include <GLUT/glut.h>
#else
#  include <GL/glut.h>
#endif

/* I hardcoded the data and use globals. I know it sucks, but I was in
   a hurry. */
#define NF 17518
#define NV 8761
unsigned int fs[3 * NF];
float vs[3 * NV];
float angle = 0.0f;

/* callback when the window changes size (copied from Internet example) */
void changeSize(int w, int h) {
  if (h == 0) h = 1;  
  float ratio =  w * 1.0 / h;
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glViewport(0, 0, w, h);
  gluPerspective(45.0f, ratio, 0.2f, 50000.0f); /*  45 degrees fov in Y direction; 50km z-clipping*/
  glMatrixMode(GL_MODELVIEW);
}

/* this renders and updates the scene (mostly copied from Internet examples) */
void renderScene() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  glLoadIdentity();
  gluLookAt(0.0f, 0.0f,  10000.0f, /* eye is looking down along the Z-direction at 10km */
            0.0f, 0.0f,  0.0f,     /* center at (0, 0, 0) */
            0.0f, 1.0f,  0.0f);    /* y direction along natural y-axis */

  /* just add a simple rotation */
  glRotatef(angle, 0.0f, 0.0f, 1.0f);    
  /* use the facets and vertices to insert triangles in the buffer */
  glBegin(GL_TRIANGLES);
  unsigned int counter;
  for(counter=0; counter<3 * NF; ++counter) {
    glVertex3fv(vs + 3 * fs[counter]); /* here is where I'm loading
                                          the data - why do I need to
                                          load it every time? */
  }
  glEnd();  
  angle += 0.1f;                /* update the rotation angle */
  glutSwapBuffers();  
}


int main(int argc, char* argv[]) {
  FILE *fp;
  unsigned int counter;


  /* load vertices */
  fp = fopen("wild2.vs", "r");
  counter = 0;
  while(fscanf(fp, "%f", &vs[counter++]) > 0);
  fclose(fp);

  /* load facets */
  fp = fopen("wild2.fs", "r");
  counter = 0;
  while(fscanf(fp, "%d", &fs[counter++]) > 0);
  fclose(fp);

  /* this initialization and "configuration" is mostly copied from Internet */
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
  glutInitWindowPosition(0, 0);
  glutInitWindowSize(1024, 1024);
  glutCreateWindow("Wild-2 Shape");

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);

  GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat mat_shininess[] = { 30.0 };
  GLfloat light_position[] = {3000.0, 3000.0, 3000.0, 0.0 };
  glClearColor (0.0, 0.0, 0.0, 0.0);
  glShadeModel (GL_SMOOTH);
  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);

  glutDisplayFunc(renderScene);
  glutReshapeFunc(changeSize);
  glutIdleFunc(renderScene);

  glutMainLoop();
  return 0;  
}

編集

見た目は良くなり始めており、当面は調査するリソースがたくさんあります。それはまだひどいですが、私の質問は答えられました!

あまり吸わない別の画像

法線を追加し、「テクスチャ」とワイヤフレームを切り替えることができます。

法線付き

PS。リポジトリには、SeedmanJの提案に従って行われた変更が表示されます。

4

3 に答える 3

3

OpenGL でのワイヤフレーム レンダリングへの変更は非常に簡単です。

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

塗りつぶしレンダリングに戻すには、

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

ライトについては、OpenGL では最大 8 つの異なるライトを使用でき、法線とマテリアルのおかげで最終的なレンダリングを生成できます。次の方法で照明モードを有効にできます。

glEnable(GL_LIGHTING);

次に、次のいずれかで各ライトをアクティブにします。

 glEnable(GL_LIGHT0);
 glEnable(GL_LIGHT1);

位置などのライト プロパティを変更するには、 http://linux.die.net/man/3/gllightfvを参照してください。

glBegin() メソッドを使用している場合は、定義する頂点ごとに法線を設定する必要があります。VBO レンダリングでも同じですが、法線も vram に含まれています。glBegin() メソッドでは、使用できます

glNormal3f(x, y, z); for example

定義する頂点ごとに。

また、できることの詳細については、レッドブックから始めることをお勧めします。

「シーン」を移動することは、OpenGL が間接的に行うことができるもう 1 つのことです。すべてマトリックスで動作するため、

どちらかを使用できます

glTranslate3f(x, y, z);
glRotate3f(num, x, y, z);
....

キー イベントとマウス イベントの管理は (ほぼ確実に) OpenGL とは関係ありません。たとえば glut/SDL/... など、使用しているライブラリに依存するため、独自のドキュメントを参照する必要があります。 .

最後に、使用できる機能の詳細については、http://www.opengl.org/sdk/docs/man/を参照してください。チュートリアルの部分もあり、さまざまな興味深い Web サイトにアクセスできます。

お役に立てれば!

于 2013-02-22T23:04:28.910 に答える
1

形状の非常に基本的な「ワイヤーフレーム」レンダリングを作成するにはどうすればよいですか?

glPolygonMode( GL_FRONT, GL_LINE );

太陽が「下」方向 (つまり、-Y に沿った方向) に沿っていると仮定すると、どうすれば光を追加して反対側の影を見ることができるでしょうか?

特に固定機能のパイプラインでは、適切なシャドウを作成するのは困難です。

ただし、その前に、頂点に対応する法線が必要です。面ごとの法線は非常に簡単に計算できます。

ビューを回転させたり、ズームイン/ズームアウトしたりできるように、「マウスイベント」を追加するにはどうすればよいですか?

ここで行ったマウス ハンドラーを試してください。

于 2013-02-22T23:03:15.627 に答える