使用 OpenGL 创建三角形
Creating a triangle with OpenGL
我在使用 OpenGL 程序的 C++ 代码时遇到问题,该程序应该创建一个 2D 三角形并不断收到此错误消息:
Error! Fragment shader failed to compile.
ERROR: 0:1: '' : syntax error: #version directive must occur in a shader before anything else.
Error! Shader Program Linker Failure.
我尝试将第 13-27 行的代码放在 const char* APP_TITLE 行(第 8 行)之前,但这似乎没有什么不同。
如何生成这个 2D 三角形?
#include <iostream>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
const char* APP_TITLE = "Texturing a Pyramid";
const int gwindowWidth = 800;
const int gwindowHeight = 600;
GLFWwindow* gWindow = NULL;
const GLchar* vertexShaderSrc =
"#version 330 core\n"
"layout (location = 0) in vec3 pos;"
"void main()"
"{"
" gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);"
"}";
const GLchar* fragmentShaderSrc =
"version 330 core\n"
"out vec4 frag_color;"
"void main()"
"{"
" frag_color = vec4(0.35f, 0.96f, 0.3f, 1.0);"
"}";
void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mode);
void showFPS(GLFWwindow* window);
bool initOpenGL();
int main()
{
if (!initOpenGL())
{
std::cerr << "GLFW intialization failed." << std::endl;
return false;
}
GLfloat vertices[] = {
0.0f, 0.5f, 0.0f, // Top Vertex
0.5f, -0.5f, 0.0f, // Right Vertex
-0.5f, -0.5f, 0.0f // Left Vertex
};
GLuint vbo, vao;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource (vs, 1, &vertexShaderSrc, NULL);
glCompileShader(vs);
GLint result;
GLchar infoLog[512];
glGetShaderiv(vs, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(vs, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Vertex shader failed to compile." << infoLog << std::endl;
}
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource (fs, 1, &fragmentShaderSrc, NULL);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(fs, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Fragment shader failed to compile." << infoLog << std::endl;
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vs);
glAttachShader(shaderProgram, fs);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderProgram, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Shader Program Linker Failure" << std::endl;
}
glDeleteShader(vs);
glDeleteShader(fs);
// Main loop
while (!glfwWindowShouldClose(gWindow))
{
showFPS(gWindow);
glfwPollEvents();
glfwSwapBuffers(gWindow);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSetKeyCallback(gWindow, glfw_onKey);
}
glDeleteProgram(shaderProgram);
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glfwTerminate();
return 0;
}
bool initOpenGL()
{
if (!glfwInit())
{
std::cerr << "GLFW initialization failed." << std::endl;
return -1;
}
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);
GLFWwindow* gWindow = glfwCreateWindow(gwindowWidth, gwindowHeight, APP_TITLE, NULL, NULL);
if (gWindow == NULL)
{
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(gWindow);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cerr << "GLEW initialization failed." << std::endl;
return false;
}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
return true;
}
void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void showFPS(GLFWwindow* window)
{
static double previousSeconds = 0.0;
static int frameCount = 0;
double elapsedSeconds;
double currentSeconds = glfwGetTime(); // returns # of seconds since GLFW started, as a double
elapsedSeconds = currentSeconds - previousSeconds;
// limit text update 4 times per second
if (elapsedSeconds > 0.25)
{
previousSeconds = currentSeconds;
double fps = (double)frameCount / elapsedSeconds;
double msPerFrame = 1000.0 / fps;
std::ostringstream outs;
outs.precision(3);
outs << std::fixed
<< APP_TITLE << " "
<< "FPS: " << fps << " "
<< "FrameTime: " << msPerFrame << " (ms)";
glfwSetWindowTitle(window, outs.str().c_str());
frameCount = 0;
}
frameCount++;
}
fragmentShaderSrc
在 version
前面缺少一个 #
(U+0023 NUMBER SIGN):
"version 330 core\n"
^ note lack of #
应该是:
"#version 330 core\n"
^ note the #
我在使用 OpenGL 程序的 C++ 代码时遇到问题,该程序应该创建一个 2D 三角形并不断收到此错误消息:
Error! Fragment shader failed to compile.
ERROR: 0:1: '' : syntax error: #version directive must occur in a shader before anything else.
Error! Shader Program Linker Failure.
我尝试将第 13-27 行的代码放在 const char* APP_TITLE 行(第 8 行)之前,但这似乎没有什么不同。
如何生成这个 2D 三角形?
#include <iostream>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
const char* APP_TITLE = "Texturing a Pyramid";
const int gwindowWidth = 800;
const int gwindowHeight = 600;
GLFWwindow* gWindow = NULL;
const GLchar* vertexShaderSrc =
"#version 330 core\n"
"layout (location = 0) in vec3 pos;"
"void main()"
"{"
" gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);"
"}";
const GLchar* fragmentShaderSrc =
"version 330 core\n"
"out vec4 frag_color;"
"void main()"
"{"
" frag_color = vec4(0.35f, 0.96f, 0.3f, 1.0);"
"}";
void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mode);
void showFPS(GLFWwindow* window);
bool initOpenGL();
int main()
{
if (!initOpenGL())
{
std::cerr << "GLFW intialization failed." << std::endl;
return false;
}
GLfloat vertices[] = {
0.0f, 0.5f, 0.0f, // Top Vertex
0.5f, -0.5f, 0.0f, // Right Vertex
-0.5f, -0.5f, 0.0f // Left Vertex
};
GLuint vbo, vao;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource (vs, 1, &vertexShaderSrc, NULL);
glCompileShader(vs);
GLint result;
GLchar infoLog[512];
glGetShaderiv(vs, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(vs, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Vertex shader failed to compile." << infoLog << std::endl;
}
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource (fs, 1, &fragmentShaderSrc, NULL);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(fs, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Fragment shader failed to compile." << infoLog << std::endl;
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vs);
glAttachShader(shaderProgram, fs);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderProgram, sizeof(infoLog), NULL, infoLog);
std::cout << "Error! Shader Program Linker Failure" << std::endl;
}
glDeleteShader(vs);
glDeleteShader(fs);
// Main loop
while (!glfwWindowShouldClose(gWindow))
{
showFPS(gWindow);
glfwPollEvents();
glfwSwapBuffers(gWindow);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSetKeyCallback(gWindow, glfw_onKey);
}
glDeleteProgram(shaderProgram);
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glfwTerminate();
return 0;
}
bool initOpenGL()
{
if (!glfwInit())
{
std::cerr << "GLFW initialization failed." << std::endl;
return -1;
}
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);
GLFWwindow* gWindow = glfwCreateWindow(gwindowWidth, gwindowHeight, APP_TITLE, NULL, NULL);
if (gWindow == NULL)
{
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(gWindow);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cerr << "GLEW initialization failed." << std::endl;
return false;
}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
return true;
}
void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void showFPS(GLFWwindow* window)
{
static double previousSeconds = 0.0;
static int frameCount = 0;
double elapsedSeconds;
double currentSeconds = glfwGetTime(); // returns # of seconds since GLFW started, as a double
elapsedSeconds = currentSeconds - previousSeconds;
// limit text update 4 times per second
if (elapsedSeconds > 0.25)
{
previousSeconds = currentSeconds;
double fps = (double)frameCount / elapsedSeconds;
double msPerFrame = 1000.0 / fps;
std::ostringstream outs;
outs.precision(3);
outs << std::fixed
<< APP_TITLE << " "
<< "FPS: " << fps << " "
<< "FrameTime: " << msPerFrame << " (ms)";
glfwSetWindowTitle(window, outs.str().c_str());
frameCount = 0;
}
frameCount++;
}
fragmentShaderSrc
在 version
前面缺少一个 #
(U+0023 NUMBER SIGN):
"version 330 core\n"
^ note lack of #
应该是:
"#version 330 core\n"
^ note the #