“Hello triangle”没有显示。有哪些函数使用不正确?

3
我的目标是达到能够像这个视频的最终结果一样的程度:https://www.youtube.com/watch?v=ZpAeH0SpR5Y&list=PL6xSOsbVA1eYSZTKBxnoXYboy7wc4yg-Z&index=13。然而,无论我运行什么代码,它都只给了我一个黑屏,尽管没有出现错误。

我已经尝试使用从4.4到4.6所有版本,但都不起作用。 VAO、VBO和EBO都被定义了,而改变每个函数的具体细节也没有起作用。我唯一的线索是core_program和VAO分别为3和1,这很可疑,因为它们应该包含更多数据(在第224行)。 当我下载GLFW时,教程指出要使用来自zip文件的文件版本比您使用的Visual Studio版本低一个版本,但我看到了一个glfw2019文件夹,于是我使用了它。也许这会改变一些东西?顺便说一下,我使用的是GLAD,而不是教程中使用的GLEW。 对于代码的数量,我很抱歉,但我无法将问题隔离到足够小的范围。(我也用奇怪的名称!)

libs.h:

#pragma once

#include <iostream>
#include <glad.h>
#include <glfw3.h>
#include <glm.hpp>
#include <vec2.hpp>
#include <vec3.hpp>
#include <vec4.hpp>
#include <mat4x4.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>

struct Vertex
{
    glm::vec3 position;
    glm::vec3 color;
    glm::vec2 texcoord;
};

vertexium.glsl:

#version 450
layout (location = 0) in vec3 vertex_position;
layout (location = 1) in vec3 vertex_color;
layout (location = 2) in vec2 vertex_texcoord;

out vec3 vs_position;
out vec3 vs_color;
out vec2 vs_texcoord;

void main()
{
    vs_position = vertex_position;
    vs_color = vertex_color;
    vs_texcoord = vec2(vertex_texcoord.x, vertex_texcoord.y * -1.f);

    gl_Position = vec4(vertex_position, 1.f);
}

fragmentium.glsl:

#version 450

in vec3 vs_position;
in vec3 vs_color;
in vec2 vs_texcoord;

out vec4 fs_color;

void main()
{
    fs_color = vec4(vs_color, 1.f);
}

最后是main.cpp:

#include "libs.h"
#include <fstream>
#include <string>

#include <vector>


//makes window size known
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

//loads shaders, obviously
bool loadShaders(GLuint& program)
{
    bool didItWork = true;
    char infoLog[512];
    GLint success;
    std::string temp = "";
    std::string src = "";
    std::ifstream in_file;

    //Vertexium, Activate!
    in_file.open("vertexium.glsl");
    if (in_file.is_open())
    {
        while (std::getline(in_file, temp))
            src += temp + "\n";
    }
    else
    {
        std::cout << "The program could not open the vertexium.";
        didItWork = false;
    }

    in_file.close();
    //replace with unsigned int if needed
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    const GLchar* vertSrc = src.c_str();
    glShaderSource(vertexShader, 1, &vertSrc, NULL);
    glCompileShader(vertexShader);

    //make sure it's good
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "The vertexium was not successfully compiled." << "\n";
        std::cout << infoLog << "\n";
        didItWork = false;
    }


    //Fragmentium, Activate!
    temp = "";
    src = "";

    in_file.open("fragmentium.glsl");
    if (in_file.is_open())
    {
        while (std::getline(in_file, temp))
            src += temp + "\n";
    }
    else
    {
        std::cout << "The program could not open the fragmentium.";
        didItWork = false;
    }

    in_file.close();
    //replace with unsigned int if needed
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    const GLchar* fragSrc = src.c_str();
    glShaderSource(fragmentShader, 1, &fragSrc, NULL);
    glCompileShader(fragmentShader);

    //make sure it's good
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "The fragmentium was not successfully compiled." << "\n";
        std::cout << infoLog << "\n";
        didItWork = false;
    }

    //program thingio
    program = glCreateProgram();

    //attach
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);

    glLinkProgram(program);

    //make sure
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if (!success)
    {
        glGetProgramInfoLog(program, 512, NULL, infoLog);
        std::cout << "The omega program was not successfully linked." << "\n";
        std::cout << infoLog << "\n";
        didItWork = false;
    }

    //end
    //start usin'
    glUseProgram(0);
    //yeetus deletus: we didn't need you
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    return didItWork;
}
//for escaping the system
void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GLFW_TRUE);
}
//triangle
Vertex vertices[] = 
{
    glm::vec3(0.0f, 0.5f, 0.f),         glm::vec3(1.f, 0.f, 0.f),       glm::vec2(0.f, 1.f),
    glm::vec3(-0.5f, -0.5f, 0.f),       glm::vec3(0.f, 1.f, 0.f),       glm::vec2(0.f, 0.f),
    glm::vec3(-0.5f, 0.5f, 0.f),        glm::vec3(0.f, 0.f, 1.f),       glm::vec2(1.f, 0.f)
};
//number = nr
unsigned nrOfVertices = sizeof(vertices) / sizeof(Vertex);

