对于CUBE这个例子,之前分析了它的框架,至于图怎么弄上去的还怎么细看。现在尝试弄了一下。首先分析它怎么对应的,原本是一张图,怎么分成六面的。于是像高中时代那样开始了计算理解
这样就清楚多了,一张图,划分为6个块,一个面一块。
至于归一化,可能是
// Wrap texture coordinates by repeating
// f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
texture->setWrapMode(QOpenGLTexture::Repeat);
这句话在起作用。
再前一篇的框架下修改
- #ifndef GLWIGDET_H
- #define GLWIGDET_H
-
- #include <QOpenGLWidget>
- #include <QOpenGLFunctions>
- #include <QOpenGLShaderProgram>
-
- #include <QMouseEvent>
- #include <QTimerEvent>
- #include <QKeyEvent>
- #include <QBasicTimer>
- #include <QVector3D>
- #include <QVector2D>
-
-
-
-
-
-
-
- class GLWigdet : public QOpenGLWidget, protected QOpenGLFunctions
- {
- Q_OBJECT
- public:
- GLWigdet(QWidget *parent = 0);
-
- protected:
- void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
- void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
- void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
- void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE;
-
- void initializeGL() Q_DECL_OVERRIDE;
- void resizeGL(int w, int h) Q_DECL_OVERRIDE;
- void paintGL() Q_DECL_OVERRIDE;
-
- void initShaders();
-
- virtual void do_init() {}
- virtual void do_paint() {}
- virtual void do_resize() {}
-
- int attribLocation(const char *name) {
- return program.attributeLocation(name);
- }
-
- void enableAttribArray(int location) {
- program.enableAttributeArray(location);
- }
-
- void setAttribBuffer
- (int location, GLenum type, int offset, int tupleSize, int stride = 0)
- {
- program.setAttributeBuffer(location, type, offset, tupleSize, stride);
- }
-
- void setUnifValue(const char *name, GLfloat value)
- {
- program.setUniformValue(name, value);
- }
-
- private:
- QBasicTimer timer;
- QVector2D mousePressPosition;
- QVector3D rotationAxis;
- qreal angularSpeed;
- QQuaternion rotation;
- QMatrix4x4 m_proj;
- QOpenGLShaderProgram program;
- };
-
- #endif // GLWIGDET_H
- #ifndef DRAWTRIANGLE_H
- #define DRAWTRIANGLE_H
-
- #include "glwigdet.h"
-
- #include <QOpenGLBuffer>
- #include <QOpenGLVertexArrayObject>
- #include <QOpenGLTexture>
-
- class DrawTriangle : public GLWigdet
- {
- public:
- DrawTriangle(QWidget *parent = 0);
- ~DrawTriangle();
-
- protected:
- void initTextures();
- void do_init() Q_DECL_OVERRIDE;
- void do_paint() Q_DECL_OVERRIDE;
-
- private:
- int num;
- QOpenGLBuffer arrayBuf;
- QOpenGLShaderProgram *program;
-
- QOpenGLTexture *texture;
- };
-
- #endif // DRAWTRIANGLE_H
- #include "drawtriangle.h"
-
- #include <QVector>
-
- DrawTriangle::DrawTriangle(QWidget *parent)
- : GLWigdet(parent), num(0),
- arrayBuf(QOpenGLBuffer::VertexBuffer)
- {
- setWindowTitle("绘制三角形");
-
- program = NULL;
- texture = NULL;
- }
-
- DrawTriangle::~DrawTriangle()
- {
-
- makeCurrent();
- arrayBuf.destroy();
- if(texture)
- delete texture;
- doneCurrent();
- }
-
- void DrawTriangle::initTextures()
- {
-
- texture = new QOpenGLTexture(QImage(":/textures/uname.jpg").mirrored());
-
-
- texture->setMinificationFilter(QOpenGLTexture::Nearest);
-
-
- texture->setMagnificationFilter(QOpenGLTexture::Linear);
-
-
-
- texture->setWrapMode(QOpenGLTexture::Repeat);
- }
-
- void DrawTriangle::do_init()
- {
- initializeOpenGLFunctions();
-
-
- glEnable(GL_CULL_FACE);
-
- initTextures();
-
- GLfloat vertData[] = {
- 0.0f, 0.0f, 0.0f,
- 1.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
- 1.0f, 1.0f, 0.0f,
- };
-
- num = 4;
-
-
- arrayBuf.create();
- arrayBuf.bind();
- arrayBuf.allocate(vertData, num * 3 * sizeof(GLfloat));
- arrayBuf.release();
- }
-
- void DrawTriangle::do_paint()
- {
-
- texture->bind();
- arrayBuf.bind();
-
-
- setUnifValue("texture", 0);
-
-
- int a_pos = attribLocation("a_position");
- enableAttribArray(a_pos);
- setAttribBuffer(a_pos, GL_FLOAT, 0, 3, 3 * sizeof(GLfloat));
-
-
- int a_tex = attribLocation("a_texcoord");
- enableAttribArray(a_tex);
- setAttribBuffer(a_tex, GL_FLOAT, 0, 2, 3 * sizeof(GLfloat));
-
-
-
-
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, num);
-
- arrayBuf.release();
- texture->release();
-
- glFlush();
- }
成功之前一直纠结于“程序异常退出”、出现窗体了但没有图像画出来。
原来在我的这个框架下,
需要放在init()中才会去创建,放在构造函数里不行。
结果:
修改为锥体,这里有个问题,也是个巧点。
如果以锥体底面圆心为坐标原点,而纹理图的坐标原点是左下角的顶点。这样,如果学cube例子
struct VertexData
{
QVector3D position;
QVector2D texCoord;
};
因为点比较多,不可能向cube那样一个一个列出来,肯定要用什么存储起来
QVector<VertexData> vertData,若这样做,最后出来的锥体是白色的,没有纹理。
所以,将坐标原点设置和纹理原点一样,同时纹理归一化了,将半径r设置为0.5f,这样,纹理相应点的坐标就是锥体相应点的坐标的二维。
最后的效果:
from: http://blog.csdn.net/fu851523125/article/details/51626948