2011-02-02 3 views
1

Я пишу 2D игры с использованием SDL и OpenGL на языке программирования D. На данный момент он просто пытается отобразить квадрат с отображением текстуры на экран. Проблема в том, что вся часть текстурирования не работает. Несмотря на то, что текстура явно загружается штрафом (получает ненулевой номер текстуры, не приводит к тому, что glGetError возвращает значения, отличные от нуля), квадрат отображается с последним цветом, установленным в glColor, полностью игнорируя текстуру.OpenGL текстурирование упорно отказывается работать

Я искал общие причины для сопоставления текстур с ошибкой, включая this question, но безрезультатно. Загружаемый файл изображения - 64x64, действительный размер в 2 раза.

Пожалуйста, не пугайтесь, потому что это в D-это почти полностью C-стиль SDL и OpenGL-вызовов.

SDL код инициализации:

if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) == -1 || 
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0) == -1) 
    throw new Exception("An OpenGL attribute could not be set!"); 

uint videoFlags = SDL_OPENGL | SDL_HWSURFACE | SDL_ANYFORMAT; 

if (threadsPerCPU() > 1) 
    videoFlags |= SDL_ASYNCBLIT; 

SDL_Surface* screen = SDL_SetVideoMode(800, 600, 32, videoFlags); 

if (screen == null) 
    throw new Exception("SDL_SetVideoMode failed!"); 

код инициализации OpenGL:

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(0., 800, 600, 0., 0., 1.); 
glMatrixMode(GL_MODELVIEW); 

glDisable(GL_DEPTH_TEST); 
glDisable(GL_LIGHTING); 

glEnable(GL_BLEND); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

glEnable(GL_TEXTURE_2D); 

glClearColor(0.f, 0.f, 0.f, 0.f); 

Texture загрузки Код:

SDL_Surface* s = IMG_Load(toStringz("hello.png")); 

if (s == null) 
    throw new Exception("Image file could not be loaded!"); 

uint texFormat; 

switch (s.format.BytesPerPixel) 
{ 
case 4: 
    texFormat = (s.format.Rmask == 0x000000ff ? GL_RGBA : GL_BGRA); 
    break; 
case 3: 
    texFormat = (s.format.Rmask == 0x000000ff ? GL_RGB : GL_BGR); 
    break; 
default: 
    throw new Exception("Bad pixel format!"); 
    break; 
} 

if ((s.w & (s.w - 1)) != 0) 
    throw new Exception("Width must be a power of 2!"); 
if ((s.h & (s.h - 1)) != 0) 
    throw new Exception("Height must be a power of 2!"); 

uint glName; 

glGenTextures(1, &glName); 

glBindTexture(GL_TEXTURE_2D, glName); 
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
glTexImage2D(GL_TEXTURE_2D, 0, s.format.BytesPerPixel, s.w, s.h, 0, 
    texFormat, GL_UNSIGNED_BYTE, s.pixels); 

SDL_FreeSurface(s); 

Rendering Код:

glClear(GL_COLOR_BUFFER_BIT); 

glBegin(GL_QUADS); 
    glColor4ub(255, 255, 255, 255); 
    glBindTexture(GL_TEXTURE_2D, glName); 
    glTexCoord2i(0, 0); glVertex2i(0, 0); 
    glTexCoord2i(1, 0); glVertex2i(64, 0); 
    glTexCoord2i(1, 1); glVertex2i(64, 64); 
    glTexCoord2i(0, 1); glVertex2i(0, 64); 
glEnd(); 

SDL_GL_SwapBuffers(); 

Моя программа использует Derelict2, библиотеку, которая обеспечивает привязки SDL и OpenGL для D.

Любые идеи о том, что здесь происходит здесь?

Edit: На будущее, вот решение моей проблемы:

http://www.opengl.org/wiki/Common_Mistakes#Creating_a_Texture

мне нужно, чтобы установить пару параметров перед вызовом glTexImage2D или иначе моя текстура была технически неполным. Добавление следующие четыре строки непосредственно перед тем, что вызов сделал трюк:

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_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
+0

