QOpenGL开发入门系列2:基本图形

系列教程索引:Qt开发入门系列教程索引

上一篇:OpenGL开发入门系列教程1:输出版本号

先把inherit工程复制过来

基本图形

首先先绘制一下基本图形,就是一些点线圆等等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
void GLWindow::point()
{
glPointSize(5.0f);//点的大小
glBegin(GL_POINTS);
glVertex2f(0.5f, 0.5f);
glEnd();
glFlush();
}

void GLWindow::line()
{
glEnable(GL_LINE_STIPPLE);//启动虚线模式
glLineStipple(2, 0x0F0F); //0000111100001111
glLineWidth(10.0f);
glBegin(GL_LINES);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.5f);
glEnd();
glDisable(GL_LINE_STIPPLE);//关闭虚线模式
glFlush();
}

void GLWindow::circle()
{
glBegin(GL_POLYGON); //画正n边形
for (int i = 0; i<n; ++i)
glVertex2f(R*qCos(2 * Pi / n*i), R*qSin(2 * Pi / n*i));
glEnd();
glFlush();
}

void GLWindow::triangle()
{
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,0,0);
glVertex3f(0,1,0);
glVertex3f(0.5,0,0);
glEnd();
}

void GLWindow::quad()
{
glBegin(GL_QUADS);
glVertex3f(-0.5,0.5,0);
glVertex3f(0.5,0.5,0);
glVertex3f(0.5,-0.5,0);
glVertex3f(-0.5,-0.5,0);
glEnd();
}

void GLWindow::star()
{
GLfloat a = 1 / (2 - 2 * cos(72 * Pi / 180));
GLfloat bx = a * cos(18 * Pi / 180);
GLfloat by = a * sin(18 * Pi / 180);
GLfloat cy = -a * cos(18 * Pi / 180);
GLfloat
PointA[2] = { 0, a },
PointB[2] = { bx, by },
PointC[2] = { 0.5, cy },
PointD[2] = { -0.5, cy },
PointE[2] = { -bx, by };
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINE_LOOP);
glVertex2fv(PointA);
glVertex2fv(PointC);
glVertex2fv(PointE);
glVertex2fv(PointB);
glVertex2fv(PointD);
glEnd();
glFlush();
}

void GLWindow::mySin()
{
GLfloat x;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2f(-1.0f, 0.0f);// 画x轴
glVertex2f(1.0f, 0.0f);
glVertex2f(0.0f, -1.0f);// 画y轴
glVertex2f(0.0f, 1.0f);
glEnd();
glBegin(GL_LINE_STRIP);
for (x = -1.0f / factor; x<1.0f / factor; x += 0.01f)
{
glVertex2f(x*factor, sin(x)*factor);
}
glEnd();
glFlush();
}

如果你理解了OpenGLut系列,这部分代码应该不难。

在paintGL函数中调用这些函数绘制图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void GLWindow::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

if(i>100){
i=0;
if(j>=6){
j=0;
}else j++;
}

switch(j){
case 0:
point();
break;
case 1:
line();
break;
case 2:
circle();
break;
case 3:
triangle();
break;
case 4:
quad();
break;
case 5:
star();
break;
case 6:
mySin();
break;
}
i++;

update();
}

效果为:

elements

VBO方法

绘制三角形

先准备渲染语言

1
2
3
4
5
6
7
8
9
const char* vsrc="#version 330 core\n"
"in vec3 pos;\n"
"void main(){\n"
" gl_Position=vec4(pos,1.0);\n"
"}";

const char* fsrc="void main(){\n"
" gl_FragColor=vec4(1.0f,1.0f,1.0f,1.0f);\n"
"}";

pos是输入

在initializeGL函数中进行初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
program = new QOpenGLShaderProgram;
program->addShaderFromSourceCode(QOpenGLShader::Vertex,vsrc);
program->addShaderFromSourceCode(QOpenGLShader::Fragment,fsrc);
program->bindAttributeLocation("pos",0);
program->link();//激活Program对象
program->bind();

vao.create();
vao.bind();

float vertices[]={
// 位置
0.5f, -0.5f, 0.0f,// 右下
-0.5f, -0.5f, 0.0f, // 左下
0.0f, 0.5f, 0.0f// 顶部
};

vbo.create();
vbo.bind();
vbo.allocate(vertices,sizeof(vertices)*sizeof (float));

program->enableAttributeArray(0);
program->setAttributeBuffer(0,GL_FLOAT,0,3,3*sizeof(float));

vao.release();
vbo.release();
program->release();

将渲染语言的输入pos绑定到AttribteLocation的0位置。然后调用enableAttributeArray(0)激活。

而setAttributeBuffer就是指定0号位置的数据与位置点的关系,位置是0,类型是GL_FLOAT,起始位置为0,数量为3个(一行三个数据,对应三维坐标的xyz),大小为3个GL_FLOAT的大小。

在paintGL函数中调用数据绘制

1
2
3
4
5
program->bind();
vao.bind();
glDrawArrays(GL_TRIANGLES,0,3);
vao.release();
program->release();

绘制三角形,数据位于位置0处,共有三个。

效果为:

triangle vbo

如果想要把三角形的位置移动一下呢?在OpenGLut系列中是使用glTranslatef函数,但是使用的话会发现没有效果。

需要修改一下代码

先是渲染语言部分

1
2
3
4
5
6
7
8
9
10
const char* vsrc="#version 330 core\n"
"in vec3 pos;\n"
"uniform mat4 mvpMatrix;\n"
"void main(){\n"
" gl_Position=mvpMatrix * vec4(pos,1.0);\n"
"}";

const char* fsrc="void main(){\n"
" gl_FragColor=vec4(1.0f,1.0f,1.0f,1.0f);\n"
"}";

绘制图像时进行移动图像

1
2
3
4
5
6
7
8
program->bind();
vao.bind();
m_modelView.setToIdentity();
m_modelView.translate(-1.5f,0.0f,-6.0f);
program->setUniformValue("mvpMatrix",m_projection*m_modelView);
glDrawArrays(GL_TRIANGLES,0,3);
vao.release();
program->release();

使用一个矩阵进行操作。

设置矩阵m_modelView的移动数值后,需要计算新的位置m_projection*m_modelView,之后将计算的结果赋值给渲染语言的输入mvpMatrix。

效果为:

translate

可以看到三角形位置是移动了,但是变小了。而三角形顶点数值的值没变,是因为translate的z值为-6.0f,离窗口更远了。

绘制四边形

方法和三角形的类似,就不做详细介绍了,可以查看代码。

普通的四边形

quad

四边形移动效果

translate

合在一起绘制

elements

源代码地址:OpenGL_Beginner在QOpenGL下的2.1elements、2.2triangle_vbo、2.3triangle_vbo_translate、2.4ploygon_vbo、2.5ploygon_vbo2、2.6ploygon_vbo2_translate、2.7elements_vbo_translate

下一篇:QOpenGL开发入门系列3:多边形上色