Решено: Черная полоса при выводе текстур OpenGL в Lazarus

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Решено: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение Alex. S » 22.08.2015 11:48:08

Обновление: После долгих тестов, и переписывания кода на C, проблема была найдена - неисправность драйвера видеокарты, которая приводит к таким фокусам в OpenGL...

Здравствуйте.
Использовал код примеров NeHe для Delphi, переписав его под Lazarus. Но, почему-то при компиляции помимо выводимых текстур появляется черная полоса, причем, при каждом запуске ее расположение меняется.
Скажите, в чем может быть проблема?

Архив с программой | Скриншот

Код программы:
Код: Выделить всё
program Beta;

{$MODE ObjFPC}
{$APPTYPE gui}

uses
  //
  GL, FreeImage, Windows;

const
  //
  TexturesCount = 2;

// Textures.
  //
  BackgroundTex = 0;
  //
  LogoTex       = 1;

  //
  TexturesNames: array [0..1] of String = (
    //
    'bg', 'title');

type
  //
  PByteArray = ^TByteArray;
  //
  TByteArray = array [Word] of Byte;

var
//
h_Rc: HGLRC;
//
h_Dc: HDC;
//
h_Wnd: HWND;
//
Keys: array [0..255] of Boolean;
//
Active: Boolean = True;
//
FullScreen: Boolean;

//
MenuStage: Byte;
//
Textures: array of GLuint;

//
procedure LoadTexture(
  FileName: AnsiString; var Texture: GLuint);
const
//
AlphaGreenMask = $FF00FF00;
//
ThirdByteMask  = $FF0000;
//
FirstByteMask  = $FF;
var
//
dib: PFIBITMAP; w, h: Cardinal;
//
Data: PByteArray; Dest, Src: Pointer;
begin
//
FileName:='Data\' + FileName + '.png';

//
dib:=FreeImage_Load(FIF_PNG, PChar(FileName));
//
if dib = nil then Exit;
//
FreeImage_FlipVertical(dib);
//
dib:=FreeImage_ConvertTo32Bits(dib);
//
w:=FreeImage_GetWidth(dib);
//
h:=FreeImage_GetHeight(dib);
//
GetMem(Data, 4 * w * h);
//
Dest:=Data;
//
Src:=FreeImage_GetBits(dib);

//
{$ASMMODE Intel}
  asm
//
push esi
//
push edi
//
push eax
//
push ebx
//
push ecx
//
push edx

//
mov esi, [Src]
//
mov edi, [Dest]

//
xor eax, eax
//
mov eax, w
//
mul h


@Move4Bits:
//
mov ebx, [esi]
//
mov ecx, ebx
//
and ecx, ThirdByteMask
//
shr ecx, 16
//
mov edx, ebx
//
and edx, FirstByteMask
//
shl edx, 16
//
mov dl, cl
//
and ebx, AlphaGreenMask
//
add ebx, edx
//
mov [edi], ebx
//
add esi, 4
//
add edi, 4

//
dec eax
//
jnz @Move4Bits

//
pop edx
//
pop ecx
//
pop ebx
//
pop eax
//
pop edi
//
pop esi

//
emms
  end;

//
FreeImage_Unload(dib);

//
glBindTexture(GL_TEXTURE_2D, Texture);

//
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//
w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, Data);

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

//
glEnable(GL_TEXTURE_2D);

//
FreeMem(Data, w * h * 4);
//
Data:=nil;
end;

procedure LoadTextures;
var
i, k: Byte;
begin
//
SetLength(Textures, TexturesCount);

//
k:=TexturesCount - 1;

//
for i:=0 to k do
  begin
//
glGenTextures(1, @Textures[i]);
//
LoadTexture(TexturesNames[i], Textures[i]);
  end;
end;

//
procedure ReSizeGLScene(Width: GLsizei; Height: GLsizei);
begin
//
if Height = 0 then Height:=1;
//
glViewport(0, 0, Width, Height);
//
glMatrixMode(GL_PROJECTION);
//
glLoadIdentity;

