这次主要实现在窗口上绘制点、线以及修改其属性,另外还会分析画直线的原理和相关算法。

1、在窗口指定位置画点

glBegin(GL_POINTS);

glEnd();

使用glBegin()和glEnd()方法向窗口中添加图形。要添加点时,glBegin()函数里的参数填GL_POINTS。然后通过glVertex3f()函数在指定的(坐标)位置画点,如:glVertex3f(100.0f, 100.0f, 0.0f);三个参数分别表示x,y,z坐标。

glBegin(GL_POINTS);
glVertex3f(100.0f, 100.0f, 0.0f);
glVertex3f(100.0f, 200.0f, 0.0f);
glVertex3f(200.0f, 100.0f, 0.0f);
glVertex3f(200.0f, 200.0f, 0.0f);
glEnd();

默认情况下点的大小时一个像素点,在画点之前可以通过函数glPointSize(5.0f)来修改点的大小。

如:

#include <windows.h>
#include <gl/glut.h> void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glPointSize(5.0f);
glBegin(GL_POINTS);
glVertex3f(100.0f, 100.0f, 0.0f);
glVertex3f(100.0f, 200.0f, 0.0f);
glVertex3f(200.0f, 100.0f, 0.0f);
glVertex3f(200.0f, 200.0f, 0.0f);
glEnd();
glFlush(); } void main()
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(300, 300);
glutInitWindowPosition(200, 200);
glutCreateWindow("point");
glutDisplayFunc(renderScene);
glOrtho(0.0f, 300.0f, 0.0f, 300.0f, 1.0f, -1.0f);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glutMainLoop(); }

2、画直线

(1)GL_LINES画法:

与画点相似,画直线时在函数glBegin(GL_LINES)中给的参数是GL_LINES,这种画直线的方法是,通过在glBegin和glEnd之间添加偶数个点,第2n和第2n+1个点之间是一条连线,如果添加的点的个数是奇数,那最后一个点时多余的。例如:

#include <windows.h>
#include <gl/glut.h> void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(5.0f);
glBegin(GL_LINES);
glVertex3f(100.0f, 100.0f, 0.0f);
glVertex3f(100.0f, 200.0f, 0.0f);
glVertex3f(200.0f, 100.0f, 0.0f);
glVertex3f(200.0f, 200.0f, 0.0f);
glVertex3f(250.0f, 250.0f, 0.0f);
glEnd();
glFlush(); } void main()
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(300, 300);
glutInitWindowPosition(200, 200);
glutCreateWindow("line");
glutDisplayFunc(renderScene);
glOrtho(0.0f, 300.0f, 0.0f, 300.0f, 1.0f, -1.0f);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glutMainLoop(); }

(2)GL_LINE_STRIP画法:

这种画直线方法叫做折线画法,该方法与第一种方法类似。不同的地方第一个点和第二个点连线,第二个点和第三个点连线…第n个点和第n+1个连线。

#include <windows.h>
#include <gl/glut.h> void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(5.0f);
glBegin(GL_LINE_STRIP);
glVertex3f(100.0f, 100.0f, 0.0f);
glVertex3f(100.0f, 200.0f, 0.0f);
glVertex3f(200.0f, 100.0f, 0.0f);
glVertex3f(200.0f, 200.0f, 0.0f);
glVertex3f(250.0f, 250.0f, 0.0f);
glEnd();
glFlush(); } void main()
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(300, 300);
glutInitWindowPosition(200, 200);
glutCreateWindow("line");
glutDisplayFunc(renderScene);
glOrtho(0.0f, 300.0f, 0.0f, 300.0f, 1.0f, -1.0f);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glutMainLoop(); }

3、画虚线

