当前位置:   article > 正文

[Program with me]用python开发Minecraft | 从底层代码开始 #2_minecraft源代码

minecraft源代码

上篇漏了:添加背景颜色

        位置:settings.py

  1. # colors
  2. BG_COLOR = glm.vec3(0.1, 0.16, 0.25)

 我新增一种颜色

        位置:main.py --> render()函数内

self.ctx.clear(color=BG_COLOR)

我在clear()内用BG_COLOR作为参数,以作为背景颜色


1.创建一些资源文件

 I.在meshes文件夹下,添加base_mesh.py和quad_mesh.py文件 

 II.在根目录下,添加shader_program.py和scene.py文件

 III.在shaders文件夹下,添加quad.frag和quad.vert文件,这两个文件的创建比较特殊

请跟着我的步骤走,如下:

 1).在shaders文件中新建文件

 2).直接输入quad.frag以创造这个文件

 3).但是会提示没有这个后缀名文件支持 ,并让你安装这个,跟着装就好了

然后就可以支持frag和vert文件了。

2.构造着色器管理程序

        位置:Shader_program.py下

  1. from settings import *
  2. class ShaderProgram:
  3. def __init__(self, app):
  4. self.app = app
  5. self.ctx = app.ctx
  6. # --------- shaders ---------- #
  7. self.quad = self.get_program(shader_name='quad')
  8. # ---------------------------- #
  9. self.set_uniforms_on_init()
  10. def set_uniforms_on_init(self):
  11. pass
  12. def update(self):
  13. pass
  14. def get_program(self, shader_name):
  15. with open(f'shaders/{shader_name}.vert') as file:
  16. vertex_shader = file.read()
  17. with open(f'shaders/{shader_name}.frag') as file:
  18. fragment_shader = file.read()
  19. program = self.ctx.program(vertex_shader=vertex_shader, fragment_shader=fragment_shader)
  20. return program

我做了什么:

序号代表第几行代码,逐一解释

①我从settings.py引入所有东西

④创建了和该文件名字一样的ShaderProgram类,该类用于集中管理着色器程序

⑤该类的构造方法,接受一个参数app,代表应用程序实例

⑥在初始化过程中,将app实例存储在self.app属性中

⑦从app实例中获取 OpenGL 上下文,并存储在self.ctx中

⑨调用了 get_program() 方法,用于获取我们放在shaders文件夹下的 'quad' 着色器程序,并将返回的程序对象存储在 self.quad 属性中。

(11)调用set_uniforms_on_init()方法

(13)定义set_uniforms_on_init(),目前为无内容,但该方法用于在初始化过程中设置着色器程序的统一变量(uniform variables)

(16)定义update(),目前是无内容,开发者可以在这个方法中更新着色器程序的状态或执行其他操作

(19)我创建了一个方法叫做get_program(),它接受一个shadername作为参数,该方法用于从文件中读取顶点着色器和片段着色器的源代码,并使用这些源代码创建一个着色器程序对象

(20-21)读取shaders文件夹中的quad.vert转换并放在vertex_shader对象中,此为顶点着色器

(23-24)读取shaders文件夹中的quad.frag转换并放在fragment_shader对象中,此为片段着色器

(26)我用quad.vert和quad.frag,这两个文件中读取到的信息,创建一个着色器对象

(27)该类返回构造好的着色器对象

3.创造着色器

I.位置:shaders\quad.frag下

  1. #version 330 core
  2. void main() {
  3. }

II.位置:shaders\quad.vert下

  1. #version 330 core
  2. void main() {
  3. }

 我做了什么:两个一起解释

①这是GLSL的版本声明。在这种情况下,它指定了使用OpenGL 3.3 Core Profile的GLSL版本。core 关键字表示我们正在使用OpenGL的核心配置,而不是兼容性配置,这意味着我们只能使用OpenGL核心功能,而不是过时的功能。

③这是顶点着色器(Vertex Shader)或片段着色器(Fragment Shader)的主函数;

在顶点着色器中,用于处理每个顶点;在片段着色器中,用于处理每个片段(像素)。

4.实例化着色器

I. 位置:在main.py内第⑤行

from shader_program import ShaderProgram

我将刚刚创建的着色器管理程序引入进来

II. 位置:还在main.py内 总的第(27)行,就在self.is_running = True的正下面

self.on_init()

 功能: 该方法调用了实例化着色器管理程序

III.位置:main.py内  在init()和on_init()方法之间 总的第(29)行

  1. def on_init(self):
  2. self.shader_program = ShaderProgram(self)
'
运行

 功能:该方法实例化一个着色器管理程序 

IV.位置:main.py内 在update()方法内 放在第一行 总的第(33)行

self.shader_program.update()

 功能:调用着色器管理程序的更新方法

5.构造基础网格类

