OpenGL画坐标系1

此项目为Qt5所写,用到的是可编程管线的现代OpenGL,通过继承Qt中的QOpenGLWidget和QOpenGLExtraFunctions实现。只是一个最简单的坐标系,三条不同颜色的直线分别代表x, y, z轴,整体效果如下:

 

其实实现这个坐标系在老版本的OpenGL(freeglut,glut)中是很简单的,只需几行代码,但是在可编程管线中,由于要编写着色器,复杂程度就稍微高了一点。项目整体目录如下:

 

Coordinate.h

#include <QOpenGLExtraFunctions>

class Coordinate : protected QOpenGLExtraFunctions
{
public:
    Coordinate();
    ~Coordinate();

    void init();
    void drawX();
    void drawY();
    void drawZ();

private:
    GLuint VBOX = 0;
    GLuint VBOY = 0;
    GLuint VBOZ = 0;
};

Coordinate.cpp

#include "coordinate.h"

Coordinate::Coordinate()
{
    this->initializeOpenGLFunctions();
}

Coordinate::~Coordinate()
{
    if(VBOX || VBOY || VBOZ)
    {
        glDeleteBuffers(1, &VBOX);
        glDeleteBuffers(1, &VBOY);
        glDeleteBuffers(1, &VBOZ);
    }
}

void Coordinate::init()
{
    float verticesX[] = {
        0.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f,
    };

    float verticesY[] = {
        0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
    };

    float verticesZ[] = {
        0.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f
    };

    glGenBuffers(1, &VBOX);
    glBindBuffer(GL_ARRAY_BUFFER, VBOX);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticesX), verticesX, GL_STATIC_DRAW);

    glGenBuffers(1, &VBOY);
    glBindBuffer(GL_ARRAY_BUFFER, VBOY);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticesY), verticesY, GL_STATIC_DRAW);

    glGenBuffers(1, &VBOZ);
    glBindBuffer(GL_ARRAY_BUFFER, VBOZ);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticesZ), verticesZ, GL_STATIC_DRAW);
}

void Coordinate::drawX()
{
    glBindBuffer(GL_ARRAY_BUFFER, VBOX);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glDrawArrays(GL_LINES, 0, 2);
}

void Coordinate::drawY()
{
    glBindBuffer(GL_ARRAY_BUFFER, VBOY);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glDrawArrays(GL_LINES, 0, 2);
}

void Coordinate::drawZ()
{
    glBindBuffer(GL_ARRAY_BUFFER, VBOZ);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glDrawArrays(GL_LINES, 0, 2);
}

 

Shader.h 

#include <QDebug>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QString>

class Shader {
public:
  Shader(const QString& vertexSource, const QString& fragmentSource, const QString& geometrySource = NULL);

  ~Shader();

  void use(){
    shaderProgram->bind();
  }

  void setFloat(const QString& name, const GLfloat& value){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, value);
  }

  void setInteger(const QString& name, const GLint& value){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, value);
  }

  void setVector2f(const QString& name, const GLfloat& x, const GLfloat& y){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, QVector2D(x, y));
  }

  void setVector2f(const QString& name, const QVector2D& value){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, value);
  }

  void setVector3f(const QString& name, const GLfloat& x, const GLfloat& y, const GLfloat& z){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, QVector3D(x, y, z));
  }

  void setVector3f(const QString& name, const QVector3D& value){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, value);
  }

  void setVector4f(const QString& name, const GLfloat& x, const GLfloat& y, const GLfloat& z, const GLfloat& w){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, QVector4D(x, y, z, w));
  }

  void setVector4f(const QString& name, const QVector4D& value){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, value);
  }

  void setMatrix4f(const QString& name, const QMatrix4x4& value){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, value);
  }

  void setBool(const QString& name, const GLboolean& value){
    GLuint loc = shaderProgram->uniformLocation(name);
    shaderProgram->setUniformValue(loc, value);
  }
private:
    QOpenGLShaderProgram *shaderProgram;
};

Shader.cpp

#include "shader.h"

