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)


要求

ZJUCG

ZJUCG

                                             以上 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
啥时候画个好看的男孩子出来……
(无视以上)

转载于:https://www.cnblogs.com/BirdCage/p/9974090.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值