我不得不演示几个例子来加深一下之前学习的东西(时隔这么久了,有点难以为继的感觉啊)~
我恨数学
据说这个世界上最深沉的感情不是爱而是恨,或许一开始就亮出一个数学函数能让你有动力进行下去?
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
#from numpy import *
import sys
def init():
glClearColor(1.0, 1.0, 1.0, 1.0)
gluOrtho2D(-5.0, 5.0, -5.0, 5.0)
def plotfunc():
glClear(GL_COLOR_BUFFER_BIT)
glPointSize(3.0)
glColor3f(1.0, 1.0, 0.0)
glBegin(GL_LINES)
glVertex2f(-5.0, 0.0)
glVertex2f(5.0, 0.0)
glVertex2f(0.0, 5.0)
glVertex2f(0.0, -5.0)
glEnd()
glColor3f(0.0, 0.0, 0.0)
glBegin(GL_LINES)
#for x in arange(-5.0, 5.0, 0.1):
for x in (i * 0.1 for i in range(-50, 50)):
y = x*x
glVertex2f(x, y)
glEnd()
glFlush()
def main():
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB)
glutInitWindowPosition(50,50)
glutInitWindowSize(400,400)
glutCreateWindow("Function Plotter")
glutDisplayFunc(plotfunc)
init()
glutMainLoop()
main()
这个程序也是很简单的,绘制y=x2的抛物线图像,应该是初中的知识,怎么样恨意上来了没?
这里有几个小地方要说明一下,两个注释,是使用numpy这个强大的数学库进行便捷的运算,为防止有人没装或者不知道怎么装,我注释了numpy而使用Python原生的方法做了。这里需要生产从-5.0到5.0的序列,间隔为0.1,然而python的range函数只接受整数,所以用表达式来代替了。但是记住numpy的速度是很快的,3D图像处理和展示需要大量的运算,Python孱弱的原生运算能力很快就会捉襟见肘,如果可能,请使用numpy库,以后的例子,看运算量我可能会混合使用两种方法,不一定给出替代方法,这点请谅解。
再看一下glPointSize(3.0)
这个语句,它是在整个绘制函数最前面调用的,但是实际的结果,仅有点变粗了,虽然坐标系也是通过点画出来的,但是没有影响;如果你想把线也画粗一点,请使用glLineWidth
。
但我热爱艺术
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from numpy import *
import sys
global W, H, R
(W, H, R) = (500, 500, 10.0)
def init():
glClearColor(1.0, 1.0, 1.0, 1.0)
def drawfunc():
glClear(GL_COLOR_BUFFER_BIT)
glColor3f(0.0, 0.0, 0.0)
glBegin(GL_POINTS)
for x in arange(-R, R, 0.04):
print '%.1f%%r' % ((R + x) / (R + R) * 100),
for y in arange(-R, R, 0.04):
r = cos(x) + sin(y)
glColor3f(cos(y*r), cos(x*y*r), sin(x*r))
glVertex2f(x, y)
print '100%!!'
glEnd()
glFlush()
def reshape(w, h):
if h <= 0: h = 1;
glViewport(0, 0, w, h)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
if w <= h:
gluOrtho2D(-R, R, -R * h / w, R * h / w)
else:
gluOrtho2D(-R * w / h, R * w / h, -R, R)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def keyboard(key, x, y):
if key == chr(27) or key == "q": # Esc is 27
sys.exit()
def main():
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB)
glutInitWindowPosition(20, 20)
glutInitWindowSize(W, H)
glutCreateWindow("Artist Drawer")
glutReshapeFunc(reshape)
glutDisplayFunc(drawfunc)
glutKeyboardFunc(keyboard)
init()
glutMainLoop()
main()
这个结果很漂亮,但你问怎么出来的,这个还是要归结于万恶的数学啊,而且运算速度很慢,要慢慢等才能看到结果,美丽是有代价的啊:)
这个程序里面,就有比较多的东西了,drawfunc
还是一如既往,画点而已,具体为什么要这么画,我也不知道……
还注册了一个glutReshapFunc的函数,这个是什么意思呢,就是当窗口大小改变的时候做的事情,如果你不注册这个函数,那么当改变窗口大小时,可能有一部分的图像就无法显示了。而reshape
里做的事情,是我们这次学习的重点。
glViewport:指定了视口程序显示的范围,也就是OpenGL绘制的范围,这里使用(0, 0, w, h)便是说明整个窗口,一般情况下总是如此,但是我们也是可以指定小于这个范围的ViewPort的。事实上我隐瞒了很多细节,这个函数必须和下面要讲的gluOrtho2D函数一起用才能出现正确的结果。
gluOrtho2D:这个函数派生于OpenGL的glOrtho,它创建了一个正交的视景体(View Volume),我们所看到的物体,都处在这个体中,四个参数分别代表了(left, right, bottom, top),也就是竖直的左右边界和水平的下上边界;而近远则是默认的(-1, 1),glOrtho有六个参数可以设定。这个体越大,我们看到的东西就越小;反之看到的东西就越大。我知道这样很难理解,打个比方就是一个六边形的鱼缸,这个函数定出了一个鱼缸的大小,我们所看的东西呢,都在这个鱼缸里面。
上面说glViewport要和gluOrtho2D一起用才能正确显示是个什么意思呢?gluOrtho2D只管创建一个视体,而glViewport只管绘图的范围,如果视体是个正方体,而窗口是个长方体,直接绘制的结果会是什么呢?很明显,整个视体里的东西都被拉长了,而一般我们viewport都是指明了窗口大小,自然只能修改视体来适应各种不同的比例了。
修改代码,拉伸窗口,查看最终的结果会是怎样的。
glMatrixMode:这个函数非常难以理解,但是又极其重要!这关系到了OpenGL中的“矩阵”的概念。矩阵……你是说黑客帝国么?好像很有趣诶~~ 嗯嗯没错,矩阵是个伟大的东西,通过它,3D世界的所有维度都蜷曲到内存中的一维数据里去了。这是一个有点儿抽象的概念但其实也没什么特别的,OpenGL里有如下几种矩阵:
- GL_MODELVIEW:模型观察矩阵,表示物体的位置变化和观察点的改变;
- GL_PROJECTION:投影矩阵,描述如何将一个物体投影到平面上;
- GL_TEXTURE:纹理矩阵,描述纹理坐标的动态变化
- ...
我不想搬出一堆数字和大括号来说明矩阵的基本运算和应用(好吧其实真实原因是我也不会:),也不会告诉你最后的ModelView矩阵是View矩阵与Model矩阵的乘积,更不会告诉你有glRotate和glTranslate之流的函数来改变矩阵!暂时这么理解就好了,矩阵就是我们走路的方向,我们现在朝南走,看到的南边的风景,然后说“向右拐”,现在看到西边的风景了,再说“向后转”,现在看到东边的风景了。就是通过这样可以累积的变换,我们把我们最初的一些数据变成了更复杂的东西表达了出来,转了几圈后也许有点糊涂了,用
我在查阅opengl的资料时有个疑问,就是pyglet和pyopengl应该选择哪个使用?
终于等到了新的讲解,第二个demo果然不同凡响,希望再接再厉能够多站十几个demo和讲解 ^_^
一口气看完了,博主快出新教程吧。纹理,光照,and so on。
博主大大啊,继续更新呐,等你好久罗,http://pyopengl.sourceforge.net/documentation/manual-3.0/index.xhtml
这个链接被墙了,郁闷
你写的都是 glBegin(GL_LINES),根本没有点,在我的ArchLinux上运行的结果也是线
pyopengl好慢啊,显示一个海量的点集,c语言版的可以实时,python的就不行
你的教程写得很好啊。通俗易懂很适合入门啊。继续撒。嘿嘿
比如贴纹理啊,粒子效果之类的啊。期待继续啊。
请问每次运行完程序,那个图片怎么关闭,因为都没有关闭的叉
很长时间没有更新的教程了,这是工作比较忙还是完全放弃了啊? 一直很期待后续的。例如什么normal mapping 和height map之类, 最好还能简单讲解一些GLSL的渲染例子。。
您可以考虑添加一个donate链接~像廖雪峰前辈那样~~
Just want to say your article is as amazing. The clearness in your post is just cool and i could assume you87&21#;re an expert on this subject. Well with your permission let me to grab your feed to keep updated with forthcoming post. Thanks a million and please continue the gratifying work.
博主,你撬开了我的心扉
然后告诉我坑了= =
然而还是感谢博主 教程很好 对新手帮助很大 感谢
楼主您好,有这么一个问题希望得到您的指点,Pyopengl怎么加载进来obj三维模型文件,并且从中提取出三维模型的正面、侧面、上面的三视二维图像?谢谢。
博主,您好,如有有可能请您继续更新吧,博主的讲解思路清晰,易懂,对新人(我)入门学习是一套非常棒的教程。
文笔不错,很有才华。
博主加油,继续更新。
再次十分感谢1-5的教程~~~
‘%.1f%%r’ 后面的单引号 ’ 提示 “invalid syntax”,是什么原因呢?
@xl.cn
我也碰到同样的问题,将源代码中的这两行
print ‘%.1f%%r’ % ((R + x) / (R + R) * 100),
print ‘100%!!’
改为下面这两行,就行了
print (“%.1f%%r” , ((R + x) / (R + R) * 100))
print (“100%!!”)
路过,支持楼主!
七年了,博主还在写博客。。。只是七年里写的PyOpenGL变少了,五篇偏偏精华,NB