OpenGL实验(一)彩色五角星绘制
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();
= =!我看到了纸飞机
并没有(你期待中的)总结
2018.6.4 补充
其实就是三角形确定的三个点是0 n-1 n,然后去掉了中间那个就是上面一个角上的顶点是0,然后这个效果就是后绘制的覆盖先绘制的以及双线性插值。
加入旋转和移动
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
啥时候画个好看的男孩子出来……
(无视以上)