opengl 3 qt渲染空白屏幕
Posted
技术标签:
【中文标题】opengl 3 qt渲染空白屏幕【英文标题】:opengl 3 qt rendering blank screen 【发布时间】:2016-06-14 08:19:56 【问题描述】:我是 OpenGL 新手。我正在使用 OpenGL 3 和 QT5 来最终渲染类似地形的我的世界。到目前为止,我只尝试渲染一个立方体,但我一直得到一个空白屏幕。我正在关注本教程系列:https://www.youtube.com/playlist?list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY,这是代码:
glwindow.h:
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_3_Core>
class glWiwndow : public QOpenGLWidget,
protected QOpenGLFunctions_4_3_Core
protected:
void sendDataToOpenGL();
void installShaders();
QString readShaderCode(const QString fileName);
void initializeGL();
void paintGL();
void teardownGL();
public:
;
顶点.h:
#pragma once
#include <glm\glm.hpp>
struct Vertex
glm::vec3 position;
glm::vec3 color;
glm::vec3 normal;
;
shapedata.h:
#pragma once
#include <QOpenGLShaderProgram>
#include"vertex.h"
struct shapeData
shapeData() :
vertices(0), numVertices(0),
indices(0), numIndices(0)
Vertex* vertices;
GLuint numVertices;
GLushort* indices;
GLuint numIndices;
GLsizeiptr vertexBufferSize() const
return numVertices * sizeof(Vertex);
GLsizeiptr indexBufferSize() const
return numIndices * sizeof(GLushort);
void cleanup()
delete [] vertices;
delete [] indices;
numVertices = numIndices = 0;
;
shapegenerator.h:
#include"shapedata.h"
class ShapeGenerator
public:
ShapeGenerator();
static shapeData makeTriangle();
static shapeData makeCube();
;
glwindow.cpp:
#include "glwindow.h"
#include"shapegenerator.h"
#include<iostream>
#include <QDebug>
#include <QString>
#include <QOpenGLShaderProgram>
#include<QMessageBox>
#include<QStringList>
#include <QMatrix4x4>
#include<QFile>
#include "glm\gtc\matrix_transform.hpp"
#include "glm\gtx\transform.hpp"
using glm::mat4;
using glm::vec3;
GLint programID;
GLuint numIndices;
QString glWiwndow::readShaderCode(const QString fileName)
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return NULL;
QByteArray total;
QByteArray line;
while (!file.atEnd())
line = file.read(1024);
total.append(line);
return QString(total);
void glWiwndow::installShaders()
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar * adapter[1];
QString temp = readShaderCode(":/vertexshader.vert");
adapter[0] = temp.toStdString().c_str();
glShaderSource(vertexShaderID,1,adapter,0);
temp = readShaderCode(":/fragmentshader.frag");
adapter[0] = temp.toStdString().c_str();
glShaderSource(fragmentShaderID,1,adapter,0);
//cout<<"here";
glCompileShader(vertexShaderID);
//cout<<"yoo";
glCompileShader(fragmentShaderID);
GLuint programID = glCreateProgram();
glAttachShader(programID,vertexShaderID);
glAttachShader(programID,fragmentShaderID);
glLinkProgram(programID);
glUseProgram(programID);
void glWiwndow :: initializeGL()
// Initialize OpenGL Backend
initializeOpenGLFunctions();
connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(teardownGL()), Qt::DirectConnection);
glEnable(GL_DEPTH_TEST);
shapeData cube = ShapeGenerator::makeCube();
GLuint myBufferID;
glGenBuffers(1,&myBufferID);
glBindBuffer(GL_ARRAY_BUFFER,myBufferID);
glBufferData(GL_ARRAY_BUFFER,cube.vertexBufferSize(),cube.vertices,GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(float)*6,0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(float)*6,(char*)(sizeof(float)*3));
GLuint indexArrayBufferID;
glGenBuffers(1,&indexArrayBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indexArrayBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,cube.indexBufferSize(),cube.indices,GL_STATIC_DRAW);
numIndices = cube.numIndices;
installShaders();
void glWiwndow :: paintGL()
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glViewport(0,0,width(),height());
mat4 modelTransformMatrix = glm::translate(mat4(),vec3(0.0f,0.0f,-3.0f));
mat4 projectionMatrix = glm::perspective(60.0f, ((float)width()) / height(), 0.1f, 20.0f);
GLint modelTransformMatrixUniformLocation = glGetUniformLocation(programID,"modelTransformMatrix");
GLint projectionMatrixUniformLocation = glGetUniformLocation(programID,"projectionMatrix");
glUniformMatrix4fv(modelTransformMatrixUniformLocation,1,GL_FALSE,&modelTransformMatrix[0][0]);
glUniformMatrix4fv(projectionMatrixUniformLocation,1,GL_FALSE,&projectionMatrix[0][0]);
glDrawElements(GL_TRIANGLES,numIndices,GL_UNSIGNED_SHORT,0);
void glWiwndow::teardownGL()
shapegenerator.cpp:
#include "ShapeGenerator.h"
#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <vertex.h>
using glm::vec3;
using glm::mat4;
using glm::mat3;
#define NUM_ARRAY_ELEMENTS(a) sizeof(a) / sizeof(*a)
glm::vec3 randomColor()
glm::vec3 ret;
ret.x = rand() / (float)RAND_MAX;
ret.y = rand() / (float)RAND_MAX;
ret.z = rand() / (float)RAND_MAX;
return ret;
shapeData ShapeGenerator::makeTriangle()
shapeData ret;
Vertex verts[] =
glm::vec3(+0.0f, +1.0f, +0.0f),
glm::vec3(+0.0f, +1.0f, +0.0f),
glm::vec3(-1.0f, -1.0f, +0.0f),
glm::vec3(+0.0f, +1.0f, +0.0f),
glm::vec3(+1.0f, -1.0f, +0.0f),
glm::vec3(+0.0f, +0.0f, +1.0f),
;
ret.numVertices = NUM_ARRAY_ELEMENTS(verts);
ret.vertices = new Vertex[ret.numVertices];
memcpy(ret.vertices, verts, sizeof(verts));
GLushort indices[] = 0, 1, 2 ;
ret.numIndices = NUM_ARRAY_ELEMENTS(indices);
ret.indices = new GLushort[ret.numIndices];
memcpy(ret.indices, indices, sizeof(indices));
return ret;
shapeData ShapeGenerator::makeCube()
shapeData ret;
Vertex stackVerts[] =
vec3(-1.0f, +1.0f, +1.0f), // 0
vec3(+1.0f, +0.0f, +0.0f), // Color
vec3(+1.0f, +1.0f, +1.0f), // 1
vec3(+0.0f, +1.0f, +0.0f), // Color
vec3(+1.0f, +1.0f, -1.0f), // 2
vec3(+0.0f, +0.0f, +1.0f), // Color
vec3(-1.0f, +1.0f, -1.0f), // 3
vec3(+1.0f, +1.0f, +1.0f), // Color
vec3(-1.0f, +1.0f, -1.0f), // 4
vec3(+1.0f, +0.0f, +1.0f), // Color
vec3(+1.0f, +1.0f, -1.0f), // 5
vec3(+0.0f, +0.5f, +0.2f), // Color
vec3(+1.0f, -1.0f, -1.0f), // 6
vec3(+0.8f, +0.6f, +0.4f), // Color
vec3(-1.0f, -1.0f, -1.0f), // 7
vec3(+0.3f, +1.0f, +0.5f), // Color
vec3(+1.0f, +1.0f, -1.0f), // 8
vec3(+0.2f, +0.5f, +0.2f), // Color
vec3(+1.0f, +1.0f, +1.0f), // 9
vec3(+0.9f, +0.3f, +0.7f), // Color
vec3(+1.0f, -1.0f, +1.0f), // 10
vec3(+0.3f, +0.7f, +0.5f), // Color
vec3(+1.0f, -1.0f, -1.0f), // 11
vec3(+0.5f, +0.7f, +0.5f), // Color
vec3(-1.0f, +1.0f, +1.0f), // 12
vec3(+0.7f, +0.8f, +0.2f), // Color
vec3(-1.0f, +1.0f, -1.0f), // 13
vec3(+0.5f, +0.7f, +0.3f), // Color
vec3(-1.0f, -1.0f, -1.0f), // 14
vec3(+0.4f, +0.7f, +0.7f), // Color
vec3(-1.0f, -1.0f, +1.0f), // 15
vec3(+0.2f, +0.5f, +1.0f), // Color
vec3(+1.0f, +1.0f, +1.0f), // 16
vec3(+0.6f, +1.0f, +0.7f), // Color
vec3(-1.0f, +1.0f, +1.0f), // 17
vec3(+0.6f, +0.4f, +0.8f), // Color
vec3(-1.0f, -1.0f, +1.0f), // 18
vec3(+0.2f, +0.8f, +0.7f), // Color
vec3(+1.0f, -1.0f, +1.0f), // 19
vec3(+0.2f, +0.7f, +1.0f), // Color
vec3(+1.0f, -1.0f, -1.0f), // 20
vec3(+0.8f, +0.3f, +0.7f), // Color
vec3(-1.0f, -1.0f, -1.0f), // 21
vec3(+0.8f, +0.9f, +0.5f), // Color
vec3(-1.0f, -1.0f, +1.0f), // 22
vec3(+0.5f, +0.8f, +0.5f), // Color
vec3(+1.0f, -1.0f, +1.0f), // 23
vec3(+0.9f, +1.0f, +0.2f), // Color
;
ret.numVertices = NUM_ARRAY_ELEMENTS(stackVerts);
ret.vertices = new Vertex[ret.numVertices];
memcpy(ret.vertices, stackVerts, sizeof(stackVerts));
unsigned short stackIndices[] =
0, 1, 2, 0, 2, 3, // Top
4, 5, 6, 4, 6, 7, // Front
8, 9, 10, 8, 10, 11, // Right
12, 13, 14, 12, 14, 15, // Left
16, 17, 18, 16, 18, 19, // Back
20, 22, 21, 20, 23, 22, // Bottom
;
ret.numIndices = NUM_ARRAY_ELEMENTS(stackIndices);
ret.indices = new GLushort[ret.numIndices];
memcpy(ret.indices, stackIndices, sizeof(stackIndices));
return ret;
main.cpp:
#include "glwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
QApplication a(argc, argv);
glWiwndow w;
w.show();
return a.exec();
顶点着色器代码:(vertexshader.vert)
#version 430
layout(location = 0) in vec3 position;
layout(location=1) in vec3 vertexColor;
uniform mat4 modelTransformMatrix;
uniform mat4 projectionMatrix;
out vec3 theColor;
void main()
vec4 v = vec4(position,1.0);
vec4 newPosition = modelTransformMatrix * v;
vec4 projectedPosition = projectionMatrix * newPosition;
gl_Position = projectedPosition;
theColor = vertexColor;
片段着色器代码:(fragmentshader.frag)
#version 430
out highp vec4 fColor;
in vec3 theColor;
void main()
fColor =vec4(theColor,1.0);
【问题讨论】:
至少glVertexAttribPointer
的步幅是错误的。您的顶点结构有 9 个浮点数,而不是 6 个。您是否检查过着色器编译和链接是否成功?
您好,谢谢您的回复,是的,着色器编译和链接已经成功。我的顶点结构确实有 9 个浮点数,但到目前为止我只使用了 6 个浮点数,我没有使用法线还没有。
您在 makeTriangle 和 makeCube 中初始化顶点数组的方式可能与您期望的不太一样。即,我认为 makeTriangle 将返回一个 shapeData 结构,其中 numVertices 设置为 2。
我尝试手动设置 NumVertices(在 makeCube 中设置为 144)但没有任何变化,我仍然得到一个空白屏幕。
您目前仅使用 6 个浮点数,但您仍然为每个顶点上传其中的 9 个到缓冲区。步幅告诉 OpenGL 连续顶点的起点彼此相距多少字节。因此,如果您为每个顶点上传 9 个浮点数,则 vertex[i+1] 将在 vertex[i] 之后开始 9 个浮点数。
【参考方案1】:
问题在于programID
,但不是因为我在评论中概述的原因。目前你有一个全球可验证...
GLint programID;
但是在glWiwndow::installShaders
你有...
GLuint programID = glCreateProgram();
因此,您的代码使用本地范围的programID
调用glUseProgram
,但随后在glWiwndow::paintGL
中,您将未初始化的全局programID
传递给glGetUniformLocation
,它返回-1 表示失败。您确实需要在 GL 中检查这些类型的错误。
【讨论】:
以上是关于opengl 3 qt渲染空白屏幕的主要内容,如果未能解决你的问题,请参考以下文章