2014-09-13 41 views
4

目前,我试图让一个三角形使用OpenGL 3.3和C++与GLM,GLFW3和GLEW库来渲染,而是得到一个错误试图创建时我的shader程序。的OpenGL 3.3/GLSL&C++的错误:“必须写入GL_POSITION”

Vertex info

(0) : error C5145: must write to gl_Position

我已经试图找出为什么出现这种情况,并要求对其他论坛,但没有人知道是什么原因。有三种可能的点,其中该错误可能有他的起源 - 在我main.cpp中,在那里我创建窗口,上下文,该程序,则VAO等...

#include <GL/glew.h> 
#include <GLFW/glfw3.h> 
#include <glm/glm.hpp> 

#include <iostream> 
#include <string> 

#include "util/shaderutil.hpp" 

#define WIDTH 800 
#define HEIGHT 600 

using namespace std; 
using namespace glm; 

GLuint vao; 
GLuint shaderprogram; 

void initialize() { 
    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    glClearColor(0.5, 0.7, 0.9, 1.0); 

    string vShaderPath = "shaders/shader.vert"; 
    string fShaderPath = "shaders/shader.frag"; 
    shaderprogram  = ShaderUtil::createProgram(vShaderPath.c_str(), fShaderPath.c_str()); 
} 

void render() { 
    glClear(GL_COLOR_BUFFER_BIT); 

    glUseProgram(shaderprogram); 

    glDrawArrays(GL_TRIANGLES, 0, 3); 
} 

void clean() { 
    glDeleteProgram(shaderprogram); 
} 


int main(int argc, char** argv) { 
    if (!glfwInit()) { 
    cerr << "GLFW ERROR!" << endl; 
    return -1; 
    } 

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 

    GLFWwindow* win = glfwCreateWindow(WIDTH, HEIGHT, "Rendering a triangle!", NULL, NULL); 
    glfwMakeContextCurrent(win); 
    glewExperimental = GL_TRUE; 

    if (glewInit() != GLEW_OK) { 
    cerr << "GLEW ERROR!" << endl; 
    return -1; 
    } else { 
    glGetError(); 
    //GLEW BUG: SETTING THE ERRORFLAG TO INVALID_ENUM; THEREFORE RESET 
    } 

    initialize(); 

    while (!glfwWindowShouldClose(win)) { 
    render(); 

    glfwPollEvents(); 
    glfwSwapBuffers(win); 
    } 

    clean(); 

    glfwDestroyWindow(win); 
    glfwTerminate(); 

    return 0; 
} 

...的ShaderUtil一流的,在这里我在着色器文件中读取,编译它们,做错误检查,并返回一个最终方案...

#include "shaderutil.hpp" 

#include <iostream> 
#include <string> 
#include <fstream> 
#include <vector> 

using namespace std; 