3-й параметр glTexImage, «формат» IS NOT байтов на пиксель. Исторически значения 1, 2, 3, 4 были приняты OpenGL-1.0. Начиная с OpenGL-1.1 и далее параметр формата принимает только четко определенные токены, такие как GL_RGBA, GL_RGB и т. Д., Какое числовое значение не имеет отношения к фактическому формату. – datenwolf

+0

Пожалуйста, забудьте о концепции «OpenGL initialization». Да, вы загружаете текстуры и прочее, но в любом реальном приложении это не одно время, но происходит по требованию. Все состояние рендеринга, то есть проекция, прозрачный цвет, область просмотра и т. Д., Должны быть установлены прямо до того, как они понадобятся в процедуре визуализации. Все материалы, которые вы разместили в разделе «Код инициализации OpenGL», относятся к началу раздела «Код визуализации». – datenwolf

+0

@ datenwolf: Полученные очки. Что касается вашего первого комментария, документы, которые я использовал, должны быть устаревшими, поэтому я буду обновлять вызов, чтобы использовать одно из значений переименования OpenGL. Что касается второго комментария, я думаю, что в моем конкретном приложении уместно объединить такие вещи, как проекция, просмотр и т. Д. В код инициализации, но только потому, что мое конкретное приложение использует только одну перспективу сцены (просто статическое 2D-представление, Я могу сделать 2D-чертеж с аппаратным ускорением). Я определенно вижу вашу точку зрения. – jgottula

ответ

7

Общей ошибкой является создание/использование неполной текстуры, см. here.

Ваш код не показывает вызов:

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR/*or GL_NEAREST*/); 
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*or GL_NEAREST*/); 

, а также не показывает создание MIPMAP.

Возможно, проблема связана с неполностью вашей текстурой.

+0

Вау, ты совершенно прав. После добавления четырех строк, перечисленных на связанной странице, текстура теперь отображается полностью, как предполагалось. Спасибо, что вел меня в правильном направлении! – jgottula

+0

Интересно, почему glGetError ничего не указывал после glTexImage2D; возможно, его доступные коды ошибок просто не покрывают такого рода вещи. В любом случае, по крайней мере, у меня сейчас есть что-то работающее, поэтому я могу беспокоиться о mipmaps или других модификациях позже. – jgottula

+0

hm, glTexImage2D не может указывать/обнаруживать ошибку, поскольку она используется для построения текстуры, а во время процесса она является «законной» для неполной текстуры. Возможно, «glBindTexture» может обнаружить это как ошибку, но я не уверен, как с шейдерами, если вы проецируете текстуру только в mipmap 0, она может работать (не проверена). Когда вы много раз укусили эту проблему, вы привыкли к ней;) – rotoglup

0

бы вам не нужно в функции paintGL в glOrtho(0., 800, 600, 0., 0., 1.);?

+0

Довольно уверен, что это не так, потому что я определенно получаю экранный белый квадрат. Проблема glOrtho была бы проблемой с позицией/ориентацией сцены, правильно? – jgottula

1

Просто неопределенная теория здесь: вы пробовали рисовать вершины против часовой стрелки, а не по часовой стрелке?

glTexCoord2i(0, 0); glVertex2i(0, 0); 
glTexCoord2i(0, 1); glVertex2i(0, 64); 
glTexCoord2i(1, 1); glVertex2i(64, 64); 
glTexCoord2i(1, 0); glVertex2i(64, 0); 
+0

Просто перекомпилирован с изменением направления; такой же сделка. :( – jgottula

+0

Есть ли причина для вызова glBindTexture в коде загрузки текстуры (по крайней мере, в том месте, в котором он находится)? Я бы подумал, что это произойдет после вызова glTexImage2D - прошло некоторое время с тех пор, как я работал с OpenGL, хотя – Xono

+0

@Xono: Насколько мне известно, вызов 'glBindTexture' сообщает автору состояния OpenGL« мы сейчас работаем с этой текстурой », а вызов' glTexImage2D' неявно понимает, что он должен применяться к текстуре, связанной в данный момент. если я ошибаюсь, конечно. – jgottula

0

Старайтесь включать GL_COLOR_MATERIAL? Я не использовал конвейер с фиксированной функциональностью, но я думаю, что это возможно.

+0

Я добавил 'glEnable (GL_COLOR_MATERIAL)' в мой код инициализации, но, к сожалению, он, похоже, не помогает. – jgottula

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