c++ - OpenGL 3.3/GLSL 和 C++ 错误 : "must write to gl_Position"

标签 c++ opengl glsl glfw glew

我目前正在尝试使用 OpenGL 3.3 和 C++ 以及 GLM、GLFW3 和 GLEW 库来渲染一个三角形,但在尝试创建我的着色器程序时出现错误。

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;
}

片段着色器只是输出一个名为 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 错误消息不再出现,但三角形也没有出现,所以我假设这个函数只是清除信息日志以放入一些关于验证过程的新信息

    <

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

最佳答案

问题解决了!我尝试打印 OpenGL 尝试编译的源代码,发现 ifstream 没有加载任何源代码。我必须改变的事情:

  1. 将“while (vVStream.is_open())”更改为“if (vVStream.is_open())”。
  2. 错误检查,如果我首先列出的条件被执行(添加“else {cerr << “OH NOES!” << endl}
  3. 向我正在创建的 ifstreams 添加第二个参数:将“ifstream(path)”更改为“ifstream(path, ios::in)”
  4. 将我传递的路径从相对路径(例如“../shaders/shader.vert”)更改为绝对路径(例如“/home/USERNAME/Desktop/project/src/shaders/shader.vert” ");这在某种程度上是必要的,因为相对路径不被理解;虽然使用绝对值不是永久解决方案,但它解决了找不到着色器的问题。

现在它实际加载并编译着色器;仍有一些错误需要修复,但如果有人遇到相同的“必须写入 gl_Position”问题,请仔细检查您尝试编译的源代码是否已实际加载以及 ifstream 是否已打开。

我感谢所有试图帮助我的人,尤其是@MtRoad。这个问题差点让我秃头。

关于c++ - OpenGL 3.3/GLSL 和 C++ 错误 : "must write to gl_Position",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25818858/

相关文章:

opengl - OpenGL 3.1 中已弃用 glLineStipple

c++ - C++ int数组中的foreach

具有类设计的 C++ OOP

c++ - 将 Javascript 函数作为参数传递给 C++ 函数

c++ - 在类中启动的第二个线程中的 OpenGL

c++ - 在 ubuntu 中编译 GLUT 时出错

c++ - OpenGL 顶点属性指针或着色器不工作

ios - 有没有办法在片段着色器中使用64个以上的向量?或替代?

c++ - 对象数组 - std::array - 构造函数初始化问题

glsl - (未使用的)GLSL 制服/进/出是否有助于注册压力?