Packt 学习OpenGL教程,渲染三角形时出现段错误。与GLchar * vertexShaderSource和GLchar *fragmentShaderSource相关?

问题描述 投票:0回答:1

我在上一个由 packt 学习 OpenGL 的示例中制作了一个橙色三角形。当我使用shader.h、core.vs和core.frag将代码更新到下一个示例时,我编译得很好,但出现了段错误。和

GLchar * fragmentShaderSource
GLchar * vertexShaderSource
有关系吗?我注意到它们被从
colouredtriangle.cpp
中取出,#version 330 核心被移至
core.frag
core.vs
中。我收到一个错误,它们没有定义,所以我把它们放回去。我有:

#include <iostream>
#define GLEW_STATIC
#include "shader.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>

Shader ourShader("core.vs", "core.frag");

const GLchar *vertexShaderSource = "#version 330 core\n";

const GLchar *fragmentShaderSource = "#version 330 core\n";

const GLuint WIDTH = 800, HEIGHT = 600;

int main() {
  glfwInit();

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

  glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

  GLFWwindow *window =
      glfwCreateWindow(WIDTH, HEIGHT, "Learn OpenGL", nullptr, nullptr);

  int screenWidth, screenHeight;

  glfwGetFramebufferSize(window, &screenWidth, &screenHeight);

  if (nullptr == window) {
    std::cout << "Failed to create glfw window!\n";
    glfwTerminate();

    return EXIT_FAILURE;
  }

  glfwMakeContextCurrent(window);

  glewExperimental = GL_TRUE;

  if (GLEW_OK != glewInit()) {
    std::cout << "Failed to initialize glew!" << std::endl;

    return EXIT_FAILURE;
  }

  glViewport(0, 0, screenWidth, screenHeight);
  GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);

  glCompileShader(vertexShader);
  GLint success;
  GLchar infoLog(512);

  glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);

  if (!success) {
    glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED" << infoLog
              << std::endl;
  }

  GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
  glCompileShader(fragmentShader);
  glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);

  if (!success) {
    glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION::FAILED\n"
              << infoLog << std::endl;
  }

  GLuint shaderProgram = glCreateProgram();
  glAttachShader(shaderProgram, vertexShader);
  glAttachShader(shaderProgram, fragmentShader);
  glLinkProgram(shaderProgram);

  glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);

  if (!success) {
    glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::PROGRAM::LINKING::FAILED\n"
              << infoLog << std::endl;
  }

  glDeleteShader(vertexShader);
  glDeleteShader(fragmentShader);

  GLfloat vertices[] = {0.5f, -0.5f, 0.0f, -0.5f, -0.5f,
                        0.0f, 0.0f,  0.5f, 0.0f};

  GLuint VBO, VAO;
  glGenVertexArrays(1, &VAO);
  glGenBuffers(1, &VBO);

  glBindVertexArray(VAO);
  glBindBuffer(GL_ARRAY_BUFFER, VBO);
  glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
                        (GLvoid *)0);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
                        (GLvoid *)(3 * sizeof(GLfloat)));

  glBindVertexArray(0);

  while (!glfwWindowShouldClose(window)) {
    glfwPollEvents();
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    ourShader.Use();
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);

    glfwSwapBuffers(window);
  }

  glDeleteVertexArrays(1, &VAO);
  glDeleteBuffers(1, &VBO);

  glfwTerminate();

  return EXIT_SUCCESS;
}

着色器.h

#ifndef SHADER_H
#define SHADER_H
#include <GL/glew.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

class Shader {
public:
  GLuint Program;
  Shader(const GLchar *vertexPath, const GLchar *fragmentPath) {

    std::string vertexCode;
    std::string fragmentCode;
    std::ifstream vShaderFile;
    std::ifstream fShaderFile;

    vShaderFile.exceptions(std::ifstream::badbit);
    fShaderFile.exceptions(std::ifstream::badbit);

    try {
      vShaderFile.open(vertexPath);
      fShaderFile.open(fragmentPath);
      std::stringstream vShaderStream, fShaderStream;
      vShaderStream << vShaderFile.rdbuf();
      fShaderStream << fShaderFile.rdbuf();
      vShaderFile.close();
      fShaderFile.close();
      vertexCode = vShaderStream.str();
      fragmentCode = fShaderStream.str();
    } catch (std::ifstream::failure e) {
      std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
    }

    const GLchar *vShaderCode = vertexCode.c_str();
    const GLchar *fShaderCode = fragmentCode.c_str();

    GLuint vertex, fragment;
    GLint success;
    GLchar infoLog[512];

    vertex = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex, 1, &vShaderCode, NULL);
    glCompileShader(vertex);
    glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
    if (!success) {
      glGetShaderInfoLog(vertex, 512, NULL, infoLog);
      std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED" << infoLog
                << std::endl;
    }

    this->Program = glCreateProgram();
    glAttachShader(this->Program, vertex);
    glAttachShader(this->Program, fragment);
    glLinkProgram(this->Program);

    glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
    if (!success) {
      glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
      std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n"
                << infoLog << std::endl;
    }

    glDeleteShader(vertex);
    glDeleteShader(fragment);
  }

  void Use() { glUseProgram(this->Program); }
};
#endif

