2011-12-22 11 views
7

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_FALSEgl_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).

+1

Gdzie jest twoja deklaracja "# version" w twoim cieniu? –

+0

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

+0

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

Odpowiedz

14

OK, wiedziałem, kiedy napisałem, że to będzie zawstydzające, ale jest dość źle: aplikacja do konfiguracji grafiki Intel, która zazwyczaj towarzyszy sterownikowi Intel, ma zakładkę ustawień 3D; Teraz pole wyboru "Ustawienia niestandardowe" zostało odznaczone, ale wyszarzona opcja pod ustawieniem "Przetwarzanie wierzchołków" zawiera "Włącz przetwarzanie oprogramowania". Mimo że nie było zaznaczenia i wszystko było szare, po prostu wprowadziłem ustawienia niestandardowe i sprawdziłem wszystko w "Ustawieniach aplikacji".

To naprawiło to! Wszystko jak powinno! Nie wiem, kto pomyślał o tej opcji, dlaczego miałoby to być przydatne ?! Jest to jedyna opcja, która wygląda oszałamiająco nie na miejscu.

Przeszedłem kilka ponownych instalacji sterowników, intensywne debugowanie i konfigurację badań, musiałem spekulować i drugi domysły na absolutnie wszystko! Okropne, nie życzyłbym tego moim najgorszym wrogom. Przepraszam, że przeszkadzam wszystkim, ale jeśli jest inny głupi jak ja tam, nie ma za co. :)

Powiązane problemy