2012-12-13 4 views
3

Я работаю над графическим интерфейсом в OpenGL. Я использую это изображение для текстуры моей кнопки: enter image description hereИзмените только часть текстуры, OpenGL

Вы не можете видеть это очень хорошо, но у него есть легкая граница (ширина 2 пикселя) вокруг него.

Я хочу добиться того, чтобы иметь красиво изменяемую размерную кнопку, которая не затрагивает границы. По намеками дал мне здесь, на StackOverflow я решил использовать 9-элементный-шаблон, поэтому я разделил свой квадроцикл на 9 частей, как это:

enter image description here

мне очень нравится эффект я достигается, если речь идет о границы, но проблема с четырехугольника, который находится в центре (9):

enter image description here

Я хотел бы повторить или завернуть текстуру, как я, но с игнорированием границ.

Так что мой вопрос: есть ли способ сделать это только с одной текстурой, которую я сейчас использую? Или мне нужно создать вторую текстуру, которая будет уменьшена шириной границы и отобразить этот квадрат посередине этой текстурой?

Кроме того, я не знаю, если это необходимо, но я помещаю здесь фрагмент моего кода:

Это код, я использую для плитки/обертывание текстуры:

switch(m_bTiling) 
{ 
case true: 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
        GL_REPEAT); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
        GL_REPEAT); 
    break; 
case false: 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
        GL_CLAMP); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
        GL_CLAMP); 
    break; 
} 

а вот код рисовать каре:

// Top left quad [1] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(0.0f, 1.0-maxTexCoordBorderY);      
    glVertex2i(pos.x, pos.y + m_borderWidth); 

    // Top left 
    glTexCoord2f(0.0f, 1.0);  
    glVertex2i(pos.x, pos.y); 

    // Top right 
    glTexCoord2f(maxTexCoordBorderX, 1.0); 
    glVertex2i(pos.x + m_borderWidth, pos.y); 

    // Bottom right 
    glTexCoord2f(maxTexCoordBorderX, 1.0-maxTexCoordBorderY); 
    glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth); 
glEnd(); 

// Top middle quad [2] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(maxTexCoordBorderX, 1.0 - maxTexCoordBorderY);    
    glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth); 

    // Top left 
    glTexCoord2f(maxTexCoordBorderX, 1.0); 
    glVertex2i(pos.x + m_borderWidth, pos.y); 

    // Top right 
    glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, 1.0); 
    glVertex2i(pos.x + width - m_borderWidth, pos.y); 

    // Bottom right 
    glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, 1.0 - maxTexCoordBorderY); 
    glVertex2i(pos.x + width - m_borderWidth, pos.y + m_borderWidth); 
glEnd(); 

// Top right quad [3] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(1.0 - maxTexCoordBorderX, 1.0 - maxTexCoordBorderY);     
    glVertex2i(pos.x + width - m_borderWidth, pos.y + m_borderWidth); 

    // Top left 
    glTexCoord2f(1.0 - maxTexCoordBorderX, 1.0); 
    glVertex2i(pos.x + width - m_borderWidth, pos.y); 

    // Top right 
    glTexCoord2f(1.0, 1.0); 
    glVertex2i(pos.x + width, pos.y); 

    // Bottom right 
    glTexCoord2f(1.0, 1.0 - maxTexCoordBorderY);  
    glVertex2i(pos.x + width, pos.y + m_borderWidth); 
glEnd(); 

// Middle left quad [4] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(0.0, maxTexCoordBorderY);    
    glVertex2i(pos.x, pos.y + height - m_borderWidth); 

    // Top left 
    glTexCoord2f(0.0, maxTexCoordHeight - maxTexCoordBorderY); 
    glVertex2i(pos.x, pos.y + m_borderWidth); 

    // Top right 
    glTexCoord2f(maxTexCoordBorderX, maxTexCoordHeight - maxTexCoordBorderY);   
    glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth); 

    // Bottom right 
    glTexCoord2f(maxTexCoordBorderX, maxTexCoordBorderY); 
    glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth); 
