LINUX.ORG.RU

Текстуры в OpenGL 4

 


2

2

Проблема с наложением текстуры в OpenGL 4. Рисуется простой прямоугольник. Хочу наложить на него простейшую 2x2 текстуру (первый тексель-красный цвет, второй - зеленый, третий - синий, четевертый - желтый). То есть по логике в мой прямоугольник должны вписаться 4 разноцветных прямоугольника (красный, зеленый, синий, желтый). В итоге на выходе получаю прямоугольник, залитый одним цветом (темно-желтым). Причем этот итоговый цвет судя по всему является смешением цветов текселей (пробовал менять тексели 2x2 текстуры). То есть вместо того, чтобы накладывать на пиксели прямоугольника пиксели текстуры(тексели), OpenGL смешивает все тексели текстуры, получает 1 итоговый цвет и полностью им заливает прямоугольник. Как так? P.S. API еще только изучаю по OpenGL Red book 8th edition.

Вот фрагмент исходников:


			static GLuint TexCoordAttribLoc=glGetAttribLocation(SHAP,"inTextura_coord");
			static GLuint TextureId;
			static GLuint SamplerId;

			static const GLfloat TexCoord[]=
			{
				0.0f,0.0f,	1.0f,0.0f,
				1.0f,1.0f,	0.0f,1.0f
			};

			static const GLfloat Texels[16]=
			{
				1.0f,0.0f,0.0f,1.0f,	0.0f,1.0f,0.0f,1.0f,
				0.0f,0.0f,1.0f,1.0f,	1.0f,1.0f,0.0f,1.0f
			};

                        glActiveTexture(GL_TEXTURE0);

			glGenTextures(1,&TextureId);
			glGenSamplers(1,&SamplerId);
			glBindSampler(0, SamplerId);

                        glBindTexture(GL_TEXTURE_2D, TextureId);

			glTexStorage2D(GL_TEXTURE_2D,1,GL_RGBA32F, 2,2);

			glTexSubImage2D(GL_TEXTURE_2D,0,0,0,2,2,GL_RGBA,GL_FLOAT,Texels);

			glVertexAttribPointer(TexCoordAttribLoc,2,GL_FLOAT,GL_FALSE,0,TexCoord);
			glEnableVertexAttribArray(TexCoordAttribLoc);

Код вершинного шейдера

#version 430 core 
layout (location = 0) in vec4 vPosition;
layout(location=1) uniform mat4 CurrentMdMatrix=mat4(1.0f); 
layout(location=5) uniform mat4 CurrentPrMatrix=mat4(1.0f);
layout(location=9) in vec4 vColor;

layout(location=15) in vec2 inTextura_coord;
out vec2 textura_coord;

out vec4 FragmentColor;
void main()
{
  textura_coord=inTextura_coord;
  FragmentColor=vColor;
  gl_Position=CurrentPrMatrix*CurrentMdMatrix*vPosition;
} 

на переменные vColor и FragmentColor не обращайте внимание,я просто их не стал удалять с предыдущей версии шейдера.

Фрагментный (пиксельный) шейдер:

#version 430 core
uniform sampler2D textura;
in vec2 textura_coord;
in vec4 FragmentColor;
out vec4 fColor;
void main()
{
  gl_FragColor=texture(textura,textura_coord);
} 

Ответ на: комментарий от Stil

первое что я тебе посоветую — срисовать у него функцию

А я уже примерно это и сделал.Стер свой код из моих функций Scene::OnPrepare и Scene::Draw() и вставил его код из функций OnDrawFrame, prepareBuffer, prepareTexture и поставил его шейдеры (при этом код по загрузке шейдеров оставил свой и его место тоже не поменял). В итоге заработало.Ща буду постепенно трансформировать в свой код. Ребят, чтоб я без вас делал...

Nerevarino
() автор топика
Ответ на: комментарий от Nerevarino

ok, еще 2 замечания:

1. добавь в код явное определение версии OpenGL

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);

2. (и это реальная ошибка) добавь в код glewExperimental = GL_TRUE; перед GLenum err = glewInit();

/* ух, сколько всего нового я за сегодня узнал :) */

Stil ★★★★★
()
Ответ на: комментарий от Stil

Тем не менее я сегодня тоже много узнал, надо будет интегрировать в код нормальный debug для OpenGL.

Nerevarino
() автор топика
Ответ на: комментарий от Stil

1. добавь в код явное определение версии OpenGL

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);

Добавил. Это конфликтует с glewInit() (так как по идее glewInit сам должен выбирать версию автоматически).Либо одно, либо другое. Впрочем, в Linux можно действительно обойтись без glewInit и задать версию через SDL, а вот как в Windows - хз.

Nerevarino
() автор топика
Ответ на: комментарий от Nerevarino

