【发布时间】:2015-10-19 22:22:13
【问题描述】:
我正在使用 OpenGL 和 SFML。我是这两个方面的初学者。我正在阅读一些教程,并尝试自己调整一下。但我就是无法让下面的代码工作。它应该显示一个白色三角形,但它只显示黑屏。它不打印任何错误消息。
有几行注释掉了,它们将使用顶点缓冲区对象而不是当前使用的顶点数组。但这两个都不起作用。
我想我一定错过了一些非常简单的东西......但不知道是什么。
我的卡说它支持 OpenGL3.1,但这会是问题的根源吗?当我在 Qt 中尝试使用 OpenGL 的类似示例时,它运行良好。
#include <SFML/Window.hpp>
#include <GL/glew.h>
#include <iostream>
bool createShader(GLuint &shaderID, GLenum shaderType, const char* shaderSource)
{
shaderID = glCreateShader(shaderType);
glShaderSource(shaderID, 1, &shaderSource, 0);
glCompileShader(shaderID);
GLint compileStatus;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus == GL_TRUE)
return true;
// log error
GLint infoLogLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* buffer = new GLchar[infoLogLength];
glGetShaderInfoLog(shaderID, infoLogLength, &infoLogLength, buffer);
std::cerr << buffer << std::endl;
delete[] buffer;
return false;
}
bool createShaderProgram(GLuint &programID)
{
const char *vertexShaderSource =
"attribute vec2 position;\n"
"void main() {\n"
" gl_Position = vec4(position, 0.0, 0.0);\n"
"}\n";
const char *fragmentShaderSource =
"void main() {\n"
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
"}\n";
GLuint vertexShaderID;
if (! createShader(vertexShaderID, GL_VERTEX_SHADER, vertexShaderSource))
return false;
GLuint fragmentShaderID;
if (! createShader(fragmentShaderID, GL_FRAGMENT_SHADER, fragmentShaderSource))
return false;
programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
GLint linkStatus;
glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus);
if (linkStatus == GL_TRUE)
return true;
// log error
GLint infoLogLength;
glGetShaderiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* buffer = new GLchar[infoLogLength];
glGetShaderInfoLog(programID, infoLogLength, &infoLogLength, buffer);
std::cerr << buffer << std::endl;
delete[] buffer;
return false;
}
int main()
{
sf::Window window(sf::VideoMode(800, 600), "OpenGL", sf::Style::Default, sf::ContextSettings(32));
window.setVerticalSyncEnabled(true);
GLenum err = glewInit();
if (GLEW_OK != err)
{
std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
exit(1);
}
std::cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;
GLuint programID;
if (! createShaderProgram(programID))
exit(1);
glUseProgram(programID);
static const GLfloat vertices[] =
{
0.0f, 1.0f,
-1.0f, -1.0f,
1.0f, -1.0f
};
//GLuint vertexBufferID;
//glGenBuffers(1, &vertexBufferID);
//glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLint posAttrID = glGetAttribLocation(programID, "position");
glVertexAttribPointer(posAttrID, 2, GL_FLOAT, GL_FALSE, 0, vertices); // 0);
glEnableVertexAttribArray(posAttrID);
bool running = true;
while (running)
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
running = false;
}
else if (event.type == sf::Event::Resized)
{
glViewport(0, 0, event.size.width, event.size.height);
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
window.display();
}
// release resources...
return 0;
}
更新:
下面的一些人建议我必须使用 VBO 和 VAO。真的吗?或者它只是可选的以获得更好的性能?我不能将数据从普通 RAM 发送到 glVertexAttribPointer() 吗?
我还在支持 OpenGL4.4 的台式机上尝试了上面的代码(之前我只尝试了支持 OpenGL3.1 的集成显卡的懒惰笔记本电脑),结果是:整个屏幕都是白色的。之前是黑色的。为什么?老实说,我不明白。
【问题讨论】:
-
VAO 不是 VBO的替代品。在现代 GL 中你需要both。
-
我没有以任何方式使用或提到过 VAO,我知道它是完全不同的东西(上下文处理、绑定、不绑定的东西等)。而且我坚信如果我可以手动绑定/取消绑定东西,我根本不需要使用 VAO。
-
现代 GL 需要 VAO。但无论如何,顶点数组也不是 VBO 的替代品,您需要将顶点数组放入 VBO。现在不清楚你是否打算使用现代 GL,我也不知道 SFML 默认会创建什么上下文。
-
我不明白。您是否建议如果我也使用 VAO,那么它可以工作吗?好吧,我对此不确定,因为我看过即使没有 VAO 也能工作的教程。还是您的意思是我的 SFML 使用了甚至不支持 VBO 的“旧”上下文?
-
VAO 是一个 OpenGL 对象,它存储属性的格式以及存储数据的缓冲区。因此,VAO 仅引用缓冲区对象。缓冲区对象具有包含数据的数据存储,但它们对该数据一无所知。所以你需要两者,因为它们具有非常不同的功能。是的,旧技术不需要您使用 VAO 或缓冲区(如 glBegin()/glEnd())