Muszę przyznać, że to moja pierwsza implementacja programów cieniujących, wcześniej pracowałem tylko z potokowymi funkcjami; jednakże, chociaż jestem pewien, że wszystko, co zrobiłem, jest poprawne - musi istnieć błąd.OpenGL glLinkProgram zwraca wartość false, ale dziennik informacji jest pusty; wszystko sprawdzone
glLinkProgram(program)
- zwraca GL_FALSE
, gdy pytano o numer GL_LINK_STATUS
. Ponadto, dziennik informacji jest pusty (kiedy wysyłam zapytanie o długość dziennika - jest to 1, który jest terminatorem zerowym dla dokumentów, to się sprawdza). Tak więc błędy linkera i brak dzienników. Ponadto, właśnie odkryłem, że problemy z linkerem pojawiają się, gdy tylko wykorzystam zmienną gl_Position
w vertex shader, zarówno podczas przypisywania, jak i wtedy, gdy używam go do obliczeń. Próbowałem różne warianty shaderów, ale nie udało się wygenerować dzienników - wydaje się, że w każdym momencie jest zwracany GL_FALSE
gl_Position
. Co ciekawe, cieniowanie fragmentów nie powoduje żadnych problemów.
Zarówno shadery fragmentów i wierzchołków kompilują dobrze bez błędów. Kiedy wprowadzam błędy składniowe, są one wykrywane, drukowane, a proces jest przerywany przed utworzeniem programu (więc wydaje się, że działa dobrze). Debugowałem i upewniłem się, że pliki są ładowane poprawnie, źródło jest zakończone null, rozmiary są poprawne, sprawdziłem liczbę załączonych programów po załączniku i jest 2 (poprawny lol). Została usunięta dla jasności, mam metodę checkForErrors()
, która sprawdza i drukuje błędy OpenGL - żadne nie są wykrywane.
Jestem zaskoczony, proszę, pomóżcie! Zostałem tracąc sen nad tym przez 2 dni teraz ...
Jest to kod, aby załadować shader:
FILE *file = fopen(fileName.c_str(), "rb");
if(file == NULL)
{
Log::error("file does not exist: \"" + fileName + "\"");
return NULL;
}
// Calculate file size
fseek(file , 0 , SEEK_END);
int size = ftell(file);
rewind(file);
// If file size is 0
if(size == 0)
{
Log::error("file is empty: \"" + fileName + "\"");
return NULL;
}
char **source = new char*[1];
source[0] = new char[size+1];
source[0][size] = '\0';
// If we weren't able to read the entire file into memory
int readSize = fread(source[0], sizeof(char), size, file);
if(size != readSize)
{
int fileError = ferror(file);
// Free the source, log an error and return false
delete source[0];
delete [] source;
fclose(file);
Log::error("couldn't load file into memory [ferror(" + toString<int>(fileError) + ")]: \"" + fileName + "\" (Size: " + toString<int>(readSize) + "/" + toString<int>(size) + " bytes)");
return NULL;
}
// Close the file
fclose(file);
// Create the shader object
// shaderType is GLenum that is set based on the file extension. I assure you it is correctly set to either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
GLuint shaderID = glCreateShader(shaderType);
// If we could not create the shader object, check for OpenGL errors and return false
if(shaderID == 0)
{
checkForErrors();
Log::error("error creating shader \"" + name);
delete source[0];
delete [] source;
return NULL;
}
// Load shader source and compile it
glShaderSource(shaderID, 1, (const GLchar**)source, NULL);
glCompileShader(shaderID);
GLint success;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
if(!success)
{
GLchar error[1024];
glGetShaderInfoLog(shaderID, 1024, NULL, error);
Log::error("error compiling shader \"" + name + "\"\n Log:\n" + error);
delete source[0];
delete [] source;
return NULL;
}
else
{
Log::debug("success! Loaded shader \"" + name + "\"");
}
// Clean up
delete source[0];
delete [] source;
Szybka uwaga: glShaderSource - rzucam do (const GLchar **), ponieważ GCC narzeka na const na niestałe znaki ostrzegawcze; W przeciwnym razie uważam, że jestem całkowicie zgodny.
Nie ma tam żadnych błędów, przy okazji. Shadery (poniżej) kompilują się bez żadnych błędów.
Vertex Shader:
void main()
{
// If I comment the line below, the link status is GL_TRUE.
gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
}
Fragment Shader:
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Poniżej znajduje się kod, który tworzy program cieniowania, przywiązuje obiektów i linki itp .:
// Create a new shader program
GLuint program = glCreateProgram();
if(program == 0)
{
Log::error("RenderSystem::loadShaderProgram() - could not create OpenGL shader program; This one is fatal, sorry.");
getContext()->fatalErrorIn("RenderSystem::loadShaderProgram(shader1, shader2)", "OpenGL failed to create object using glCreateProgram()");
return NULL;
}
// Attach shader objects to program
glAttachShader(program, vertexShaderID);
glAttachShader(program, fragmentShaderID);
// Link the program
GLint success = GL_FALSE;
glLinkProgram(program);
checkForErrors();
glGetProgramiv(program, GL_LINK_STATUS, &success);
if(success == GL_FALSE)
{
GLchar errorLog[1024] = {0};
glGetProgramInfoLog(program, 1024, NULL, errorLog);
Log::error(std::string() + "error linking program: " + errorLog);
return NULL;
}
success = GL_FALSE;
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &success);
if(success == GL_FALSE)
{
GLchar errorLog[1024] = {0};
glGetProgramInfoLog(program, 1024, NULL, errorLog);
checkForErrors();
Log::error(std::string() + "error validating shader program; Details: " + errorLog);
return NULL;
}
zazwyczaj nawet nie osiąga tak daleko, jak zatwierdzanie programu ... Jestem tak sfrustrowany tym, że bardzo trudno jest nie b e wulgarny.
Twoja pomoc jest potrzebna i każda pomoc jest naprawdę doceniana!
EDYCJA: Mam wszystko na Intel HD 3000 (z obsługą OpenGL do wersji 3.1). Moja docelowa wersja OpenGL to 2.0.
EDIT2: Chciałbym również zauważyć, że miałem pewne problemy z odczytaniem shaderów z plików tekstowych, jeśli ustawiłem flagę "r" lub "rt" w fopen - rozmiar odczytu był mniejszy niż rzeczywisty rozmiar o około 10 bajtów (konsekwentnie we wszystkich plikach) - i feof() zwróci true. Kiedy przełączyłem się na czytanie w systemie binarnym ("rb"), problem zniknął i pliki zostały w pełni odczytane. Próbowałem kilku alternatywnych implementacji i wszystkie powodowały ten sam błąd podczas łączenia (i wydrukowałem źródło shadera na konsolę zaraz po odczytaniu pliku, aby upewnić się, że wygląda poprawnie, tak robi).
Gdzie jest twoja deklaracja "# version" w twoim cieniu? –
Nie uwzględniłem jednego ... czy to możliwe? Będę google, ale jeśli mogę - jaka byłaby odpowiednia wersja shadera dla celu OpenGL 2.0? – Kaa
Próbowałem używać #version 150, #version 140 i #version 130 w trzech osobnych testach (ta sama wersja dla obu shaderów), a wyniki są takie same - status łącza zwraca GL_FALSE, a log z informacjami :( – Kaa