opengl和Qt5.0.2
openGL的初学者,尝试把opengl与Qt结合
程式目的 : 画一个三角形
平台 : mac osx 10.8.3
编译器 : clang3.2
问题有二
1 : 无法显示三角形
2 : 关闭视窗后程式不会跟着关闭
.hpp
#include <QGLWidget>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
class QWidget;
class ch1HelloTriangle : public QGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit ch1HelloTriangle(QWidget *parent = 0);
protected:
virtual void initializeGL();
void initShaders();
void InitializeVertexBuffer();
virtual void resizeGL(int w, int h);
virtual void paintGL();
private:
QOpenGLShaderProgram program;
GLuint positionBufferObject;
};
#include <locale.h>
#include <QWidget>
#include "ch1HelloTriangle.hpp"
namespace
{
float const vertexPositions[] = {
0.75f, 0.75f, 0.0f, 1.0f,
0.75f, -0.75f, 0.0f, 1.0f,
-0.75f, -0.75f, 0.0f, 1.0f,
};
}
ch1HelloTriangle::ch1HelloTriangle(QWidget *parent) :
QGLWidget(parent)
{
}
void ch1HelloTriangle::initializeGL()
{
initializeOpenGLFunctions();
InitializeVertexBuffer();
initShaders();
}
void ch1HelloTriangle::initShaders()
{
// Override system locale until shaders are compiled
setlocale(LC_NUMERIC, "C");
// Compile vertex shader
if (!program.addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n"))
{
close();
}
// Compile fragment shader
if (!program.addShaderFromSourceCode(QOpenGLShader::Fragment,
"out vec4 outputColor;\n"
"void main()\n"
"{\n"
" outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
"}\n"))
{
close();
}
// Link shader pipeline
if (!program.link())
close();
// Bind shader pipeline for use
if (!program.bind())
close();
// Restore system locale
setlocale(LC_ALL, "");
}
void ch1HelloTriangle::InitializeVertexBuffer()
{
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void ch1HelloTriangle::resizeGL(int w, int h)
{
// Set OpenGL viewport to cover whole widget
glViewport(0, 0, w, h);
}
void ch1HelloTriangle::paintGL()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
int vertexLocation = program.attributeLocation("position");
program.enableAttributeArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
#include <QApplication>
#include "ch1HelloTriangle.hpp"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ch1HelloTriangle ch1;
ch1.show();
return a.exec();
}
==================================[GLWidget.h]==================================
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QtOpenGL/QGLWidget>
class GLWidget : public QGLWidget {
Q_OBJECT
public:
GLWidget(QWidget *parent = 0);
~GLWidget();
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
virtual void hideEvent(QHideEvent *event);
virtual void showEvent(QShowEvent *event);
virtual void timerEvent(QTimerEvent *event);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void wheelEvent(QWheelEvent *event);
private:
int timerId;
QPoint lastPos;
GLfloat rotateX;
GLfloat rotateY;
GLfloat rotateZ;
GLfloat zoom;
void drawCube(GLfloat factorX = 1, GLfloat factorY = 1,
GLfloat factorZ = 1, GLfloat w = 1);
void drawCone(GLfloat radius = 1.0f, GLfloat height = 1,
GLuint steps = 18);
};
#endif // GLWIDGET_H
==================================[GLWidget.cpp]==================================
#include "GLWidget.h"
#include <qDebug>
#include <QTimerEvent>
#include <QMouseEvent>
#include <cmath>
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(parent) {
setFormat(QGLFormat(QGL::DoubleBuffer
[解决办法]
QGL::DepthBuffer));
rotateX = 0.0f;
rotateY = 0.0f;
rotateZ = 0.0f;
zoom = 1.0f;
}
GLWidget::~GLWidget() {
}
void GLWidget::hideEvent(QHideEvent *event) {
this->killTimer(this->timerId);
}
void GLWidget::showEvent(QShowEvent *event) {
this->timerId = this->startTimer(500);
}
void GLWidget::timerEvent(QTimerEvent *event) {
if (event->timerId() == this->timerId) {
} else {
QGLWidget::timerEvent(event);
}
}
void GLWidget::mousePressEvent(QMouseEvent *event) {
if (Qt::LeftButton == event->button()) {
lastPos = event->pos();
} else if (Qt::RightButton == event->button()) {
lastPos = event->pos();
}
}
void GLWidget::mouseMoveEvent(QMouseEvent *event) {
if (Qt::LeftButton & event->buttons()) {
GLfloat dx = event->pos().x() - lastPos.x();
GLfloat dy = event->pos().y() - lastPos.y();
rotateX += dy;
rotateY += dx;
updateGL();
//qDebug() << QString("RotateX:%1, RotateY:%2").arg(rotateX).arg(rotateY);
} else if (Qt::RightButton & event->buttons()) {
GLfloat dz = event->pos().y() - lastPos.y();
dz *= 0.01f;
zoom += dz;
updateGL();
}
lastPos = event->pos();
}
void GLWidget::mouseReleaseEvent(QMouseEvent *event) {
}
void GLWidget::wheelEvent(QWheelEvent *event) {
GLfloat degrees = event->delta();
zoom -= degrees * 0.0002f;
// 注意, 如果zoom为负值, eye就会被放置到z轴的负方向, 而从物体的背面看了.
if (zoom < 1.0f) {
zoom = 1.0f;
}
updateGL();
}
///////////////////////////////////////////////////////////////////////////////
// Opengl Code
///////////////////////////////////////////////////////////////////////////////
void GLWidget::initializeGL() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CCW);
//glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glShadeModel(GL_SMOOTH);
// Point size
// glPointSize(GLfloat size);
GLfloat sizes[2];
GLfloat step;
glGetFloatv(GL_LINE_WIDTH_RANGE, sizes);
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &step);
}
void GLWidget::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75, (GLdouble)w / h, 0.1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT
[解决办法]
GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//glTranslatef(0.0f, 0.0f, zoom);
gluLookAt(0.0f, 0.0f, zoom, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(rotateX, 1, 0, 0);
glRotatef(rotateY, 0, 1, 0);
glRotatef(rotateZ, 0, 0, 1);
// Real draw code.
//glColor3f(1.0f, 0.0f, 0.0f);
//drawCube(1, 1, 1, 1);
glPolygonMode(GL_BACK, GL_LINE);
drawCone(1.0f, 1.50, 48);
}
void GLWidget::drawCube(GLfloat factorX, GLfloat factorY,
GLfloat factorZ, GLfloat w) {
GLfloat x = factorX * 0.5f;
GLfloat y = factorY * 0.5f;
GLfloat z = factorZ * 0.5f;
// x / w, y / w, z / w
// 前左下, 前右下, 前右上, 前左上: p0, p1, p2, p3
// 后左下, 后右下, 后右上, 后左上: p4, p5, p6, p7
GLfloat p0[4] = {-x, -y, z, w};
GLfloat p1[4] = {x, -y, z, w};
GLfloat p2[4] = {x, y, z, w};
GLfloat p3[4] = {-x, y, z, w};
GLfloat p4[4] = {-x, -y, -z, w};
GLfloat p5[4] = {x, -y, -z, w};
GLfloat p6[4] = {x, y, -z, w};
GLfloat p7[4] = {-x, y, -z, w};
// 开始绘制Cube的六个面: 逆时针
glBegin(GL_QUADS);
// 前面: p0, p1, p2, p3
glVertex4fv(p0);
glVertex4fv(p1);
glVertex4fv(p2);
glVertex4fv(p3);
// 右面: p1, p5, p6, p2
glVertex4fv(p1);
glVertex4fv(p5);
glVertex4fv(p6);
glVertex4fv(p2);
// 后面: p5, p4, p7, p6
glVertex4fv(p5);
glVertex4fv(p4);
glVertex4fv(p7);
glVertex4fv(p6);
// 左右: p4, p0, p3, p7
glVertex4fv(p4);
glVertex4fv(p0);
glVertex4fv(p3);
glVertex4fv(p7);
// 上面: p2, p6, p7, p3
glVertex4fv(p2);
glVertex4fv(p6);
glVertex4fv(p7);
glVertex4fv(p3);
// 下面: p0, p4, p5, p1
glVertex4fv(p0);
glVertex4fv(p4);
glVertex4fv(p5);
glVertex4fv(p1);
glEnd();
}
void GLWidget::drawCone(GLfloat radius, GLfloat height,
GLuint steps) {
const GLfloat GL_PI = 3.1415f;
GLfloat angles = 2 * GL_PI / steps;
GLfloat vertices[steps][3];
for (int i = 0; i < steps; ++i) {
vertices[i][0] = radius * cos(i * angles);
vertices[i][1] = radius * sin(i * angles);
vertices[i][2] = 0;
}
// top surface
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, height);
for (int i = 0; i < steps; ++i) {
glVertex3fv(vertices[i]);
if ((i & 1) == 0) {
glColor3f(1.0f, 0.0f, 0.0f);
} else {
glColor3f(0.0f, 0.0f, 1.0f);
}
}
glVertex3fv(vertices[0]);
glEnd();
// bottom surface
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0f, 0.0f, 0);
for (int i = steps - 1; i >= 0; --i) {
glVertex3fv(vertices[i]);
if ((i & 1) == 0) {
glColor3f(0.0f, 1.0f, 0.0f);
} else {
glColor3f(1.0f, 0.0f, 1.0f);
}
}
glVertex3fv(vertices[steps - 1]);
glEnd();
}