[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[技术讨论] [图形/游戏开发]PyOpenGL的实现

本帖最后由 523066680 于 2012-3-8 23:37 编辑

关于OPENGL ,http://zh.wikipedia.org/wiki/OpenGL
OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言、跨平台的编程接口(Application programming interface)的规格,
它用于生成二维、三维图像。这个接口由近三百五十个不同的函数调用组成,用来从简单的图元绘制复杂的三维景象。
而另一种编程接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟实境、科学视觉化程式和电子游戏开发。


本人环境 WIN32   Python2.7

以下页面提供了 模块下载、相关文档、GL函数介绍以及对应实例  链接
http://pyopengl.sourceforge.net/

模块(接口)以及源码包下载:
http://pypi.python.org/pypi/PyOpenGL/3.0.1

当然也可以在,开始菜单打开 Python2.7\Module docs    搜索OpenGL并选择安装
实例下载: http://pypi.python.org/pypi/PyOpenGL-Demo
实例中包括了  OPENGL红皮书、NeHe教程、 GLUT库演示 的各种教材对应C语言版本的实例。

图片为demo之一

怎样在Windows里面搭建Python环境啊?

TOP

本帖最后由 523066680 于 2012-2-16 22:34 编辑

http://www.python.org/这个吗?E文不是每个人都看得懂啊
听说有2.x和3.x,初学者应该选择哪个呀?

TOP

如果英文好的话,直接从3开始学。
否则从2x学吧,中文的教程相对多一些。

TOP

Sample.py

本帖最后由 523066680 于 2012-3-8 11:08 编辑
  1. from OpenGL.GLUT import *
  2. from OpenGL.GL import *
  3. import sys
  4. def display():
  5.     glClearColor(0.0,0.0,0.0,0.0)  #R,G,B=(0,0,0)=black , Alpha=0
  6.     glClear(GL_COLOR_BUFFER_BIT)
  7.     glColor3f(0.0,1.0,0.0);        #R,G,B=(0,1,0)=Green
  8.     glRectf(-0.5,-0.5,0.5,0.5)     #Draw a green Rectangle
  9.     glFlush()                      #将以上的图形绘制到窗口上
  10. glutInit(sys.argv)
  11. glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA)  #绘图模式,单缓冲,RGBA颜色模式
  12. glutInitWindowSize(500,500)                 # size
  13. glutInitWindowPosition(100,100)             # position 位置
  14. glutCreateWindow("simple")                  # 建立视窗(并返回一个ID)
  15. glutDisplayFunc(display)                    # 注册用于绘图的回调函数
  16. glutMainLoop()                              #进入主循环,期间将运行注册的回调函数
复制代码
一个比较简单的opengl程序
有很多的配置过程并没有写出,GL系统会采用隐含的设置。
例如,默认的二维窗口坐标系是[-1,-1] 到 [1,1] ,也就是绘制一个(-1,-1)到 (1,1)的矩形将占据整个窗口
(当然,实际有更多的东西,z轴坐标这里也没有用上,默认区间为0->1 , 绘图默认在z=0的位置)





b   8位整数         signed          char GLbyte
s   16位整数        short           GLshort
i   32位整数        long            GLint, GLsizei
f   32位浮点数      float           GLfloat, GLclampf
d   64位浮点数      double          GLdouble, GLclampd
ub  8位无符号整数   unsigned char   GLubyte, GLboolean
us  16位无符号整数  unsigned short  GLushort
ui  32位无符号整数  unsigned long   GLuint, GLenum, GLbitfield

TOP

概览

本帖最后由 523066680 于 2012-2-20 09:03 编辑

OK,连载不能没了纲领,下面对将要介绍的内容、实例,列一个表单:

基本的视图矩阵设置 (glutDisplayMode 以及空间坐标矩阵配置)
点、线、面,几何形状的描绘
色彩
空间
基本的鼠标、键盘响应函数
显示列表
变换函数(glRotate glTranslate glScale)
视图矩阵堆栈函数
光照
立体图形、曲面 绘制函数
纹理映射
抗锯齿效果
颜色混合(透明效果)
动态模糊

大部分内容我会做一些实例和注释,但是更详细的更多的函数使用以及原理,请参考书籍:
《计算机图形学》 第三版,opengl版
《OpenGL编程指南》现在出到第七版,中文

在第一个sample中,出现了gl打头的函数,以及glut打头的函数,区分在于,gl是opengl的基本函数
完成基本渲染功能,但是它的窗口操作并不是很完整,glut是一个实用工具库,提供了更多的函数扩展,使操作和配置变得简单。
所有的pyopengl函数列表,上面也提供了对应函数的大量的实例
http://pyopengl.sourceforge.net/ ... -3.0/index.xhtml#GL

TOP

视口设置、坐标空间定义

