opengl 着色器抽象后仅绘制白色三角形

xu3bshqb  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(137)

我一直在关注YouTube上关于使用OpenGL的教程,并将其整合到现有的项目中。当我将着色器源代码声明为硬编码的c字符串时,一切都正确绘制,但当我看到this视频将着色器抽象到自己的类和文件中时,我突然只得到白色三角形。我不知道我做错了什么,因为我复制粘贴到一个文本文件的确切着色器代码。
我使用上面来自this博客的视频中建议的代码来读取文件:

#include <fstream>
#include <string>
#include <cerrno>

std::string get_file_contents(const char *filename)
{
  std::ifstream in(filename, std::ios::in | std::ios::binary);
  if (in)
  {
    std::string contents;
    in.seekg(0, std::ios::end);
    contents.resize(in.tellg());
    in.seekg(0, std::ios::beg);
    in.read(&contents[0], contents.size());
    in.close();
    return(contents);
  }
  throw(errno);
}

字符串
我在编译、链接或阅读着色器文件时没有错误,所以我很困惑。我已经在这里研究了一些类似的问题,所有的答案要么不适合我的用法,要么不能解决这个问题。下面列出了着色器文件以及我如何使用着色器。我很感激你能给予我的任何帮助!<3

default.vert

#version 330 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 col;
out vec4 vertColor;
void main()
{
   gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
   vertColor   = vec4(col.x, col.y, col.z, 1.0);
}

default.frag

#version 330 core
in vec4 vertColor;
out vec4 FragColor;
void main()
{
   FragColor = vertColor;
}

shader.h

#include "gl/glew.h"

class Shader {
public:
    GLuint ID;

    Shader(const char*, const char*);
    ~Shader();
    void activate();
    void deactivate();
};

shader.cpp

#include "shader.h"
#include "gl/glew.h"
#include "GLFW/glfw3.h"
#include <fstream>
#include <string>
#include <cerrno>

std::string get_file_contents(const char* filename)
{
    std::ifstream in(filename, std::ios::in | std::ios::binary);
    if (in)
    {
        std::string contents;
        in.seekg(0, std::ios::end);
        contents.resize(in.tellg());
        in.seekg(0, std::ios::beg);
        in.read(&contents[0], contents.size());
        in.close();
        return(contents);
    }
    throw(errno);
}

Shader::Shader(const char* vertexFilename, const char* fragmentFilename) {
    // read in the shader files
    std::string vertexSourceString = get_file_contents(vertexFilename);
    std::string fragmentSourceString = get_file_contents(fragmentFilename);
    const char* vertexSource = vertexSourceString.c_str();
    const char* fragmentSource = fragmentSourceString.c_str();

    // create vertex shader
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexSource, NULL);
    glCompileShader(vertexShader);

    // create fragment shader
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
    glCompileShader(fragmentShader);

    // link shaders together
    ID = glCreateProgram();
    glAttachShader(ID, vertexShader);
    glAttachShader(ID, fragmentShader);
    glLinkProgram(ID);

    // cleanup
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
}

Shader::~Shader() {
    glDeleteProgram(ID);
}

void Shader::activate() {
    glUseProgram(ID);
}

void Shader::deactivate() {
    glUseProgram(0);
}


main.cpp

const char* defaultVertexShaderSource = "../../../res/shaders/default.vert";
const char* defaultFragmentShaderSource = "../../../res/shaders/default.frag";
Shader defaultShader = Shader(defaultVertexShaderSource, defaultFragmentShaderSource);


然后,我通过渲染函数传递这个着色器对象,在那里它被用来绘制代表棋盘上空间的正方形。着色器的使用方式如下:

shader.activate();
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLES, 0, vertex_buffer_data.size() / 2);
shader.deactivate();


Edit:Per Botje's comment:下面是完整的图形管道代码:

GLuint vertex_buffer, vertex_array;
glGenVertexArrays(1, &vertex_array);
glGenBuffers(1, &vertex_buffer);

std::vector<float> vertex_buffer_data;

glm::vec3 top_right_corner = top_left_corner + square_top_right_offset;
glm::vec3 bottom_left_corner = top_left_corner + square_bottom_left_offset;
glm::vec3 bottom_right_corner = top_left_corner + square_bottom_right_offset;
glm::vec3 color = (is_black) ? BLACK_SQUARE_COLOR : WHITE_SQUARE_COLOR;

std::vector<glm::vec3*> vertices = {&top_left_corner, &top_right_corner, &bottom_left_corner, &top_right_corner, &bottom_left_corner, &bottom_right_corner};
for (auto vertex : vertices) {
    vertex_buffer_data.push_back(vertex->x);
    vertex_buffer_data.push_back(vertex->y);
    vertex_buffer_data.push_back(vertex->z);
    vertex_buffer_data.push_back(color.x);
    vertex_buffer_data.push_back(color.y);
    vertex_buffer_data.push_back(color.z);
}

glBindVertexArray(vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data.size() * sizeof(float), vertex_buffer_data.data(), GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

shader.activate();
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLES, 0, vertex_buffer_data.size() / 2);

shader.deactivate();
glBindVertexArray(0);
glDeleteVertexArrays(1, &vertex_array);
glDeleteBuffers(1, &vertex_buffer);

yftpprvb

yftpprvb1#

正如Botje指出的那样,问题在于着色器初始化在使用之前就被删除了。通过将着色器声明为堆变量,程序可以按预期工作。

相关问题