Решил заняться самообразованием в области OpenGL. На opengl.org почитал спецификацию, взялся за Red Book и решил параллельно устроить себе типа курса лабораторных работ, правда примеры не прямо из редбука, а взял заготовку простейшего оконного Win32 приложения на асме и начал экспериментировать в нем, постепенно добавляя изучаемые в редбуке фичи в прогу. Получение OpenGL-контекста, примитивы, цвета, матричные преобразования, материалы, освещение, блендинг, битмапы и имиджи прошли нормально. Споткнулся на текстурах. Упорно не хочет отображаться. Стал проверять glGetError после каждой относящейся к текстурированию команды - нет ошибок. Прочитал через glGetTexImage уже загруженную текстуру в другой массив в другом формате (специально, чтоб не сработало как просто тупое копирование) и отобразил прочитанное через glDrawPixels - отобразилось правильно, значит текстура загрузилась. Как ни бьюсь - рисуется подсвещенный белый прямоугольник без каких-либо признаков текстурирования. Пробовал выключать блендинг, освещение - не помогает. Третий день бьюсь. Больше идей нет. Подскажите, в каком месте у меня в ДНК ошибка? Инициализационная часть (сразу после получения контекста): Код (Text): invoke glEnable,GL_NORMALIZE invoke glEnable,GL_DEPTH_TEST invoke glDepthFunc,GL_LEQUAL invoke glEnable,GL_BLEND invoke glBlendFunc,GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA invoke glEnable,GL_LIGHTING invoke glLightModeli,GL_LIGHT_MODEL_TWO_SIDE,TRUE invoke glLightModeli,GL_LIGHT_MODEL_LOCAL_VIEWER,TRUE invoke glMatrixMode,GL_PROJECTION invoke glLoadIdentity invoke glFrustum,DWORD PTR frustLeft,DWORD PTR frustLeft+4,DWORD PTR frustRight,DWORD PTR frustRight+4,DWORD PTR frustBottom,DWORD PTR frustBottom+4,DWORD PTR frustTop,DWORD PTR frustTop+4,DWORD PTR frustNear,DWORD PTR frustNear+4,DWORD PTR frustFar,DWORD PTR frustFar+4 invoke glMatrixMode,GL_MODELVIEW invoke glLoadIdentity Загрузка и настройка текстуры: Код (Text): invoke glPixelStorei,GL_UNPACK_ALIGNMENT,1 invoke glTexImage2D,GL_TEXTURE_2D,0,3,64,64,0,GL_RGB,GL_UNSIGNED_BYTE,ADDR testTexture invoke glTexParameteri,GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT invoke glTexParameteri,GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT invoke glTexParameteri,GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST invoke glTexParameteri,GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST invoke glTexEnvf,GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL invoke glShadeModel,GL_SMOOTH Кусок функции рисования (рисующий примитив, на который хочу натянуть текстуру): Код (Text): invoke glMaterialfv,GL_FRONT_AND_BACK,GL_SPECULAR,ADDR whiteColor invoke glMaterialfv,GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,ADDR whiteColor invoke glNormal3f,0,0,flt1 invoke glEnable,GL_TEXTURE_2D invoke glBegin,GL_QUADS invoke glTexCoord2f,0,0 invoke glVertex3fv,ADDR whtSheetP1 invoke glTexCoord2f,flt1,0 invoke glVertex3fv,ADDR whtSheetP2 invoke glTexCoord2f,flt1,flt1 invoke glVertex3fv,ADDR whtSheetP3 invoke glTexCoord2f,0,flt1 invoke glVertex3fv,ADDR whtSheetP4 invoke glEnd invoke glFlush invoke glDisable,GL_TEXTURE_2D здесь flt1 dd 1.0
Простота результата не означает простоты решения!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! КТО ВАМ СКАЗАЛ, что огл будет угадывать ваши желания? Графику нужно грузить в память самостоятельно. Ну в крайнем случае либами. Код (Text): ifndef _BMP_ASM _BMP_ASM equ 1 ; ------------------------------------------------------ ; Includes include Files.asm ; ------------------------------------------------------ ; Structures BMP struct _Datas dword ? _Width dword ? _Height dword ? _Bits dword ? BMP ends ; ------------------------------------------------------ ; Name: Load_BMP ; Desc: Load a 24 or 32 bits BMP file into memory Load_BMP proc uses ebx esi edi BMP_FName:dword, BMP_Struct:dword, Color_Key:dword local BMP_Buffer:dword local FSize:dword local DatOffset:dword local _Modulo:dword local _Width:dword local _Height:dword mov esi, BMP_Struct mov [esi + BMP._Datas], NULL ; Load texture into memory invoke Load_File, BMP_FName, addr FSize test eax, eax jz Err_BMP_Load mov BMP_Buffer, eax ; Decode the BMP file mov ebx, eax mov edi, eax mov ax, "MB" cmp word ptr [edi + BITMAPFILEHEADER.bfType], ax jne Err_BMP_Format mov eax, FSize cmp dword ptr [edi + BITMAPFILEHEADER.bfSize], eax jne Err_BMP_Format mov DatOffset, CMEM([edi + BITMAPFILEHEADER.bfOffBits]) lea edi, [edi + sizeof BITMAPFILEHEADER] mov eax, dword ptr [edi + BITMAPINFOHEADER.biWidth] test eax, eax js Err_BMP_Format jz Err_BMP_Format ; Fix the raster lines stuff mov [esi + BMP._Width], eax mov _Width, eax imul eax, 3 cdq mov ecx, 4 idiv ecx xchg edx, eax mov _Modulo, 0 .if eax != 0 sub ecx, eax mov _Modulo, ecx .endif movzx eax, word ptr [edi + BITMAPINFOHEADER.biHeight] test eax, eax js Err_BMP_Format jz Err_BMP_Format mov [esi + BMP._Height], eax mov _Height, eax movzx eax, word ptr [edi + BITMAPINFOHEADER.biBitCount] mov [esi + BMP._Bits], eax cmp eax, 24 ; Must be 24 bits (bottom left) je GoodTextureFormat cmp eax, 32 ; or 32 bits je GoodTextureFormat Err_BMP_Format: FREEMEM BMP_Buffer Err_BMP_Load: xor eax, eax ; Not loaded ret GoodTextureFormat: mov eax, [esi + BMP._Width] imul eax, [esi + BMP._Height] push eax shl eax, 2 mov eax, ALLOCMEM(eax) pop ecx test eax, eax jz Err_BMP_Format mov [esi + BMP._Datas], eax mov edi, eax mov eax, DatOffset .if [esi + BMP._Bits] == 32 lea esi, [ebx + eax] ; 24 bits image datas mov ecx, _Height Loop_32Bits_Y: push ecx mov ecx, _Width Loop_32Bits_X: lodsb ror eax, 8 lodsb ror eax, 8 lodsb ror eax, 8 lodsb bswap eax and eax, 000ffffffh mov edx, Color_Key test edx, edx js _No_Set_Alpha_32 and edx, 000ffffffh cmp edx, eax jne _No_Set_Alpha_32 mov eax, 0ff000000h ; Turn alpha channel on for this color _No_Set_Alpha_32: xor eax, 0ff000000h stosd loop Loop_32Bits_X pop ecx loop Loop_32Bits_Y .else lea esi, [ebx + eax] ; 24 bits image datas mov ecx, _Height Loop_24Bits_Y: push ecx mov ecx, _Width Loop_24Bits_X: or eax, -1 lodsb shl eax, 8 lodsb shl eax, 8 lodsb and eax, 000ffffffh mov edx, Color_Key test edx, edx js _No_Set_Alpha_24 and edx, 000ffffffh cmp edx, eax jne _No_Set_Alpha_24 mov eax, 0ff000000h ; Turn alpha channel on for this color _No_Set_Alpha_24: xor eax, 0ff000000h stosd loop Loop_24Bits_X add esi, _Modulo pop ecx loop Loop_24Bits_Y .endif FREEMEM BMP_Buffer mov eax, TRUE ; Loaded ret Load_BMP endp ; ------------------------------------------------------ ; Name: Unload_BMP ; Desc: Free an allocated BMP picture Unload_BMP proc uses esi BMP_Struct:dword mov esi, BMP_Struct test esi, esi jz @F mov eax, [esi + BMP._Datas] test eax, eax jz @F FREEMEM eax @@: ret Unload_BMP endp endif Это часть исходников Франка Чарлета (Franck Charlet) Качайте с WASM-а и будет вам счастье.
Если Вы про заполнение того массива данных, который я подставляю в glTexImage2D для загрузки текстуры, то конечно же я его заполнил. Просто здесь не показал. Правда заполнял я его не из BMP или какого-либо другого файла, а просто пока для примера руками нарисовал в нем шахматную доску, поскольку формат вполне простой и понятный - GL_RGB,GL_UNSIGNED_BYTE - подряд по три байта для каждого тексела, построчно тексел за текселом, выравнивание строк побайтное, так что без всяких пропусков. И если верить вызываемым после glTexImage2D для проверки функциям glGetTexImage и glDrawPixels - эта шахматная доска занеслась в качестве текстуры успешно, поскольку прочитанная в другой буфер И В ДРУГОМ ФОРМАТЕ (четырехбайтовый GL_RGBA), она на экране (как результат glDrawPixels) отобразилась правильно. Собственно, именно так и в примере в редбуке сделано - шахматная доска, сформированная вручную.
Попробуйте закомментировать Код (Text): ;В части инициализации ; invoke glEnable,GL_NORMALIZE ; invoke glEnable,GL_DEPTH_TEST ; invoke glDepthFunc,GL_LEQUAL ; invoke glEnable,GL_BLEND ; invoke glBlendFunc,GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA ; invoke glEnable,GL_LIGHTING ; invoke glLightModeli,GL_LIGHT_MODEL_TWO_SIDE,TRUE ; invoke glLightModeli,GL_LIGHT_MODEL_LOCAL_VIEWER,TRUE ; invoke glFrustum,DWORD PTR frustLeft,DWORD PTR frustLeft+4,DWORD PTR frustRight,DWORD PTR frustRight+4,DWORD PTR frustBottom,DWORD PTR frustBottom+4,DWORD PTR frustTop,DWORD PTR frustTop+4,DWORD PTR frustNear,DWORD PTR frustNear+4,DWORD PTR frustFar,DWORD PTR frustFar+4 ; invoke glLoadIdentity ;В части отрисовки: ; invoke glMaterialfv,GL_FRONT_AND_BACK,GL_SPECULAR,ADDR whiteColor ; invoke glMaterialfv,GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,ADDR whiteColor ; invoke glNormal3f,0,0,flt1 Естественно, при этом поправьте координаты вертексов, чтоб на экран влезали. Что-то подсказывает, что либо текстура выводится, но не тем размером, каким хотелось бы, либо ее из-за лайтинга/блендинга "засвечивает", либо с нормалями чего-то не то (кстати, в оригинале из RedBook нормалей нет). А вообще, давайте весь исходник! Вместе с генерацией текстуры, и вообще, чтоб можно было в компилятор сунуть.
Вот, вообще все лишнее убрал, только окно, один прямоугольник и текстура. Справа сверху от прямоугольника - просто вывод прочитанного обратно из текстуры для проверки того, что картинка текстуры правильно создана и загрузилась. Сам прямоугольник по прежнему остается белым, хотя вроде должен быть текстурированным.
Волшебство таилось вот тут: Код (Text): invoke glTexEnvi,GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL вместо glTexEnvf. Нет, это не опечатка, полагаю, в RedBook - просто С++ нормально преобразует константу к плавающему виду. Ну а нам, кабанам... в данном случае интегеры самое оно.
FatMoon Скорее таки опечатка. glTexEnvf нужен для установки флоатного параметра. А енам-параметры все ставят через glTexEnvi. То, что токен из флоата преобразовался в инт, и во внутрях подошел под нужный кейс - это конечно работает, но это удаление гланд в кабинете проктолога.
FatMoon, А, ГЕНИЙ!! Блин, а ведь в одном месте я уже на подобное наступил, тоже было f вместо i и целочисленная константа, автоматически преобразовывавшаяся в СИ, но конечно же неизменная в асме. Но там нашлось через glGetError, а тут glGetError сказал, что все ОК, сцука такой :-? FatMoon, огромное спасибо! Тема исчерпана.
К сожалению проктологом оказался автор официального редбука , на который официальная ссылка c официального сайта opengl.org. У него и в других местах такие же вещи есть, только там мне glGetError подсказал, где нечисто, а тут промолчал, ну а я по природной невнимательности не заметил :-/