OpenGL画小球(无光照渲染)

#define GLUT_DISABLE_ATEXIT_HACK

#include <gl/glut.h>
#include <gl/glu.h>
void display()
{
 glClear(GL_COLOR_BUFFER_BIT);
 glMatrixMode(GL_MODELVIEW);  
 glLoadIdentity();  
 glColor3f( 1.0f, 1.0f, 1.0f );
 glutSolidSphere( 50.f, 15, 15 );  //glutSolidSphere中的第一个参数太大,要小于1才能看到,第一个参数为半径
 glutSwapBuffers();
}
int main(int argc, char* argv[])
{
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
 glutCreateWindow("小球");
 glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
 glutDisplayFunc(display);
 
 glutMainLoop(); 

 return 0;
}

上述的代码会画出实心球,整个实心小球是一个颜色,立体效果差,若想显示立体效果,需要用颜色,光照等渲染。


下面的代码画出球比较慢,是按照一个一个切面的圆显示出来的,最终为这些切面组成的网状图。这个球的立体感较强,但是画一个球的时间较长。

//球心坐标为(x,y,z),球的半径为radius,M,N分别表示球体的横纵向被分成多少份
void drawSphere(GLfloat xx, GLfloat yy, GLfloat zz, GLfloat radius, GLfloat M, GLfloat N)
{
 glClear(GL_COLOR_BUFFER_BIT);
 glMatrixMode(GL_MODELVIEW);  
 glLoadIdentity();  
 glColor3f( 1.0f, 1.0f, 1.0f );
 float step_z = PI/M;
 float step_xy = 2*PI/N;
 float x[4],y[4],z[4];
 float angle_z = 0.0;
 float angle_xy = 0.0;
 int i=0, j=0;
 glBegin(GL_POLIGON);
  for(i=0; i<M; i++)
  {
   angle_z = i * step_z;
   
   for(j=0; j<N; j++)
   {
    angle_xy = j * step_xy;
    x[0] = radius * sin(angle_z) * cos(angle_xy);
    y[0] = radius * sin(angle_z) * sin(angle_xy);
    z[0] = radius * cos(angle_z);
    x[1] = radius * sin(angle_z + step_z) * cos(angle_xy);
    y[1] = radius * sin(angle_z + step_z) * sin(angle_xy);
    z[1] = radius * cos(angle_z + step_z);
    x[2] = radius*sin(angle_z + step_z)*cos(angle_xy + step_xy);
    y[2] = radius*sin(angle_z + step_z)*sin(angle_xy + step_xy);
    z[2] = radius*cos(angle_z + step_z);
    x[3] = radius * sin(angle_z) * cos(angle_xy + step_xy);
    y[3] = radius * sin(angle_z) * sin(angle_xy + step_xy);
    z[3] = radius * cos(angle_z);
    for(int k=0; k<4; k++)
    {
     glVertex3f(xx+x[k], yy+y[k],zz+z[k]);
    }
   }
  }
 glEnd();
}


注意glvertex3f函数,各个坐标均在0~1之间,如果参数不满足上述要求,则不能画出球形。屏幕为背景色。

glbegin的模式参数决定图像的立体感,如果为GL_QUADS,立体感较差。如果未GL_POLYGON,立体感稍好一些。


这里需要说明一点,第一份代码中使用了双缓冲技术。

   通常, 我们所看到的窗体、文字、图像,从根本上来说都是“画”出来的。比如,制作一个简单的五子棋, 我们可能先要绘制棋盘,然后绘制棋子,我们可能还要绘制一些提示信息。虽然这些绘制操作有一定的先后顺序,通常情况下,操作系统的这些绘制速度非常的快,使人眼误认为这些绘制操作是同时完成的。 
  但当我们进行复杂的绘图操作时,画面便可能有明显的闪烁。解决这个问题的关键在于使绘制的东西同时出现在屏幕上。
所谓双缓冲技术, 是指使用两个缓冲区: 前台缓冲和后台缓冲。前台缓冲即我们看到的屏幕,后台缓冲则在内存当中,对我们来说是不可见的。每次的所有绘图操作都在后台缓冲中进行, 当绘制完成时, 把绘制的最终结果复制到屏幕上, 这样, 我们看到所有GDI元素同时出现在屏幕上,从而解决了频繁刷新导致的画面闪烁问题。

    glutSwapBuffers函数是OpenGLGLUT工具包中用于实现双缓冲技术的一个重要函数。该函数的功能是交换两个缓冲区指针。 使用glutSwapBuffers函数需要glutInitDisplayMode函数中时, 开启GLUT_DOUBLE,即glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE)。这里将我们惯用的GLUT_SINGLE替换为GLUT_DOUBLE,意为要使用双缓冲而非单缓冲。 


第二份代码中使用了单缓冲技术。

   glutInitDisplayMode函数中时, 开启GLUT_SINGLE。glFlush函数是强制刷新,强制马上输出命令执行的结果,而不是存储在缓冲区中,继续等待其他OpenGL命令。因为OPENGL是使用一条渲染管线线性处理命令的,一般情况下,我们提交给OPENGL的指令并不是马上送到驱动程序里执行的,而是放到一个缓冲区里面,等这个缓冲区满了再一次过发到驱动程序里执行;很多时候只有几条指令是填充不满那个缓冲区的,这就是说这些指令根本没有被发送到驱动里,所以我们要调用glFlush来强制把这些指令送到驱动里进行处理。

因此使用该技术,可以看到每次画图的过程,而不是直接显示最终结果。


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值