具有 OpenGL VBO 和着色器的 Qt 应用程序不产生输出
我正在尝试使用直接从 Qt OpenGL 示例中获取的一些代码在屏幕上显示一些内容。但是,我无法在屏幕上显示任何内容。所有 GL 函数似乎都返回正确的值,并且错误日志没有显示任何问题。调试完全不工作的 VBO/着色器的最佳方法是什么?
这是我的着色器代码:
QGLShaderProgram* ShaderFactory::buildFlatShader(QObject *parent)
{
string vertSource = string("in vec3 vertex;\n" \
"in vec2 a_texcoord;\n" \
"uniform mat4 objToWorld;\n" \
"uniform mat4 cameraPV;\n" \
"void main() {\n" \
" gl_Position = cameraPV * objToWorld * vec4(vertex,1.0);\n" \
" gl_FrontColor = vec4(a_texcoord.x, 1, 0, 1);\n" \
"}\n");
string fragSource = string("void main() {\n" \
" gl_FragColor = gl_Color;\n" \
"}\n");
QGLShader* vertShader = new QGLShader(QGLShader::Vertex);
vertShader->compileSourceCode(vertSource.c_str());
QGLShader* fragShader = new QGLShader(QGLShader::Fragment);
fragShader->compileSourceCode(fragSource.c_str());
QGLShaderProgram* program = new QGLShaderProgram(parent);
program->addShader(vertShader);
program->addShader(fragShader);
program->link();
cout << program->log().toStdString() << endl;
cout << "Log end--" << endl;
return program;
}
QGLShaderProgram* ShaderFactory::buildShader(QObject *parent)
{
string vertSource = string("in vec3 vertex;\n" \
"in vec3 normal;\n" \
"in vec4 color;\n" \
"varying vec3 worldNormal;\n" \
"varying vec3 worldPos;\n" \
"uniform vec3 cameraPos;\n" \
"uniform mat4 objToWorld;\n" \
"uniform mat4 cameraV;\n" \
"uniform mat4 cameraP;\n" \
"uniform mat4 cameraPV;\n" \
"void main() {\n" \
" gl_Position = cameraPV * objToWorld * vec4(vertex,1.0);\n" \
" gl_FrontColor = color;\n" \
" gl_BackColor = color;\n" \
" worldPos = vertex;\n" \
" worldNormal = normal;\n" \
"}\n");
string fragSource = string("varying vec3 worldNormal;\n" \
"varying vec3 worldPos;\n" \
"uniform vec3 cameraPos;\n" \
"uniform vec3 lightDir;\n" \
"uniform vec4 singleColor;\n" \
"uniform float isSingleColor;\n" \
"void main() {\n" \
" vec3 L = lightDir;\n" \
" vec3 V = normalize(cameraPos - worldPos);\n" \
" vec3 N = normalize(worldNormal);\n" \
" vec3 H = normalize(L+V);\n" \
" vec4 color = isSingleColor*singleColor + (1.0-isSingleColor)*gl_Color;\n" \
" //vec4 color = gl_Color;\n" \
" float amb = .4;\n" \
" vec4 ambient = color * amb;\n" \
" vec4 diffuse = color * (1.0 - amb) * max(dot(L, N), 0.0);\n" \
" vec4 specular = vec4(0);\n" \
" gl_FragColor = vec4(ambient + diffuse + specular);\n" \
"}\n");
QGLShader* vertShader = new QGLShader(QGLShader::Vertex);
vertShader->compileSourceCode(vertSource.c_str());
QGLShader* fragShader = new QGLShader(QGLShader::Fragment);
fragShader->compileSourceCode(fragSource.c_str());
QGLShaderProgram* program = new QGLShaderProgram(parent);
program->addShader(vertShader);
program->addShader(fragShader);
return program;
}
这是我的 OpenGL 代码
PanelGL::PanelGL() : QGLWidget(PanelGL::defaultFormat())
{
setMouseTracking(true);
_validShaders = false;
camera = new Camera();
if (mainGrid == NULL) {
int range[] = {-10,10};
int numSegments = range[1]-range[0]+1;
QVector<LineSegment> segments(numSegments);
for (int i = 0; i < numSegments; i++) {
segments[i].p1 = Point3(i, 0, 10);
segments[i].p2 = Point3(i, 0, -10);
segments[i].r = 0.4f;
segments[i].g = 0.4f;
segments[i].b = 0.4f;
}
mainGrid = new LineRenderer(segments, 2);
}
}
QGLFormat PanelGL::defaultFormat()
{
QGLFormat format;
//format.setVersion(3,2);
//format.setProfile(QGLFormat::CompatibilityProfile);
return format;
}
bool glewInitialized = false;
void PanelGL::initializeGL()
{
if (!glewInitialized) {
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
cerr << "Error: " << glewGetErrorString(err) << endl;
}
}
}
void PanelGL::paintGL()
{
glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glEnable(GL_DEPTH_TEST);
if (!_validShaders) {
_dummyShader = ShaderFactory::buildShader(this);
_flatShader = ShaderFactory::buildFlatShader(this);
_validShaders = true;
}
// render the grid
mainGrid->render(this);
//glDisable(GL_DEPTH_TEST);
}
void PanelGL::resizeGL(int width, int height)
{
glViewport(0,0,width,height);
}
LineRenderer::LineRenderer(QVector<LineSegment> segments, float lineWidth)
{
_validVBOs = FALSE;
//_segments = segments;
_lineWidth = lineWidth;
}
struct VertexData
{
Vector3 position;
Vector2 texCoord;
};
void LineRenderer::render(PanelGL* panel)
{
if (!_validVBOs) {
glGenBuffers(2, _vboIds);
_validVBOs = TRUE;
}
loadVBOs(panel);
Camera* camera = panel->camera;
QMatrix4x4 cameraViewM = Camera::getViewMatrix(camera,panel->width(),panel->height());
QMatrix4x4 cameraProjM = Camera::getProjMatrix(camera,panel->width(),panel->height());
QMatrix4x4 cameraProjViewM = cameraProjM * cameraViewM;
QMatrix4x4 objToWorld;
QGLShaderProgram* flatShader = panel->getFlatShader();
glLineWidth(_lineWidth);
flatShader->bind();
int objToWorldLoc = flatShader->attributeLocation("objToWorld");
flatShader->setUniformValue(objToWorldLoc, objToWorld);
int cameraPVLoc = flatShader->attributeLocation("cameraPV");
flatShader->setUniformValue(cameraPVLoc, cameraProjViewM);
int overrideStrengthLoc = flatShader->attributeLocation("overrideStrength");
flatShader->setUniformValue(overrideStrengthLoc, 0.0f);
// Tell OpenGL which VBOs to use
glBindBuffer(GL_ARRAY_BUFFER, _vboIds[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIds[1]);
// Offset for position
int offset = 0;
// Tell OpenGL programmable pipeline how to locate vertex position data
int vertexLocation = flatShader->attributeLocation("vertex");
flatShader->enableAttributeArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);
// Offset for texture coordinate
offset += sizeof(QVector3D);
// Tell OpenGL programmable pipeline how to locate vertex texture coordinate data
int texcoordLocation = flatShader->attributeLocation("a_texcoord");
flatShader->enableAttributeArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);
// Draw cube geometry using indices from VBO 1
glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, 0);
//drawSegments.call
flatShader->release();
}
void LineRenderer::loadVBOs(PanelGL* panel)
{
VertexData vertices[] = {
// Vertex data for face 0
{QVector3D(-1.0, -1.0, 1.0), QVector2D(0.0, 0.0)}, // v0
{QVector3D( 1.0, -1.0, 1.0), QVector2D(0.33, 0.0)}, // v1
{QVector3D(-1.0, 1.0, 1.0), QVector2D(0.0, 0.5)}, // v2
{QVector3D( 1.0, 1.0, 1.0), QVector2D(0.33, 0.5)}, // v3
// Vertex data for face 1
{QVector3D( 1.0, -1.0, 1.0), QVector2D( 0.0, 0.5)}, // v4
{QVector3D( 1.0, -1.0, -1.0), QVector2D(0.33, 0.5)}, // v5
{QVector3D( 1.0, 1.0, 1.0), QVector2D(0.0, 1.0)}, // v6
{QVector3D( 1.0, 1.0, -1.0), QVector2D(0.33, 1.0)}, // v7
// Vertex data for face 2
{QVector3D( 1.0, -1.0, -1.0), QVector2D(0.66, 0.5)}, // v8
{QVector3D(-1.0, -1.0, -1.0), QVector2D(1.0, 0.5)}, // v9
{QVector3D( 1.0, 1.0, -1.0), QVector2D(0.66, 1.0)}, // v10
{QVector3D(-1.0, 1.0, -1.0), QVector2D(1.0, 1.0)}, // v11
// Vertex data for face 3
{QVector3D(-1.0, -1.0, -1.0), QVector2D(0.66, 0.0)}, // v12
{QVector3D(-1.0, -1.0, 1.0), QVector2D(1.0, 0.0)}, // v13
{QVector3D(-1.0, 1.0, -1.0), QVector2D(0.66, 0.5)}, // v14
{QVector3D(-1.0, 1.0, 1.0), QVector2D(1.0, 0.5)}, // v15
// Vertex data for face 4
{QVector3D(-1.0, -1.0, -1.0), QVector2D(0.33, 0.0)}, // v16
{QVector3D( 1.0, -1.0, -1.0), QVector2D(0.66, 0.0)}, // v17
{QVector3D(-1.0, -1.0, 1.0), QVector2D(0.33, 0.5)}, // v18
{QVector3D( 1.0, -1.0, 1.0), QVector2D(0.66, 0.5)}, // v19
// Vertex data for face 5
{QVector3D(-1.0, 1.0, 1.0), QVector2D(0.33, 0.5)}, // v20
{QVector3D( 1.0, 1.0, 1.0), QVector2D(0.66, 0.5)}, // v21
{QVector3D(-1.0, 1.0, -1.0), QVector2D(0.33, 1.0)}, // v22
{QVector3D( 1.0, 1.0, -1.0), QVector2D(0.66, 1.0)} // v23
};
// Indices for drawing cube faces using triangle strips.
// Triangle strips can be connected by duplicating indices
// between the strips. If connecting strips have opposite
// vertex order then last index of the first strip and first
// index of the second strip needs to be duplicated. If
// connecting strips have same vertex order then only last
// index of the first strip needs to be duplicated.
GLushort indices[] = {
0, 1, 2, 3, 3, // Face 0 - triangle strip ( v0, v1, v2, v3)
4, 4, 5, 6, 7, 7, // Face 1 - triangle strip ( v4, v5, v6, v7)
8, 8, 9, 10, 11, 11, // Face 2 - triangle strip ( v8, v9, v10, v11)
12, 12, 13, 14, 15, 15, // Face 3 - triangle strip (v12, v13, v14, v15)
16, 16, 17, 18, 19, 19, // Face 4 - triangle strip (v16, v17, v18, v19)
20, 20, 21, 22, 23 // Face 5 - triangle strip (v20, v21, v22, v23)
};
// Transfer vertex data to VBO 0
glBindBuffer(GL_ARRAY_BUFFER, _vboIds[0]);
glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(VertexData), vertices, GL_STATIC_DRAW);
// Transfer index data to VBO 1
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIds[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 34 * sizeof(GLushort), indices, GL_STATIC_DRAW);
}
I'm trying to get something up on my screen using some code I took directly from a Qt OpenGL example. However, I can't get anything to show up on my screen. All the GL functions seem to return correct values and the error log doesn't show any problems. What's the best way to debug a VBO/shader that's not working at all?
This is my shader code:
QGLShaderProgram* ShaderFactory::buildFlatShader(QObject *parent)
{
string vertSource = string("in vec3 vertex;\n" \
"in vec2 a_texcoord;\n" \
"uniform mat4 objToWorld;\n" \
"uniform mat4 cameraPV;\n" \
"void main() {\n" \
" gl_Position = cameraPV * objToWorld * vec4(vertex,1.0);\n" \
" gl_FrontColor = vec4(a_texcoord.x, 1, 0, 1);\n" \
"}\n");
string fragSource = string("void main() {\n" \
" gl_FragColor = gl_Color;\n" \
"}\n");
QGLShader* vertShader = new QGLShader(QGLShader::Vertex);
vertShader->compileSourceCode(vertSource.c_str());
QGLShader* fragShader = new QGLShader(QGLShader::Fragment);
fragShader->compileSourceCode(fragSource.c_str());
QGLShaderProgram* program = new QGLShaderProgram(parent);
program->addShader(vertShader);
program->addShader(fragShader);
program->link();
cout << program->log().toStdString() << endl;
cout << "Log end--" << endl;
return program;
}
QGLShaderProgram* ShaderFactory::buildShader(QObject *parent)
{
string vertSource = string("in vec3 vertex;\n" \
"in vec3 normal;\n" \
"in vec4 color;\n" \
"varying vec3 worldNormal;\n" \
"varying vec3 worldPos;\n" \
"uniform vec3 cameraPos;\n" \
"uniform mat4 objToWorld;\n" \
"uniform mat4 cameraV;\n" \
"uniform mat4 cameraP;\n" \
"uniform mat4 cameraPV;\n" \
"void main() {\n" \
" gl_Position = cameraPV * objToWorld * vec4(vertex,1.0);\n" \
" gl_FrontColor = color;\n" \
" gl_BackColor = color;\n" \
" worldPos = vertex;\n" \
" worldNormal = normal;\n" \
"}\n");
string fragSource = string("varying vec3 worldNormal;\n" \
"varying vec3 worldPos;\n" \
"uniform vec3 cameraPos;\n" \
"uniform vec3 lightDir;\n" \
"uniform vec4 singleColor;\n" \
"uniform float isSingleColor;\n" \
"void main() {\n" \
" vec3 L = lightDir;\n" \
" vec3 V = normalize(cameraPos - worldPos);\n" \
" vec3 N = normalize(worldNormal);\n" \
" vec3 H = normalize(L+V);\n" \
" vec4 color = isSingleColor*singleColor + (1.0-isSingleColor)*gl_Color;\n" \
" //vec4 color = gl_Color;\n" \
" float amb = .4;\n" \
" vec4 ambient = color * amb;\n" \
" vec4 diffuse = color * (1.0 - amb) * max(dot(L, N), 0.0);\n" \
" vec4 specular = vec4(0);\n" \
" gl_FragColor = vec4(ambient + diffuse + specular);\n" \
"}\n");
QGLShader* vertShader = new QGLShader(QGLShader::Vertex);
vertShader->compileSourceCode(vertSource.c_str());
QGLShader* fragShader = new QGLShader(QGLShader::Fragment);
fragShader->compileSourceCode(fragSource.c_str());
QGLShaderProgram* program = new QGLShaderProgram(parent);
program->addShader(vertShader);
program->addShader(fragShader);
return program;
}
This is my OpenGL code
PanelGL::PanelGL() : QGLWidget(PanelGL::defaultFormat())
{
setMouseTracking(true);
_validShaders = false;
camera = new Camera();
if (mainGrid == NULL) {
int range[] = {-10,10};
int numSegments = range[1]-range[0]+1;
QVector<LineSegment> segments(numSegments);
for (int i = 0; i < numSegments; i++) {
segments[i].p1 = Point3(i, 0, 10);
segments[i].p2 = Point3(i, 0, -10);
segments[i].r = 0.4f;
segments[i].g = 0.4f;
segments[i].b = 0.4f;
}
mainGrid = new LineRenderer(segments, 2);
}
}
QGLFormat PanelGL::defaultFormat()
{
QGLFormat format;
//format.setVersion(3,2);
//format.setProfile(QGLFormat::CompatibilityProfile);
return format;
}
bool glewInitialized = false;
void PanelGL::initializeGL()
{
if (!glewInitialized) {
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
cerr << "Error: " << glewGetErrorString(err) << endl;
}
}
}
void PanelGL::paintGL()
{
glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glEnable(GL_DEPTH_TEST);
if (!_validShaders) {
_dummyShader = ShaderFactory::buildShader(this);
_flatShader = ShaderFactory::buildFlatShader(this);
_validShaders = true;
}
// render the grid
mainGrid->render(this);
//glDisable(GL_DEPTH_TEST);
}
void PanelGL::resizeGL(int width, int height)
{
glViewport(0,0,width,height);
}
LineRenderer::LineRenderer(QVector<LineSegment> segments, float lineWidth)
{
_validVBOs = FALSE;
//_segments = segments;
_lineWidth = lineWidth;
}
struct VertexData
{
Vector3 position;
Vector2 texCoord;
};
void LineRenderer::render(PanelGL* panel)
{
if (!_validVBOs) {
glGenBuffers(2, _vboIds);
_validVBOs = TRUE;
}
loadVBOs(panel);
Camera* camera = panel->camera;
QMatrix4x4 cameraViewM = Camera::getViewMatrix(camera,panel->width(),panel->height());
QMatrix4x4 cameraProjM = Camera::getProjMatrix(camera,panel->width(),panel->height());
QMatrix4x4 cameraProjViewM = cameraProjM * cameraViewM;
QMatrix4x4 objToWorld;
QGLShaderProgram* flatShader = panel->getFlatShader();
glLineWidth(_lineWidth);
flatShader->bind();
int objToWorldLoc = flatShader->attributeLocation("objToWorld");
flatShader->setUniformValue(objToWorldLoc, objToWorld);
int cameraPVLoc = flatShader->attributeLocation("cameraPV");
flatShader->setUniformValue(cameraPVLoc, cameraProjViewM);
int overrideStrengthLoc = flatShader->attributeLocation("overrideStrength");
flatShader->setUniformValue(overrideStrengthLoc, 0.0f);
// Tell OpenGL which VBOs to use
glBindBuffer(GL_ARRAY_BUFFER, _vboIds[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIds[1]);
// Offset for position
int offset = 0;
// Tell OpenGL programmable pipeline how to locate vertex position data
int vertexLocation = flatShader->attributeLocation("vertex");
flatShader->enableAttributeArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);
// Offset for texture coordinate
offset += sizeof(QVector3D);
// Tell OpenGL programmable pipeline how to locate vertex texture coordinate data
int texcoordLocation = flatShader->attributeLocation("a_texcoord");
flatShader->enableAttributeArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset);
// Draw cube geometry using indices from VBO 1
glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, 0);
//drawSegments.call
flatShader->release();
}
void LineRenderer::loadVBOs(PanelGL* panel)
{
VertexData vertices[] = {
// Vertex data for face 0
{QVector3D(-1.0, -1.0, 1.0), QVector2D(0.0, 0.0)}, // v0
{QVector3D( 1.0, -1.0, 1.0), QVector2D(0.33, 0.0)}, // v1
{QVector3D(-1.0, 1.0, 1.0), QVector2D(0.0, 0.5)}, // v2
{QVector3D( 1.0, 1.0, 1.0), QVector2D(0.33, 0.5)}, // v3
// Vertex data for face 1
{QVector3D( 1.0, -1.0, 1.0), QVector2D( 0.0, 0.5)}, // v4
{QVector3D( 1.0, -1.0, -1.0), QVector2D(0.33, 0.5)}, // v5
{QVector3D( 1.0, 1.0, 1.0), QVector2D(0.0, 1.0)}, // v6
{QVector3D( 1.0, 1.0, -1.0), QVector2D(0.33, 1.0)}, // v7
// Vertex data for face 2
{QVector3D( 1.0, -1.0, -1.0), QVector2D(0.66, 0.5)}, // v8
{QVector3D(-1.0, -1.0, -1.0), QVector2D(1.0, 0.5)}, // v9
{QVector3D( 1.0, 1.0, -1.0), QVector2D(0.66, 1.0)}, // v10
{QVector3D(-1.0, 1.0, -1.0), QVector2D(1.0, 1.0)}, // v11
// Vertex data for face 3
{QVector3D(-1.0, -1.0, -1.0), QVector2D(0.66, 0.0)}, // v12
{QVector3D(-1.0, -1.0, 1.0), QVector2D(1.0, 0.0)}, // v13
{QVector3D(-1.0, 1.0, -1.0), QVector2D(0.66, 0.5)}, // v14
{QVector3D(-1.0, 1.0, 1.0), QVector2D(1.0, 0.5)}, // v15
// Vertex data for face 4
{QVector3D(-1.0, -1.0, -1.0), QVector2D(0.33, 0.0)}, // v16
{QVector3D( 1.0, -1.0, -1.0), QVector2D(0.66, 0.0)}, // v17
{QVector3D(-1.0, -1.0, 1.0), QVector2D(0.33, 0.5)}, // v18
{QVector3D( 1.0, -1.0, 1.0), QVector2D(0.66, 0.5)}, // v19
// Vertex data for face 5
{QVector3D(-1.0, 1.0, 1.0), QVector2D(0.33, 0.5)}, // v20
{QVector3D( 1.0, 1.0, 1.0), QVector2D(0.66, 0.5)}, // v21
{QVector3D(-1.0, 1.0, -1.0), QVector2D(0.33, 1.0)}, // v22
{QVector3D( 1.0, 1.0, -1.0), QVector2D(0.66, 1.0)} // v23
};
// Indices for drawing cube faces using triangle strips.
// Triangle strips can be connected by duplicating indices
// between the strips. If connecting strips have opposite
// vertex order then last index of the first strip and first
// index of the second strip needs to be duplicated. If
// connecting strips have same vertex order then only last
// index of the first strip needs to be duplicated.
GLushort indices[] = {
0, 1, 2, 3, 3, // Face 0 - triangle strip ( v0, v1, v2, v3)
4, 4, 5, 6, 7, 7, // Face 1 - triangle strip ( v4, v5, v6, v7)
8, 8, 9, 10, 11, 11, // Face 2 - triangle strip ( v8, v9, v10, v11)
12, 12, 13, 14, 15, 15, // Face 3 - triangle strip (v12, v13, v14, v15)
16, 16, 17, 18, 19, 19, // Face 4 - triangle strip (v16, v17, v18, v19)
20, 20, 21, 22, 23 // Face 5 - triangle strip (v20, v21, v22, v23)
};
// Transfer vertex data to VBO 0
glBindBuffer(GL_ARRAY_BUFFER, _vboIds[0]);
glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(VertexData), vertices, GL_STATIC_DRAW);
// Transfer index data to VBO 1
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIds[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 34 * sizeof(GLushort), indices, GL_STATIC_DRAW);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我将从一个非常简单的片段着色器(没有顶点着色器)开始,例如:
I'd start with just a really simple fragment shader (no vertex shader) like: