3

適用される頂点データに関係なく、元のスケール (テクスチャ内の 1 ピクセル = 画面上の 1 ピクセル) を常に維持する繰り返しテクスチャを適用するにはどうすればよいですか。

これは最も一般的なタスクではないことを認識していますが、これを行うためにopenglを簡単に設定することは可能ですか、それとも元の外観を尊重する頂点データにある種のマスクを適用する必要がありますか?

編集: 私の特定のケースでは、同じピクセル パターンで異なるサイズの 2D 楕円を描画しようとしています。楕円は三角形のファンでできており、その上に繰り返しテクスチャを描くのに苦労しています。これを簡単に行うためのいくつかのopengl構成の組み合わせがあることを望んでいました。また、私はiPhoneにopenglesを使用していることに言及することが重要であることを認識しているため、GLUは利用できません。

4

3 に答える 3

6

問題の 3D オブジェクトを表示せずに作成します。

gluProject を使用してオブジェクトの境界をピクセル位置として取得できます (オブジェクトのエッジを表すピクセルを取得します。その後、gluUnProject を使用して、介在するピクセルをオブジェクトの座標にマップします。

次に、描画をやり直してマップします。同じオブジェクトにカスタム (オンザフライ) テクスチャを適用して表示する.

なぜこれを行う必要があるのか​​ はわかりませんが、それは良い出発点になるはずです.

編集:

カスタムとは、境界がオブジェクトの (1 次元で) が -3.0 から 1.0 で、最初のピクセル行が -3.0 から -2.0 の場合、テクスチャ マップは、カスタム テクスチャ マップの 25% がそのスポットにマップされていることを示します。そこに表示したいピクセルの色ですべてです。

よく考えてみると、投影された画面座標の上にテクスチャを描画するだけでよいことに気付きました (2D 描画機能を使用)

。「オブジェクト」が近づいたり遠ざかったり、テクスチャが拡大縮小していないように見える場合、インタラクティブな 3D デモではうまく機能しないと思います。しかし、あなたは実際に何をしていたかを言いませんでした。

編集 2:

OpenGL 2D プロジェクション:


注意
関数名に注意してください。たとえば、opengles 1.1 には glOrthox と glOrthof があります。gl.h ヘッダー ファイルで何が利用できるかを確認してください。

const XSize = 640, YSize = 480
glMatrixMode (GL_PROJECTION)
glLoadIdentity ()
glOrtho (0, XSize, YSize, 0, 0, 1)
glMatrixMode (GL_MODELVIEW)
glDisable(GL_DEPTH_TEST)
glClear(GL_COLOR_BUFFER_BIT)

// Now draw with 2i or 2f vertices instead of the normal vertex3f functions.
// And for ES, of course set up your data structures and call drawarrays ofr drawelements.

SwapBuffers()

これにより、OpenGL で 2D 形状を描画できます (3D 投影を使用するよりもはるかに簡単です)。たとえば、3D で描画してから 2D で描画するなど、2 つを混在させるには、2 番目のリンクに従ってください。

2D 描画に関する優れたチュートリアルは


のとおりです
。 ?topic_id=96440

それがあなたの望むものであることを願っています。あなたの投稿から、テクスチャを三角形のポイントにマッピングして「まっすぐ」に表示するのに問題があるという疑いがこっそりとあります。NeHe で基本的なテクスチャ マッピングを確認することをお勧めします:
http://www.gamedev.net/community/forums/topic.asp?topic_id=96440
たとえば、 gltexcoord2f は、テクスチャ内のポイント (0.0-1.0) を、次に描画される頂点にマップされるテクスチャの幅と高さのパーセンテージで指定します。三角形ファンを使用すると、オブジェクト全体の幅と高さの何%を頂点で指定するかを計算するために、いくつかの数学的解釈を行うことができます。

たとえば、テクスチャ マップ (地球のメルカトル図法) を持つ球は、テクスチャ座標の計算が容易になるため、基礎となる三角ファンの頂点値の基礎として緯度線を計算することによって最適にマッピングされます。ポリゴンを単純な幾何学的形状に近似させると、三角法を使用してテクスチャ座標をより簡単に計算できます。

これがお役に立てば幸いです。

ここで、変更が必要なデスクトップの例を続けるのはやめておきます。適切な 3D テクスチャ マッピングを行う OpenGLES の例を次に示します。上で述べたこととこの例を使用して、2D テクスチャ マッピングを行うことができます。
http://www.zeuscmd.com/tutorials/opengles/17-TextureMapping.php

于 2008-11-23T10:44:25.200 に答える
2

次のコード スニペットは、あなたが話していることだと思います。ただし、ハックがないと、ビューポートのサイズが均一でないreshape()場合にかなりひどく揺らめきます。GL_NEAREST任意の洞察をいただければ幸いです。

ただし、テクスチャ座標の生成を使用しているため、OpenGL ES 1.1 について何を伝えればよいかわかりません。PowerVR の担当者は解決策をほのめかしましたが、あまり明確ではありませんでした。

#include <GL/glut.h>
#include <cstdlib>
#include <cmath>

static GLuint texName;

void init(void)
{
glClearColor(0,0,0,0);

// create random texture
const int texWidth = 8;
const int texHeight = 8;
GLubyte tex[texHeight][texWidth][4];
for(int i = 0; i < texHeight; i++)
    {
    for(int j = 0; j < texWidth; j++) 
        {
        tex[i][j][0] = (GLubyte) rand()%255;
        tex[i][j][1] = (GLubyte) rand()%255;
        tex[i][j][2] = (GLubyte) rand()%255;
        tex[i][j][3] = (GLubyte) 255;
        }
    }
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex);

// planes for texture coordinate generation
GLfloat xp[] = {1,0,0,0};
GLfloat yp[] = {0,1,0,0};
GLfloat zp[] = {0,0,1,0};
GLfloat wp[] = {0,0,0,1};
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_S, GL_EYE_PLANE, xp);
glTexGenfv(GL_T, GL_EYE_PLANE, yp);
glTexGenfv(GL_R, GL_EYE_PLANE, zp);
glTexGenfv(GL_Q, GL_EYE_PLANE, wp);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);

glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// projection
glMatrixMode(GL_PROJECTION); glLoadIdentity();
int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport);
gluPerspective(60.0, (GLdouble)viewport[2]/(GLdouble)viewport[3], 1.0, 100.0 );

// texture matrix trickery
int tw,th;
glMatrixMode(GL_TEXTURE); glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, texName);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tw);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &th);
glScaled( (viewport[2]/2)/(GLdouble)tw, (viewport[3]/2)/(GLdouble)th, 0 );
GLdouble proj[16];
glGetDoublev(GL_PROJECTION_MATRIX, proj); // grab projection matrix
glMultMatrixd(proj);

// view transform
glMatrixMode(GL_MODELVIEW); glLoadIdentity();
glTranslatef(0,0,-2.5);

// render textured teapot
glPushMatrix();
const float ANGLE_SPEED = 60; // degrees/sec
float angle = ANGLE_SPEED * (glutGet(GLUT_ELAPSED_TIME) / 1000.0f);
glRotatef(angle*0.5f, 1, 0, 0);
glRotatef(angle, 0, 1, 0);
glRotatef(angle*0.7f, 0, 0, 1);
glScalef(-1,-1,-1); // teapot is wound backwards (GL_CW), so flip it
glutSolidTeapot(1);
glPopMatrix();

glutSwapBuffers();
}

void reshape(int w, int h)
{
// make width/height evenly divisible by 2
w -= (w%2);
h -= (h%2);
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
}

void keyboard (unsigned char key, int x, int y)
{
switch (key) 
    { 
    case 27: exit(0); break;
    default: break; 
    }
}

void idle() { glutPostRedisplay(); }

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow (argv[0]);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(idle);

init();
glutMainLoop();
return 0;
}

編集:テクスチャマトリックスのみの方法を理解しました(OpenGL ES 1.1対応である必要があります):

#include <GL/glut.h>
#include <cstdlib>
#include <cmath>

