您的位置:首页 > 运维架构

OpenGL实验(一)彩色五角星绘制

2017-03-27 16:48 781 查看
Open Graphics Library (OpenGL) is a cross-language, cross-platform application programming interface (API) for rendering 2D and 3D vector graphics. The API is typically used to interact with a graphics processing unit (GPU), to achieve hardware-accelerated rendering. (wikipedia)

要求





以上 FROM ZJUCG


六角星……

思路

根据尺寸要求首先对12个点中6个未标示的点的坐标进行计算。

其中两个为(0.1,0.3)(0.25,0)其余由对称可得。

对颜色进行分析。中点(0,0)为白色,周围一圈边界为一段纯色一段渐变。(这里mark一下 矩形的内部填充不知道是怎么实现的。三角形的填充可以认为,比如投影到R坐标系中的三个点,那中间任意一个点的R是可以用线性进行确定的)

OrenGL相关

具体可以参考

http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html

头文件

#include <GL/glut.h>


主函数

int main(int argc, char *argv[])

{

glutInit(&argc, argv);  //对GLUT进行初始化

glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式,RGB 单缓存&多缓存

glutInitWindowPosition(100, 100); //窗口在屏幕中的位置

glutInitWindowSize(400, 400);//窗口的大小

glutCreateWindow("Birdy's OpenGL");//创建窗口

glutDisplayFunc(&myDisplay);

glutMainLoop();//循环

return 0;

}


简单的绘制

glBegin — delimit the vertices of a primitive or a group of like primitives

与glEnd对应 为一次绘制

glBegin说明

https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glBegin.xml

glColor3f(1, 0, 0); //选择红色
glBegin(GL_QUADS);//开始绘制 矩形
{
glVertex2f(-0.9, 0.6);
glVertex2f(0.9, 0.6);
glVertex2f(0.9, -0.6);
glVertex2f(-0.9, -0.6);
}
glEnd();//结束


实现

对glBegin的模式进行分析后认为GL_TRIANGLE_FAN比较符合预期。

GL_TRIANGLE_FAN:Draws a connected group of triangles. One triangle is defined for each vertex presented after the first two vertices.

以中心为第一个绘制的点。

函数如下

/*@author Birdy@C*/
//确定每个点的坐标
const GLfloat point[2][12] =
{
{ 0, 0.1, 0.4, 0.25, 0.4, 0.1, 0,-0.1, -0.4, -0.25, -0.4, -0.1 },
{ 0.5, 0.3, 0.3, 0, -0.3, -0.3, -0.5, -0.3, -0.3, 0, 0.3, 0.3 }
};

//确定每个点的颜色
GLfloat Color[3][12] = { 0 };

for (int i = 0; i < 12; i++)
{
if (i <= 3 || i >= 10) Color[0][i] = 1;    // 0 1 2 3 10 11
if (i >= 2 && i <= 7) Color[1][i] = 1;     // 2 3 4 5 6 7
if (i >= 6 && i <= 11) Color[2][i] = 1;    // 6 7 8 9 10 11
}

//六角星绘制
glBegin(GL_TRIANGLE_FAN); //开始绘制
{
glColor3f(1, 1, 1);
glVertex2f(0, 0); //中心点
for (int i = 0; i < 12; i++)
{
glColor3f(Color[0][i], Color[1][i], Color[2][i]);//选择颜色
glVertex2f(point[0][i], point[1][i]);//顶点
}
glColor3f(Color[0][0], Color[1][0], Color[2][0]);
glVertex2f(point[0][0], point[1][0]);//最后一个点要重画

}
glEnd();


要是没有最后for循环外的两行代码图是这样的



完成图



其他尝试

关于颜色

之前提到的对颜色的差值特别好奇。想知道如果没有中间一个点的白色,会生成什么样的图片

/*@author Birdy@C*/
glBegin(GL_POLYGON);
{
//  glColor3f(1, 1, 1);
//  glVertex2f(0, 0);
for (int i = 0; i < 12; i++)
{
glColor3f(Color[0][i], Color[1][i], Color[2][i]);
glVertex2f(point[0][i], point[1][i]);
}
//glColor3f(Color[0][0], Color[1][0], Color[2][0]);
//glVertex2f(point[0][0], point[1][0]);

}
glEnd();




= =!我看到了纸飞机

并没有(你期待中的)总结

加入旋转和移动