Shader::Shader(const QString& vertexSource, const QString& fragmentSource, const QString& geometrySource){
    QOpenGLShader vertexShader(QOpenGLShader::Vertex);
    bool success = vertexShader.compileSourceFile(vertexSource);
    if(!success){
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED" << endl;
    }

    QOpenGLShader fragmentShader(QOpenGLShader::Fragment);
    success  = fragmentShader.compileSourceFile(fragmentSource);
    if(!success){
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED" << endl;
    }

    QOpenGLShader geometryShader(QOpenGLShader::Geometry);
    if(geometrySource != NULL){
        success  = geometryShader.compileSourceFile(geometrySource);
        if(!success){
            qDebug() << "ERROR::SHADER::GEOMETRY::COMPILATION_FAILED" << endl;
        }
    }

    shaderProgram = new QOpenGLShaderProgram();
    shaderProgram->addShader(&vertexShader);
    shaderProgram->addShader(&fragmentShader);
    if(geometrySource != NULL)
        shaderProgram->addShader(&geometryShader);
    success = shaderProgram->link();
    if(!success){
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED" << endl;
    }
}

 

Widget.h 

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <coordinate.h>
#include <shader.h>

class Widget : public QOpenGLWidget, protected QOpenGLExtraFunctions
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    void paintGL() override;

private:
    Coordinate *coordinate;
    Shader *shaderX;
    Shader *shaderY;
    Shader *shaderZ;
};

Widget.cpp 

#include "widget.h"

Widget::Widget(QWidget *parent) : QOpenGLWidget(parent)
{
    this->setWindowTitle("Coordinate");
}

Widget::~Widget()
{
    delete shaderX;
    delete shaderY;
    delete shaderZ;
}

void Widget::initializeGL(){
    this->initializeOpenGLFunctions();

    // load shaders
    shaderX = new Shader(":/shaders/CoordinateX.vert",":/shaders/CoordinateX.frag");
    shaderY = new Shader(":/shaders/CoordinateY.vert",":/shaders/CoordinateY.frag");
    shaderZ = new Shader(":/shaders/CoordinateZ.vert",":/shaders/CoordinateZ.frag");

    coordinate = new Coordinate();
    coordinate->init();

    // set projection and view matrix
    QMatrix4x4 projection, view;
    view.translate(QVector3D(0.0f, -0.5f, -3.0f)); // camera view
    projection.perspective(45.0f, (GLfloat)width() / (GLfloat)height(), 0.1f, 100.0f);

    shaderX->use();
    shaderX->setMatrix4f("view", view);
    shaderX->setMatrix4f("projection", projection);
    shaderY->use();
    shaderY->setMatrix4f("view", view);
    shaderY->setMatrix4f("projection", projection);
    shaderZ->use();
    shaderZ->setMatrix4f("view", view);
    shaderZ->setMatrix4f("projection", projection);

    glEnable(GL_DEPTH_TEST);
}

void Widget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void Widget::paintGL()
{
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 model;
    model.setToIdentity(); // Initializing, Set the rectangle to an identity matrix
    model.rotate(-45.0f, 0.0f, 1.0f ,0.0f); // rotate coordinate system to aovid blocking z-axis

    // draw x,y,z coordinate axis
    shaderX->use();
    shaderX->setMatrix4f("model", model);
    coordinate->drawX();
    shaderY->use();
    shaderY->setMatrix4f("model", model);
    coordinate->drawY();
    shaderZ->use();
    shaderZ->setMatrix4f("model", model);
    coordinate->drawZ();
}

 

CoordinateX.vert 

#version 330 core
layout (location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main(){
    gl_Position = projection * view * model * vec4(aPos, 1.0f);
}

CoordinateX.frag 

#version 330 core
out vec4 FragColor;

void main()
{
        FragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
}

y轴z轴着色器的代码和上面两个是一样的,除了FragColor中改了颜色,pro文件和main.cpp是自动生成的就不放代码了。很简单的一个坐标系,在每个轴末端加上一个小圆锥体效果会更好,有空尝试一下。

 

在"OpenGL画坐标系2"中增加了轴末端的四棱锥,效果更好,并且重构了代码,链接如下:https://blog.csdn.net/qq_37996632/article/details/103178120

 

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值