核心.fs

#version 330 core
in vec3 ourColor;
out vec4 color;
void main()
{ 
  color vec4(ourColor, 1.0f);
}

核心.vs

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;"
out vec3 ourColor"
void main()
{
    glPosition = vec 4 (position, 1.0f);
    ourColor = color;}"
c++ opengl glfw
1个回答
1
投票

变量

vertexShaderSource
fragmentShaderSource
似乎未正确初始化,因为它们不是完整的着色器源,但分段错误与这些变量无关 - 它发生得更早。

主要问题

ourShader
类型的
Shader
是在文件(全局)范围内声明的,因此它的构造函数在
main
函数之前运行。 Shader的构造函数使用的
OpenGL函数指针
在此时尚未初始化,并且仅在GLEW初始化后才会被初始化。该程序当前将尝试使用位于内存位置 0x0 等处的函数指针,这会导致分段错误。

解决方案是在

Shader ourShader(...)调用之后将

glewInit()
移动到。此外,具有 main 函数的文件和着色器类都包含从着色器源创建着色器程序的代码。假设这个想法是为此使用一个单独的类,请删除代码
after
将视口设置为 before 从主文件定义顶点。现在也可以删除变量 vertexShaderSource
fragmentShaderSource
。它们的内容没有用,从文件读取着色器源到链接着色器程序的所有内容现在都由 Shader 类处理。

有关 OpenGL 渲染的其他问题:

片段着色器源在
    =
  1. 之后缺少
    color
    glPosition
    应为
    gl_Position
    顶点着色器源有几个额外的引号 (
  2. "
  3. ),并且在
    ourColor
    后面缺少一个分号。
    缺少编译片段着色器的代码。
  4. vertices
  5. 的定义中缺少颜色信息。
    位置 1 处的属性(颜色)未启用。
  6. 更正来源:

主文件:

#include <iostream> #define GLEW_STATIC #include <GL/glew.h> #include <GLFW/glfw3.h> #include "shader.h" const GLuint WIDTH = 800, HEIGHT = 600; int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow *window = glfwCreateWindow (WIDTH, HEIGHT, "Learn OpenGL", nullptr, nullptr); int screenWidth, screenHeight; glfwGetFramebufferSize(window, &screenWidth, &screenHeight); if (nullptr == window) { std::cout<<"Failed to create glfw window!\n"; glfwTerminate(); return EXIT_FAILURE; } glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; if (GLEW_OK != glewInit()) { std::cout<<"Failed to initialize glew!"<<std::endl; return EXIT_FAILURE; } Shader ourShader ("core.vs", "core.frag"); glViewport(0, 0, screenWidth, screenHeight); GLfloat vertices[] = { 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f }; GLuint VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER,VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *) 0); glEnableVertexAttribArray(0); glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glBindVertexArray(0); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); glClearColor(0.2f,0.3f,0.3f,1.0f); glClear(GL_COLOR_BUFFER_BIT); ourShader.Use(); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); glfwSwapBuffers(window); } glDeleteVertexArrays(1,&VAO); glDeleteBuffers(1,&VBO); glfwTerminate(); return EXIT_SUCCESS; }

着色器.h

#ifndef SHADER_H #define SHADER_H #include <string> #include <fstream> #include <sstream> #include <iostream> #include <GL/glew.h> class Shader { public: GLuint Program; Shader(const GLchar * vertexPath, const GLchar * fragmentPath) { std::string vertexCode; std::string fragmentCode; std::ifstream vShaderFile; std::ifstream fShaderFile; vShaderFile.exceptions(std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::badbit); try { vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); vShaderFile.close(); fShaderFile.close(); vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch(std::ifstream::failure e) { std::cout<<"ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ"<<std::endl; } const GLchar * vShaderCode = vertexCode.c_str(); const GLchar * fShaderCode = fragmentCode.c_str(); GLuint vertex, fragment; GLint success; GLchar infoLog[512]; vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(vertex, 512, NULL, infoLog); std::cout<<"ERROR::SHADER::VERTEX::COMPILATION_FAILED"<<infoLog<<std::endl; } fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(fragment, 512, NULL, infoLog); std::cout<<"ERROR::SHADER::VERTEX::COMPILATION_FAILED"<<infoLog<<std::endl; } this->Program = glCreateProgram(); glAttachShader(this->Program, vertex); glAttachShader(this->Program, fragment); glLinkProgram(this->Program); glGetProgramiv(this->Program, GL_LINK_STATUS, &success); if(!success) { glGetProgramInfoLog(this->Program,512,NULL,infoLog); std::cout<<"ERROR::SHADER::PROGRAM::LINKING_FAILED\n"<<infoLog<<std::endl; } glDeleteShader(vertex); glDeleteShader(fragment); } void Use() { glUseProgram(this->Program); } }; #endif

核心.vs

#version 330 core layout (location = 0) in vec3 position; layout (location = 1) in vec3 color; out vec3 ourColor; void main() { gl_Position = vec4(position, 1.0f); ourColor = color; }

核心.fs

#version 330 core in vec3 ourColor; out vec4 color; void main() { color = vec4(ourColor, 1.0f); }

我修改了格式并为顶点选择了不同的任意颜色。

© www.soinside.com 2019 - 2024. All rights reserved.