位置:在base_mesh.py

  1. import numpy as np
  2. class BaseMesh:
  3. def __init__(self):
  4. # OpenGL context
  5. self.ctx = None
  6. # shader program
  7. self.program = None
  8. # vertex buffer data type format: "3f 3f"
  9. self.vbo_format = None
  10. # attribute names according to the format: ("in_position", "in_color")
  11. self.attrs: tuple[str, ...] = None
  12. # vertex array object
  13. self.vao = None
  14. def get_vertex_data(self) -> np.array: ...
  15. def get_vao(self):
  16. vertex_data = self.get_vertex_data()
  17. vbo = self.ctx.buffer(vertex_data)
  18. vao = self.ctx.vertex_array(self.program, [(vbo, self.vbo_format, *self.attrs)], skip_errors=True)
  19. return vao
  20. def render(self):
  21. self.vao.render()
'
运行

我做了什么:

序号代表第几行

①引入numpy并重命名为np

④我创建了BaseMesh类作为基类,其他更复杂的网格mesh类都会继承于它,减少代码量

⑤我创建了构造方法init()以初始化一些属性参数,所有属性都初始化为空对象

⑦他们分别为:ctx ->OpenGL 上下文对象。

program:着色器程序对象,用于渲染网格。

(11)vbo_format:顶点缓冲区数据类型的格式,例如 "3f 3f" 表示每个顶点有两个部分,每个部分有三个浮点数。

(13)attrs:顶点属性名称的元组,用于指定每个顶点缓冲区中的数据对应的属性名称。

(15)vao:顶点数组对象,用于管理顶点缓冲区的状态。

(17)创建一个get_vertex_data()方法,用于从派生类中获取顶点数据;派生类需要实现这个方法,并返回一个包含顶点数据的NumPy数组。

(19)创建一个get_vao方法,该方法用于创建和返回顶点数组对象

(20)调用 get_vertex_data() 方法获取顶点数据,并存储在vertex_data对象中

(21)它创建一个顶点缓冲区对象(VBO),并使用vertex_data对象初始化它

(22-23)它使用顶点缓冲区数据、顶点缓冲区数据类型格式和顶点属性名称创建一个顶点数组对象,并返回它.

(25)创建了render()方法,方法用于渲染网格对象

(26)简单地调用了顶点数组对象的 render() 方法,该方法将执行着色器程序,绑定顶点缓冲区数据,并绘制网格。

6.构造四边形网格

位置:meshes\quad.mesh.py内

  1. from settings import *
  2. from meshes.base_mesh import BaseMesh
  3. class QuadMesh(BaseMesh):
  4. def __init__(self, app):
  5. super().__init__()
  6. self.app = app
  7. self.ctx = app.ctx
  8. self.program = app.shader_program.quad
  9. self.vbo_format = '3f 3f'
  10. self.attrs = ('in_position', 'in_color')
  11. self.vao = self.get_vao()
  12. def get_vertex_data(self):
  13. vertices = [
  14. (0.5, 0.5, 0.0), (-0.5, 0.5, 0.0), (-0.5, -0.5, 0.0),
  15. (0.5, 0.5, 0.0), (-0.5, -0.5, 0.0), (0.5, -0.5, 0.0),
  16. ]
  17. colors = [
  18. (0, 1, 0), (1, 0, 0), (1, 1, 0),
  19. (0, 1, 0), (1, 1, 0), (0, 0, 1)
  20. ]
  21. vertex_data = np.hstack([vertices, colors], dtype='float32')
  22. return vertex_data

我做了什么:

①从settings.py引入所有东西

②从meshes文件夹下的base_mesh.py文件中引入BaseMesh网格基类

⑤定义一个QuadMesh()类,意思是四边形网格,它继承至BaseMesh类,

⑥这是 QuadMesh 类的构造函数,它接受一个参数 app,代表应用程序的实例

⑦调用了基类 BaseMesh 的构造函数,使用 super().__init__() 进行初始化

⑨获得app的实例并存储在self.app属性中

⑩获得app的openGL上下文对象并存储在self.ctx中

(11)获得app实例化的四边形着色器程序

(13-14)设置了顶点坐标数为'3f '和颜色数据格式为 '3f',意思是顶点坐标和颜色都是三个浮点数

(15)调用了基类的 get_vao() 方法来创建顶点数组对象(VAO)

(17)创建get_vertex_data()方法,定义四边形的顶点数据

(18-21)根据opengl的要求,我在此处需要定义两个逆时针遍历的三角形,每个括号内的三个数字构成一个顶点坐标(x,y,z),此处的两组坐标分别为可形成两个互补为正方形的直角三角形,(感兴趣的可以动手自己试画下)。

(22-25)这是一个颜色列表,包含了六个元组,每个元组代表一个颜色(R,G,B),从左到右,从上到下,分别为绿色,红色,黄色,绿色,黄色,蓝色。

(26)将上述的顶点坐标和颜色列表作为参数,np.hstack 函数将这两个数组按水平方向堆叠在一起,即将 colors 数组的每一行添加到 vertices 数组的对应行的右侧,形成一个形状为 (6, 6) 的新数组;

dtype='float32':这个参数指定了新数组的数据类型为 32 位浮点数,确保了顶点数据和颜色数据的数值类型一致。

(27)vertex_data 数组的形状为 (6, 6),其中每行代表一个顶点,前三个元素表示顶点的坐标,后三个元素表示顶点的颜色,这个数组将作为顶点缓冲区的数据传递给 OpenGL

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/796987
推荐阅读
相关标签
  

闽ICP备14008679号