OpenGLテクスチャ縮小表示で縞模様が出る問題について

このQ&Aのポイント
  • OpenGLのglTexImage2D関数でテクスチャを作成して表示する際に、縮小表示すると縞模様が出てしまう問題が発生しています。
  • 縮小表示とはWindowsFormアプリ内のOpenGL描画用コントロール(glControl)のリサイズのことを指し、テクスチャ作成時には縮小操作は行っていません。
  • 問題の原因や解決策について分かっていない状況であり、glGetTexImage関数を用いてテクスチャの作成状態を確認しようとしています。
回答を見る
  • ベストアンサー

OpenGL テクスチャを縮小表示すると縞模様が…

こんにちは。お知恵をお借りしたく質問致します。 OpenGLのglTexImage2D関数でテクスチャを作り、Windowsフォームアプリケーション上に表示する際に起きた問題です。 なお、GLSLフラグメントシェーダでテクスチャは編集されています。 そのシェーダを利用した結果を表示すると、dot by dotで表示した際は正常に表示されるのですが、縮小して表示するとモアレと言いますか、縞模様が出てしまいます。※画像参照 また、縮小と言いますのはWindowsFormアプリ内のOpenGL描画用コントロール(glControl)そのものをリサイズするという意味で、テクスチャを作成する際に何か縮小操作を行ったというわけではありません。 テクスチャの貼付は以下のように行っています。 GL.Viewport(0, 0, glControl.Width, glControl.Height); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.Enable(EnableCap.Texture2D); GL.Begin(BeginMode.Quads); { GL.TexCoord2(0, 0); GL.Vertex2(-1, 1); GL.TexCoord2(1, 0); GL.Vertex2(1, 1); GL.TexCoord2(1, 1); GL.Vertex2(1, -1); GL.TexCoord2(0, 1); GL.Vertex2(-1, -1); } GL.End(); GL.Disable(EnableCap.Texture2D); glControl.SwapBuffers(); テクスチャ(1920x1080、RGBA)自体の作成が(理由は不明ですが)縮小時のみおかしくなっている、又はテクスチャの貼り方やビューポート周りの設定不足のように思って居るのですが、原因が掴めていない状況です。 参考までに、補間方法を変えた際の違いも一応スクリーンショットに撮りましたのでよろしければご覧ください。 たった今、glGetTexImageという関数で、作成したテクスチャを取得できるらしいということが分かり、これを用いて縮小表示している際もテクスチャそのものが正常に作成されているかどうかを確認しようと思っています。(が、環境が手元に無く、この確認は明日の朝となります。) この原因及び対処法など、解決の手助けとなるようなことがありましたら何でも構いませんので教えていただきたいです。 その他、説明不足な点がありましたら随時追記致しますので、ご指摘願います。 どうかよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • qwertfk
  • ベストアンサー率67% (55/81)
回答No.2

なるほど。16bit1画素ということはrgba画像の1ピクセルに2画素が入っているということでしょうか。 それは少し特殊な状況ですね。 たとえば、(255,0,0,255),(0,0,255,255)のチェック模様のテクスチャをズームアウトする場合、 OpenGL標準のサンプリングでは、NEAREST以外で縮小すると、(127,0,127,255)に近い値になります。 そこから独自のサンプリングを行うと確かに横縞が出たりする可能性が高そうです。 このような場合、OpenGLのサンプリングはNEARESTにして、自前のサンプリングする、という処理にする必要があります。

user10407
質問者

お礼

まず、自分の補足を訂正です > テクスチャの作成には、16bitで1画素情報が得られるという状態ですので 16bitで1画素と間違えていいましたが、16bitからRGBA2画素分を得られる が正しかったです。 ちなみにやっていることは、YUV422フォーマットをRGBAに変換するという処理です。 で、結論を先に言いますと無事に解決できました。 これは自分の勉強不足を痛感する次第ですが、別のテクセルをピンポイントで参照するためにはピクセルに換算して0.5の補正をしてあげる必要があるらしく、私はその処理をしていませんでした。 結局それが全てだったようで、テクセル座標の取得に補正をすることで一気に解決できました。 この度はアドバイスしていただき、本当にありがとうございました。 大変参考になりました。