//
glMatrixMode(GL_MODELVIEW); 
//
glLoadIdentity;
end;

//
procedure LoadData;
begin
//
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//
LoadTextures;
end;

procedure FreeTextures;
var
i, k: Byte;
begin
//
k:=TexturesCount - 1;

//
for i:=0 to k do
//
glDeleteTextures(1, @Textures[i]);
end;

procedure FreeData;
begin
//
FreeTextures;
end;

function InitGL: Boolean;
begin
//
LoadData;

//
Result:=True;
end;

procedure PreRender;
begin
//
glMatrixMode(GL_PROJECTION);
//
glLoadIdentity;
//
glOrtho(0, 800, 600, 0, 0, 1);
//
glMatrixMode(GL_MODELVIEW);
//
glLoadIdentity;

//
glBindTexture(GL_TEXTURE_2D, Textures[BackgroundTex]);
//
glBegin(GL_QUADS);
//
glTexCoord2f(0, 0);
//
glVertex2f(0,   0);
//
glTexCoord2f(1, 0);
//
glVertex2f(800, 0);
//
glTexCoord2f(1, 1);
//
glVertex2f(800, 600);
//
glTexCoord2f(0, 1);
//
glVertex2f(0,   600);
//
glEnd;

//
glBindTexture(GL_TEXTURE_2D, Textures[LogoTex]);
//
glBegin(GL_QUADS);
//
glTexCoord2f(0, 0);
//
glVertex2f(304,   68);
//
glTexCoord2f(1, 0);
//
glVertex2f(495, 68);
//
glTexCoord2f(1, 1);
//
glVertex2f(495, 150);
//
glTexCoord2f(0, 1);
//
glVertex2f(304, 150);
//
glEnd;
end;

function glDraw: Boolean;
begin
//
glViewport(0, 0, 800, 600);
//
glColor3f(1, 1, 1);
//
glClearColor(0, 0, 0, 0);
//
glClearDepth(1);
//
glClear(GL_COLOR_BUFFER_BIT or
  GL_DEPTH_BUFFER_BIT);

//
PreRender;

//
Result:=True;
end;