glEnd(); 

// Middle right quad [5] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(1.0 - maxTexCoordBorderX, maxTexCoordBorderY);      
    glVertex2i(pos.x + width - m_borderWidth, pos.y + height - m_borderWidth); 

    // Top left 
    glTexCoord2f(1.0 - maxTexCoordBorderX, maxTexCoordHeight - maxTexCoordBorderY); 
    glVertex2i(pos.x + width - m_borderWidth, pos.y + m_borderWidth); 

    // Top right 
    glTexCoord2f(1.0, maxTexCoordHeight - maxTexCoordBorderY); 
    glVertex2i(pos.x + width, pos.y + m_borderWidth); 

    // Bottom right 
    glTexCoord2f(1.0, maxTexCoordBorderY); 
    glVertex2i(pos.x + width, pos.y + height - m_borderWidth); 
glEnd(); 

// Bottom left quad [6] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(0.0, 0.0);      
    glVertex2i(pos.x, pos.y + height); 

    // Top left 
    glTexCoord2f(0.0, maxTexCoordBorderY); 
    glVertex2i(pos.x, pos.y + height - m_borderWidth); 

    // Top right 
    glTexCoord2f(maxTexCoordBorderX, maxTexCoordBorderY); 
    glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth); 

    // Bottom right 
    glTexCoord2f(maxTexCoordBorderX, 0.0); 
    glVertex2i(pos.x + m_borderWidth, pos.y + height); 
glEnd(); 

// Bottom middle quad [7] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(maxTexCoordBorderX, 0.0);       
    glVertex2i(pos.x + m_borderWidth, pos.y + height); 

    // Top left 
    glTexCoord2f(maxTexCoordBorderX, maxTexCoordBorderY); 
    glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth); 

    // Top right 
    glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, maxTexCoordBorderY);  
    glVertex2i(pos.x + width - m_borderWidth, pos.y + height - m_borderWidth); 

    // Bottom right 
    glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, 0.0); 
    glVertex2i(pos.x + width - m_borderWidth, pos.y + height); 
glEnd(); 

// Bottom right quad [8] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(1.0 - maxTexCoordBorderX, 0.0);       
    glVertex2i(pos.x + width - m_borderWidth, pos.y + height); 

    // Top left 
    glTexCoord2f(1.0 - maxTexCoordBorderX, maxTexCoordBorderY); 
    glVertex2i(pos.x + width - m_borderWidth, pos.y + height - m_borderWidth); 

    // Top right 
    glTexCoord2f(1.0, maxTexCoordBorderY); 
    glVertex2i(pos.x + width, pos.y + height - m_borderWidth); 

    // Bottom right 
    glTexCoord2f(1.0, 0.0); 
    glVertex2i(pos.x + width, pos.y + height); 
glEnd(); 

// Middle middle quad [9] 
glBegin(GL_QUADS); 
    // Bottom left 
    glTexCoord2f(maxTexCoordBorderX, maxTexCoordBorderY);     
    glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth); 

    // Top left 
    glTexCoord2f(maxTexCoordBorderX, maxTexCoordHeight - maxTexCoordBorderY); 
    glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth); 

    // Top right 
    glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, maxTexCoordHeight - maxTexCoordBorderY);   
    glVertex2i(pos.x + width - m_borderWidth, pos.y + m_borderWidth); 

    // Bottom right 
    glTexCoord2f(maxTexCoordWidth - maxTexCoordBorderX, maxTexCoordBorderY); 
    glVertex2i(pos.x + width - m_borderWidth, pos.y + height - m_borderWidth); 
glEnd(); 
+0

Обратите внимание, что ваша текстура не может быть легко черепицей из-за цветового градиента внутри. Вы можете попытаться взять квад из приблизительного (x = 2, y = 20, w = 18, h = 18) и наложить его на лучшие результаты – Constantin

ответ

0