その他の回答 (1)

  • qwertfk
  • ベストアンサー率67% (55/81)
回答No.1

貼り付ける画像が縦縞の模様があるものでしょうか。 そうであれば、完全にモアレを除去するのは難しいですが、ミップマップを使えばある程度は改善できます。 Native CのOpenGLのAPIの場合、 glTexImage2D を gluBuild2DMipmaps に変更する。 また、min, mag filter を glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); に変更するとミップマップを使用できます。

user10407
質問者

お礼

この度はありがとうございました。回答No2にて詳細を記します。

user10407
質問者

補足

回答ありがとうございます。 貼り付ける元画像に縦縞はありません。 アドバイス通りMIPMAPを用いてみましたが、やはり縦縞は出てしまいました。 参考画像の中に3枚の画像がありますが、全てテクスチャとして作成したものをglControlに貼り付けた結果です。 左上はテクスチャの幅・高さと、glControlの幅・高さが一致している状態で、この場合は縞模様は出ずきれいに表示されるのですが、少しでも横幅を変えると、左上や右下のように縞々模様が出てしまいます。 ちなみに幅を変えると、縞々の間隔も伸縮して、dot by dot時以外でも縦縞が出なくなる幅があります。 今思うと、高さは変えても横縞が出ないということも気になります。 どうして幅を変えた時だけ、縞々が出てしまうのでしょう・・・。 テクスチャの作成には、16bitで1画素情報が得られるという状態ですので、以下のように作成しています。(※16bitの色情報の並びは少し特殊です。) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, srcWidth, srcHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, *src); これを、ピクセルシェーダを用いて、16bitから一定の変換処理を行ってRGBに変換しています。 ちなみに変換処理を行わず、そのまま表示しても縞々は出るので変換アルゴリズム等に問題はないと思います。(そもそも、dot by dotでの表示は正常ですのでピクセルシェーダに異常は無いと考えております。)

