opengl: как избежать масштабирования текстур - PullRequest
3 голосов
/ 23 ноября 2008

Как применить повторяющуюся текстуру , которая всегда сохраняет свой первоначальный масштаб (1 пиксель в текстуре = 1 пиксель на экране), независимо от данных вершин, к которым она применяется.

Я понимаю, что это не самая обычная задача, но можно ли легко настроить opengl для этого, или мне нужно применить какую-то маску к данным вершин, которая соответствует их первоначальному виду?

edit: в моем конкретном случае я пытаюсь нарисовать двухмерные эллипсы разных размеров с одинаковым рисунком пикселей. Эллипсы сделаны из веерного треугольника, и мне трудно рисовать на нем повторяющуюся текстуру. Я надеялся, что есть некоторая комбинация конфигурации opengl, чтобы сделать это легко. Кроме того, теперь я понимаю, что важно упомянуть, что я использую opengles для iphone, поэтому GLU недоступен.

Ответы [ 3 ]

6 голосов
/ 23 ноября 2008

Создайте рассматриваемый трехмерный объект, не отображая его.

Вы можете получить границы объекта как местоположения в пикселях, используя gluProject (чтобы получить пиксели, которые представляют края объекта. Затем вы можете использовать gluUnProject для сопоставления промежуточных пикселей с координатами объекта.

Затем вы начинаете рисовать заново, сопоставляете пользовательскую текстуру (на лету) с тем же объектом и отображаете ее.

Не знаю, почему вы хотите это сделать, но это должно стать хорошей отправной точкой.

Edit:

Под пользовательским пониманием я понимаю, что если границы вашего объекта (в одном измерении) составляют от -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()

Это позволит вам рисовать 2D-фигуры в OpenGL (гораздо проще, чем при использовании 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) в текстуре в процентах от ширины и высоты текстуры, которая отображается на следующую нарисованную вершину. С треугольными веерами вы можете иметь некоторые математические подсказки, чтобы выяснить, какой% ширины и высоты всего объекта вы указываете с вершиной.

Например, сфера с текстурной картой (проекция Меркатора на Землю) лучше всего отображается путем вычисления линий широты в качестве основы для значений вершин вашего основного треугольника веера, поскольку это облегчает вычисление координат текстуры. Создание из ваших полигонов приближенных простых геометрических фигур позволяет использовать тригонометрию для более простого вычисления координат текстуры.

Я надеюсь, что это полезно.

Хе-хе, я перестану продолжать настольные примеры, которые вы должны модифицировать. Вот пример OpenGLES, который правильно отображает 3D текстуру. Вы можете использовать то, что я сказал выше, и этот пример, чтобы сделать 2D текстурное наложение.
http://www.zeuscmd.com/tutorials/opengles/17-TextureMapping.php

2 голосов
/ 09 декабря 2008

Я думаю, что вы говорите о следующем фрагменте кода. Тем не менее, без взлома в 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;
}
0 голосов
/ 23 ноября 2008

Я не совсем уверен, но попробуйте что-то вроде этого:

Возьмите свою матрицу модели, матрицу перспективы и тому подобное. Сделайте их вместе в правильном порядке, умножив их. Возьмем обратную матрицу. Умножьте это на свою матрицу текстур (которая, вероятно, является единичной матрицей). Установите это в качестве матрицы текстур.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...