OpenGL 3.0 GLSL 130片段着色器编译错误

时间:2017-11-12 17:43:30

标签: opengl glsl

我正在尝试使用OpenGL 3(GLSL 130)编译一个简单的彩色三角形示例,但我的片段着色器从不编译。报告的错误始终为

syntax error unexpected $end

我的顶点着色器编译并显示几何体,但片段着色器失败。

以下是来源(非常简单): Vertex.vs:

attribute vec3 vertex_position;
attribute vec3 vertex_color;

varying vec4 out_color;

void main(void)
{
    gl_Position = vec4(vertex_position, 1.0);
    out_color = vec4(vertex_color, 1.0);
}

和fragment.fs:

varying vec4 out_color;

void main(void)    
{    
    gl_FragColor = out_color;            
}

[编辑]这是我的着色器编译代码:

char *loadShader(const char *fname)
{
    FILE* fp = fopen(fname, "rb");
    long size = 0;
    if (!fp)
        return NULL;

    fseek(fp, 0, SEEK_END);
    size = ftell(fp) + 1;
    fseek(fp, 0, SEEK_SET);
    char* data = (char*) malloc((sizeof(char) * size));
    ::fread(data, 1, size, fp);
    data[size-1] = '\0';
    fclose(fp);
    return data;
}

Shader::Shader(const char *fname)
    : m_data(NULL),
      ID(0)
{
    if (fname)
        m_data = ilian::loadShader(fname);
}

Shader::Shader(const char *data, size_t size)
{
    if (data && size >0)
    {
        m_data = (char*) malloc(sizeof(char) * size);
        ::memmove(m_data, data, size);
    }
}

Shader::~Shader()
{
    if (m_data)
    {
        free(m_data);
        m_data = NULL;
    }
    glDeleteShader(ID);
    std::cout << "~Shader()\n";
}

std::string Shader::data()
{
    std::string s((char*)m_data);
    return s;
}

GLuint &Shader::getID()
{
    return ID;
}

void Shader::createShader(ShaderType type)
{
    GLint res = -1;
    switch (type)
    {
    case VERTEX:
        ID = glCreateShader(GL_VERTEX_SHADER);
        break;
    case FRAGMENT:
        ID = glCreateShader(GL_FRAGMENT_SHADER);
        break;
    default:
        break;
    }
    const GLchar* source = (const GLchar*) data().c_str();
    int shader_len = data().length();

    glShaderSource(ID, 1, &source, &shader_len);
    glCompileShader(ID);
    glGetShaderiv(ID, GL_COMPILE_STATUS, &res);

    if (res == GL_TRUE)
    {
        std::cout << "Shader Compile OK!\n";
    }
    else
    {
        std::cout << "Shader Compile FAIL!\n";
        GLint maxLength = 0;
        glGetShaderiv(ID, GL_INFO_LOG_LENGTH, &maxLength);

        //The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetShaderInfoLog(ID, maxLength, &maxLength, &infoLog[0]);
        std::cout << (char*)infoLog.data() << "\n";
        //We don't need the shader anymore.
        glDeleteShader(ID);
    }
}

GLProgram::GLProgram(const char *vs_source, const char *fs_source)
    : ID(0), vs(nullptr), fs(nullptr)
{
    vs = new Shader(vs_source);
    fs = new Shader(fs_source);
    vs->createShader(VERTEX);
    fs->createShader(FRAGMENT);
}

GLProgram::~GLProgram()
{
    if (vs)
        delete vs;
    if (fs)
        delete fs;
}

VAO &GLProgram::getVertexArrayObject()
{
    return vao;
}

bool GLProgram::createProgram()
{
    static GLint msg;

    ID = glCreateProgram();
    glAttachShader(ID, vs->getID());
    glAttachShader(ID, fs->getID());
    glLinkProgram(ID);

    glGetProgramiv(ID, GL_LINK_STATUS, &msg);

    std::cout << "Link status: (" <<msg
              << ")"<< std::endl;
    if (!msg)
    {
        GLint infoLen = 0;
        glGetProgramiv(ID, GL_INFO_LOG_LENGTH, &infoLen);
        if(infoLen > 1)
        {
           char* infoLog = new char[infoLen];
           glGetProgramInfoLog(ID, infoLen, NULL, infoLog);
           printf("Error linking program:\n%s\n", infoLog);
           delete [] infoLog;
        }
    }
}

void GLProgram::bind(int location, const char *attribyte)
{
    glBindAttribLocation(ID, location, attribyte);
}

void GLProgram::useProgram()
{
    glUseProgram(ID);
    glBindVertexArray(vao.ID());
}

1 个答案:

答案 0 :(得分:1)

您正在将指向无效内存地址的指针传递给glShaderSource。发生这种情况是因为您尝试从此行中的临时字符串对象获取c_str()指针:

const GLchar* source = (const GLchar*) data().c_str();

在此行之后,data()返回的临时字符串将被删除,源指针指向无效的内存地址。

对代码的最短(但很难看)修复是通过存储它来确保在使用指针时字符串对象仍然存在:

auto data_str = data();
const GLchar* source = (const GLchar*)data_str.c_str();

但是由于整个字符串对象的构造在你的代码中完全没用(并且实际上因为字符串对象创建了底层char数组的副本而损害了性能),更好的方法是返回char *而不是new data()函数中的std :: string:

const char* Shader::data()
{
    return m_data;
}

并将其用于:

 const GLchar* source = data();

甚至更好:首先不要使用带有malloc的char *并使用正确的C ++方法直接从文件中加载std :: string。