Если вы растягивая края/центра, вы бы хорошо, но так как вы черепицей, вы будете иметь, чтобы создать второй текстуры только с центральной частью.

Обратите внимание, что это может быть сделано программно, если у вас есть размер границы. Вы скопировали содержимое центра в новый 2d-массив, а затем загрузите его в другую текстуру.

Другим решением (как я указал в комментарии) было бы установить координаты текстуры среднего среднего квадрата на те же самые, что и внутренние вершины угла. Таким образом, текстура центрального квадроцикла растянута. Обратите внимание, что это создаст какое-то странное растяжение на сиянии в верхнем правом углу, если все это не содержится в верхнем правом углу квадрата. У вас все еще есть проблемы с этим, если вы хотите использовать свое повторное решение.

Если вы все еще хотите повторить центральную часть и не возражаете переместить весь конвейер рендеринга в не устаревший OpenGL, тогда ответ ananthonline лучше. Если вы не хотите/не можете перенести свой код рендеринга на более современный OpenGL, то копия текстуры - это почти единственное решение.

+0

Спасибо Роберту за ответ, но что вы имели в виду, растягивая края/центр ? Вы имели в виду использование GL_CLAMP вместо GL_REPEAT? –

+0

Не определенно вы просто определяете координаты текстуры центрального квадроцикла как одни и те же текстурные коорды внутри угловых блоков. Таким образом, центр текстуры простирается над центральным квадрантом. –

+0

Дублирование текстуры расточительно, переосмысливание текстурных коордов проще - обратите внимание, что это также можно сделать гораздо эффективнее, используя два флеш-шейдера, работающих на одной текстуре с двумя пробоотборниками, см. Мой ответ выше. – Ani

1

Ну, я вижу вашу проблему. Вы используете постоянное значение maxTexCoordBorderX (и Y) для вашего «среднего среднего» квадранта. Вам нужно перекомпоновать УФ-координаты центральных квадрациклов с изменением размера (например: width/(currWidth - 2 * borderWidth)), тогда вы можете установить, что текстура повторяется всегда, но так как вы изменяете текстурные координаты как элемент ui изменяет размеры, центральная часть никогда не повторится.

Конечно, если вы собираетесь использовать VBO или что-то более совершенное в какой-то момент в будущем, вы можете просто определить два фрагментарных шейдера (каждый со своими собственными sampler2D объектами, один повторяет, остальные растягиваются) для каждого из режимов черепицы и рендеринга всех угловых квадрантов и средне-средних квадроциклов с использованием «повторного» шейдера и всех крайних квадов с использованием растягивающего шейдера. Это не потребует компромисса и должно быть очень быстрым.

Примечание: здесь вы рисуете несколько квадроциклов, это не очень хорошая идея. Я бы рекомендовал использовать индексированную сетку с общими вершинами. Это позволит свести к минимуму возможность «слез» на границах ваших квадроциклов.

+0

Спасибо Ananthonline за ответ. У меня есть еще один вопрос: я совершенно не знаю об этом современном OpenGL, поэтому мне нужно будет прочитать о VBOs и отдыхе, но можно ли просто заменить этот код чертежных квадратов на «современный», или я бы изменить все настройки и т. д.? И это намного сложнее, чем эта старая версия? –

+0

Вы можете сделать простую замену - вместо двух шейдеров используйте один шейдер с равномерным контролем того, какой пробоотборник использовать (повторите или растяните) и установите его соответствующим образом, прежде чем рисовать каждый квад. Проблема с использованием двух шейдеров в графике немедленного режима заключается в том, что вы будете делать это изменение много раз при рисовании одного квадранта, а изменение состояния часто плохо для производительности. В идеале вы должны собрать все состояния, которые имеют одно и то же состояние и пакетную визуализацию (после настройки этого состояния), если это возможно. Здесь (http://www.lighthouse3d.com/opengl/glsl/) - это учебное пособие по GLSL, которое должно помочь вам приступить к работе. – Ani

Смежные вопросы