Witam,
Mam problem związany z OpenGL i nie wiem jak go "ugryźć".
Ładuję teksturę monochromatyczną 16-bitową do maszynki jako teksturę, i wyświetla mi go poprawnie.
Poprawnie - to na razie tyle powiedziane. Docelowo chciałbym, aby maszynka mogła wyświetlić teksturę w następujący sposób:
Zadaję dwa parametry wejściowe (X1 i X2) z zakresu 0-65535 (16 bitów). Maszynka na podstawie tych parametrów wyświetla teksturę w taki sposób, aby wszystkie wartości poniżej X1 były wyświetlane jako czarne, a powyżej X2 - jako białe. Zakres pośredni ma być przeskalowany do głębi bitowej monitora (najczęściej jest to 8 bitów).
W jaki sposób mogę to zrobić?
Poniżej przedstawiam całą procedurę ładowania OpenGL i tekstury:
Tworzenie formy (na samym początku):
procedure TForm1.FormCreate(Sender: TObject);
var
DC:HDC;
RC:HGLRC;
begin
OsX:=0;
OsY:=0;
OsZ:=-5;
Obrot:=0;
// dla Open GL
DC:=GetDC(Panel1.Handle);
SetupPixelFormat(DC); //wywołanie procedury odpowiedzialnej za ustawienie formatu pikseli
RC:=wglCreateContext(DC); //makes OpenGL window out of DC
wglMakeCurrent(DC, RC); //makes OpenGL window active
GLInit; //wywołanie procedury inicjalizującej maszynę stanów OpenGL
end;
Ustawienie formatu pikseli:
procedure TForm1.setupPixelFormat(DC:HDC);
const
pfd:TPIXELFORMATDESCRIPTOR = (
nSize:sizeof(TPIXELFORMATDESCRIPTOR); //rozmiar struktury - opisuje rozmiar struktury przekazywanych za pomocą wskaźnika, służy do określenia wielkości pamięci zajmowanej przez strukturę. Umieszczenie w pierwszym polu umożliwia szybkie pobranie przez deferencję wskaźnika.
nVersion:1; //zawsze wartość 1
dwFlags:PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER; //znaczniki właściwości bufora pikseli - określa właściwości bufora pikseli (PFD_DRAW_TO_WINDOW ? umożliwia tworzenie grafiki w oknie, PFD_SUPPORT_OPENGL ? umożliwia tworzenie grafiki opengl, PFD_DOUBLEBUFFER ? podwójne buforowanie /wyklucza się ze znacznikiem PFD_SUPPORT_GDI/, PFD_SWAP_LAYER_BUFFERS ? urządzenie może przełączać pojedyncze plany warstw z formatami pikseli o podwójnym buforowaniu /w przeciwnym razie wszystkie plany warstw przełączane są grupowo/; jeśli znacznik jest ustawiony, to dostępna jest funkcja wglSwapLayerBuffers, PFD_DEPTH_DONTCARE ? dla danego formatu pikseli może być wykorzystywany bufor głębi, PFD_DOUBLEBUFFER_DONTCARE ? piksele mogą być buforowane pojedynczo lub podwójnie),
iPixelType:PFD_TYPE_RGBA; //typ danych piksela - określa typ danych piksela (PFD_TYPE_RGBA ? piksele opisane w standardzie RGBA czyli dla każdego piksela określony jest kolor czerwony, zielony, niebieski oraz współczynnik alfa, PFD_TYPE_COLORINDEX ? piksele opisane są za pomocą wartości indeksu koloru),
cColorBits:24; //liczba bitów piksela - opisuje liczbę bitów określających kolor piksela i może przyjmować wartości 8, 16, 24 i 32. W przypadku gdy karta grafiki nie umożliwia reprezantacji koloru pikseli za pomocą danej liczby bitów to przyjmowana jest jej największa możliwa wartość.
cRedBits:0; //liczba bitów koloru czerwonego oraz
cRedShift:0; //przesunięcie bitów koloru czerwonego
cGreenBits:0; //liczba bitów koloru zielonego
cGreenShift:0; //przesunięcie bitów koloru zielonego
cBlueBits:0; //liczba bitów koloru niebieskiego
cBlueShift:0; //przesunięcie bitów koloru niebieskiego
cAlphaBits:0; //liczba bitów alfa
cAlphaShift:0; //przesunięcie bitów alfa
cAccumBits: 0; //liczba bitów bufora akumulacji
cAccumRedBits: 0; //liczba bitów akumulacji czerni
cAccumGreenBits: 0; //liczba bitów akumulacji zieleni
cAccumBlueBits: 0; //liczba bitów akumulacji błękitu
cAccumAlphaBits: 0; //liczba bitów akumulacji alfa
cDepthBits:16; //liczba bitów bufora głębi
cStencilBits:0; //liczba bitów bufora powielania
cAuxBuffers:0; //liczba buforów pomocniczych
iLayerType:PFD_MAIN_PLANE; //nie jest już wykorzystywany
bReserved: 0; //liczba podkładanych i nakładanych jednostek
dwLayerMask: 0; //nie jest już wykorzystywany
dwVisibleMask: 0; //indeks podłożonej płaszczyzny
dwDamageMask: 0; //nie jest już wykorzystywany
);
var
pixelFormat : integer;
begin
//ustawienie formatu pikseli
pixelFormat := ChoosePixelFormat(DC, @pfd);
if (pixelFormat = 0) then
exit;
if (SetPixelFormat(DC, pixelFormat, @pfd) <> TRUE) then
exit;
end;
Inicjalizacja maszynki:
procedure TForm1.GLInit();
var
Tablica:PTablica2Word;
Tab:PTablica1Word;
Wys,Szer:Cardinal;
pData:Pointer;
p:Pointer;
i,j:Integer;
Krok:Cardinal;
begin
glMatrixMode(GL_PROJECTION);
//glOrtho(0, ClientWidth, 0, ClientHeight, 0, 128);
glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
//ładowanie pliku 3.tiff
New(Tablica);
TIFFForm.LoadFile('3.tiff',Tablica,True); //moduł ładujący plik 16-bitowy tiff do tablicy dwuwymiarowej
TablicaRozmiar(Tablica,Szer,Wys);
New(Tab);
SetLength(Tab.Dane,Szer*Wys);
Krok:=0;
//wsadzanie danych do bufora
For i:=0 to Wys-1 do
Begin
For j:=0 to Szer-1 do
Begin
Tab.Dane[Krok]:=Tablica.Dane[j,i];
Inc(Krok);
End;
End;
//przypisanie pointera
pData:=Pointer(@Tab.Dane[0]);
CreateTexture(Szer,Wys,pData);
Dispose(Tab);
Dispose(Tablica);
//ShowMessage(TimerStop);
Draw();
end;
Tworzenie tekstury:
function TForm1.CreateTexture(Width,Height:Word;pData:Pointer):Cardinal;
Begin
glGenTextures(1, Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//Result:=gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pData); // - gdy ładujemy zwykły RGB 8 bitów na kanał
//Result:=gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB16, Width, Height, GL_RGB, GL_UNSIGNED_SHORT, pData); // - gdy wsadzamy RGB 16 bitów na kanał
Result:=gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE16, Width, Height, GL_LUMINANCE, GL_UNSIGNED_SHORT, pData); // - gdy wsadzamy Mono 16 bitów
If Result<>0 then
Begin
ShowMessage(gluErrorString(Result));
End;
end;
Rysowanie:
procedure TForm1.Draw();
begin
Application.ProcessMessages;
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(OsX,0,0);
glTranslatef(0,OsY,0);
glTranslatef(0,0,OsZ);
glRotate(Obrot,0,1,0);
glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, Texture);
glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 0.0);
glEnd();
SwapBuffers(wglGetCurrentDC);
end;
Bardzo dziękuję za wszelkie wskazówki.