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
    评论
以下是使用OpenGL坐标系动态曲线图的基本步骤: 1. 在Visual Studio 2019创建一个空项目,并添加OpenGL的头文件和库文件。 2. 创建一个窗口并初始化OpenGL,可以使用glut库来实现。在窗口创建一个OpenGL视口。 3. 定义一个坐标系,在OpenGL使用glOrtho函数来设置视口大小和坐标系范围。 4. 在OpenGL使用glBegin和glEnd函数来绘制曲线图。使用glColor函数来设置线条颜色。使用glVertex2f函数来定义坐标点。 5. 使用glFlush函数来刷新绘图缓冲区。 6. 在每次绘制之前,清空绘图缓冲区,使用glClear函数来实现。 7. 使用glut库的glutTimerFunc函数来定时刷新曲线图,实现动态效果。 下面是一个简单的示例代码,使用OpenGL和glut库绘制一个简单的坐标系动态曲线图: ``` #include <GL/glut.h> #include <math.h> #define PI 3.14159265358979323846 float x = -10.0f, y = 0.0f; float dx = 0.1f, dy = 0.0f; void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-15.0, 15.0, -10.0, 10.0, -1.0, 1.0); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); // 绘制坐标系 glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINES); glVertex2f(-15.0, 0.0); glVertex2f(15.0, 0.0); glVertex2f(0.0, -10.0); glVertex2f(0.0, 10.0); glEnd(); // 绘制曲线图 glColor3f(1.0, 0.0, 0.0); glBegin(GL_LINE_STRIP); for (float x = -10.0f; x <= 10.0f; x += 0.1f) { float y = sin(x * PI / 2.0f); glVertex2f(x, y); } glEnd(); // 刷新缓冲区 glFlush(); } void timer(int value) { // 更新坐标位置 x += dx; y += dy; if (x > 10.0f || x < -10.0f) { dx = -dx; } if (y > 1.0f || y < -1.0f) { dy = -dy; } glutPostRedisplay(); glutTimerFunc(10, timer, 0); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(800, 600); glutInitWindowPosition(100, 100); glutCreateWindow("Dynamic Curve Graph"); init(); glutDisplayFunc(display); glutTimerFunc(10, timer, 0); glutMainLoop(); return 0; } ``` 在这个示例代码,我们使用sin函数绘制一个正弦曲线,并使用定时器来更新曲线图的坐标位置,实现动态效果。同时,我们也绘制了一个简单的坐标系,使曲线图更加直观。您可以根据需要修改绘制的曲线图和坐标系
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值