関連するQ&A

  • カメラで撮影した画像をOpenGLで表示する方法

    webカメラで撮影した映像を,OpenGLを用いて表示することを考えております. 撮影した映像を,できる限り高速に表示する方法を教えていただけないでしょうか? 用途としては,仮想世界の視点移動に合わせて,カメラで撮影した画像を張り付けたポリゴンを 自由な視点から観察することを考えています. 私の考えつく解決策は,以下の通りです. 1.OpenGLの背景(バックバッファ)の領域を指定し,書き込む 2.ポリゴンにテクスチャマッピング 2.について実装してみたのですが,表示速度がいまひとつでした. 実装としては,テクスチャ用画像を,毎フレーム更新して, テクスチャマッピングする方法をとっています. コードを抜粋したものは,以下の通りです. ------------------------------------ glBindTexture(GL_TEXTURE_2D, g_texture[0]);//テクスチャの指定 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texture_img[0]->width,texture_img[0]->height, GL_RGB,GL_UNSIGNED_BYTE,texture_img[0]->imageData); ---------------------------------- ※texture_img[0]を毎フレーム更新して,テクスチャマッピング お忙しいと思いますが, アドバイスをいただけますと幸いです. よろしくお願いいたします.

  • Openglでテクスチャを透明にする方法について

    Microsoft Visual C++ 2008 Express Edition を使ってtgaファイルをテクスチャとして取り込んで表示するプログラムを作っております. Openglのスポットライト機能を使ってテクスチャを照らしたいと考えています. しかし,どこかのプログラミングがおかしいのか,テクスチャの張り付けに指定された座標4点付近にライトが当たったときでないとテクスチャが光りません. 方法がわからなかったので,テクスチャを大きな球体の内部に配置し,球体の内部からスポットライトでテクスチャ方向を照らすようにしました. 添付した図の左下にスポットライトが白っぽく見えているのは,この大きな球体の内部を照らした光となっています. このように球体内部がスポットライトで照ったので,後はテクスチャさえ透明にすることができれば,間接的にテクスチャをスポットライトで照らしているような感じで見えるのではないかと考えています. しかし肝心のテクスチャを透明にする方法が全くわかりません.(´・ω・) アルファ値というのを使ったり,ブレンド?を使ったりしたらできるのでは,と思ったのですが,どこにどうプログラムしたらいいのかの具体的な説明がなかったので,わかりませんでした(´・ω・) テクスチャを透かして,奥の大きな球体内部を照らすことができれば,その明るさで半透明の手前のテクスチャもうっすら光るのではないかと考えています. わかる方,教えてください. 本当に困ってます;w; 今のプログラム内部のテクスチャの部分は以下に書きます. よろしくお願いします><; void initTexture(void) { FILE *fp; int x, z; /* texture file open */ if((fp=fopen("ougonzan.tga", "rb"))==NULL){ fprintf(stderr, "texture file cannot open\n"); return; } fseek(fp, 18, SEEK_SET); for(x=0; x<TEX_HEIGHT; x++){ for(z=0; z<TEX_WIDTH; z++){ image[x][z][2]=fgetc(fp);/* B */ image[x][z][1]=fgetc(fp);/* G */ image[x][z][0]=fgetc(fp);/* R */ image[x][z][3]=fgetc(fp);/* alpha */ } } fclose(fp); } void displayTexPolygon(void) { glEnable(GL_TEXTURE_2D); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0.0, 0.0); glVertex3f(-16.0,-12.0, 5.0); //左下 glTexCoord2f(0.0, 1.0); glVertex3f(-16.0, 12.0, 5.0); //左上 glTexCoord2f(1.0, 1.0); glVertex3f( 16.0, 12.0, 5.0); //右上 glTexCoord2f(1.0, 0.0); glVertex3f( 16.0,-12.0, 5.0); //右下 glEnd(); glDisable(GL_TEXTURE_2D); } void display(void) { static const float floor_Color[] = { 1.0, 1.0, 1.0, 1.0 }; static GLfloat red[] = { 0.8, 0.2, 0.2, 1.0 }; static GLfloat yellow[] = { 0.8, 0.8, 0.2, 0.0 }; static GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 }; static float spin=0.0; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); //gluLookAt( 視点の位置x,y,z, 視界の中心位置の参照点座標x,y,z, 視界の上方向のベクトルx,y,z); gluLookAt( 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0); // 内側から //集中型スポットライト //glLightfv(光源番号, パラメータ, パラメータの値); glLightfv(GL_LIGHT0, GL_POSITION, SpotLight.pos); //光源の位置[pos] glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, SpotLight.spotDir); glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, SpotLight.spotCutoff); glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, SpotLight.spotExp); //巨大な球体 glPushMatrix(); glTranslated(0.0, 0.0, 7); glMaterialfv(GL_FRONT, GL_DIFFUSE, white); glutSolidSphere(60, 10000, 10000); glPopMatrix(); glPushMatrix(); glPopMatrix(); glPushMatrix(); glClearColor(0.0, 0.0, 1.0, 0.5); glTranslatef(0.0, 0.0, 45.0); //テクスチャの位置設定 // glRotatef(spin, 0.0, 1.0, 0.0); //テクスチャの回転 glColor4f(1.0, 0.0, 0.0, 0.0); //テクスチャの色設定 displayTexPolygon(); } spin+=1.0; glPopMatrix(); glFlush(); glutSwapBuffers(); }

  • C言語のOpenGLで複数のテクスチャをロード方法

    こんにちは、 よく探してたが、 C言語のOpenGLで一つだけじゃなくて複数のテクスチャをロードする方法は? 見つかったコードは 「一つだけのテクスチャをロードする」 ーーーーーーーーーーー void LoadGLTextures() { // Load Texture Image *image1; // allocate space for texture image1 = (Image *) malloc(sizeof(Image)); if (image1 == NULL) { printf("Error allocating space for image"); exit(0); } if (!ImageLoad("Data/01.bmp", image1)) { exit(1); } // Create Texture glGenTextures(1, &texture[0]); glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image, // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself. glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data); }; ーーーーーーーーーーー お願いします

  • openGL support を受けるには for 3DCG

    3DCGを作るソフトウェアでマップを作るのにopenGL supporがないと使えないとエラーが出てしまいました。 :No GL_EXT_texture_env_dot3 support! :GL_INVALID_ENUM openGLのサポートを受けるにはどうしたらいいのでしょうか? Intel websiteでいろんなアップデートを試そうとしましたが :現在のハードウェアと互換性のあるドライバを見つけることができませんでした。 :インストールしようとしているドライバはこのコンピュータでは無効です。製造元から適切なドライバを入手してください。 となってインストールできません… パソコンの仕様は DELL:INSPIRON6400 chipset:Intel 945GM OS:Win XP Home Ed 現在DELLに問い合わせ中ですが、 急いでいるのでどなたかご教授宜しくお願いできませんでしょうか?? よろしくお願いいたします。

  • DirectXとOpenGLについて

    現在DirectXにてプログラムを作成しているのですが、パソコンの性能に対して柔軟性を持とうと思い、OpenGLに変えようと思っています。 ですが、OpenGLを使ったことがないため苦戦しております。 DirectXのAという関数は、OpenGLの?関数にあたる。 のような感じで書かれているサイト等を知っている方はいますでしょうか? ちなみに使用しているのは、 IDirect3D9 IDirect3DDevice9 IDirect3DTexture9 IDirect3DSurface9 です。 これをOpenGLで表現するには何を使ったらいいのでしょうか? サイトや調べ方(検索)などありましたら教えてください。 よろしくお願い致します。

  • opengl

    C++,openGLの質問です. 画像の上で2点を指定し,その2点を用いて画像上に四角形を表示したいのですがどういったpログラムを書けばいいでしょうか?イメージは図のような感じです.(1)と(2)が画像上で指定した点で高さが255の長方形になるようにしたいです. http://www.wakayama-u.ac.jp/~tokoi/opengl/libglut.html#5 のサイトを参考に作ってみたのですが,いまいちわかりません. 以下,自分で作ってみたところです. わかりにくいと思いますが,アドバイスいただけたら嬉しいです. painted_pointはint型のベクターでクリックされた点の位置を保存しています. 最終的には,3点以上の折れ線上に長方形がつながってくっつくのことを予定しています. for(int i = 0; i<painted_point.size(); i++){ GLdouble vertex[][3] = { { painted_point.at(i).x, painted_point.at(i)., 0 }, { painted_point.at(i).x, painted_point.at(i)., 255 } } }; int edge[][2] = { {1 , 2} for(int i=0; i<painted_point.size(); i++){ edge[][2] ={{ i*2 , i*2 + 2}, { i*2+1 , i*2 + 3}, } {painted_point.size()-1,painted_point.size()} }; /* 図形の描画 */ glColor3d(0.0, 0.0, 0.0); glBegin(GL_LINES); for (i = 0; i < 12; ++i) { glVertex3dv(vertex[edge[i][0]]); glVertex3dv(vertex[edge[i][1]]); } glEnd(); }

  • OpenGLからDirect3Dへの移行

    今までGLはOpenGLを使用していたのですが、今回、Windows依存命令を書くこととなり、これを機会としてDirect3Dへの移行を考えております。 そこで、Direct3Dでの3Dの処理を理解しようと基礎的な内容のサイトを探したのですが、まったく見つからなく困っています。 ウインドウの作成から、ポリゴン1つを画面に表示するまでを解説したサイトや、 DirectXの基本的な処理の考え方を解説したサイトがありましたら、教えてください。

  • JOGLで、GLJpanelの外でOpenGLの関数を呼ぶには

    JOGLでは、GLJPanelの各種メソッド(init,display,reshapeなど)でしか、OpenGLの関数を呼べないみたいですが、どうしてもGLJPanelの外でOpenGL の関数を呼びたいんです。携帯電話とPCの両方で動かすことができる2D描画のライブラリをつくっているので、特定のクラスの派生クラスにしなくちゃいけないとかではなく、ユーザーが自作したクラスからOpenGLを呼べるようにしたいんです。 試しに以下のコードを参考にして、initで取得したGLクラスの参照を使って、GLJPanelの外でOpenGLの関数を呼んだら、AccessVioration(アクセス違反)のエラーが出てJavaのVMが落ちてしまいました。しかも、GLJPanelのinitが呼び出されるタイミングが分からず、最初はglがnullになっていることもあります。何かいい方法はないでしょうか・・? http://d.hatena.ne.jp/SofiyaCat/20090425/1240646625

  • OpenGL 画像のα値操作

    こんにちは。 現在、授業の一環でGLUTを用いたOpenGLのプログラムを作っています。 そのプログラムの機能の中に、読み込んだ画像のα値を記憶した後、キー操作によって表示・非表示を切り替える機能を作ろうとしています。 目的の機能自体は一応途中まで(各ピクセルのα値を255⇔0への切り替え)は作れたのですが、原理がよく分かりません。 具体的に書くと、(幅)×(高さ)×(色のチャンネル数) の画像を読み込んだのに、4倍の高さの範囲までα値に関する処理を加えないと、処理後の効果が画像全体に現れないのです。 下にプログラムの断片を張るので、わかる方がいたら解説お願いします。 出来れば、後々のために理由を知っておきたいので。 -*-*-*-*-*-*-*-*-*- /* テクスチャの情報を格納する構造体 */ typedef struct{ unsigned int name; /* 識別番号 */ unsigned char* data; /* 画像のデータ */ int width; /* 画像の幅 */ int height; /* 画像の高さ */ int channels; /* 画像の色成分の数 */ }texture; /* テクスチャ(グローバル変数) */ texture a; /* 画面表示用の関数 */ void display (void) {  /* 初期化 */ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* 透明色を描けるようにする */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  /* 描画 */ glDrawPixels(a.width, a.height, GL_RGBA, GL_UNSIGNED_BYTE, a.data); glutSwapBuffers (); } /* α値の操作(代入値がかわるだけなので、255にする方は省略) */ void alpham(void) { int i, j; for (i = 0; i < a.height * 4; ++i) { for (j = 0; j < (a.width); ++j) { a.data[(a.width * i) + (a.channels * j) +3] = 0; } } } ※画像データ の メモリ確保サイズ a.data = (unsigned char*) malloc(width * height * channels)

  • OpenGLで写真を表示したい

    OpenGLで書いた四角の中に写真を表示したいのですが、どうやって良いのか良くわかりません。 具体的には、 glNewList(i*2,GL_COMPILE); glBegin(GL_LINE_LOOP); glColor3fv(col[i]); glVertex2i(xpos[i]-radiusx[i],ypos[i]-radiusy[i]); glVertex2i(xpos[i]+radiusx[i],ypos[i]-radiusy[i]); glVertex2i(xpos[i]+radiusx[i],ypos[i]+radiusy[i]); glVertex2i(xpos[i]-radiusx[i],ypos[i]+radiusy[i]); glEnd(); glEndList(); で描画した四角形の中に radiusx[i]*2 , radiusy[i]*2 の大きさに縮小した i番目のJpeg写真(640x480)を書きたいのです。 現在、以下のファイルをインクルードしています。 #include <windows.h> #include <gl\gl.h> #include <gl\glu.h> #include <gl\glaux.h> #include <stdio.h> 追加すべきインクルードファイル、DLLなどお教えください。 なお、開発環境はフリーの Visual Windows for BC++ です。