function WndProc(hWnd: HWND;
  message: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
//
if message = WM_SYSCOMMAND then
  begin
//
    case wParam of
//
SC_SCREENSAVE, SC_MONITORPOWER:
      begin
//
Result:=0;
//
Exit;
      end;
    end;
  end;

  case message of
//
WM_ACTIVATE:
    begin
//
if HiWord(wParam) = 0 then Active:=True else Active:=False;
//
Result:=0;
    end;

//
WM_CLOSE:
    begin
//
FreeData;
//
PostQuitMessage(0);
//
Result:=0;
    end;

//
WM_KEYDOWN:
    begin
//
Keys[wParam]:=True;
//
Result:=0;
    end;

//
WM_KEYUP:
    begin
//
Keys[wParam]:=False;
//
Result:=0;
    end;

else
//
    begin
//
Result:=DefWindowProc(hWnd, message, wParam, lParam);
    end;
  end;
end;


procedure KillGLWindow;
begin
//
if FullScreen then
  begin
//
ChangeDisplaySettings(devmode(nil^),0);
//
ShowCursor(True);
  end;

//
if h_rc <> 0 then
  begin
if (not wglMakeCurrent(h_Dc,0)) then
MessageBox(0, 'Release of DC and RC failed.', ' Shutdown Error', MB_OK or MB_ICONERROR);
if (not wglDeleteContext(h_Rc)) then
    begin
MessageBox(0, 'Release of Rendering Context failed.', ' Shutdown Error', MB_OK or MB_ICONERROR);
h_Rc:=0;
    end;
  end;

//
if (h_Dc = 1) and (ReleaseDC(h_Wnd, h_Dc) <> 0) then
  begin
MessageBox(0, 'Release of Device Context failed.', ' Shutdown Error', MB_OK or MB_ICONERROR);
h_Dc:=0;
  end;

//
if (h_Wnd <> 0) and (not DestroyWindow(h_Wnd)) then
  begin
MessageBox(0, 'Could not release hWnd.', ' Shutdown Error', MB_OK or MB_ICONERROR);
h_Wnd:=0;
  end;

//
if not (UnregisterClass('OpenGL Window', hInstance)) then
//
MessageBox(0, 'Could Not Unregister Class.', 'SHUTDOWN ERROR', MB_OK or MB_ICONINFORMATION);
end;


function CreateGlWindow(FullScreenflag: Boolean):boolean stdcall;
var
//
Pixelformat: GLuint;
//
wc: TWndclass;
//
dwExStyle: DWord;
//
dwStyle: DWord;
//
pfd: pixelformatdescriptor;
//
dmScreenSettings: Devmode;
//
h_Instance: hinst;
//
WindowRect: TRect;
begin
//
WindowRect.Left:=0;
//
WindowRect.Top:=0;
//
WindowRect.Right:=800;
//
WindowRect.Bottom:=600;
//
h_instance:=GetModuleHandle(nil);
//
FullScreen:=FullScreenflag;

//
with wc do
  begin
//
style:=CS_HREDRAW or CS_VREDRAW or CS_OWNDC;
//
lpfnWndProc:=@WndProc;
//
cbClsExtra:=0;
//
cbWndExtra:=0; 
//
hInstance:=h_Instance;
//
hIcon:=LoadIcon(0, IDI_APPLICATION);
//
hCursor:=LoadCursor(0, IDC_ARROW);
//
hbrBackground:=0;
//
lpszMenuName:=nil;
//
lpszClassName:='OpenGL Window';
  end;

//
if RegisterClass(wc) = 0 then
  begin
MessageBox(0, 'Failed To Register The Window Class.', 'Error', MB_OK or MB_ICONERROR);
Result:=False;
Exit;
  end;
 
//
if FullScreen then
  begin
ZeroMemory(@dmScreenSettings, SizeOf(dmScreenSettings));
with dmScreensettings do
    begin
//
dmSize:=SizeOf(dmScreenSettings);
//
dmPelsWidth:=800;
//
dmPelsHeight:=600;
//
dmBitsPerPel:=32;
//
dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
    end;
//
if (ChangeDisplaySettings(dmScreenSettings, CDS_FullScreen))<>DISP_CHANGE_SUCCESSFUL THEN
    begin
//
if MessageBox(0, 'This FullScreen Mode Is Not Supported. Use Windowed Mode Instead?', 'NeHe GL', MB_YESNO or MB_ICONEXCLAMATION) = IDYES then
FullScreen:=False
else
      begin
//
MessageBox(0, 'Program Will Now Close.', 'Error', MB_OK or MB_ICONERROR);
//
Result:=False;
//
Exit;
      end;
    end;
  end;

//
if FullScreen then
  begin
//
dwExStyle:=WS_EX_APPWINDOW;
//
dwStyle:=WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
//
Showcursor(False);
  end
              else
  begin
//
dwExStyle:=WS_EX_APPWINDOW or WS_EX_WINDOWEDGE;
//
dwStyle:=WS_OVERLAPPEDWINDOW or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
  end;
 
//
AdjustWindowRectEx(WindowRect,dwStyle,False,dwExStyle);
//
H_wnd:=CreateWindowEx(dwExStyle,
  'OpenGL Window',
  'OpenGL',
  dwStyle,
  0, 0,
  WindowRect.Right - WindowRect.Left,
  WindowRect.Bottom - WindowRect.Top,
  0, 0,
  hInstance, nil);

//
if h_Wnd = 0 then
  begin
//
KillGlWindow; 
//
MessageBox(0, 'Window creation error.', 'Error', MB_OK or MB_ICONEXCLAMATION);
//
Result:=False;
//
Exit;
  end;

//
FillChar(pfd,
//
  SizeOf(PIXELFORMATDESCRIPTOR), 0);

//
with pfd do
  begin
//
nSize:=SizeOf(PIXELFORMATDESCRIPTOR);
//
nVersion:=1;
//
dwFlags:=PFD_DRAW_TO_WINDOW
//
   or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
//
iPixelType:=PFD_TYPE_RGBA;
//
cColorBits:=32;
//
cDepthBits:=32;
//
iLayerType:=PFD_MAIN_PLANE;
  end;

//
h_Dc:=GetDC(h_Wnd); 

//
if h_Dc = 0 then
  begin
//
KillGLWindow;
//
MessageBox(0, 'Cant''t create a GL device context.', 'Error', MB_OK or MB_ICONEXCLAMATION);
//
Result:=False;
//
Exit;
  end;

//
PixelFormat:=ChoosePixelFormat(h_Dc, @pfd);
//
if PixelFormat = 0 then
  begin
//
KillGLWindow;
//
MessageBox(0, 'Cant''t Find A Suitable PixelFormat.', 'Error', MB_OK or MB_ICONEXCLAMATION);
//
Result:=False;
//
Exit;
  end;

//
if not SetPixelFormat(h_Dc, PixelFormat, @pfd) then
  begin
//
KillGLWindow;
//
MessageBox(0, 'Cant''t set PixelFormat.', 'Error', MB_OK or MB_ICONEXCLAMATION);
//
Result:=False;
//
Exit;
  end;

//
h_Rc:=wglCreateContext(h_Dc);   

//
if h_Rc = 0 then
  begin
//
KillGLWindow;
//
MessageBox(0, 'Cant''t create a GL rendering context.', 'Error', MB_OK or MB_ICONEXCLAMATION);
//
Result:=False;
//
Exit;
  end;

//
if not wglMakeCurrent(h_Dc, h_Rc) then
  begin
//
KillGLWindow;
//
MessageBox(0, 'Cant''t activate the GL rendering context.', 'Error', MB_OK or MB_ICONEXCLAMATION);
//
Result:=False;
//
Exit;
  end;
 
//
ShowWindow(h_Wnd, SW_SHOW);
//
SetForegroundWindow(h_Wnd);
//
SetFocus(h_Wnd); 
//
ReSizeGLScene(800, 600); 

//
if not InitGl then
  begin
//
KillGLWindow;   
//
MessageBox(0, 'initialization failed.', 'Error', MB_OK or MB_ICONEXCLAMATION);
//
Result:=False;
//
Exit;
  end;
 
//
Result:=True;                                       // Vљe probмhlo v poшбdku
end;

function WinMain: Integer; stdcall;
var
//
WndMsg: TMsg;
//
Done: Boolean;
begin
//
Done:=False;
//
if MessageBox(0, 'Would You Like To Run In FullScreen Mode?', 'Start FullScreen',
MB_YESNO or MB_ICONQUESTION) = IDNO then
//
FullScreen:=False else FullScreen:=True;

//
if not CreateGLWindow(FullScreen) then
  begin
//
Result:=0;
//
Exit;
  end;

//
while not Done do
  begin
//
if PeekMessage(WndMsg, 0, 0, 0, PM_REMOVE) then
    begin
//
if WndMsg.message = WM_QUIT then Done:=True                                // Konec programu
                            else
      begin
//
TranslateMessage(WndMsg);
//
DispatchMessage(WndMsg);
      end;
    end
else
    begin
//
if ((Active) and (not glDraw)) or (Keys[vk_Escape]) then Done:=True
//
                                                    else SwapBuffers(h_Dc);

//
if Keys[vk_F1] then
      begin
//
Keys[vk_F1]:=False;
//
KillGLWindow;
//
FullScreen:=not FullScreen;
//
if not CreateGLWindow(FullScreen) then
//
Result:=0;
      end;
    end;
  end;

//
killGLwindow;
//
Result:=WndMsg.wParam;
end;

{$R *.res}

begin
//
WinMain;
end.
Последний раз редактировалось Alex. S 25.01.2016 20:44:08, всего редактировалось 3 раз(а).
Alex. S
новенький
 
Сообщения: 39
Зарегистрирован: 22.08.2015 11:37:00

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение vitaly_l » 22.08.2015 12:08:16

Попробуйте отключить FreeImage_FlipVertical и FreeImage_ConvertTo32Bits - зачем это нужно?
И подобные априори ненужные операции отключить, т.к. ВОЗМОЖНО сбой при конвертации или повороте.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение Alex. S » 22.08.2015 12:15:15

Проверил при отключении этих функций, полоса появляется всё равно. По-моему, проблема возникает при выводе, загрузка текстур происходит нормально. Только я не могу понять, откуда она берется, и при переходе в полноэкранный режим или выходе из него (F1), она почему-то еще оказывается в разных местах.
Alex. S
новенький
 
Сообщения: 39
Зарегистрирован: 22.08.2015 11:37:00

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение zub » 22.08.2015 12:33:07

Для начала приложте скрин с проблемой
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение Alex. S » 22.08.2015 12:53:42

Изображение
Alex. S
новенький
 
Сообщения: 39
Зарегистрирован: 22.08.2015 11:37:00

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение zub » 22.08.2015 13:02:50

https://www.google.ru/search?q=zfightin ... LAodMiID5A
?
Рисуете 2 квада в одной плоскости? z буфер нужно при этом отключить
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение Alex. S » 22.08.2015 13:21:12

zub, а разве z буфер включен? Я нигде не нашел упоминание об этом.
Alex. S
новенький
 
Сообщения: 39
Зарегистрирован: 22.08.2015 11:37:00

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение zub » 22.08.2015 13:32:50

Разные реализации опенгл ведут себя по разному, если вы чтото не указали при инициализации - будет работать\неработать на усмотрение драйверописателей. Поэтому стоит указывать\инициализировать\включать\выключать - всё что понадобится в дальнейшем, иначе на разных компах возможно будут проблемы - значения по умолчанию могут быть разные
кроме того
cDepthBits:=32;

z буфер создан... Работает он или нет если напрямую не указано как проходит ztest?
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение Alex. S » 22.08.2015 13:39:25

Добавил glDisable(GL_DEPTH_TEST) в функцию InitGL, cDepthBits выставил на 24, полоса появляется всё равно :( Не пойму, откуда она берётся?
Alex. S
новенький
 
Сообщения: 39
Зарегистрирован: 22.08.2015 11:37:00

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение zub » 22.08.2015 13:41:35

добавь glDisable(GL_DEPTH_TEST) куданибудь где контекст уже создан, например непосредственно перед отрисовкой
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение Alex. S » 22.08.2015 13:46:57

Добавил перед glMatrixMode(GL_PROJECTION) в PreRender, полоса осталась :(
Alex. S
новенький
 
Сообщения: 39
Зарегистрирован: 22.08.2015 11:37:00

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение vitaly_l » 22.08.2015 13:47:57

Вообще у Вас какой-то странный пример запуска. Там всё гораздо проще. Возможно Вы взяли пример, когда кто-то придумывал какой-то костыль? Судя по картинке - никаких текстур там нет. А когда нет чёрного квадрата, текстуры есть? Скорее всего система не может подгрузить текстуры и поэтому оно то чёрное то прозрачное...
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение Alex. S » 22.08.2015 13:55:31

Текстуры - это фон и синяя надпись "OpenGL".

Текстуры выводятся нормально, я их подключал по отдельности и даже сохранял в файл.

Полоса появляется сама по себе, причем она может быть в разных местах, иногда ее не видно вообще (наверно в этот момент она отрисовывается за видимыми координатами).
Alex. S
новенький
 
Сообщения: 39
Зарегистрирован: 22.08.2015 11:37:00

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение vitaly_l » 22.08.2015 13:57:52

Возможно это какой-то текст, для которого отсутствует необходимая текстура со шрифтом. Но я могу ошибаться... Но внешне очень похоже... На объект у которого утрачена текстура.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Черная полоса при выводе текстур OpenGL в Lazarus

Сообщение zub » 22.08.2015 14:03:35

У меня ваш пример работает нормально, без каких либо полос. вывод - чтото "недоинициализировано"
Экспериментируйте - разнесите квады, сделайте их непаралельными - причина найдется
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 273

Рейтинг@Mail.ru
cron