GLuint ShaderUtil::createProgram(const char* vShaderPath, const char* fShaderPath) { 
    /*VARIABLES*/ 
    GLuint vertexShader; 
    GLuint fragmentShader; 
    GLuint program; 

    ifstream vSStream(vShaderPath); 
    ifstream fSStream(fShaderPath); 
    string vSCode, fSCode; 

    /*CREATING THE SHADER AND PROGRAM OBJECTS*/ 
    vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    program = glCreateProgram(); 

    /*READING THE SHADERCODE*/ 
    /*CONVERTING THE SHADERCODE TO CHAR POINTERS*/ 
    while (vSStream.is_open()) { 
    string line = ""; 
    while (getline(vSStream, line)) { 
     vSCode += "\n" + line; 
    } 
    vSStream.close(); 
    } 
    const char* vSCodePointer = vSCode.c_str(); 

    while (fSStream.is_open()) { 
    string line = ""; 
    while (getline(fSStream, line)) { 
     fSCode += "\n" + line; 
    } 
    fSStream.close(); 
    } 
    const char* fSCodePointer = fSCode.c_str(); 

    /*COMPILING THE VERTEXSHADER*/ 
    glShaderSource(vertexShader, 1, &vSCodePointer, NULL); 
    glCompileShader(vertexShader); 

    /*VERTEXSHADER ERROR CHECKING*/ 
    GLint vInfoLogLength; 
    glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &vInfoLogLength); 

    if (vInfoLogLength > 0) { 
    vector<char> vInfoLog(vInfoLogLength + 1); 
    glGetShaderInfoLog(vertexShader, vInfoLogLength, &vInfoLogLength, &vInfoLog[0]); 

    for(int i = 0; i < vInfoLogLength; i++) { 
     cerr << vInfoLog[i]; 
    } 
    } 

    /*COMPILING THE FRAGMENTSHADER*/ 
    glShaderSource(fragmentShader, 1, &fSCodePointer, NULL); 
    glCompileShader(fragmentShader); 

    /*FRAGMENTSHADER ERROR CHECKING*/ 
    GLint fInfoLogLength; 
    glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &fInfoLogLength); 

    if (fInfoLogLength > 0) { 
    vector<char> fInfoLog(fInfoLogLength + 1); 
    glGetShaderInfoLog(fragmentShader, fInfoLogLength, &fInfoLogLength, &fInfoLog[0]); 

    for(int i = 0; i < fInfoLogLength; i++) { 
     cerr << fInfoLog[i]; 
    } 
    } 

    /*LINKING THE PROGRAM*/ 
    glAttachShader(program, vertexShader); 
    glAttachShader(program, fragmentShader); 
    glLinkProgram(program); 
    //glValidateProgram(program); 

    /*SHADERPROGRAM ERROR CHECKING*/ 
    GLint programInfoLogLength; 
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &programInfoLogLength); 

    if (programInfoLogLength > 0) { 
    vector<char> programInfoLog(programInfoLogLength + 1); 
    glGetProgramInfoLog(program, programInfoLogLength, &programInfoLogLength, &programInfoLog[0]); 

    for(int i = 0; i < programInfoLogLength; i++) { 
     cerr << programInfoLog[i]; 
    } 
    } 

    /*CLEANUP & RETURNING THE PROGRAM*/ 
    glDeleteShader(vertexShader); 
    glDeleteShader(fragmentShader); 

    return program; 
} 

...和顶点着色器本身,这是没有什么特别的。我只是创建一个顶点数组,并将它们推入gl_Position。

#version 330 core 

void main() { 
    const vec3 VERTICES[3] = vec3[3] { 
    0.0, 0.5, 0.5, 
    0.5,-0.5, 0.5, 
    -0.5,-0.5, 0.5 
    }; 

    gl_Position.xyz = VERTICES; 
    gl_Position.w = 1.0; 
} 

fragmentshader只输出一个叫做color的vec4,它被设置为(1.0,0.0,0.0,1.0)。编译器不会显示任何错误,但是当我尝试执行该程序时,我只是得到一个没有三角形的窗口和上面显示的错误消息。

还有我已经尝试过解决这个问题的几件事情,但他们没有工作:

  • 我尝试创建我的main.cpp里面的顶点,并通过顶点推入顶点着色器缓冲对象;我改变了一些受opengl-tutorials.org启发的代码,最后得到了一个三角形来显示,但着色器没有应用;我只有main.cpp中的顶点出现在屏幕上,但“必须写入gl_Position”问题依然存在。

  • 我尝试了不同的地方使用glGetError(),并得到了2个不同的错误代码:1280和1282;第一个是由GLEW内部的一个错误引起的,这导致状态从GL_NO_ERROR改变为GL_INVALID_ENUM或类似的东西。我被告知忽略这个,并且在初始化GLEW之后通过使用glGetError()将状态改回到GL_NO_ERROR。在渲染函数中使用glUseProgram()后出现了另一个错误代码。我想从中获得一些信息,但gluErrorString()函数在OpenGL 3.3中已被弃用,我找不到任何我的库提供的替代方法。

  • 我试着将它链接验证后通过glValidateProgram我的程序()。当我这样做时,GL_POSITION错误信息没有露面了,但三角形没有任何,所以我认为这个功能只是清除信息日志把一些新的信息有关验证过程

