3

如何应用始终保持其原始比例的重复纹理(纹理中的 1 个像素 = 屏幕上的 1 个像素),而不管应用的顶点数据如何。

我意识到这不是最常见的任务,但是否可以轻松设置 opengl 来执行此操作,或者我是否需要对尊重其原始外观的顶点数据应用某种掩码?

编辑:在我的具体情况下,我正在尝试使用相同的像素模式绘制不同大小的 2D 椭圆。椭圆是由三角形扇形制成的,我很难在上面画出任何类型的重复纹理。我希望有一些 opengl 配置组合可以轻松地做到这一点。另外,现在我意识到重要的是要提到我正在为 iphone 使用 opengles,因此 GLU 不可用。

4

3 回答 3

6

创建有问题的 3D 对象,但不显示它。

您可以使用 gluProject 将对象的边界作为像素位置获取(以获取表示对象边缘的像素。然后您可以使用 gluUnProject 将中间像素映射到对象的坐标。

然后,您开始绘制并映射同一对象上的自定义(即时)纹理并显示它。

不知道为什么要这样做,但这应该是一个很好的起点。

编辑:

我的意思是自定义,是如果边界你的对象(在一个维度上)是 -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 中绘制,请点击第二个链接。

这是关于 2D 绘图的优秀教程:http:
//basic4gl.wikispaces.com/2D+Drawing+in+OpenGL

以下是混合两者的基础知识:
http ://www.gamedev.net/community/forums/topic.asp ?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

我认为以下代码片段就是您所说的。但是,如果没有 hack,它会在视口大小不均匀的情况下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-able):

#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 回答