【发布时间】:2021-08-18 21:55:37
【问题描述】:
我刚开始通过https://learnopengl.com/Getting-started/Hello-Triangle 学习 OpenGL,按照教程我根据我的理解编写了代码,该代码编译并确实给了我一个输出,但它不是一个橙色的三角形,而是一个白色的三角形。如果我用https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/2.1.hello_triangle/hello_triangle.cpp 中的代码替换shaderProgram() 它可以工作(显示橙色三角形),所以我认为我将问题缩小到着色器程序编译,我只是找不到它有什么问题,以下是我的代码.
// Local Headers
#include "glitter.hpp"
// System Headers
#include <glad/glad.h>
#include <GLFW/glfw3.h>
// Standard Headers
#include <cstdio>
#include <cstdlib>
#include <stdexcept>
#include <iostream>
#include <memory>
void _delete_shader(const GLuint *shader)
{
if (!shader) return;
glDeleteShader(*shader);
delete shader;
}
using shader_t = std::unique_ptr<GLuint, decltype(&_delete_shader)>;
// window resize callback
void framebuffer_size_callback(GLFWwindow* , int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
}
shader_t compileShader(const char *source, GLenum shaderType)
{
auto shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &source, nullptr);
glCompileShader(shader);
int success;
char log[512];
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, sizeof(log), nullptr, log);
throw std::runtime_error(log);
}
return shader_t(new GLuint {shader}, &_delete_shader);
}
shader_t vertexshader() try
{
static const char *source = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
)";
return compileShader(source, GL_VERTEX_SHADER);
}
catch(const std::exception& e)
{
printf("error in vertex shader, %s\n", e.what());
exit(-1);
}
shader_t fragmentShader() try
{
static const char *source = R"(
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
)";
return compileShader(source, GL_FRAGMENT_SHADER);
}
catch(const std::exception &e)
{
printf("error in fragment shader, %s\n", e.what());
exit(-1);
}
uint32_t shaderProgram() try
{
uint32_t program = glCreateProgram();
const auto vertexShader = ::vertexshader();
glAttachShader(program, *vertexShader);
const auto fragmentShader = ::fragmentShader();
glAttachShader(program, *fragmentShader);
glLinkProgram(program);
int success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success)
{
char log[512];
glGetProgramInfoLog(program, 512, nullptr, log);
throw std::runtime_error(log);
}
}
catch(const std::exception &e)
{
printf("error in shader program, %s\n", e.what());
exit(-1);
}
int main(int , char * [])
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
if (window == nullptr)
{
printf("Failed to create window\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
puts("Failed to initialize GLAD\n");
glfwTerminate();
return -1;
}
glViewport(0, 0, 800, 600);
float vertices[] =
{
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
const auto shaderProgram = ::shaderProgram();
unsigned int VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
// copy vertices into gpu memory
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// how data should be interpretted
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
{
// inputs
processInput(window);
// paint color
glClearColor(.2f, .3f, .3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// final rendering step
glfwSwapBuffers(window);
// check for events
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
【问题讨论】: