opengl: how to avoid texture scaling

后端 未结 3 1962
有刺的猬
有刺的猬 2021-01-03 10:36

How do I apply a repeating texture that always maintains its original scale (1 pixel in the texture = 1 pixel on screen), regardless of the vertex data it is applie

3条回答
  •  盖世英雄少女心
    2021-01-03 10:58

    I think the following code snippet is what you're talking about. However, without the hack in reshape() it shimmers pretty badly with GL_NEAREST and non-even viewport sizes. Any insight would be appreciated.

    It uses texture coordinate generation though, so I'm not sure what to tell you on the OpenGL ES 1.1 front. A PowerVR rep hinted at a solution, but wasn't very explicit.

    #include 
    #include 
    #include 
    
    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;
    }
    

    EDIT: Got the texture matrix only method figured out (should be OpenGL ES 1.1-able):

    #include 
    #include 
    #include 
    
    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;
    }
    

提交回复
热议问题