当前位置: 首页 > 知识库问答 >
问题:

OpenGL 3.3/GLSL

计寒
2023-03-14

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

顶点信息

(0):错误C5145:必须写入gl_位置

我已经试图找出为什么会发生这种情况,并在其他论坛上提问,但没有人知道原因是什么。这一错误有三个可能的根源——主要是我。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;
}

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

我已经尝试了一些方法来解决这个问题,但没有一个有效:

>

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

链接程序后,我尝试通过glValidateProgram()验证程序。当我这样做时,gl_位置错误消息不再显示,但三角形也没有显示,所以我假设该函数只是清除信息日志,以输入有关验证过程的一些新信息

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

共有3个答案

许正平
2023-03-14

最近遇到了这个问题

然而,我不熟悉g,关于VS One的构建环境

Project Properties -> General -> Output directory ->

Visual Studio Express-更改调试输出目录

还有一个类似的问题“系统在运行C程序时找不到指定的文件”

您需要确保如果您已更改构建环境并且您正在从不同的输出目录进行调试,则任何相关文件都与执行*exe的位置相关。

这可以解释为什么您不得不使用“if(vVStream.is_open())”,我怀疑它失败了,

我的问题和你的一模一样,但只是在发布模式下。一旦我将着色器复制到*exe可以访问它们的发布文件夹中,问题就消失了。

冯渝
2023-03-14

顶点着色器在每个顶点上单独运行,因此gl_Position是您希望应用于顶点着色器正在处理的顶点的任何变换后的输出顶点,因此尝试发出多个顶点是没有意义的。几何着色器可以动态发出额外的几何图形,并且可以用于创建运动模糊等。

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

云利
2023-03-14

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

  1. 将“while(vVStream.is_open())”更改为“if(vVStream.is_open())”

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

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

 类似资料:
  • 我想要一个非常简单的解释,为什么这些变量在“Android Studio”上不起作用,以及如何解决我的问题(一些用于“TheeBookOfShaders”,一些用于“Atom”,另一些用于两者,一些仅用于“ShaderToy”,一些仅用于“Android Studio”)。 *为了真正理解,这是一个示例(来自“fragment.glsl”文件)* i、 e.*从“ShaderToy”到“Atom”

  • 我用的是三。InstancedBufferGeometry,我希望访问顶点着色器中编码为纹理的数据。 我想做的是,创建一个每个实例一个像素的数据纹理,它将存储每个实例的位置数据(然后在稍后的阶段,我可以使用带有流场的模拟来更新纹理,以设置位置动画)。 我正在努力从顶点着色器中的纹理访问数据。 目前,图像中的数据似乎无法在顶点着色器中访问(例如,如果我只是将vUv设置为vec2(1.0,0.0),并

  • 所以我有一个非常简单的glsl着色器,可以用纹理和平行光渲染对象。 现在我有一个非常艰难的时间试图得到的纹理显示,其他一切工作,除此之外。 当我禁用着色器(glUseProgram(0))时,纹理以黑色和白色渲染,但当我启用它时,整个网格是单一颜色,没有纹理,当我尝试不同的纹理时,它会改变颜色。 这就是我加载纹理的方式 这就是我如何绑定我的纹理 这是我的顶点着色器 这是我的碎片着色器 最后但并非最

  • 我希望在2D OpenGL应用程序上实现着色器。我的计划是将场景渲染到帧缓冲区对象,然后使用着色器将该帧缓冲区对象渲染到屏幕。 这是我绘制到帧缓冲区对象的场景,然后从那里绘制到屏幕。使用箭头键可以让月亮四处移动(我很自豪!) 但是,当我尝试使用着色器程序将帧缓冲区对象渲染到屏幕上时,我得到以下结果: 这是非常可悲的。这个片段着色器是我从一个教程中得到的,我相信问题一定是统一变量。 以下是片段着色器

  • 我已经实现了基本的阴影映射算法,但它只适用于一种灯光。 我想用以下两个点光源渲染场景: 灯1-位置:vec3(-8.0f,5.0f,8.0f),方向:vec3(1.3f,-1.0f,-1.0f) 灯2-位置:vec3(8.0华氏度,5.0华氏度,8.0华氏度),方向:vec3(1.3华氏度,-1.0华氏度,-1.0华氏度) 如果我分别渲染两个灯,我有以下结果: Light_1渲染: 使用灯光_2渲

  • 我有一个由2个网格(平面、立方体)、一个灯和一个相机组成的场景。我想使用GLSL着色器和OpenGL的阴影映射技术在我的场景中显示阴影。 以下是我得到的结果(为了简单起见,我的立方体和平面都是蓝色和蓝色): 这是FBO和深度纹理初始化: 以下是我的顶点着色器的内容: 还有我的片段着色器: 正如你所见,模型上有一些工件,我不知道如何取出它们。但是阴影看起来是正确的,所以我的着色器中输入的变量也应该是

  • 我在Mac OSX下工作,试图通过GLSL着色器在立方体上映射图像。 我显示立方体(以及图像,当它不通过着色器时)的方法是: 正如你所看到的,我正在检查,在这个测试中,是否有一个着色器应用到我的对象上(它是一个包装,效果非常好) 如果没有着色器,我只启用GL_纹理_坐标_数组,如果有,我尝试将图像绑定到着色器中的采样2D均匀。 我使用的着色器非常简单:它只显示纹理。我在Quartz Compose