编辑:523066680
(这部分不好讲呐。。。  要描述的东西多。按书上的话又有较多的篇幅)
从sample实例中我们看到一个注册回调函数的函数:
glutDisplayFunc(display)   
此后每次绘图、重绘,系统都会调用display函数。GL的渲染并不是一下就结束的,他是一个循环
允许你动态的改变场景、物体,实现一些动画效果以及人机交互。
所以它也定义了一系列回调函数,下面先介绍一部分常用的,为了方便描述,用C语言方式:
glutReshapeFunc(void (*func)(int width,int height))      当人为改变窗口大小时自动调用的函数
glutKeyboardFunc(void (*func)(unsigned char key,int x,int y))  用户按下按键时调用的函数。
glutMouseFunc(void (*func)(int button,int sate,int x,int y))  用户按下鼠标时,自动调用的函数
glutIdleFunc(void(*func)(void));  OGL红皮书释义:
当没有其他事件处理时,就调用这个函数,它对于连续的动画或其他背景过程非常有用

这些函数具体做什么,由编写者定义。除了命名是相对自由的,调用参数需要遵照约定,
例如对应窗口修改事件的函数 reshape() 在定义时必须有两个参数,(宽度,高度)
可以是(x,y)也可以是(foo,bar) ,系统会将窗口的像素大小传递给这两个参数,
你可以根据获取的参数对图像做相应改变。例如,窗口缩小时,图像可能应该成比例缩放。
python中就不用显式定义类型了。

还是写个实例+注释吧:
测试了一下,在脚本中添加了中文注释貌似不能直接双击执行,但是可以在IDLE中按F5执行。
  1. from OpenGL.GLUT import *
  2. from OpenGL.GL import *
  3. import sys
  4. blue=(0.0,0.0,1.0)
  5. green=(0.0,1.0,0.0)
  6. red=(1.0,0.0,0.0)
  7. color=blue
  8. def display():
  9.     glClearColor(0.0,0.0,0.0,0.0)  #背景色=黑色,RGBA全为0
  10.     glClear(GL_COLOR_BUFFER_BIT)   #清除颜色缓冲区
  11.     glColor3fv(color)              #设置下面绘制物体的颜色
  12.                         #f表示参数类型为浮点类型,v表示接受的参数为数组形式
  13.     glRectf(-2.0,-2.0,2.0,2.0)
  14.     glFlush()
  15. def reshape(winx,winy):
  16.     glViewport(0,0,winx,winy)      #定义相对视窗大小(像素范围)
  17.     glMatrixMode(GL_PROJECTION)    #选择投影矩阵
  18.     glLoadIdentity()               #读取规范化的单位矩阵
  19.     glOrtho(-100.0,100.0, -100.0,100.0, 0.0,100.0)
  20.                                    #定义空间坐标系范围
  21.     glMatrixMode(GL_MODELVIEW)     #选择模型视图矩阵
  22.     glLoadIdentity()
  23.    
  24. def hitkey(key,mousex,mousey):
  25.     global color
  26.     if (key=='q'):                 #按下q按键时
  27.         glutDestroyWindow(winid)   #根据ID结束窗口
  28.         sys.exit()
  29.     elif (key=='b'):
  30.         color=blue
  31.         glutPostRedisplay()        #重绘,将调用display
  32.     elif (key=='g'):
  33.         color=green
  34.         glutPostRedisplay()
  35.     elif (key=='r'):
  36.         color=red
  37.         glutPostRedisplay()
  38.         
  39. def mouse(button,state,x,y):
  40.     pass
  41. glutInit(sys.argv)
  42. glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA)
  43. glutInitWindowSize(500,500)
  44. glutInitWindowPosition(100,100)
  45. winid=glutCreateWindow("hitkeytest")    #建立窗口的ID返回到winid
  46. glutDisplayFunc(display)
  47. glutReshapeFunc(reshape)
  48. glutKeyboardFunc(hitkey)
  49. glutMainLoop()
复制代码
按下q退出窗口,r,g,b按键,简单的改变绘制物体的颜色。glutPostRedisplay函数将会调用
glutDisplayFunc注册的绘图函数

关于reshape中的内容注释(暂且可以这么注释):
glViewport(GLint x,GLint y,GLsizei width,GLsizei height)  
设定视窗绘图的像素范围,例如glutInitWindowSize(500,500)定义了窗口大小,500X500 的像素平面
坐标形式:左下角起点为0,0  ,右上角顶点为500,500。则:
    viewport(250,250,100,100) 将会选择从窗口中间(250,250)到 (250+100,250+100)的像素区域
即 : (250,250)->(350,350)  具体请自己实践一下,不用谢。
    glClearColor(0.0,0.0,0.0,0.0)+glClear(GL_COLOR_BUFFER_BIT) 清理所得到的背景颜色,并不仅