Без явного указания версии, по крайней мере на месе включается OpenGL 2.1.

Возможно можно не указывать версию если использовать glewExperimental...

Ну и это... Пример oh-la-la у тебя работал нормально? У него версия указывалась, поэтому если его пример работал нормально, а в твоё примере конфликт – ищи ошибку...

// правда у него был glut, а не sdl

Stil ★★★★★
()
Ответ на: комментарий от Stil

Пример Oh-la-la у меня заработал нормально. Ошибки у меня было 2: я неправильно подавал координаты текстур (надо было как говорил Oh-la-la закладывать их прямо в буфер к вершинам) и у меня не было glUniform1i(SamplerLoc,SamplerUnit); Я вообще не понимал в чем смысл SamplerUnit,в книжке о нем говорилось, но по ней я так и не понял.

Сейчас же я понял следующее: 1) Есть юниты текстур TextureUnit (GL_TEXTURE0, GL_TEXTURE1 ... и т.д. до glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,&MaxTextureUnit);

2)Есть юниты сэмплеров SamplerUnit (целые беззнаковые GLuint)

3)Есть внутришейдерные встроенные переменные, например(uniform sampler2D MySampler)

Чтобы все правильно стыковалось и работало должны выполняться следующие условия:

a)glActiveTexture(TextureUnit)

б)SamplerUnit=TextureUnit-GL_TEXTURE0

в)BindSampler(SamplerUnit,SamplerId)

г)MySampler=SamplerUnit (для этого делается вызов glUniform1i(MySamplerLoc,SamplerUnit)

Nerevarino
() автор топика
Ответ на: комментарий от Stil

Забавно, только что после использования glewInit сделал запрос загруженной версии через SDL_GL_GetAttribute, тоже оказалась 2.1, это при том, что официальные дрова на карту от АМД, glxinfo пишет, что у меня поддержка OpenGL 4.3. И при том, что у меня загружается версия 2.1, у меня спокойно работают функции из 4-ой версии.... (теперь когда я исправил те 2 ошибки)

Я кажется догадываюсь в чем дело: glew обеспечивает максимально возможную версию OpenGL посредством расширений (вроде так в самом мане по библиотеке glew написано).То есть официально он запускает версию 2.1, а все остальное, что может твое оборудование, он дозагружает через расширения.

А в случае явного задания версии, то официально загружается выбранная версия, без расширений ..... как-то так

Хэх, если я прав, то для кроссплатформенности нужно таки использовать glewInit, а не явное задание версии в SDL, ведь виндовс официально поддерживает только 1.3 или 1.1 вроде.

Nerevarino
() автор топика
Ответ на: комментарий от Nerevarino

Ну в общих чертах как-то так. Если всё очень сильно упростить, то получается примерно такая картина:
Есть текстура (объект, который хранит пиксели в определенном формате + некоторую вспомогательную информацию), есть семплер (объект, который хранит параметры фильтрации и адресации текстуры). Есть программа-шейдер, которая с текстурами напрямую не работает, она имеет к ним доступ через некий «интерфейс» - TMU (Texture Mapping Unit). TMU занимается непосредственно выборкой из текстуры и передачей ее в шейдер для дальнейшей обработки (по запросу из шейдера). По этому с одной стороны перед запуском шейдера нужно правильно настроить TMU (подключить нужную текстуру и нужный семплер), а с другой стороны каким-то образом сообщить шейдеру из какого TMU запрашивать выборку. Здесь это делается через юниформы - это некие глобальные константы, которые видны на всех шейдерных стадиях (вершинная, геометрическая, фрагментная и т.д.). Шейдер кстати эти константы хранит, и как в моем примере (именно в данном случае) нет смысла звать glUniform*** каждый кадр.

По историческим причинам в OpenGL текстура и семплер были объеденены в одно целое, и лишь недавно ввели семплер как отдельный объект (опциональный). То, что ты назвал TextureUnit и SamplerUnit по-большому счету одно и тоже, это и есть TMU. Неконсистентность методов установки (glActiveTexture + glBindTexture vs glBindSampler) и параметров (именованые константы GL_TEXTUREi vs номера) это тоже по историческим причинам. Количество TMU ограничивается железкой (на современных картах GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS гарантируется вроде 32, если не больше).

Про GLEW и SDL ты скорее всего не разобрался. На сколько я помню GLEW не занимается созданием контекстов, а лишь достает функции из библиотеки. Созданием конекста занимается оконная система. В твоем случае через обертку SDL.

Вобщем читай доки, начинай с простых примеров.

oh-la-la
()
Ответ на: комментарий от oh-la-la

Ок, почитаю. А OpeGL 2.1 это судя по всему версия, выдаваемая SDL2 по умолчанию, если явно не указывать.

Nerevarino
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.