在glBegin()函数前面调用glEnable(GL_LINE_STIPPLE);glLineStipple(factor, 0x5555);期中glEnable(GL_LINE_STIPPLE)表示启用虚线模式,glLineStipple为甚至画虚线的规则。(下面引用关于glLineStipple函数的解释:http://baike.baidu.com/link?url=t7CeuQzNxSNKqi7l43QIRlmcwhxC4yQX5tC3v6cpWPOejgQx9K-e_X7Ac7WYsb4RmYuml7BIpmRFCTxRVXeOWa

viod glLineStipple(GLint factor,GLshort pattern);

OpenGL中设置直线的当前点画模式。pattern参数是由1或0组成的16位序列,它们根据需要进行重复,对一条特定的直线进行点画处理。从这个模式的低位开始,一个像素一个像素的进行处理。如果模式中对应的位是1,就绘制这个像素,否则就不绘制。模式可以使用factor参数(表示重复因子)进行扩展,它与1和0的连续子序列相乘。因此,如果模式中出现了3个1,并且factor是2,那么它们就扩展为6个连续的1。必须以GL_LINE_STIPPLE为参数调用glEnable()才能启用直线点画功能。为了禁用直线点画功能,可以向glDisable()函数传递同一个参数。

例如:

glLineStipple(1, Ox3F07);

glEnable(GL_LINE_STIPPLE);

此时模式为Ox3F07(二进制形式为0011111100000111),它所画出来的直线是这样的:先连续绘制3个像素,然后连续5个像素留空,再连续绘制6个像素,最后两个像素留空(注意,首先是从低位开始的)。如果factor是2,那么这个模式便被扩展为:先连续绘制6个像素,然后连续10个像素留空,再连续绘制12个像素,最后4个像素留空。

如果没有启用点画线功能,OpenGL会自动把pattern当做为OxFFFF,把factor当成1。

代码如下:

#include <windows.h>
#include <gl/glut.h> //画虚线 void renderScene()
{
GLint factor = 5;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(5.0f);
glEnable(GL_LINE_STIPPLE);
glLineStipple(factor, 0x5555);
glBegin(GL_LINES);
glVertex2f(100.0f, 100.0f);
glVertex2f(100.0f, 200.0f);
glVertex2f(200.0f, 100.0f);
glVertex2f(200.0f, 200.0f);
glEnd();
glFlush(); } void main()
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(300, 300);
glutInitWindowPosition(200, 200);
glutCreateWindow("line");
glutDisplayFunc(renderScene);
glOrtho(0.0f, 300.0f, 0.0f, 300.0f, 1.0f, -1.0f);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glutMainLoop(); }

4、简单分析画直线的算法

以前高中的时候我们就学过两点确定一条直线。图形学中的画直线也是使用这种方法。通过两个端点,确定这条线段(所经过的像素点),然后再调用画点的的方法,给这些像素点画图。

(1)使用两点式公式的方法(为了简便,用两维的举例子):



x1,y1表示点1,x2,y2表示点2的坐标。当|x2-x1|大于|y2-y1时|,假设x1小于x2,我们从x1,x1+1,x1+2…x2,然后按照上面公式求出y坐标对于的值,这些点就是这条直线经过的点。

(2)优化算法提高效率

按照上面的方法,我们每个x坐标的值都要调用一次上面这个公式求出y坐标对应的值。上面的公式涉及到乘法(对计算机来说触发就是乘法的变形)。学过计算机操作系统我们都知道,对于计算机来说,计算乘除法比计算加减法要复杂很多。如果我们能想到其他方法,通过使用加减法去求出线段经过的点的坐标,将大大减小计算量。

a)首先我们求x1到x2的横坐标的变化量(像素点),x2-x1。同样求出y2-y1。再求x坐标每增加要给像素点时,y坐标的变化量,即步长为:



(当|y2-y1|大于|x2-x1|,以y轴为自变量,x轴为因变量)

然后x坐标每次增加1个像素点,y坐标的值增加一个步长。这样我们只需要经过一次除法计算,大大减少了画直线时的计算量,从而提高了运行效率。

注:对于小数点,采用四舍五入的方法求整。

下图引用《计算机图形学》

当然还有更好的画直线的算法。