限于viewport区域,而是整个500X500。但是你绘图的内容,会在这个像素区域之内。
可以参考这个尝试的结果 http://blog.csdn.net/paktc/article/details/7269049

    glOrtho(GLdouble left,GLdouble right, GLdouble bottom,GLdouble top, GLdouble near,GLdouble far)
官方说法:定义了一个正交平行的视景体
    其实我一直纠结这个该怎么描述,大概就是这样,glOrtho定义一个矩形空间,同时定义好的是空间坐标
范围。你可以依据这个空间坐标绘制任何物体,可以说是与平台无关的,但是超出空间的部分将被截去。
然后,图像终究是要显示在屏幕上的,这个空间将通过一定的形式映射到viewport定义的像素区域。
成为眼前的画面。所以,假如你定义了一个
left=-500,right=500,bottom=-500,top=500,near=0,far=500 的空间,其精细度虽然可以是任意的,
但正面图像最终会被映射到{这里的实例是 (250,250)->(350,350) 也就是100X100的}像素区间上。
这时绘制一个-500,-500->500,500的矩形,映射过来,刚好占领100X100像素区间。
Z轴的事情,一拖再拖,以后再说,我是IF_EXIST兼523066680

下面附参考图:

TOP

TRIANGLES and COLOR

本帖最后由 523066680 于 2012-2-21 22:49 编辑



图例中DISPLAY部分的代码,
def display():
    glClearColor(0.0,0.0,0.0,0.0)  
    glClear(GL_COLOR_BUFFER_BIT)   
    glBegin(GL_TRIANGLES)           #绘制几何形状的一个起始标志,GL_TRIANGLES是众多几何形状的常量之一
    glColor3f(1.0,0.0,0.0)              #定义顶点的颜色
    glVertex3f(-50.0,0.0,0.0)         #定义顶点坐标
    glColor3f(0.0,1.0,0.0)
    glVertex3f(50.0,0.0,0.0)
    glColor3f(0.0,0.0,1.0)
    glVertex3f(0.0,80.0,0.0)
    glEnd()
    glFlush()

这个例子中为了同时说明颜色,在三个顶点前面都设置了不同的颜色。
gl中的颜色设置是这样的,设置了一个颜色后,接下来的所有几何都将采用这种颜色
直到设置了下一个颜色。
这里使用的是RGB混合搭配的方式,(另一种是颜色索引模式),RGB比较直观,
可以自己预定需要的颜色(通过不同颜色的分量分配)。 其R,G,B取值范围为0.0-1.0之间。
0.0,0.0,0.0为黑色  1.0,1.0,1.0为白色   0.5,0.5,0.5为灰色。。。。

然后,如果一个几何形状,一条直线的两个、多个顶点设置了不同的颜色,
GL默认采用平滑(线性)过渡的方式进行渲染,得到一个比较柔和的效果。
是否手工设置着色方式,可以通过这个函数定义:glShadeModel(mode) mode为常量 :
    GL_FLAT 、 GL_SMOOTH
如果在绘制三角形的例子中采用了GL_FLAT,将得到一个蓝色三角形。因为最后的颜色为蓝色
具体参考 http://pyopengl.sourceforge.net/ ... /glShadeModel.xhtml

绘制基本形状的过程:
由glBegin(mode)开始,
  glVertex函数负责设置几何的顶点
由glEnd()结束。 glBegin的参数决定了绘制的几何类型。其参数mode选项如下:
GL_POINTS
GL_LINES
GL_LINE_STRIP
GL_LINE_LOOP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN
GL_QUADS
GL_POLYGON

glVertex 的C版本函数定义:
void glVertex[234]{sifd}(TYPE coords);
void glVertex[234]{sifd}v(const TYPE* coords);

[此部分待编辑]

绘制形状对应类型如下图(引用OPENGL红皮书英文版第七版):

TOP

旋转变换以及平移

