上一篇文章讲述了如何画一个三角形, 这篇文章讲如何画一个矩形。 大家肯定会想到两个三角形拼起来以后不就是个矩形吗, 思路就是这样的。
两个三角形需要六个顶点, 只要将前面的例子init_data部分做下修改,传进去6个顶点即可,代码如下:
void init_data()
{
...
/*
97 GLfloat vertices[3][2] = {
98 { -0.8, -0.9 },
99 { 0.8, -0.9 },
100 { 0, 0.9 },
101 };
102 */
103 GLfloat vertices[6][2] = {
104 { -0.8, -0.9 },
105 { -0.8, 0.9 },
106 { 0.8, -0.9 },
107 { 0.8, -0.9 },
108 { -0.8, 0.9 },
109 { 0.8, 0.9 }
110 };
...
}
在Draw的时候改变图形个数
glDrawArrays(GL_TRIANGLES, 0, 6);
即可绘制矩形, 效果如下:
但是从上面可以看出使用glDrawArrays画矩形需要六个顶点, 有的顶点重复定义了两次,这样浪费了资源。实际上矩形只需要定义4个顶点就可以了,下面就是index buffer的使用
使用glDrawElements来画矩形。 代码如下:
1 #include <GL/glew.h>
2 #include <GL/freeglut.h>
3 #include <iostream>
4 #define BUFFER_OFFSET(x) ((const void*) (x))
5
6 enum VAO_IDs {Triangles, NumVAOs};
7 enum Buffer_IDs {ArrayBuffer, NumBuffers};
8 enum Attrib_IDs {vPosition = 0};
9
10 GLuint VAOs[NumVAOs];
11 GLuint Buffers[NumBuffers];
12 GLuint program;
13
14 // index number
15 GLuint indices[] = {
16 0, 1, 3,
17 1, 2, 3
18 };
19
20 const GLchar* vertex_shader = "#version 430 core \n"
21 "layout(location = 0)\n"
22 "in vec4 vPosition;\n"
23 "void main()\n"
24 "{\n"
25 "gl_Position = vPosition;\n"
26 "}\n";
27
28 const GLchar* fragment_shader = "#version 430 core \n"
29 "uniform vec4 color;\n"
30 "out vec4 fColor;\n"
31 "void main()\n"
32 "{\n"
33 "fColor = color;\n"
34 "}\n";
35
36 void init_shader()
37 {
38 // vertex shader
39 GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
40 glShaderSource(vertexShader, 1, &vertex_shader, NULL);
41 glCompileShader(vertexShader);
42 // check vertex shader compiling status
43 GLint compiled;
44 GLchar log[256];
45 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compiled);
46 if (!compiled)
47 {
48 glGetShaderInfoLog(vertexShader, 256, NULL, log);
49 std::cerr << "vertex shader compile failed" << log << std::endl;
50 }
51
52 // fragment shader
53 GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
54 glShaderSource(fragmentShader, 1, &fragment_shader, NULL);
55 glCompileShader(fragmentShader);
// check fragment shader compiling status
57 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compiled);
58 if (!compiled)
59 {
60 glGetShaderInfoLog(fragmentShader, 256, NULL, log);
61 std::cerr << "fragment shader compile failed" << log << std::endl;
62 }
63
64 // link shaders
65 program = glCreateProgram();
66 glAttachShader(program, vertexShader);
67 glAttachShader(program, fragmentShader);
68 glLinkProgram(program);
69 //check link status
70 GLint linked;
71 glGetProgramiv(program, GL_LINK_STATUS, &linked);
72 if (!linked)
73 {
74 glGetProgramInfoLog(program, 256, NULL, log);
75 std::cerr << "shader linking failed" << log << std::endl;
76 }
77 // delete shader
78 glDeleteShader(vertexShader);
79 glDeleteShader(fragmentShader);
80 }
81
82 void init_data()
83 {
84 glClearColor(1, 1, 1, 0);
85 glClear(GL_COLOR_BUFFER_BIT);
86
87 glGenVertexArrays(NumVAOs, VAOs);
88 glBindVertexArray(VAOs[Triangles]);
89
90 /*
91 GLfloat vertices[3][2] = {
92 { -0.8, -0.9 },
93 { 0.8, -0.9 },
94 { 0, 0.9 },
95 };
96
97 GLfloat vertices[6][2] = {
98 { -0.8, -0.9 },
99 { -0.8, 0.9 },
100 { 0.8, -0.9},
101 { 0.8, -0.9 },
102 { -0.8, 0.9},
103 { 0.8, 0.9}
};
105 */
106 // only use four vertices when use index buffer
107 GLfloat vertices[4][2] = {
108 { -0.8, -0.9 }, // correspond to index 0
109 { -0.8, 0.9 }, // index 1
110 { 0.8, 0.9 }, // index 2
111 { 0.8, -0.9 } // index 3
112 };
113
114 glGenBuffers(NumBuffers, Buffers);
115 glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
116 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
117
118 // use element array buffer
119 GLuint ebo;
120 glGenBuffers(1, &ebo);
121 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
122 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
123
124 glUseProgram(program);
125 GLint loc = glGetUniformLocation(program, "color");
126 glUniform4f(loc, 1.0f, 0.0f, 0.0f, 1.0f);
127 glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
128 glEnableVertexAttribArray(vPosition);
129 }
130
131 void display()
132 {
133 glClear(GL_COLOR_BUFFER_BIT);
134
135 glBindVertexArray(VAOs[Triangles]);
136 // glDrawArrays(GL_TRIANGLES, 0, 6);
137 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
138 glFlush();
139 }
140
141 int main(int argc, char* argv[])
142 {
143 glutInit(&argc, argv);
144 glutInitDisplayMode(GLUT_RGBA);
145 glutInitWindowSize(300 ,300);
146 glutInitWindowPosition(100, 100);
147 glutCreateWindow("Learn opengl: draw quad");
148
149 glewExperimental = GL_TRUE;
150 if(glewInit())
151 {
152 std::cout << "Unable to Initialize" << std::endl;
153 exit(1);
154 }
155 init_shader();
156 init_data();
157 glutDisplayFunc(display);
158 glutMainLoop();
}
运行此程序即可得到上图所示的矩形。