GLuint indices[] =
{
    0, 1, 2
};
unsigned nrOfIndices = sizeof(indices) / sizeof(GLuint);

//inputs

int main()
{
    //instantiation for window (is my favorite word)
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    //time for windows bois


    GLFWwindow* window = glfwCreateWindow(800, 600, "yoyleoscopy", NULL, NULL);
    glfwMakeContextCurrent(window);
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "Failed to initialise GLAD" << std::endl;
    }
    //make look good and stable sizing
    glViewport(0, 0, 800, 600);

    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    //stock options

    glEnable(GL_DEPTH_TEST);

    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glFrontFace(GL_CCW);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    //here is a program
    GLuint core_program;
    //load things
    if (!loadShaders(core_program))
    {
        glfwTerminate();
    }

    //model

    //VAO and binding
    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    //VBO and binding
    GLuint VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //EBO and binding
    GLuint EBO;
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    //vertexattribpointers and enabling extras (INPUT ASSEMBLY)
    //position
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position));
    glEnableVertexAttribArray(0);
    //color
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, color));
    glEnableVertexAttribArray(1);
    //texcoord
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, texcoord));
    glEnableVertexAttribArray(2);

    //bind VAO 0
    if (core_program)
    {
        std::cout << nrOfIndices;
    }
    glBindVertexArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //VERY IMPORTANT
    //THIS IS THE RENDER LOPP
    //LOPP IS A MISSPELLING (but i don't care, this makes it more noticeable)
    while (!glfwWindowShouldClose(window))
    {
        //input and stuff
        processInput(window);

        //RENDER STUFF
        //nice color there, chartreuse
        glClearColor(0.f, 0.f, 0.f, 1.f);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        //programme
        glUseProgram(core_program);
        //bind vertex array object
        glBindVertexArray(VAO);
        //draw
        //glDrawElements(GL_TRIANGLES, nrOfIndices, GL_UNSIGNED_INT, 0);
        glDrawArrays(GL_TRIANGLES, 0, 3);


        //gl background stuff i don't care about
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    //we're over it
    glfwDestroyWindow(window);
    glfwTerminate();

    //delete program
    glDeleteProgram(core_program);

    return 0;
}

再次打开窗口应该会有一个像彩虹般的三角形,但是这里显示的是一片黑屏。尽管编译和运行过程中没有错误或警告信息,希望有人能够找出问题所在。

1个回答

4
问题是由面剔除引起的。
三角形的卷绕顺序为顺时针:
Vertex vertices[] = 
{
   glm::vec3(0.0f, 0.5f, 0.f),         glm::vec3(1.f, 0.f, 0.f),       glm::vec2(0.f, 1.f),
   glm::vec3(-0.5f, -0.5f, 0.f),       glm::vec3(0.f, 1.f, 0.f),       glm::vec2(0.f, 0.f),
   glm::vec3(-0.5f, 0.5f, 0.f),        glm::vec3(0.f, 0.f, 1.f),       glm::vec2(1.f, 0.f)
};
2      0
 +----+
 |   /
 |  /
 | /
 |/
 +
1

但是您已经定义了背面被剔除而正面按逆时针方向:

glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);

有许多可能解决此问题。

其中一种可能是将定义的正面改为顺时针:

glFrontFace(GL_CW);

另一种可能性是保留 glFrontFace(GL_CWW),但使用索引来定义逆时针三角形:
GLuint indices[] = { 0, 2, 1 };

根据索引来绘制三角形:

glDrawElements(GL_TRIANGLES, nrOfIndices, GL_UNSIGNED_INT, 0);
//glDrawArrays(GL_TRIANGLES, 0, 3);

那就是它了。我记得当时想着如果出了什么问题,我会改变它,但我想我忘了这件事。谢谢! - XnossisX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接