OpenGL编程(五)绘直线以及分析绘直线的算法的更多相关文章

  1. 用MFC实现OpenGL编程

    一.OpenGL简介 众所周知,OpenGL原先是Silicon Graphics Incorporated(SGI公司)在他们的图形工作站上开发高质量图像的接口.但最近几年它成为一个非常优秀的开放式 ...

  2. OpenGL编程(一)渲染一个指定颜色的背景窗口

    上次已经搭好了OpenGL编程的环境.已经成功运行了第一个程序.可只是照搬书上的代码,并没弄懂其中的原理.这次通过一个小程序来解释使用GLUT库编写OpenGL程序的过程. 程序的入口 与其他程序一样 ...

  3. OpenGL编程指南(第七版)

    OpenGL编程指南(第七版) 转自:http://blog.csdn.net/w540982016044/article/details/21287645 在接触OpenGL中,配置显得相当麻烦,特 ...

  4. Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤

    http://blog.csdn.net/vagrxie/article/details/4602961 Win32 OpenGL 编程( 1 ) Win32 下的 OpenGL 编程必须步骤 wri ...

  5. 编译opengl编程指南第八版示例代码通过

    最近在编译opengl编程指南第八版的示例代码,如下 #include <iostream> #include "vgl.h" #include "LoadS ...

  6. 在 Mac OS X Yosemite 10.10.5 上配置 OpenGL 编程环境

    这个教程主要参考了youtube上的视频 Getting Started in OpenGL with GLFW/GLEW in Xcode 6 ,这个视频有点问题,不能照搬.本人通过自己摸(瞎)索( ...

  7. Linux网络编程(五)

    /*Linux网络编程(五)——多路IO复用之select() 网络编程中,使用IO复用的典型场合: 1.当客户处理多个描述字时(交互式输入以及网络接口),必须使用IO复用. 2.一个客户同时处理多个 ...

  8. [转]VS 2012环境下使用MFC进行OpenGL编程

    我就不黏贴复制了,直接给出原文链接:VS 2012环境下使用MFC进行OpenGL编程 其它好文链接: 1.OpenGL系列教程之十二:OpenGL Windows图形界面应用程序

  9. VS15 openGL 编程指南 配置库 triangle例子

    最近去图书馆借了一本书<OpenGL编程指南(原书第八版)>,今天倒腾了一天才把第一个例子运行出来. 所以,给大家分享一下,希望能快速解决配置问题. 一.下载需要的库文件 首先,我们需要去 ...

随机推荐

  1. MongoDB 数据库下载和安装

    MongoDB是一款非常流行的非关系型数据库,将面向对象数据存储做的非常好.这里就不具体介绍它的使用,本文主要解说怎样安装MongoDB数据库.把自己安装过程中碰到的问题和最后解决方法分享给大家,希望 ...

  2. Android应用内加载pdf的方法?

    [可行] 最直接的方式下载到本地, 然后调用相关应用打开 [可行,有局限] 使用 webview 加载, 需要在 原url 前面加上 http://docs.google.com/gview?url= ...

  3. CxImage 简单配置与使用

    CxImage 简单配置与使用 如果本篇文章还不能解决你在生成解决方案以及便宜过程中的问题 请参阅: http://blog.csdn.net/afterwards_/article/details/ ...

  4. jqGrid冻结列

    jqgrid冻结列 冻结列:就是横向移动表格时,让某一列保持不动 做法: 1.colModel的行要加上属性: frozen:true.注意:冻结列必须从第一列开始,包括隐藏列 2.加载jqgrid后 ...

  5. eclipse用tomcat发布网站的目录

    用eclipse添加的tomcat发布网站时,在tomcat安装目录中的webapps时找不到发布的网站.这是由于eclipse的默认配置,把项目发布到别的文件夹中了.如果想发布到webapps里面, ...

  6. web监控脚本

    #!/bin/bashvalues=`curl -H 'Cache-Control: no-cache' -k -s -m 10 --connect-timeout 10 "$1" ...

  7. js函数参数理解

    eg: function setName(obj){ obj.name = "Nicholas"; obj = new Object(); obj.name = "Gre ...

  8. 第三方库requests

    requests库 # 1.记得安装 第三方 模块 requests # pip install requests import requests url = 'http://www.baidu.co ...

  9. Session与Token认证机制 前后端分离下如何登录

     字号 1 Web登录涉及到知识点 1.1 HTTP无状态性 HTTP是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的.当然它知道是哪个客户端地址发过来的 ...

  10. 【BZOJ3678】Wangxz和OJ

    题意: 不想讲 题解: Rope真香! 正解是Splay缩点,访问时再拆成一个序列 代码: //STL dafa good! #include<algorithm> #include< ...