void glutTexturedCube(GLdouble size)
{
    GLfloat texc[] = {
        1,1,    0,1,    0,0,    1,0,
        0,1,    0,0,    1,0,    1,1,
        1,0,    1,1,    0,1,    0,0,
        1,1,    0,1,    0,0,    1,0,
        0,0,    1,0,    1,1,    0,1,
        0,0,    1,0,    1,1,    0,1,
    };

    GLfloat norm[] = {
        0,0,1,      0,0,1,      0,0,1,      0,0,1,
        1,0,0,      1,0,0,      1,0,0,      1,0,0,
        0,1,0,      0,1,0,      0,1,0,      0,1,0,
        -1,0,0,     -1,0,0,     -1,0,0,     -1,0,0,
        0,-1,0,     0,-1,0,     0,-1,0,     0,-1,0,
        0,0,-1,     0,0,-1,     0,0,-1,     0,0,-1,
    };

    GLfloat vert[] = {
        1,1,1,      -1,1,1,     -1,-1,1,    1,-1,1,
        1,1,1,      1,-1,1,     1,-1,-1,    1,1,-1,
        1,1,1,      1,1,-1,     -1,1,-1,    -1,1,1,
        -1,1,1,     -1,1,-1,    -1,-1,-1,   -1,-1,1,
        -1,-1,-1,   1,-1,-1,    1,-1,1,     -1,-1,1,
        1,-1,-1,    -1,-1,-1,   -1,1,-1,    1,1,-1,
    };

    GLuint idxs[] = { 
        0, 1, 2, 3,     
        4, 5, 6, 7,     
        8, 9, 10, 11,
        12, 13, 14, 15,
        16, 17, 18, 19,
        20, 21, 22, 23,
    };

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);
    // feed vertices in as texture coordinates
    glTexCoordPointer(3, GL_FLOAT, 0, vert);
    glNormalPointer(GL_FLOAT, 0, norm);
    glVertexPointer(3, GL_FLOAT, 0, vert);

    glPushMatrix();
    glColor4f(1, 1, 1, 1);
    glScaled(size, size, size);
    glDrawElements(GL_QUADS, sizeof(idxs)/sizeof(idxs[0]), GL_UNSIGNED_INT, idxs);
    glPopMatrix();

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
}

static GLuint texName;

void init(void)
{
glClearColor(0,0,0,0);

// create random texture
const int texWidth = 8;
const int texHeight = 8;
GLubyte tex[texHeight][texWidth][4];
for(int i = 0; i < texHeight; i++)
    {
    for(int j = 0; j < texWidth; j++) 
        {
        tex[i][j][0] = (GLubyte) rand()%255;
        tex[i][j][1] = (GLubyte) rand()%255;
        tex[i][j][2] = (GLubyte) rand()%255;
        tex[i][j][3] = (GLubyte) 255;
        }
    }
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex);

glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// projection
glMatrixMode(GL_PROJECTION); glLoadIdentity();
int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport);
gluPerspective(60.0, (GLdouble)viewport[2]/(GLdouble)viewport[3], 1.0, 100.0 );

// view transform
glMatrixMode(GL_MODELVIEW); glLoadIdentity();
glTranslatef(0,0,-3);

// render textured teapot
glPushMatrix();
const float ANGLE_SPEED = 10; // degrees/sec
float angle = ANGLE_SPEED * (glutGet(GLUT_ELAPSED_TIME) / 1000.0f);
glRotatef(angle*0.5f, 1, 0, 0);
glRotatef(angle, 0, 1, 0);
glRotatef(angle*0.7f, 0, 0, 1);

// texture matrix trickery
int tw,th;
glBindTexture(GL_TEXTURE_2D, texName);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tw);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &th);
GLint mmode = 0;
glGetIntegerv(GL_MATRIX_MODE, &mmode);
glMatrixMode(GL_TEXTURE); glLoadIdentity();
glScaled( (viewport[2]/2)/(GLdouble)tw, (viewport[3]/2)/(GLdouble)th, 0 );
GLdouble mat[16];
glGetDoublev(GL_PROJECTION_MATRIX, mat);
glMultMatrixd(mat);
glGetDoublev(GL_MODELVIEW_MATRIX, mat);
glMultMatrixd(mat);
glMatrixMode(mmode);

glutTexturedCube(1);
glPopMatrix();

glutSwapBuffers();
}

void reshape(int w, int h)
{
// make width/height evenly divisible by 2
w -= (w%2);
h -= (h%2);
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
}

void keyboard (unsigned char key, int x, int y)
{
switch (key) 
    { 
    case 27: exit(0); break;
    default: break; 
    }
}

void idle() { glutPostRedisplay(); }

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow (argv[0]);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(idle);

init();
glutMainLoop();
return 0;
}
于 2008-12-09T20:33:45.690 に答える
0

よくわかりませんが、次のようにしてみてください。

モデル マトリックス、パースペクティブ マトリックスなどを考えてみましょう。それらを乗算して、適切な順序で一緒にマッシュします。その行列の逆を取ります。これにテクスチャ マトリックス (おそらく単位マトリックス) を掛けます。それをテクスチャ マトリックスとして設定します。

于 2008-11-23T04:46:20.757 に答える