日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python opengl 截图_初试PyOpenGL二 (Python+OpenGL)基本地形生成与高度检测

發(fā)布時(shí)間:2023/12/15 python 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python opengl 截图_初试PyOpenGL二 (Python+OpenGL)基本地形生成与高度检测 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在上文中,講述了PyOpenGL的基本配置,以及網(wǎng)格,球形的生成,以及基本的漫游?,F(xiàn)在利用上一篇的內(nèi)容,來利用高程圖實(shí)現(xiàn)一個(gè)基本的地形,并且,利用上文中的第三人稱漫游,以小球?yàn)橐暯?#xff0c;來在地形上前后左右漫游,能實(shí)時(shí)檢測高度。下面先看下效果圖:

二張圖,球分別在不同的地方,不同的顯示模型,一個(gè)是全填充的,一個(gè)是線連,可以從中看到一些基本的思路。大致過程分別如下,首先拿到一張高度圖,檢索其中的高度對應(yīng)的通道的值,然后用來改變網(wǎng)格的高度。這個(gè)過程只需要在初始化時(shí)生成就行了,所以我們可以簡單的用CPU來完成這個(gè)。然后是球體的漫游,這部分在上文中已經(jīng)講了第一與第三人稱漫游,用的就是其中的第三人稱作漫游,在這里,我們主要是要檢索球下面的地形的高度,因?yàn)樾枰獙?shí)時(shí)計(jì)算,這部分用GPU來完成。

我們先看下,根據(jù)高度圖來改變網(wǎng)格高度的相關(guān)代碼(請對照前文中的網(wǎng)格類Plane來看,下面的setHeight為其中的一個(gè)方法):

1 def setHeight(this,image):2 ix = image.size[0]3 iy = image.size[1]4 this.heightImage =image5 print ix,iy6 #print "xr,yr",this.xr,this.yr7 lerp = lambda a,b,d:a * d + b * (1.0 -d)8 fade = lambda t : t*t*(3.0-2.0*t) #t*t*t*(t*(t*6.0-15.0)+10.0)9 for y in range(this.yr):10 for x in range(this.xr):11 index = 5 * (this.xr * y + x) + 3

12 #print index13 fx = float(x) / float(this.xr - 1) * float(ix - 1)14 fy = float(y) / float(this.yr - 1) * float(iy - 1)15 #print float(x) / float(this.xr - 1),fx,float(y) / float(this.yr - 1),fy16 xl,xr,yu,yd = int(math.floor(fx)),int(math.ceil(fx)),int(math.floor(fy)),int(math.ceil(fy))17 dx,dy = fade(fx - xl),fade(fy -yu)18 #print "loc:",xl,xr,yu,yd,dx,dy19 #left up,right up,left down,right down20 lu,ru,ld,rd = image.im[ix * yu + xl],image.im[ix * yu + xr],image.im[ix * yd + xl],image.im[ix * yd +xr]21 #print ix * yu +xl,lu,ru,ld,rd22 hight =lerp(lerp(lu,ru,dx),lerp(ld,rd,dx),dy)23 this.data[index] = hight / 255.0

24 #print "setHeight:",hight / 255.0

檢索高度圖

當(dāng)初完成這段代碼后,我有時(shí)后悔在前面學(xué)習(xí)noise時(shí),沒有自己先完成一個(gè)根據(jù)高度圖生成地形,不然理解柏林噪聲函數(shù)會是一件非常簡單的事,這段代碼很簡單,得到image的信息,然后把原來的地形網(wǎng)格他們二個(gè)做一個(gè)映射關(guān)系,就好像二個(gè)大小不同的矩陣,根據(jù)其中一個(gè)在本矩陣?yán)锏奈恢?#xff0c;找出在另一個(gè)矩陣中對應(yīng)的位置。首先index得到的是當(dāng)初位置網(wǎng)絡(luò)數(shù)據(jù)里的高度索引,第前面文章中,這個(gè)值是0,然后根據(jù)線性關(guān)系,就如上面后說,找到當(dāng)前位置對應(yīng)在image的位置,fx,fy.為什么我說很后悔先看了noise,大家可以看下,這里的代碼的邏輯和noise里的就是一樣,但是這里我可以自己推出來,而看noise里的過程花費(fèi)太多不必要的時(shí)間。在這里,我們可以想象的到,fx,fy是整數(shù)的機(jī)會不大,那么無論取floor(fx)或ceil(fx),都有較大的偏差,正確的方法應(yīng)該是根據(jù)fx的小數(shù)位來做floor(fx)或ceil(fx)權(quán)重進(jìn)行計(jì)算。簡單來說,就是根據(jù)fx,fy來取在它周圍的四個(gè)像素點(diǎn),然后根據(jù)他們的小數(shù)位來對四個(gè)小數(shù)點(diǎn)進(jìn)行混合計(jì)算。其中小數(shù)部分需要的fade可以用lerp,也可以用二階平滑來至三階平滑的映射關(guān)系,而像素值根據(jù)簡單線性關(guān)系求就可以了。理解這里的以后,再去看柏林噪聲實(shí)踐(一) 海波等就容易理解多了。

