使用Opengl绘制一个五环,,且要求颜色重叠部分完全和下图相同(即需要虑颜色的遮挡)。
并让五环在拖动窗口大小时不变形?
①画一个圆环,阐述实现原理和对应代码、运行结果截图。
②画五个环,完成上色和环的位置偏移操作。阐述实现原理和对应代码、运行结果截图。
③实现穿插,阐述穿插实现原理、对应代码、运行结果截图。
④拖动不变形,阐述穿插实现原理、对应代码、运行结果截图。
参考
#include <GL/glut.h>
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT), 0, -1, 1);
glColor3f(0.0, 0.0, 1.0);
glPushMatrix();
glTranslatef(150, 150, 0);
glutSolidTorus(10, 60, 50, 50);
glPopMatrix();
glColor3f(1.0, 1.0, 0.0);
glPushMatrix();
glTranslatef(270, 150, 0);
glutSolidTorus(10, 60, 50, 50);
glPopMatrix();
glColor3f(0.0, 0.0, 0.0);
glPushMatrix();
glTranslatef(390, 150, 0);
glutSolidTorus(10, 60, 50, 50);
glPopMatrix();
// 绘制绿色圆环
glColor3f(0.0, 1.0, 0.0);
glPushMatrix();
glTranslatef(210, 210, 0);
glutSolidTorus(10, 60, 50, 50);
glPopMatrix();
glColor3f(1.0, 0.0, 0.0);
glPushMatrix();
glTranslatef(330, 210, 0);
glutSolidTorus(10, 60, 50, 50);
glPopMatrix();
glFlush();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(600, 300);
glutCreateWindow("环");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
该回答引用ChatGPTc++
const int segments = 360;
const float radius = 0.5;
const float inner_radius = 0.4;
// 定义圆的顶点数组
std::vector vertices;
for (int i = 0; i < segments; i++) {
float theta = 2.0f * 3.1415926f * float(i) / float(segments - 1);
float x = radius * cosf(theta);
float y = radius * sinf(theta);
vertices.push_back(x);
vertices.push_back(y);
}
// 定义圆的索引数组
std::vector indices;
for (int i = 0; i < segments; i++) {
int ii = (i + 1) % segments;
indices.push_back(i);
indices.push_back(ii);
}
// 绘制大圆
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);
// 定义内圆的顶点数组
std::vector inner_vertices;
for (int i = 0; i < segments; i++) {
float theta = 2.0f * 3.1415926f * float(i) / float(segments - 1);
float x = inner_radius * cosf(theta);
float y = inner_radius * sinf(theta);
inner_vertices.push_back(x);
inner_vertices.push_back(y);
}
// 绘制小圆
glBindVertexArray(InnerVAO);
glBindBuffer(GL_ARRAY_BUFFER, InnerVBO);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, inner_vertices.size() * sizeof(float), &inner_vertices[0], GL_STATIC_DRAW);
glDrawArrays(GL_TRIANGLE_FAN, 0, segments);
c++
const int segments = 360;
const float thickness = 0.1;
const float radius1 = 0.5;
const float radius2 = 0.4;
// 定义圆的顶点数组
std::vector vertices;
for (int i = 0; i < segments; i++) {
float theta = 2.0f * 3.1415926f * float(i) / float(segments - 1);
float x = radius1 * cosf(theta);
float y = radius1 * sinf(theta);
vertices.push_back(x);
vertices.push_back(y);
}
// 定义圆的索引数组
std::vector indices;
for (int i = 0; i < segments; i++) {
int ii = (i + 1) % segments;
indices.push_back(i);
indices.push_back(ii);
}
// 绘制外圆
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);
// 定义内圆的顶点数组
std::vector inner_vertices;
for (int i = 0; i < segments; i++) {
float theta = 2.0f * 3.1415926f * float(i) / float(segments - 1);
float x = radius2 * cosf(theta);
float y = radius2 * sinf(theta);
inner_vertices.push_back(x);
inner_vertices.push_back(y);
}
// 绘制内圆
glBindVertexArray(InnerVAO);
glBindBuffer(GL_ARRAY_BUFFER, InnerVBO);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, inner_vertices.size() * sizeof(float), &inner_vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, InnerEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);
// 定义圆弧的顶点数组
std::vector arc_vertices;
for (int i = 0; i < segments; i++) {
float theta = 2.0f * 3.1415926f * float(i) / float(segments - 1);
float x = (radius1 - thickness) * cosf(theta);
float y = (radius1 - thickness) * sinf(theta);
arc_vertices.push_back(x);
arc_vertices.push_back(y);
x = (radius2 + thickness) * cosf(theta);
y = (radius2 + thickness) * sinf(theta);
arc_vertices.push_back(x);
arc_vertices.push_back(y);
}
// 定义圆弧的索引数组
std::vector arc_indices;
for (int i = 0; i < segments; i++) {
int ii = (i + 1) % segments;
arc_indices.push_back(i * 2);
arc_indices.push_back(i * 2 + 1);
arc_indices.push_back(ii * 2 + 1);
arc_indices.push_back(ii * 2 + 1);
arc_indices.push_back(ii * 2);
arc_indices.push_back(i * 2);
}
// 绘制五个圆弧
for (int i = 0; i < 5; i++) {
glBindVertexArray(ArcVAO[i]);
glBindBuffer(GL_ARRAY_BUFFER, ArcVBO[i]);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, arc_vertices.size() * sizeof(float), &arc_vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ArcEBO[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, arc_indices.size() * sizeof(unsigned int), &arc_indices[0], GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, arc_indices.size(), GL_UNSIGNED_INT, 0);
}
c++
const int segments = 360;
const float thickness = 0.1;
const float radius1 = 0.5;
const float radius2 = 0.4;
const int colors = 5;
// 绘制五个圆弧
for (int i = 0; i < colors; i++) {
int start = i * segments / colors;
int end = (i + 1) * segments / colors;
int count = end - start;
// 定义圆弧的顶点数组
std::vector arc_vertices;
for (int j = start; j < end; j++) {
float theta = 2.0f * 3.1415926f * float(j) / float(segments - 1);
float x1 = (radius1 - thickness) * cosf(theta);
float y1 = (radius1 - thickness) * sinf(theta);
float x2 = (radius2 + thickness) * cosf(theta);
float y2 = (radius2 + thickness) * sinf(theta);
arc_vertices.push_back(x1);
arc_vertices.push_back(y1);
arc_vertices.push_back(x2);
arc_vertices.push_back(y2);
}
// 定义圆弧的索引数组
std::vector arc_indices;
for (int j = 0; j < count; j++) {
int jj = (j + 1) % count;
arc_indices.push_back(j * 2);
arc_indices.push_back(j * 2 + 1);
arc_indices.push_back(jj * 2 + 1);
arc_indices.push_back(jj * 2 + 1);
arc_indices.push_back(jj * 2);
arc_indices.push_back(j * 2);
}
// 绘制圆弧的颜色段
for (int j = 0; j < colors; j++) {
if (i != j) {
glBindVertexArray(ArcVAOS[i][j]);
glBindBuffer(GL_ARRAY_BUFFER, ArcVBOS[i][j]);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, colors_data[j], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ArcEBOS[i][j]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 6, colors_indices, GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
}
// 绘制当前圆弧的剩余部分
glBindVertexArray(ArcVAOS[i][i]);
glBindBuffer(GL_ARRAY_BUFFER, ArcVBOS[i][i]);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, arc_vertices.size() * sizeof(float), &arc_vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ArcEBOS[i][i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, arc_indices.size() * sizeof(unsigned int), &arc_indices[0], GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, arc_indices.size(), GL_UNSIGNED_INT, 0);
}
c++
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
projection_matrix = glm::perspective(glm::radians(45.0f), (float) width / (float) height, 0.1f, 100.0f);
}
while (!glfwWindowShouldClose(window)) {
// 处理窗口大小改变的事件
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// 清空屏幕和深度缓冲
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 绘制圆环
glm::mat4 model_matrix = glm::mat4(1.0f);
glm::mat4 view_matrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 mvp_matrix = projection_matrix * view_matrix * model_matrix;
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, glm::value_ptr(mvp_matrix));
glStencilFunc(GL_ALWAYS, 0, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0xFF);
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);
// 绘制五环不同位置的圆环
for (int i = 0; i < 5; i++) {
float angle = 2 * 3.1415926f * i / 5.0f;
glm::mat4 model_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(cos(angle), sin(angle), 0.0f));
glm::mat4 view_matrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 mvp_matrix = projection_matrix * view_matrix * model_matrix;
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, glm::value_ptr(mvp_matrix));
glStencilFunc(GL_EQUAL, i + 1, 0xFF);
glStencilMask(0x00);
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);
}
// 交换缓冲区和轮询IO事件
glfwSwapBuffers(window);
glfwPollEvents();
}
以下是使用OpenGL绘制奥运五环的代码示例:
```
#include <GL/glut.h>void drawCircle(float x, float y, float radius, float r, float g, float b){ glColor3f(r, g, b); glBegin(GL_TRIANGLE_FAN); glVertex2f(x, y); for (int i = 0; i <= 360; i++) { float angle = i * 3.1415926 / 180; float px = x + radius * cos(angle); float py = y + radius * sin(angle); glVertex2f(px, py); } glEnd();}void display(){ glClear(GL_COLOR_BUFFER_BIT); // draw blue circle drawCircle(-0.5, 0, 0.15, 0, 0, 1); // draw yellow circle drawCircle(0.5, 0, 0.15, 1, 1, 0); // draw black circle drawCircle(0, 0, 0.15, 0, 0, 0); // draw green circle drawCircle(-0.25, -0.25, 0.15, 0, 1, 0); // draw red circle drawCircle(0.25, -0.25, 0.15, 1, 0, 0); glutSwapBuffers();}void reshape(int w, int h){ glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w >= h) { float aspect = (float)w / h; glOrtho(-1.5 * aspect, 1.5 * aspect, -1.5, 1.5, -1, 1); } else { float aspect = (float)h / w; glOrtho(-1.5, 1.5, -1.5 * aspect, 1.5 * aspect, -1, 1); } glMatrixMode(GL_MODELVIEW);}int main(int argc, char** argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500, 500); glutCreateWindow("Olympic Rings"); glutDisplayFunc(display); glutReshapeFunc(reshape); glClearColor(1, 1, 1, 1); glutMainLoop(); return 0;}
```c++
该代码使用了OpenGL的基本绘图函数和窗口管理函数,其中glOrtho()函数用于让五环在拖动窗口大小时不变形。drawCircle()函数用于绘制圆形,其中glBegin()和glEnd()函数用于指定绘制的图元类型,glVertex2f()函数用于指定顶点坐标,glColor3f()函数用于指定顶点颜色。在display()函数中,分别绘制了五个圆形,并指定了其颜色和位置。在reshape()函数中,根据窗口的宽高比例调整了视口大小和投影矩阵,确保五环在拖动窗口大小时不变形。
Opengl绘制奥运五环的示例代码,根据情况进行修改
#include <GL/glut.h>
void display() {
glClear(GL_COLOR_BUFFER_BIT);
// 绘制蓝色圆环
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_CIRCLE);
glVertex2f(-5.0f, -5.0f);
glVertex2f(5.0f, -5.0f);
glEnd();
// 绘制黄色圆环
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_CIRCLE);
glVertex2f(-5.0f, 5.0f);
glVertex2f(5.0f, 5.0f);
glEnd();
// 绘制黑色圆环
glColor3f(0.0f, 1.0f, 0.0f);
glBegin(GL_CIRCLE);
glVertex2f(-5.0f, -5.0f);
glVertex2f(5.0f, -5.0f);
glEnd();
// 绘制绿色圆环
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_CIRCLE);
glVertex2f(-5.0f, -5.0f);
glVertex2f(5.0f, -5.0f);
glEnd();
// 绘制红色圆环
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_CIRCLE);
glVertex2f(-5.0f, -5.0f);
glVertex2f(5.0f, -5.0f);
glEnd();
glFlush();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow("Olympic Rings");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
#include<GL/glut.h>
GLfloat winWidth,winHeight;
void myInit()
{
glClearColor(0.67,0.61,0.06,0.0); //设置背景颜色
glShadeModel(GL_SMOOTH); //明暗平滑
glMatrixMode(GL_PROJECTION); //投影模式
gluOrtho2D(0.0,winWidth,0.0,winHeight); //设置2D的投影
glMatrixMode(GL_MODELVIEW); // Modelview模式
glLoadIdentity(); //初始化矩阵
}
// 绘制五环
void drawRing()
{
// 设置五环颜色
GLfloat colors[][4]={{0.55, 0.38, 0.15, 1.0}, {0.59, 0.82, 0.14, 1.0},
{1.00, 0.06, 0.06, 1.0}, {0.21, 0.62, 0.93, 1.0}, {0.00, 0.35, 0.07, 1.0}};
int x = winWidth/2; //横向中点
int y = winHeight/2;//纵向中点
float firstLength = x * 0.2;//第一环半径
float secondLength = x * 0.33;//第二环半径
float thirdLength = x * 0.54;//第三环半径
float forthLength = x * 0.6; //第四环半径
float fifthLength = x * 0.76; //第五环半径
glColor4fv(colors[0]); //指定绘制第一环的颜色
glBegin(GL_POLYGON); //构造多边形对象
for(int i = 0; i < 360; i++)
{
//绘制第一环
float r = firstLength;
float bx = x + r * cos((float)i * 3.14 / 180.0);
float by = y + r * sin((float)i * 3.14 / 180.0);
glVertex2f(bx, by);
}
glEnd();
glColor4fv(colors[1]); //指定绘制第二环的颜色
glBegin(GL_POLYGON); //构造多边形对象
for(int i = 0; i < 360; i++)
{
//绘制第二环
float r = secondLength;
float bx = x + r * cos((float)i * 3.14 / 180.0);
float by = y + r * sin((float)i * 3.14 / 180.0);
glVertex2f(bx, by);
}
glEnd();
glColor4fv(colors[2]); //指定绘制第三环的颜色
glBegin(GL_POLYGON); //构造多边形对象
for(int i = 0; i < 360; i++)
{
//绘制第三环
float r = thirdLength;
float bx = x + r * cos((float)i * 3.14 / 180.0);
float by = y + r * sin((float)i * 3.14 / 180.0);
glVertex2f(bx, by);
}
glEnd();
glColor4fv(colors[3]); //指定绘制第四环的颜色
glBegin(GL_POLYGON); //构造多边形对象
for(int i = 0; i < 360; i++)
{
//绘制第四环
float r = forthLength;
float bx = x + r * cos((float)i * 3.14 / 180.0);
float by = y + r * sin((float)i * 3.14 / 180.0);
glVertex2f(bx, by);
}
glEnd();
glColor4fv(colors[4]); //指定绘制第五环的颜色
glBegin(GL_POLYGON); //构造多边形对象
for(int i = 0; i < 360; i++)
{
//绘制第五环
float r = fifthLength;
float bx = x + r * cos((float)i * 3.14 / 180.0);
float by = y + r * sin((float)i * 3.14 / 180.0);
glVertex2f(bx, by);
}
glEnd();
}
void Reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h); //视口映射
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
winWidth = w;
winHeight = h;
}
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT); //清空绘制内容
drawRing(); //绘制五环
glFlush(); //显示图像
}
int main(int argc, char**argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(1000, 0);
glutInitWindowSize(1000, 500);
glutCreateWindow("Olympic Rings");
myInit();
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutMainLoop();
return 0;
}