2017-07-16 2 views
1

Je m'attends à ce que mon programme me dessine un simple triangle rouge. Les vertex et fragment shaders sont censés être chargés à partir de fichiers externes via ma fonction loadShader(), mais pour une raison étrange, ma fonction loadShader() lit des caractères non-ASCII, de sorte que les erreurs de compilation shader sont générées. Les tentatives de convertir mes deux fichiers shader au format ASCII en suivant les instructions fournies here (en utilisant Notepad ++) ont échoué, car le résultat est le même - à savoir, l'erreur du compilateur shader concernant les caractères non-ASCII (voir les captures d'écran ci-dessous) et un triangle rouge blanc au lieu d'un attendu (en raison de la non compilation du shader).Pourquoi fgetc() lit-il un caractère non-ASCII? (Essayer de charger les shaders GLSL)

Autres Dépannage Les tentatives:

:

Les parties de code critiques vont 14-44 - ma fonction loadShader (note I plus téléchargé mon code source Pastebin pour le numéro de ligne facile référencement.) . La section "dire la taille du fichier" commençant à la ligne 22 fonctionne correctement, comme le montrent les captures d'écran ci-dessous, puisque ma sortie de débogage (ligne 25) a le même nombre d'octets que la taille fournie par Windows Explorer. En outre, le tampon (dans la ligne 28) correspond exactement aux tailles des fichiers de shader, comme en témoigne la sortie de débogage dans la ligne 41 (voir les captures d'écran). Enfin, les syntaxes de mes deux shaders sont correctes, puisque je les ai préalablement codées en dur et le résultat était le rendu du triangle rouge désiré.

Screenshot:

enter image description here

Code Source:

// Expected result: Draws a simple red colored triangle to the screen 
// Problem to debug: Why does my loadShader function read non-ASCII characters? 

#include <glad/glad.h> 
#define GLFW_DLL 
#include <GLFW\glfw3.h> 
#include <cstdio> 
#include <iostream> 

// TODO: Debug 
/* Loads shader text files from a given file name (extension required) 
* and returns the shader code as a null terminated string from that file. 
*/ 
const char * loadShader(const char * shaderFileName) { 
    FILE * shaderFile{}; 
    fopen_s(&shaderFile, shaderFileName, "r"); 
    if (!shaderFile) { 
     std::cerr << "ERROR: Cannot open file" << std::endl; 
     return "\0"; 
    } 
    // Tell file size 
    fseek(shaderFile, 0L, SEEK_END); 
    unsigned long shaderFileSize{}; 
    shaderFileSize = ftell(shaderFile); 
    std::cout << "DEBUG: shaderFileSize: " << shaderFileSize << std::endl; // Debug output 
    rewind(shaderFile); 
    // Read from file 
    char * buffer = (char *)malloc(sizeof(char)*(shaderFileSize+1UL)); 
    if (!buffer) { 
     std::cerr << "ERROR: Failed to allocate memory" << std::endl; 
     return "\0"; 
    } 
    int c{}; 
    int i = 0; 
    while ((c = fgetc(shaderFile))!= EOF) { 
     buffer[i++] = c; 
    } 
    // Put '\0' at the end of the buffer (required for OpenGL) 
    buffer[shaderFileSize] = '\0'; 
    std::cout << "DEBUG: buffer: " << buffer << std::endl; // Debug output 
    std::cout << "DEBUG: strlen: " << strlen(buffer) << std::endl; // Debug output 
    fclose(shaderFile); 
    return buffer; 
} // end of loadShader() 

int main() { 
    // Initialize GLFW 
    if (!glfwInit()) { 
     std::cerr << "ERROR: Failed to initialize GLFW3" << std::endl; 
     return -1; 
    } 
    // Create window 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
    GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL Game", nullptr, nullptr); 
    if (!window) { 
     std::cerr << "ERROR: Failed to create window with GLFW3" << std::endl; 
     glfwTerminate(); 
     return -1; 
    } 
    glfwMakeContextCurrent(window); 
    // Load all OpenGL function pointers. 
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { 
     std::cerr << "ERROR: Failed to initialize GLAD" << std::endl; 
     return -1; 
    } 
    // Get info from renderer 
    const GLubyte* rendererName = glGetString(GL_RENDERER); 
    const GLubyte* OpenGLVersionSupported = glGetString(GL_VERSION); 
    std::cout << rendererName << std::endl << OpenGLVersionSupported << std::endl; 
    // Enable depth 
    glEnable(GL_DEPTH_TEST); 
    glDepthFunc(GL_LESS); 
    // Define triangle 
    GLfloat points[] = { 0.0f, 0.5f, 0.0f, 
         0.5f, -0.5f, 0.0f, 
         -0.5f, -0.5f, 0.0f }; 
    // Create buffer object 
    GLuint vertexBufferObject = 0; 
    glGenBuffers(1, &vertexBufferObject); 
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); 
    // Create vertex attribute object 
    GLuint vertexAttributeObject = 0; 
    glGenVertexArrays(1, &vertexAttributeObject); 
    glBindVertexArray(vertexAttributeObject); 
    glEnableVertexAttribArray(0); 
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); 
    // Load shaders 
    const char * vertexShaderCode = loadShader("VertexShader.glsl"); 
    const char * fragmentShaderCode = loadShader("FragmentShader.glsl"); 
    // Compile shaders 
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertexShader, 1, &vertexShaderCode, nullptr); 
    glCompileShader(vertexShader); 
    // Check vertex shader for compile errors 
    int success = 0; 
    char message[512] = ""; 
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); 
    if (!success) { 
     glGetShaderInfoLog(vertexShader, 512, nullptr, message); 
     std::cerr << "ERROR: Failed to compile vertex shader" << std::endl << message; 
    } 
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragmentShader, 1, &fragmentShaderCode, nullptr); 
    glCompileShader(fragmentShader); 
    // Check fragment shader for compile errors 
    success = 0; 
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); 
    if (!success) { 
     glGetShaderInfoLog(fragmentShader, 512, nullptr, message); 
     // TODO: Specify error type in message 
     std::cerr << "ERROR: Failed to compile fragment shader" << std::endl << message; 
    } 
    // Create shader program and link it 
    GLuint shaderProgram = glCreateProgram(); 
    glAttachShader(shaderProgram, vertexShader); 
    glAttachShader(shaderProgram, fragmentShader); 
    glLinkProgram(shaderProgram); 
    // Check for linking errors 
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); 
    if (!success) { 
     glGetShaderInfoLog(shaderProgram, 512, nullptr, message); 
     // TODO: Specify error type in message 
     std::cerr << "ERROR: Failed to link shaders" << std::endl << message; 
    } 
    // Render loop 
    while (!glfwWindowShouldClose(window)) { 
     // Wipe the drawing surface clear 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     // Use shader program and vertex attribute object 
     glUseProgram(shaderProgram); 
     glBindVertexArray(vertexAttributeObject); 
     // Draw from the currently bound vertex attribute object 
     glDrawArrays(GL_TRIANGLES, 0, 3); 
     glfwPollEvents(); 
     glfwSwapBuffers(window); 
    } 
    // Exit program 
    glfwTerminate(); 
    return 0; 
} // end of main() 
+3

Suggestion: Vérifiez d'abord le codage de caractères du fichier de shaders. Si ce n'est pas un fichier ASCII, vous avez probablement trouvé le problème. Ensuite, assurez-vous que le fichier ne contient aucune surprise en inspectant le fichier avec un éditeur hexadécimal pour les caractères non-imprimables ou non-ASCII. – user4581301

+1

Pourquoi utilisez-vous 'fgetc'? Vous êtes allé et calculé la longueur du fichier et tout. Pourquoi ne pas simplement utiliser 'fread' et lire tout à la fois? –

Répondre

3

0xcd est une valeur utilisée par MSVC CRT pour remplir la mémoire non initialisée. Qu'est-ce qui se passe, c'est que votre fichier utilise \r\n fins de ligne, mais vous l'ouvrez en mode texte et le CRT les convertit en \n fins de ligne. En conséquence, vous lisez buffer moins d'octets que la taille retournée par ftell, de sorte que la dernière valeur de i est inférieure à shaderFileSize, et, par conséquent, vous avez des octets non initialisés entre la dernière valeur écrite à buffer[i] et le caractère null-terminator .

Au lieu de cela, remplacer votre code avec:

FILE * shaderFile{}; 
fopen_s(&shaderFile, shaderFileName, "rb"); // <-------- HERE !!!! 
fseek(shaderFile, 0L, SEEK_END); 
unsigned long shaderFileSize = ftell(shaderFile); 
rewind(shaderFile); 
char * buffer = (char *)malloc(shaderFileSize+1); 
fread(buffer, shaderFileSize, 1, shaderFile); 
buffer[shaderFileSize] = '\0';