這個(gè)是初始化地形的高度值,下面就是重點(diǎn),如果根據(jù)球所在的位置,來得到當(dāng)前位置里的高度,然后用來設(shè)定球的高度(簡化問題,只求球心下的高度,二片卡住球的問題就沒考慮)。有了前面的基礎(chǔ),在CPU中進(jìn)行得到高度值也很容易,但是現(xiàn)在是漫游過程中,當(dāng)前位置每時(shí)都在計(jì)算,CPU應(yīng)該用來進(jìn)行更復(fù)雜的邏輯運(yùn)算,這部分交給GPU了,先給出相關(guān)著色器代碼:

1 update_v = """

2 //#version 330 compatibility

3 #version 130

4 uniform sampler2D tex0;5 uniform floatxw;6 uniform floatyw;7 uniform floatheight;8 //the location of center of the sphere

9 uniform vec2 xz;10 uniform floatsphereRadius;11 uniform mat4 mMatrix;12 uniform mat4 vMatrix;13 uniform mat4 pMatrix;14 outvec4 o_color;15 voidmain() {16 vec4 pos =vec4(gl_Vertex);17 vec2 uv = vec2(xz/vec2(xw,yw) + vec2(0.5,0.5));18 uv.y = 1.0 -uv.y;19 vec3 rgb =texture2D(tex0, uv).rgb;20 pos.y = pos.y + sphereRadius + rgb.r;//height;//21 o_color = vec4(uv.x, uv.y, rgb.r, 1);22 gl_Position = pMatrix * vMatrix * mMatrix *pos;23

24 //vec4 v = vec4(gl_Vertex);25 //vec2 uv = vec2(xz/vec2(xw,yw) + vec2(0.5,0.5)).xy;26 //uv.y = 1.0 - uv.y;27 //v.x = v.x + xz.x;28 //v.z = v.z + xz.y;29 //v.y = v.y + texture2D(tex0, uv).r+ sphereRadius;30 //o_color = vec4(uv.x,uv.y, 0, 1 );31 //gl_Position = gl_ModelViewProjectionMatrix * v;

32 }"""33

34 update_f = """35 //#version 330 compatibility

36 #version 130

37 invec4 o_color;38 voidmain() {39 //vec4 color = texture2D(tex1, gl_TexCoord[0].st);

40 gl_FragColor = o_color;//vec4( 0, 1, 0, 1 );

41 }"""

著色器檢索高度

這段代碼大致思想和前面一樣,不過紋理坐標(biāo)需要映射到0-1之前,不過,也少了混合周圍定點(diǎn)的計(jì)算,因?yàn)槲覀冊谠O(shè)定紋理時(shí)(glTexParameterf),已經(jīng)告訴著色器,自動(dòng)線性混合了。在這里,需要說明的是,因?yàn)?30后,已經(jīng)廢棄了固定管線的相關(guān)功能與API,雖然還能用,但是畢竟要向前看,所以主體的部分有二部分,一部分是用的是著色器版本120固定管線提供的gl_ModelViewProjectionMatrix,以及120后的,自己提供MVP,也順便練習(xí)下如何在PyOpenGL里進(jìn)行矩陣的基本操作。其中height是CPU計(jì)算的高度,這個(gè)就放附件里,不拿出來說了,至于為什么還拿出一個(gè)CPU版,前面不是說了不交給CPU嗎,主要是我發(fā)現(xiàn),有些舊的顯卡對于這段邏輯處理還是有些問題(有一問題浪費(fèi)大量時(shí)間才發(fā)現(xiàn)是舊顯卡的問題),代碼就不放了,大家有興趣可以去附件里看。

嗯,還有必要說下繪制部分,地形網(wǎng)絡(luò)用到一個(gè)顏色紋理,而球需要用到高度紋理,在glsl中,多紋理,多著色器如何設(shè)定以及完成。

1 classallshader:2 def __init__(this):3 this.planeProgram =shaders.compileProgram(shaders.compileShader(plane_v, GL_VERTEX_SHADER),4 shaders.compileShader(plane_f, GL_FRAGMENT_SHADER))5 #the parameter tex0 must be use in shaders,otherwise the

6 #glGetUniformLocation get -1

7 this.planeProgram.tex0 = glGetUniformLocation(this.planeProgram,"tex0")8 this.planeProgram.tex1 = glGetUniformLocation(this.planeProgram,"tex1")9 printthis.planeProgram.tex0,this.planeProgram.tex110

11 this.updateProgram =shaders.compileProgram(shaders.compileShader(update_v, GL_VERTEX_SHADER),12 shaders.compileShader(update_f, GL_FRAGMENT_SHADER))13 this.updateProgram.xl = glGetUniformLocation(this.updateProgram,"xw")14 this.updateProgram.yl = glGetUniformLocation(this.updateProgram,"yw")15 this.updateProgram.height = glGetUniformLocation(this.updateProgram,"height")16 this.updateProgram.sphereRadius = glGetUniformLocation(this.updateProgram,"sphereRadius")17 this.updateProgram.tex0 = glGetUniformLocation(this.updateProgram,"tex0")18 this.updateProgram.xz = glGetUniformLocation(this.updateProgram,"xz")19 this.updateProgram.hight = glGetUniformLocation(this.updateProgram,"hight")20 this.updateProgram.mMatrix = glGetUniformLocation(this.updateProgram,"mMatrix")21 this.updateProgram.vMatrix = glGetUniformLocation(this.updateProgram,"vMatrix")22 this.updateProgram.pMatrix = glGetUniformLocation(this.updateProgram,"pMatrix")23