本帖最后由 523066680 于 2012-3-8 23:16 编辑

  1. from OpenGL.GLUT import *
  2. from OpenGL.GL import *
  3. from OpenGL.GLU import gluLookAt
  4. import time
  5. from math import sqrt,tan
  6. import sys
  7. import math
  8. winid=0
  9. Rx,Ry,Rz=(0.0,0.0,0.0)
  10. def init():
  11.     glClearColor(0.0,0.0,0.0,0.0)
  12.     glEnable(GL_DEPTH_TEST)
  13.    
  14. def display():
  15.     global Rx,Ry,Rz
  16.     length=300.0
  17.     y=length*sqrt(3.0)/2.0
  18.     x=length/2.0
  19.     movex=x/sqrt(3.0)
  20.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
  21.     glPushMatrix()
  22.     glRotatef(Rx,1.0,0.0,0.0)
  23.     glRotatef(Ry,0.0,1.0,0.0)
  24.     glRotatef(Rz,0.0,0.0,1.0)
  25.     glTranslatef(0.0,-movex,0.0)
  26.     glBegin(GL_TRIANGLES)
  27.     glColor3f(1.0,0.0,0.0);glVertex3f(-x,0.0,-1.0)
  28.     glColor3f(0.0,1.0,0.0);glVertex3f(0.0,y,-1.0)
  29.     glColor3f(0.0,0.0,1.0);glVertex3f(x,0.0,-1.0)
  30.     glEnd()
  31.     glPopMatrix()
  32.     glutSwapBuffers()
  33. def free():
  34.     global Rx,Ry,Rz
  35.     if Rx<360:
  36.         Rx+=1.0
  37.     elif Ry<360:
  38.         Ry+=1.0
  39.     elif Rz<360:
  40.         Rz+=1.0
  41.     else:
  42.         Rx,Ry,Rz=(0.0,0.0,0.0)
  43.     time.sleep(0.01)
  44.     glutPostRedisplay()
  45. def hitkey(key,mousex,mousey):
  46.     print key,mousex,mousey
  47.     if key=='q':
  48.         glutDestroyWindow(winid)
  49.         sys.exit()
  50. def reshape(winx,winy):
  51.     fa=500.0;
  52.     glMatrixMode(GL_PROJECTION)
  53.     glLoadIdentity()
  54.     glOrtho(-500,500,-500,500,-10.0,fa)
  55.     glMatrixMode(GL_MODELVIEW)
  56.     glLoadIdentity()
  57.     gluLookAt(0.0,0.0,200.0, 0.0,0.0,0.0, 0.0,1.0,200.0)
  58. glutInit(sys.argv)
  59. glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH)
  60. glutInitWindowSize(500,500)
  61. glutInitWindowPosition(100,100)
  62. winid=glutCreateWindow("1")
  63. init()
  64. glutDisplayFunc(display)
  65. glutIdleFunc(free)
  66. glutKeyboardFunc(hitkey)
  67. glutReshapeFunc(reshape)
  68. glutMainLoop()
复制代码

TOP

据说新版本的OPENGL会除去 ROTATEF 函数,一些转换算法将由手工实现……
  不过入门嘛,捡着简单的先用着,以后再深入。

TOP

题外篇:正二十面体的坐标取值:

本帖最后由 523066680 于 2012-4-3 23:29 编辑

题外篇:正二十面体的坐标取值:
资料收集/整理:[email]523066680@163.com[/email]


红皮书中举了个绘制正二十面体的例子,部分代码如下
(参见“2.10 创建多边形表面模型的一些提示”)
  1.     #define X .525731112119133606
  2.     #define Z .850650808352039932
  3.     static GLfloat vdata[12][3] = {
  4.        {-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
  5.        {0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
  6.        {Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
  7.     };
  8.     static GLuint tindices[20][3] = {
  9.        {1,4,0}, {4,9,0}, {4,5,9}, {8,5,4}, {1,8,4},
  10.        {1,10,8}, {10,3,8}, {8,3,5}, {3,2,5}, {3,7,2},
  11.        {3,10,7}, {10,6,7}, {6,11,7}, {6,0,11}, {6,1,0},
  12.        {10,1,6}, {11,0,9}, {2,11,9}, {5,2,9}, {11,2,7}
  13.     };
  14.     int i;
  15.     glBegin(GL_TRIANGLES);
  16.     for (i = 0; i < 20; i++) {
  17.     /* color information here */
  18.        glVertex3fv(&vdata[tindices[i][0]][0]);
  19.        glVertex3fv(&vdata[tindices[i][1]][0]);
  20.        glVertex3fv(&vdata[tindices[i][2]][0]);
  21.     }
  22.     glEnd();
复制代码
上面引用了两个常量  
#define X .525731112119133606
#define Z .850650808352039932
原书的解释是
我们为X 和Y 选择了两个似乎很奇怪的数,其用意在于使原点到这二十面体的每个顶点的距离均为1.0。

具体的由来我进行了一番探索


英文页面 http://en.wikipedia.org/wiki/Icosahedron
若以正二十面体的中心为原点,
各顶点的坐标分别为
(0,±1,±Φ)
(±1,±Φ,0)
(±Φ,0,±1)
此Φ = (1+√5)/2,即黄金分割数。
这些顶点能组成一些黄金矩形。

也就是说  正二十面体由三个正交黄金矩形顶点连结而成,现在坐标好找了。
至于为什么。。。。。         暂未找到理论

用正二十面体细分,来绘制球体,为了使“球体”的半径为一,需要对
(0,±1,±Φ)
(±1,±Φ,0)
(±Φ,0,±1)
进行规范化

TOP

返回列表