Poniższa funkcja powinna być wywołana w konstruktorze (zob. źródła w OpenGL_shader_BCB.zip): if (isShaderAvailable) Shader(); Ustalanie wartości zmiennej isShaderAvailable - zob. OpenGL_rozszerzenia.txt Uwagi! 1) Zmiana shaderów w plikach shader.vsh (vertex shader) i shader.psh (pixel/fragment shader) nie wymaga ponownej kompilacji projektu. 2) Aby wyłączyć vertex shader lub pixel shader wystarczy zakomentować instrukcje wywołujące funkcje glAttachObjectARB (doczepiające shader do programu). 3) Aby wyłączyć komunikaty należy przełączyć stałą ShowDebug na false. Moze ona wygladac np. tak: const bool ShowDebug=true; void __fastcall ShowDebugInfo(AnsiString tekst) { if (ShowDebug) ShowMessage(tekst); } 4) Dodatkowe kody shaderów (m.in. przykłady z superbible) znajdują się w podkatalogu shadery (w źródłach) ---------------- void __fastcall TForm1::Shader() { //deklaracja funkcji wyswietlajacej mniej wazne komunikaty void __fastcall ShowDebugInfo(AnsiString tekst); //Pobieranie adresow funkcji //funkcje obiektow shaderow PFNGLCREATESHADERPROC glCreateShader=(PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader"); PFNGLDELETESHADERPROC glDeleteShader=(PFNGLDELETESHADERPROC)wglGetProcAddress("glDeleteShader"); PFNGLSHADERSOURCEPROC glShaderSource=(PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource"); PFNGLCOMPILESHADERPROC glCompileShader=(PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader"); //obiekty programow PFNGLCREATEPROGRAMPROC glCreateProgram=(PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram"); PFNGLLINKPROGRAMPROC glLinkProgram=(PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram"); PFNGLUSEPROGRAMPROC glUseProgram=(PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram"); //funkcje obiektow (niektore ARB) PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB=(PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB"); PFNGLGETINFOLOGARBPROC glGetInfoLogARB=(PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB"); PFNGLDELETEOBJECTARBPROC glDeleteObjectARB=(PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB"); PFNGLATTACHOBJECTARBPROC glAttachObjectARB=(PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB"); //sprawdzanie czy pobrane adresy if (glCreateShader==NULL || glDeleteShader==NULL || glShaderSource==NULL || glCompileShader==NULL || glCreateProgram==NULL || glLinkProgram==NULL || glUseProgram==NULL || glGetObjectParameterivARB==NULL || glGetInfoLogARB==NULL || glDeleteObjectARB==NULL || glAttachObjectARB==NULL) { ShowMessage("Uwaga! Pobranie adresu funkcji shaderów nie powiodło się"); return; } else ShowDebugInfo("Pobranie adresu funkcji shaderów powiodło się"); /* Vertex shader */ //Tworzenie obiektu shadera GLhandleARB vsh=glCreateShader(GL_VERTEX_SHADER); if(vsh!=NULL) ShowDebugInfo("Utworzenie obiektu shadera powiodło się"); else { ShowMessage("Uwaga! Utworzenie obiektu shadera nie powiodło się"); return; } //Czytanie kodu shadera z pliku TStringList* kodShadera=new TStringList(); kodShadera->LoadFromFile("shader.vsh"); /*if (CzytajPlikTxt("VertexShader1.txt",kodShadera)==NULL) ShowMessage("Uwaga! Wczytanie kodu shadera z pliku nie powiodło się");*/ ShowDebugInfo("Kod vertex shadera:\n\n"+kodShadera->Text); /* char* CzytajPlikTxt(char* nazwaPliku,int rozmiarBufora,char* bufor); char kod[1024]; CzytajPlikTxt("shader.vsh",1024,kod); ShowDebugInfo(kod); */ //Dostarczanie zrodla do obiektu shadera const GLchar* zrodlo[1]; zrodlo[0]=kodShadera->GetText(); //zrodlo[0]=kodShadera->Text.c_str(); glShaderSource(vsh,1,zrodlo,NULL); //Kompilacja kodu shadera glCompileShader(vsh); //Weryfikacja kompilacji GLint powodzenie; glGetObjectParameterivARB(vsh,GL_OBJECT_COMPILE_STATUS_ARB,&powodzenie); if (powodzenie) ShowDebugInfo("Kompilacja shadera powiodła się"); else { const int maxInfoLogSize=2048; GLbyte infoLog[maxInfoLogSize]; glGetInfoLogARB(vsh,maxInfoLogSize,NULL,infoLog); ShowMessage((AnsiString)"Uwaga! Kompilacja shadera nie powiodła się:\n"+(char*)infoLog); } /* Pixel/Fragment Shader */ GLhandleARB psh=glCreateShader(GL_FRAGMENT_SHADER); kodShadera->Clear(); kodShadera->LoadFromFile("shader.psh"); ShowDebugInfo("Kod pixel shadera:\n\n"+kodShadera->Text); zrodlo[0]=kodShadera->GetText(); glShaderSource(psh,1,zrodlo,NULL); glCompileShader(psh); glGetObjectParameterivARB(psh,GL_OBJECT_COMPILE_STATUS_ARB,&powodzenie); if (powodzenie) ShowDebugInfo("Kompilacja pixel shadera powiodła się"); else ShowMessage("Uwaga! Kompilacja pixel nie shadera powiodła się"); /* Obiekt programu */ //tworzenie obiektu programu GLhandleARB program=glCreateProgram(); //przylaczanie shaderow glAttachObjectARB(program,vsh); //odlaczanie: glDetachObjectARB glAttachObjectARB(program,psh); //linkowanie (konsolidacja) programu glLinkProgram(program); glGetObjectParameterivARB(program,GL_OBJECT_LINK_STATUS_ARB,&powodzenie); if (powodzenie) ShowDebugInfo("Linkowanie programu powiodło się"); else { const int maxInfoLogSize=2048; GLbyte infoLog[maxInfoLogSize]; glGetInfoLogARB(program,maxInfoLogSize,NULL,infoLog); ShowMessage((AnsiString)"Uwaga! Linkowanie programu nie powiodło się:\n"+(char*)infoLog); } //walidacja programu z uwglednieniem aktualnego stanu aplikacji i biblioteki OpenGL glGetObjectParameterivARB(program,GL_OBJECT_VALIDATE_STATUS_ARB,&powodzenie); if (powodzenie) ShowDebugInfo("Walidacja programu powiodła się"); else { const int maxInfoLogSize=2048; GLbyte infoLog[maxInfoLogSize]; glGetInfoLogARB(program,maxInfoLogSize,NULL,infoLog); ShowMessage((AnsiString)"Uwaga! Walidacja programu nie powiodła się:\n"+(char*)infoLog); } //uzycie programu glUseProgram(program); //Usuwanie obiektow //usuniecie obiektu shadera nie zwolni wiazania, obiekt zostanie usuniety gdy przestanie byc uzywany glDeleteShader(vsh); glDeleteShader(psh); glDeleteObjectARB(program); }