2016-01-17 2 views
0

Я новичок в OpenGL, и я пытался написать класс Shader, который загружает шейдеры из файла и компилирует их. Проблема в том, что ни одна из них не компилируется. Оба отображаются сообщения об ошибках, как это:Ни вертекс-шейдер, ни фрагментарный шейдер не компилируются после загрузки из файла

0:1(1): error: syntax error, unexpected $end 

Я искал много вопросов здесь с той же проблемой, но ни один из них не работал. Код ниже:

Shader.h

#ifndef SHADER_H 
#define SHADER_H 

#include <GL/glew.h> 

#include <string> 
#include <fstream> 
#include <sstream> 
#include <iostream> 

class Shader { 
    public: 
     Shader(const GLchar* path); 
     GLint Compile(GLenum type); 
     GLuint GetID() const; 
     const char* GetShaderCode() const; 
     void InfoLog() const; 
    private: 
     GLuint shaderId; 
     const char* shaderCode; 
     int shaderCodeLength; 
     char log[512]; 

}; 

#endif 

Shader.cpp (функции, где проблема)

#include "Shader.h" 

Shader::Shader(const GLchar* path) { 
    std::string shaderString; 
    std::ifstream shaderFile; 
    std::stringstream shaderStream; 

    shaderFile.exceptions(std::ifstream::badbit); 

    try { 
     shaderFile.open(path); 
     shaderStream << shaderFile.rdbuf(); 
     shaderFile.close(); 
     shaderString = shaderStream.str(); 

    } catch (std::ifstream::failure e) { 
     std::cout << "Error while reading the file. (Does the file exist?)" << std::endl; 

    } 


    shaderCode = const_cast<const GLchar*>(shaderString.c_str()); 
    shaderCodeLength = shaderString.length(); 
} 

GLint Shader::Compile(GLenum type) { 
    //Compilates the shader and returns GL_TRUE if succesful or GL_FALSE otherwise. 
    GLint status; 
    shaderId = glCreateShader(type); 
    glShaderSource(shaderId, 1, &shaderCode, &shaderCodeLength); 
    glCompileShader(shaderId); 
    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); 
    glGetShaderInfoLog(shaderId, 512, NULL, log); 

    return status; 
} 

shader.vert

#version 130 

in vec2 position; 
in vec3 color; 
in vec2 texcoord; 
out vec3 Color; 
out vec2 Texcoord; 
uniform mat4 trans; 

void main() { 
    Color = color; 
    Texcoord = texcoord; 
    gl_Position = trans * vec4(position, 0.0, 1.0); 
} 

shader.frag

#version 130 

in vec3 Color; 
in vec2 Texcoord; 
out vec4 outColor; 
uniform sampler2D texKitten; 
uniform sampler2D texPuppy; 

void main() { 
    outColor = mix(texture(texKitten, Texcoord), texture(texPuppy, Texcoord), 0.5); 

}; 

Многие люди говорили, что проблема заключается в том, что источник шейдера немного напоминает это: #version 130in vec3 Color;... (но когда я печатаю его по основному коду, он печатает точно так же, как в файле), и многие люди говорят, что это правильный способ загрузки шейдеров из файла. Итак, что случилось с этим? Есть ли способ лучше?

+0

Вы можете просто использовать 'glShaderSource' в конструкторе. Таким образом, вам не нужна локальная копия, и вы можете запросить ее с помощью 'glGetShaderSource'. –

+0

@BrettHale это тоже работает, поскольку проблема заключалась в том, что glShaderSource и shaderString.c_str() не были в той же области. И тебе спасибо. –

ответ

3

shaderCode становится недействительным, как только возвращается конструктор, потому что вы сохраняете результат shaderString.c_str().
Использование не определено.

Используйте элемент std::string и выполняйте преобразование только при компиляции шейдера или используйте динамическое распределение.
Первый вариант лучше.

+0

Ничего себе, наконец-то хорошее решение! Я знал о проблеме с shaderString.c_str(), но не думал, что это так. В любом случае, большое спасибо! –