OpenGL好像有很多的坐标系……

这里暂时涉及到的是世界坐标系和当前绘图坐标系。

世界坐标系也称为全局坐标系。它是一个右手坐标系,可以认为该坐标系是固定不变的,在初始态下,其x轴为沿屏幕水平向右,y轴为沿屏幕垂直向上,z轴则为垂直屏幕面向外指向用户,长度单位这样来定:窗口范围按此单位恰好是(-1,-1)(左下角)到(1,1)(右上角)。当然,如果在程序中对视点进行了转换,就不能再认为是这样的了。我们用这个坐标系来描述物体及光源的位置。世界坐标系是始终固定不变的。

当前绘图坐标系是绘制物体时的坐标系,就是模型坐标系,也是右手坐标系。程序刚初始化时,世界坐标系和当前绘图坐标系是重合的。当用glTranslatef(),glScalef(), glRotatef()对当前绘图坐标系进行平移、伸缩、旋转变换之后, 世界坐标系和当前绘图坐标系不再重合。改变以后,再用glVertex3f()等绘图函数绘图时,都是在当前绘图坐标系进行绘图,所有的函数参数也都是相对当前绘图坐标系来讲的。


在绘制前对当前绘图坐标系进行旋转和移动,就可以实现实际绘制图形在世界坐标系的改变。

/* 输入:中心坐标(cx,cy),旋转角度 angle(顺时针) */
void drawstar(const GLfloat cx, const GLfloat cy, GLfloat angle)
{
glTranslatef(cx, cy, 0);
glRotatef(angle, 0, 0, -1);   //顺时针旋转

/*
.....中间绘制代码如上.....
*/
glLoadIdentity();//重置当前的模型观察矩阵,该句执行完后,将焦点移动到了屏幕的中心
}

void display()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
drawstar(0, 0, 0);
drawstar(0.5, 0.5, 60);
drawstar(-0.5, -0.5, 120);
glFlush();
glutSwapBuffers();          //交换两个缓冲区指针

}




好的有点丑……

不成功的绘制

由于它有点丑……就想能不能画出一个标准的圆……

然后一涉及PI……我的CPU就转不过来了……

于是我想……能不能不通过计算具体的位置画出图来