所以现在,我不知道是什么原因导致了这个错误。

+5

'VERTICES'是三个'vec3'实例的数组。 'gl_Position.xyz'是一个'vec3'。不计算。 – 2014-09-13 01:09:36

+0

是的,顶点着色器不会编译。如果你遇到错误情况,你有没有检查过调试器?出于某种原因,您可能看不到错误输出。例如,打印错误后,您不会输出换行符。尝试添加一个'cerr << endl'。 – 2014-09-13 01:32:12

回答

2

顶点着色上的每个顶点运行独立,所以GL_POSITION是输出顶点无论转换后要适用于顶点着色器正在处理的顶点,所以试图发出多个顶点就没有意义了。几何着色器可以即时发出其他几何图形,例如可用于创建运动模糊。

对于典型绘图,您可以像绑定顶点数组一样绑定顶点数组对象,但将数据放入名为Vertex Buffer Objects的缓冲区中,并告诉OpenGL如何使用glVertexAttrib解释数据的“属性”,您可以在着色器中读取它们。

+0

我创建了一个像你说的VBO,在我的main.cpp中创建了一个GLFloats数组,并将它放入VBO中,并尝试绘制它。我的三角现在出现了,但是“gl_Position” - 错误仍然存​​在,着色器似乎没有被应用。这是目前的样子:http://pastebin.com/fZs16288 – DocCoock 2014-09-13 12:19:58

+0

Cpp看起来不错,你可以发布你的着色器源代码吗? – MtRoad 2014-09-13 14:08:09

+0

当然! 顶点着色器:http://pastebin.com/VSRHQG6g 片段着色器:http://pastebin.com/nhqUT2T7 – DocCoock 2014-09-13 14:55:44

8

问题解决了!我试图打印OpenGL试图编译的源代码,并看到ifstream没有加载源代码。事情我不得不改变:

  1. 更改 “而(vVStream.is_open())”,以 “如果(vVStream.is_open())”。
  2. 错误检查,如果我先列出的条件执行(加“否则{CERR < <‘糟糕!’< < ENDL}
  3. 添加第二个参数来我创建了ifstreams:改变” ifstream的(路径)“到”ifstream(path,ios :: in)“
  4. 将我从相对路径(例如”../shaders/shader.vert“)传递到绝对路径(例如”/ home/USERNAME/Desktop/project/src/shaders/shader.vert“);这是必须的,因为相对路径不被理解;使用绝对路径并不是永久的解决方案,但它解决了未找到着色器。

现在它实际上加载和编译着色器;仍然有一些错误需要解决,但是如果某人具有相同的“必须写入gl_Position”问题,则double,no,triple-check检查您试图编译的源是否实际加载,以及ifstream是否实际打开。

我感谢所有试图帮助我的人,特别是@MtRoad。这个问题几乎让我变得秃头。

0

最近遇到此问题&我怀疑原因可能与您的相同。

我不熟悉g ++,但是,在VS的构建环境&您的* EXE运行时的位置可能会影响您的调试。 例如,一个这样的设置:

Project Properties -> General -> Output directory -> 

Visual Studios Express - change debug output directory

和另一个相似的问题在这里"The system cannot find the file specified" when running C++ program

你需要确保你已经改变构建环境,你从一个调试不同的输出目录,任何相关文件都与执行* exe的位置相关。

这可以解释为什么你不得不求助于使用“如果(vVStream.is_open())”,我怀疑发生故障,&所以随后使用着色器的完整文件路径为原始引用文件不相。

我的问题与您的问题完全相同,但仅限于发布模式。一旦我将我的着色器复制到* exe可以访问它们的发布文件夹中,问题就消失了。