24

25 defDrawGLScene():26 glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT)27 glMatrixMode(GL_MODELVIEW)28 camera.setLookat()29 #texture set

30 glActiveTexture(GL_TEXTURE0)31 glBindTexture(GL_TEXTURE_2D, colorMap)32 glActiveTexture(GL_TEXTURE1)33 glBindTexture(GL_TEXTURE_2D, hightMap)34 #plane

35 glUseProgram(shaderall.planeProgram)36 glUniform1i(shaderall.planeProgram.tex0, 0)37 plane.draw()38 glUseProgram(0)39 #sphare

40 eyeLoc =camera.origin41 uv = eyeLoc[0] / plane.xl + 0.5,eyeLoc[2] / plane.yl + 0.5

42 glUseProgram(shaderall.updateProgram)43 glUniform1f(shaderall.updateProgram.xl, plane.xl)44 glUniform1f(shaderall.updateProgram.yl, plane.yl)45 #CPU compute height

46 #glUniform1f(shaderall.updateProgram.height, plane.getHeight(eyeLoc[0],eyeLoc[2]))

47 glUniform1f(shaderall.updateProgram.sphereRadius, sph.radius)48 glUniform1i(shaderall.updateProgram.tex0, 1)49 #print uv

50 glUniform2f(shaderall.updateProgram.xz,eyeLoc[0],eyeLoc[2])51 #print "eye:",eyeLoc,eyeLoc[0],eyeLoc[2]

52 getMVP(eyeLoc)53 sph.draw()54 glUseProgram(0)55 glActiveTexture(GL_TEXTURE0)56 glBindTexture(GL_TEXTURE_2D, 0)57 glDisable(GL_TEXTURE_2D)58 glActiveTexture(GL_TEXTURE1)59 glBindTexture(GL_TEXTURE_2D, 0)60 glDisable(GL_TEXTURE_2D)61

62 glBegin(GL_LINES)63 glColor(1.0,0.0,0.0)64 glVertex3f(-plane.xl / 2.0, 1.0, -plane.yl / 2.0)65 glVertex3f(100.0, 1.0, -plane.yl / 2.0)66 glColor(0.0,1.0,0.0)67 glVertex3f(-plane.xl / 2.0, 1.0, -plane.yl / 2.0)68 glVertex3f(-plane.xl / 2.0, 1.0, 100.0)69

70 glColor(1.0,0.0,0.0)71 glVertex3f(0.0, 0.0,0.0)72 glVertex3f(100.0, 0.0, 0.0)73 glColor(0.0,1.0,0.0)74 glVertex3f(0.0, 0.0, 0.0)75 glVertex3f(0.0, 1.0, 100.0)76 glEnd()77

78 glutSwapBuffers()

glsl多紋理,多著色器

嗯,python好像對中文注解支持不友好,故采用我的鬼哭神嚎的英語,大家就不要笑了。說一下,后面給出二個(gè)坐標(biāo)系,用來確定當(dāng)家位置的,一個(gè)是左下角,一個(gè)是中心,分別向X,Z正軸發(fā)射出去。

下面這段是設(shè)定球MVP的代碼:

1 defgetMVP(eye):2 v =ny.array(glGetFloatv(GL_MODELVIEW_MATRIX), ny.float32)3 p =ny.array(glGetFloatv(GL_PROJECTION_MATRIX), ny.float32)4 m = ny.array([[1, 0, 0, 0],[0, 1, 0, 0], [0, 0, 1, 0],[eye[0],0,eye[2],1]],ny.float32)5 #print m

6 glUniformMatrix4fv(shaderall.updateProgram.pMatrix,1,GL_FALSE,p)7 glUniformMatrix4fv(shaderall.updateProgram.vMatrix,1,GL_FALSE,v)8 glUniformMatrix4fv(shaderall.updateProgram.mMatrix,1,GL_FALSE,m)9 #glgeffloat

球MVP

附件:Python地形.zip?和上方的漫游模式一樣,其中EDSF前后左右移動(dòng),WR分別向上與向下,鼠標(biāo)右鍵加移動(dòng)鼠標(biāo)控制方向,V切換第一人稱與第三人稱。UP與DOWN切換前面操作的移動(dòng)幅度。在第三人稱下,因?yàn)榍蛑兄飨薅薡軸,故那時(shí)模式看起來如2.5D的那種游戲視角,能左右轉(zhuǎn)動(dòng)視角,不能看到天,不知2.5D游戲里的那種是不是也是這樣被限制住了。

總結(jié)

以上是生活随笔為你收集整理的python opengl 截图_初试PyOpenGL二 (Python+OpenGL)基本地形生成与高度检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。