返回
OpenGL新手教程(二):正方形渲染与键盘控制
IOS
2023-10-26 16:34:50
在这个OpenGL新手教程的第二部分中,我们将继续探索OpenGL图形编程的基础知识。在上一部分中,我们设置了OpenGL环境并绘制了一个三角形。在这部分中,我们将学习如何绘制一个正方形并使用键盘控制它的移动。
正方形渲染
定义正方形顶点坐标
一个正方形有四个顶点,坐标如下:
(-0.5, -0.5)
( 0.5, -0.5)
( 0.5, 0.5)
(-0.5, 0.5)
这些坐标定义了一个边长为1.0的正方形,其中心位于原点。
渲染环境设置
在绘制正方形之前,我们需要设置渲染环境。这包括设置视口、投影矩阵和模型矩阵。
// 设置视口
glViewport(0, 0, width, height);
// 设置投影矩阵
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
// 设置模型矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
开始绘制正方形
设置好渲染环境后,我们可以开始绘制正方形。首先,我们需要创建一个顶点缓冲对象(VBO)来存储正方形的顶点坐标。
// 创建一个VBO
GLuint vbo;
glGenBuffers(1, &vbo);
// 绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 将顶点坐标传递到VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
接下来,我们需要创建一个顶点着色器和一个片段着色器。顶点着色器将处理顶点位置,而片段着色器将处理颜色。
// 创建一个顶点着色器
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
// 加载并编译顶点着色器
const char* vertexShaderSource = ...
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 创建一个片段着色器
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
// 加载并编译片段着色器
const char* fragmentShaderSource = ...
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 创建一个着色器程序
GLuint shaderProgram;
shaderProgram = glCreateProgram();
// 将顶点着色器和片段着色器附加到着色器程序
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
// 链接着色器程序
glLinkProgram(shaderProgram);
最后,我们可以绘制正方形。
// 使用着色器程序
glUseProgram(shaderProgram);
// 启用顶点数组
glEnableVertexAttribArray(0);
// 设置顶点属性指针
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
// 绘制正方形
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
键盘控制
要使用键盘控制正方形的移动,我们需要注册一个回调函数来处理键盘事件。
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'w':
// 向上移动
break;
case 's':
// 向下移动
break;
case 'a':
// 向左移动
break;
case 'd':
// 向右移动
break;
}
}
然后,我们需要注册这个回调函数。
glutKeyboardFunc(keyboard);
矩阵更新
为了实现平滑的移动,我们需要更新模型矩阵以反映正方形的当前位置。
void updateMatrix() {
// 平移模型矩阵
glTranslatef(x, y, 0.0);
}
在主循环中,我们需要调用updateMatrix()函数来更新模型矩阵。
int main() {
// ...
while (true) {
// ...
updateMatrix();
// ...
}
return 0;
}
完整代码
以下代码展示了如何绘制一个正方形并使用键盘控制它的移动:
#include <GL/glut.h>
// 正方形顶点坐标
GLfloat vertices[] = {
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f
};
// 键盘事件处理函数
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'w':
// 向上移动
break;
case 's':
// 向下移动
break;
case 'a':
// 向左移动
break;
case 'd':
// 向右移动
break;
}
}
// 模型矩阵更新函数
void updateMatrix() {
// 平移模型矩阵
glTranslatef(x, y, 0.0);
}
int main() {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpenGL新手教程(二):正方形渲染与键盘控制");
// 设置视口
glViewport(0, 0, 500, 500);
// 设置投影矩阵
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
// 设置模型矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// 创建一个VBO
GLuint vbo;
glGenBuffers(1, &vbo);
// 绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 将顶点坐标传递到VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 创建一个顶点着色器
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
// 加载并编译顶点着色器
const char* vertexShaderSource = ...
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 创建一个片段着色器
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
// 加载并编译片段着色器
const char* fragmentShaderSource = ...
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 创建一个着色器程序
GLuint shaderProgram;
shaderProgram = glCreateProgram();
// 将顶点着色器和片段着色器附加到着色器程序
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
// 链接着色器程序
glLinkProgram(shaderProgram);
// 使用着色器程序
glUseProgram(shaderProgram);
// 启用顶点数组
glEnableVertexAttribArray(0);
// 设置顶点属性指针
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
// 注册键盘事件处理函数
glutKeyboardFunc(keyboard);
// 进入主循环
while (true) {
glClear(GL_COLOR_BUFFER_BIT);
// 更新模型矩阵
updateMatrix();
// 绘制正方形
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glutSwapBuffers();
}
return 0;
}