您现在的位置是:主页 > news > 泰兴网站开发/百度搜索优化平台
泰兴网站开发/百度搜索优化平台
admin2025/5/24 8:51:38【news】
简介泰兴网站开发,百度搜索优化平台,房99西安房产网,网站建设日程表如何写#Tutorial 2.0 这次内容很多很多,基本上都是关于opengl的指令,几乎未涉及图形原理(只是一个点嘛)#考虑再三,还是把opengl全部import出来,因为opengl的函数都是以gl为前缀的,所以不会造成多少歧义,只是性能会…
#Tutorial 2.0 这次内容很多很多,基本上都是关于opengl的指令,几乎未涉及图形原理(只是一个点嘛)
#考虑再三,还是把opengl全部import出来,因为opengl的函数都是以gl为前缀的,所以不会造成多少歧义,只是性能会影响点,#不过现在也不是考虑性能的时候,舒服地学就可以了
from OpenGL.GL import *
#这个是从pyopengl中导入的着色器编译包装,我准备在2.1进行讲解这两个函数
from OpenGL.GL.shaders importcompileShader,compileProgram#导入numpy,我们可以很方便将传入数据,有性能加成哦!
importnumpy as np#pyglet不多说了吧
importpyglet#提供指针,不要看的头疼,因为它仅是个跑龙套的
importctypes#照样1.0创建一个窗口
window = pyglet.window.Window(width = 800, height = 600, caption = "tutorial 02")#接下来就是准备着色器#分为以下步骤,编写GLSL程序源代码,GLSL全称opengl shading language,是着色语言,我们通过字符串形式读入,#再用opengl提供的一系列函数进行编译,链接,组成着色器程序,着色器程序运行在GPU,与我们程序相隔#每一个着色器程序最少提供两个shader,一个是vertex shader顶点着色器,另一个是fragment shader图元着色器#它们的工作原理以后再看,我们现在只要知道它最最基本的数据传输原理就行了#VERT -- 顶点着色器#FRAG -- 图元着色器
VERT = """#version 330 /* opengl的版本 */
in vec3 position; /* in,表示输入,从我们的数据存储区输入到GPU,
vec3,代表它是三维向量,包含三个数据x,y,z,我们可以用position.x访问第一个数据
position,则是它在vertex shader中的名字 */
void main(){
gl_Position = vec4(position,1.0) ; /* vertex shader基本任务就是计算出gl_Position值,
gl_Position在标准空间中,这个以后再说
注意gl_Position是vec4类型,也即包含四个数据,
这里我们不改变传入的值,直接传入position,外加一个1.0(w值)
另外vec4可以看作是一个构造函数*/
//计算出了gl_Position,vertex shader就完成了最基本的任务,也就可以水过了
//在初学的时候,千万不要从c语言的角度看待vertex shader哦,尽管它很像c
}"""FRAG= """#version 330 /* 同样是opengl版本 */
out vec4 outputF; /*vertex shader的基本任务是计算顶点位置,
而fragment shader的基本任务就是计算每个像素的颜色值,
注意,vertex shader处理我们输入的数据,
并输出经它更改后顶点数据(不光是位置,以后我们还会看到法线,纹理坐标等),
而fragment shader处理的是每一个像素,也即对每一个像素进行操作。
*/
void main()
{
outputF = vec4(1.0, 0.0, 0.0, 1.0);/* 比照下glClearColor四个参数吧 */
}"""
#pyopengl给我们提供的两个着色器函数#compile自然是编译的意思啦,我们下节翻译再��9c�compileProgram与compileShader的细节吧
shader =compileProgram(compileShader(VERT, GL_VERTEX_SHADER),
compileShader(FRAG,GL_FRAGMENT_SHADER))#链接成功后就可以开始用,声明glUseProgram(shader),接下来的绘图数据都将由该着色器程序完成
glUseProgram(shader)#从shader中获取position的位置,这里是重中之重,它代表着色器与我们程序的交流#函数原型为 glGetAttribLocation( GLuint ( program ) , const GLchar *( name ) )-> GLint#program就是变量所在的着色器程序,name就是它的名称#会不会很像我们拿着纸(_position),询问(glGetAttribLocation)住在shader的叫position的变量是什么地址呢?#最后一点:我们要在position前加b,指明我们传入的是字节byte类型,而非str类型
_position = glGetAttribLocation(shader, b"position")#准备顶点数据#用np.array转化list类型,并声明数据类型是np.float32,(与GLfloat不一致哦)#通常GLfloat就是32bit,但会因为机器不同而有所改变,如果你运行错误,可以试试np.float64
VERTEX = np.array([0.0, 0.0, 0.0], np.float32)#准备vertex buffer object#Gen就是generate的简称,glGenBuffers就是向opengl机制说,帮我申请1个缓存,我会通过VBO来操作它#原型是glGenBuffers( GLsizei ( n ) , GLuint * ( buffers ) )-> void#但是pyopengl帮我们包装了下,我们只需要用VBO = glGenBuffer(n)形式,如果n大于1,则VBO是个列表
VBO = glGenBuffers(1)#接着,glBindBuffer绑定我们申请的VBO,完成了两件事#1.告诉了机制,我们将会把VBO指向的缓存当作GL_ARRAY_BUFFER,也即视VBO那块缓存为存储顶点数据缓存#2.告诉机制,接下对缓存的所有操作,都作用在VBO指向的那块缓存
glBindBuffer(GL_ARRAY_BUFFER, VBO)#到底是什么操作?比如我们用glBufferData向刚刚绑定的缓存(也即VBO)传输我们的数据VERTEX#原型glBufferData( GLenum ( target ) , GLsizeiptr ( size ) , const GLvoid * ( data ) , GLenum ( usage ) )-> void#第一个还是用法,表示这块缓存是存顶点数据的,第二个是数据的字节数,因为pygl的包装,我们忽略掉了这个参数#第三个是我们要传的数据,就是刚刚定义的VERTEX,第四个数据的用法,为静态绘制,也就是我们不打算频繁改变它的值#很简单吧
glBufferData(GL_ARRAY_BUFFER, VERTEX, GL_STATIC_DRAW)#对VBO缓存完成了操作,我们可以解绑定,这是一种好习惯。实际上,如果你这时再绑定其它缓存句柄,VBO同样会被解绑定。
glBindBuffer(GL_ARRAY_BUFFER, 0)#这条语句可以查看VBO的值,VBO只是一个句柄而已,相当于缓存的把手(好吧,无视掉这比喻(╯_╰))
print(VBO)#glPointSize(5.0) #如果看不清楚点的大小,请去掉第一个#,好像glPointSize被标记了“不推荐”
glClearColor(0.0, 0.0, 0.0, 1.0)
@window.eventdefon_draw():#如1.1中说,每次进入draw开始绘制前,先要擦好黑板
glClear(GL_COLOR_BUFFER_BIT)#我们在上面得到了着色器中position的地址(其实不是地址),
#于是我们可以通过_position向GPU中的position写信啦!
#首先激活_position。就像glBindBuffer,glEnableVertexAttribArray也告诉了opengl状态机一些事
#好像只有一件,我不太确定!!! ^_^
#1.告诉opengl状态机,有权对_position进行设置了
glEnableVertexAttribArray(_position)#设置什么呢?就是设置GPU中position读取缓存数据的方式,读哪里的缓存呢?就是读当前opengl绑定的缓存
#之前因为我们的好习惯,我们把当前绑定的缓存清为0了,所以要重新绑定。照样用glBindBuffer。
#接着,介绍如何设置读取缓存数据的方式
#照样原型:glVertexAttribPointer( GLuint ( index ) , GLint ( size ) , GLenum ( type ) ,
#GLboolean ( normalized ) , GLsizei ( stride ) , const GLvoid * ( pointer ) )-> void
#长的有点吓人吧?其实都是琐碎的参数啦!
#index,就是变量所在位置,size就是每次读几个值,注意是“值”,在这个程序中是3个值,0.0,0.0,0.0,
#type,每个值的类型,就是GLfloat,在大部分机子中是4个字节,相当于每次读3个GLfloat值
#normalized,是否将其转化为GLfloat,因为VBO指的缓存中存的已经相当于GLfloat,所以我们写False
#stride,就是相邻size个type数据的间隔,也即第一个与下一块数据的第一个相邻的字节数,注意是字节byte
#我们将stride设为了0,乃们会在后续翻译中看到不同于0的值的
#最后一个pointer,即从缓存什么位置开始读,这里,我们当然是从0位开始读啦,
#因为传入的是指针,我们为方便起见,导入了ctypes,c_void_p(0)就是代表null
#如果是从第12字节开始读,就是c_void_p(12),这个还会再见的
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glVertexAttribPointer(_position,3, GL_FLOAT, False, 0, ctypes.c_void_p(0))#终于混过了VAP的讲解,接下来就是最终绘制,之前所有的准备都是为了让glDrawArrays知道它该怎么画
#原型:glDrawArrays( GLenum ( mode ) , GLint ( first ) , GLsizei ( count ) )-> void
#mode,我们想画什么图元,这次是GL_POINTS,只画点图元而已,顶点和点可不一样哦,
#就像vertex shader与fragment shader处理的东西的区别
#first,从第几个顶点开始画,顶点自然是上面读出来的。
#第一个读出的顶点(实际上也只有一个)就要被画成点图元,所以first设为0
#count,指的是共有几个顶点参与绘制,1个点图元3个顶点,1个三角形图元3个顶点。这里只需1个顶点。
glDrawArrays(GL_POINTS, 0, 1)#绘毕,封印_position
glDisableVertexAttribArray(_position)#下面虽然是空白的,但还是隐藏着几个要点,有必要进行说明,
#1.pyglet什么时候调用on_draw?答:当pyglet觉得有必要调用时才会调用on_draw(废话?)
#2.只有on_draw中的指令是不会影响你屏幕的样子的,当刷屏指令执行后,屏幕才会有反应
#而这个刷新指令,你不会看到,有pyglet自主完成
#3.pyglet是默认双缓存的,至于什么是双缓存,额,百度吧,很简单的
#最后跑起来吧(只有一帧画面,没什么好跑的,别忘了,如果点太小,就反注释掉glPointSize哦)
pyglet.app.run()