回 帖 发 新 帖 刷新版面

主题:[原创]OpenGL入门学习——写给想用计算机画图的朋友

说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧?
但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率、16色来做吗?显然是不行的。

[color=0000FF]本帖的目的是让大家放弃TC的老旧图形接口,让大家接触一些新事物。[/color]

OpenGL作为当前主流的图形API之一,它在一些场合具有比DirectX更优越的特性。
[color=FF0000]1、与C语言紧密结合[/color]。
OpenGL命令最初就是用C语言函数来进行描述的,对于学习过C语言的人来讲,OpenGL是容易理解和学习的。如果你曾经接触过TC的graphics.h,你会发现,[color=0000FF]使用OpenGL作图甚至比TC更加简单[/color]。
[color=FF0000]2、强大的可移植性[/color]。
微软的Direct3D虽然也是十分优秀的图形API,但它只用于Windows系统(现在还要加上一个XBOX游戏机)。而OpenGL不仅用于Windows,还可以用于Unix/Linux等其它系统,它甚至在大型计算机、各种专业计算机(如:医疗用显示设备)上都有应用。并且,OpenGL的基本命令都做到了硬件无关,甚至是平台无关。
[color=FF0000]3、高性能的图形渲染[/color]。
OpenGL是一个工业标准,它的技术紧跟时代,现今各个显卡厂家无一不对OpenGL提供强力支持,激烈的竞争中使得OpenGL性能一直领先。
总之,OpenGL是一个很NB的图形软件接口。至于究竟有多NB,去看看DOOM3和QUAKE4等专业游戏就知道了。
OpenGL官方网站(英文)
[color=0000FF]http://www.opengl.org[/color]

下面我将对Windows下的OpenGL编程进行简单介绍。

=====================未完,请勿跟帖=====================

回复列表 (共70个回复)

51 楼

请问楼主,为什么不能正确显示出图形
此程序是用Bresenham算法来画直线,我把组成直线的点储存在一个线性链表中,画点的时候调用这个链表。
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <conio.h>
#include <time.h>

#define OK 1
#define ERROR 0
#define OVERFLOW -1
//定义链表节点
typedef struct LNode{
    GLshort x;要画的点的横坐标
    GLshort y;要画的点的竖坐标
    struct LNode* next;
}LNode, *LinkList;
LinkList L,p;
//链表初始化
int CreateList_L()
{   
    L=(LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    return OK;
}
//Bresenham算法
void Bresenham_Line(GLshort x1,GLshort y1,GLshort x2,GLshort y2)
{

int j;
GLshort x,y,dx,dy,dk;
dx=x2-x1;
dy=y2-y1;
dk=2*dy-dx;
x=x1;
y=y1;
for(j=0;j<=dx;j++)
  {
        p=(LinkList)malloc(sizeof(LNode));//将要画的点坐标用链表储存
        p->x=x;
        p->y=y;
        p->next=L->next; 
        L->next=p;                            //此上五句等价drawpixel(x,y);
        x=x+1;
        dk=dk+2*dy;
    if(dk>=0)
    {
       y=y+1;
       dk=dk-2*dx;
    }
  }

}


void myDisplay(void)
{    
    LinkList q;
    q=L->next;
    glClear(GL_COLOR_BUFFER_BIT);
    gluOrtho2D(-200,200,-200,200);
    glBegin(GL_POINTS);
    while(q!=NULL)
    {
     glVertex2s(q->x,q->y);
     q=q->next;
    }
    glEnd();
    glFlush();
}
int main(int argc, char *argv[])
{   
    GLshort a,b,c,d;
    LinkList t;
    CreateList_L();
    scanf("%d%d%d%d",&a,&b,&c,&d);
    Bresenham_Line(a,b,c,d);
    t=L->next;
    while(t!=NULL)
    {
        printf("%d    %d\n",t->x,t->y);
        t=t->next;
    }//此上六行为显示Bresenham画直线算法的正确性将所要画的点的坐标打印出来
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(400, 400);
    gluOrtho2D(-200,200,-200,200);//定义像素间距为 1
    glutCreateWindow("画直线");
    glutDisplayFunc(&myDisplay);
    glutMainLoop();
    return 0;
}
谢谢。。。。

52 楼

恕我直言,这样的问题,我是不会答复的——至少我不会直接答复。
“为什么不能正确显示图形”,什么才叫正确呢?程序要求用户给出若干输入,这些输入是起什么作用?整个程序又有什么功能?这些都不讲清楚,我实在是不愿意阅读如此枯燥的程序代码。抱歉了。

53 楼

   非常抱歉,是我的错。我是新手,编程不成功因此烦躁,未能全面考虑你的感受!那个问题我已修改,加了一些注释。但愿写得清楚!希望您能在闲暇时间看一下,指点迷津。

54 楼

这下清楚多了。我感觉你的Bresenham算法有些问题,似乎只能绘制斜率在[0, 1]之间的直线?并且,输入的两个点的坐标,必须满足x1 < x2才能正确绘制。

在图形绘制方面,程序在display函数中直接使用了gluOrtho2D(-200,200,-200,200);,这是不对的。
gluOrtho2D的功能并不是像它字面意思那样,把坐标系设置为多少多少,它的实际功效是在当前矩阵上乘以一个新的矩阵。如果当前矩阵是单位矩阵,那么确实可以达到正确设置坐标系的效果,如果当前矩阵不是单位矩阵,则效果可能就不是你所想像的那样了。由于display这个函数会被反复调用,在第二次和以后各次中,当前矩阵已经不是单位矩阵了,所以不能得到预期效果。为了保证每次使用gluOrtho2D前,当前矩阵是单位矩阵,可以在gluOrtho2D函数调用以前,使用glLoadIdentity函数来将当前矩阵复位。
另外,习惯上是把“透视矩阵”作为当前矩阵来执行gluOrtho2D操作,而用“模型视图矩阵”作为当前矩阵来执行glRotatef等操作。因此在使用gluOrtho2D前,应该选择“透视矩阵”来作为当前矩阵,使用gluOrtho2D后,重新选择“模型视图矩阵”作为当前矩阵。

因此,程序中gluOrtho2D一句可以用以下五句替换:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-200,200,-200,200);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

55 楼

太high了!
  我这个直线算法确实如你所说有局限,因为我是新手,我只想试试这种想法对不对!
  听你的解释我了解了很多知识!也知道自己知识太短浅!而且你很快就给我回复!非常感谢您!!!

56 楼

相当的好,谢谢了。
想问一下,我们用的是vc 6.0可以用吗。

57 楼

VC6.0基本上是可以的,——虽然VC6.0的bug众多,但其中很多都只在使用C++时出现。只使用C语言的话,问题不大。但为什么一定要用6.0呢?不必这样吧。就像TC,太过老旧总会被淘汰的。

58 楼


感谢感谢。

59 楼


太感谢了。。。

60 楼

这么好的帖子加精是应该的。楼主是个好人,我强烈支持

我来回复

您尚未登录,请登录后再回复。点此登录或注册