基本思路就是 画一个点 转30度……很完美啊(躺

于是有了以下代码(突然发现颜色可以少存一半

glTranslatef(cx, cy, 0);
glRotatef(angle, 0, 0, -1);   //顺时针旋转
const GLfloat length1 = 0.5, length2 = 0.3;
GLfloat Color[3][6] = { 0 }; //RGB

for (int i = 0; i < 6; i++)
{
if (i <= 1 || i >= 5) Color[0][i] = 1;   // 0 1 5
if (i >= 1 && i <= 3) Color[1][i] = 1;   // 1 2 3
if (i >= 3 && i <= 5) Color[2][i] = 1;      //3 4 5
}

glMatrixMode(GL_PROJECTION);
glBegin(GL_TRIANGLE_FAN);
{
glColor3f(1, 1, 1);
glVertex2f(0, 0);

for (int i = 0; i < 6; i++)
{
glColor3f(Color[0][i], Color[1][i], Color[2][i]);

glVertex2f(0, length1);
glRotatef(30, 0, 0, -1);   //顺时针旋转
glTranslatef(1, 1, 0);
glVertex2f(0.5, length2);
glRotatef(30, 0, 0, -1);   //顺时针旋转
}
glColor3f(Color[0][0], Color[1][0], Color[2][0]);
glVertex2f(0, length1);

}
glEnd();


然而没啥用(摊手

在绘制两个点的中间不管加旋转还是移动它都不理我

加了个glMatrixMode(GL_MODELVIEW);

还是不理我 我也很绝望啊

再留个坑吧

窗口缩放

这里涉及的问题是一拉伸窗口……看图看图



反正就是不好看QwQ

直接找个博客对着改……

http://blog.csdn.net/haohan_meng/article/details/23154511

然后一直是一个白的框

在我几次以为是背景把图盖住了(??)换了个背景色之后发现中间有一个隐隐约约的点

我画了颗星星怎么变成一个点了?

大概是隔了几亿光年吧……

综上(??),有几个参数稍微有点不一样(试一试也试出来了)(所以我大概其实没看懂这一段)

void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat aspectRatio;
// 防止被0所除
if (0 == h)
{
h = 1;
}

glViewport(0, 0, w, h);// 设置视口为窗口的大小

glMatrixMode(GL_PROJECTION);// 选择投影矩阵,并重置坐标系统

glLoadIdentity();

aspectRatio = (GLfloat)w / (GLfloat)h;// 计算窗口的纵横比(像素比)

// 定义裁剪区域(根据窗口的纵横比,并使用正投影)
if (w <= h)
{// 宽 < 高
glOrtho(-1.0, 1.0, -1 / aspectRatio, 1 / aspectRatio, 1.0, -1.0);
}
else
{// 宽 > 高
glOrtho(-1.0 * aspectRatio, 1.0 * aspectRatio, -1.0, 1.0, 1.0, -1.0);
}

glMatrixMode(GL_MODELVIEW);// 选择模型视图矩阵,并重置坐标系统

glLoadIdentity();

}




完整代码

// @author  Birdy&C

#include "gl/glut.h"

/* 输入:中心坐标(cx,cy),旋转角度 angle(顺时针) */
void drawstar(const GLfloat cx, const GLfloat cy, GLfloat angle)
{
glTranslatef(cx, cy, 0);
glRotatef(angle, 0, 0, -1);   //顺时针旋转

//确定每个点的坐标
const GLfloat point[2][12] =
{
{ 0, 0.1, 0.4, 0.25, 0.4, 0.1, 0,-0.1, -0.4, -0.25, -0.4, -0.1 },
{ 0.5, 0.3, 0.3, 0, -0.3, -0.3, -0.5, -0.3, -0.3, 0, 0.3, 0.3 }
};

//确定每个点的颜色
GLfloat Color[3][12] = { 0 };

for (int i = 0; i < 12; i++)
{
if (i <= 3 || i >= 10) Color[0][i] = 1;    // 0 1 2 3 10 11
if (i >= 2 && i <= 7) Color[1][i] = 1;     // 2 3 4 5 6 7
if (i >= 6 && i <= 11) Color[2][i] = 1;    // 6 7 8 9 10 11
}

//六角星绘制
glBegin(GL_TRIANGLE_FAN); //开始绘制
{
glColor3f(1, 1, 1);
glVertex2f(0, 0); //中心点
for (int i = 0; i < 12; i++)
{
glColor3f(Color[0][i], Color[1][i], Color[2][i]);//选择颜色
glVertex2f(point[0][i], point[1][i]);//顶点
}
glColor3f(Color[0][0], Color[1][0], Color[2][0]);
glVertex2f(point[0][0], point[1][0]);

}
glEnd();

glLoadIdentity();//重置当前的模型观察矩阵,该句执行完后,将焦点移动到了屏幕的中心
}

void display()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
drawstar(0, 0, 0);
drawstar(0.5, 0.5, 60);
drawstar(-0.5, -0.5, 120);
glFlush();
glutSwapBuffers();          //交换两个缓冲区指针

}

void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat aspectRatio;
// 防止被0所除
if (0 == h)
{
h = 1;
}

glViewport(0, 0, w, h);// 设置视口为窗口的大小

glMatrixMode(GL_PROJECTION);// 选择投影矩阵,并重置坐标系统

glLoadIdentity();

aspectRatio = (GLfloat)w / (GLfloat)h;// 计算窗口的纵横比(像素比)

// 定义裁剪区域(根据窗口的纵横比,并使用正投影)
if (w <= h)
{// 宽 < 高
glOrtho(-1.0, 1.0, -1 / aspectRatio, 1 / aspectRatio, 1.0, -1.0);
}
else
{// 宽 > 高
glOrtho(-1.0 * aspectRatio, 1.0 *aspectRatio, -1.0, 1.0, 1.0, -1.0);
}

glMatrixMode(GL_MODELVIEW);// 选择模型视图矩阵,并重置坐标系统

glLoadIdentity();

}

int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition(10, 10);
glutInitWindowSize(400, 400);

glutCreateWindow("My Star _Birdy");

glutDisplayFunc(display);
glutReshapeFunc(ChangeSize);// 设置当窗口的大小发生变化时的回调函数

glutMainLoop();   //注册绘制回调函数

return 0;
}


感想

线代要好好学……
不知道openGL的运行机制是怎么样的……
那么多杂七杂八的坐标系……
好想当一个能动不动carry全队的人w
啥时候画个好看的男孩子出来……
(无视以上)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opengl