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

上篇漏了:添加背景颜色

        位置:settings.py

# colors
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下

from settings import *


class ShaderProgram:
    def __init__(self, app):
        self.app = app
        self.ctx = app.ctx
        # --------- shaders ---------- #
        self.quad = self.get_program(shader_name='quad')
        # ---------------------------- #
        self.set_uniforms_on_init()

    def set_uniforms_on_init(self):
        pass

    def update(self):
        pass

    def get_program(self, shader_name):
        with open(f'shaders/{shader_name}.vert') as file:
            vertex_shader = file.read()

        with open(f'shaders/{shader_name}.frag') as file:
            fragment_shader = file.read()

        program = self.ctx.program(vertex_shader=vertex_shader, fragment_shader=fragment_shader)
        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下

#version 330 core

void main() {

}

II.位置:shaders\quad.vert下

#version 330 core

void main() {

}

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

①这是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)行

def on_init(self):
    self.shader_program = ShaderProgram(self)

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

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

self.shader_program.update()

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

5.构造基础网格类

位置:在base_mesh.py

import numpy as np


class BaseMesh:
    def __init__(self):
        # OpenGL context
        self.ctx = None
        # shader program
        self.program = None
        # vertex buffer data type format: "3f 3f"
        self.vbo_format = None
        # attribute names according to the format: ("in_position", "in_color")
        self.attrs: tuple[str, ...] = None
        # vertex array object
        self.vao = None

    def get_vertex_data(self) -> np.array: ...

    def get_vao(self):
        vertex_data = self.get_vertex_data()
        vbo = self.ctx.buffer(vertex_data)
        vao = self.ctx.vertex_array(self.program, [(vbo, self.vbo_format, *self.attrs)], skip_errors=True)
        return vao

    def render(self):
        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内

from settings import *
from meshes.base_mesh import BaseMesh


class QuadMesh(BaseMesh):
    def __init__(self, app):
        super().__init__()

        self.app = app
        self.ctx = app.ctx
        self.program = app.shader_program.quad

        self.vbo_format = '3f 3f'
        self.attrs = ('in_position', 'in_color')
        self.vao = self.get_vao()

    def get_vertex_data(self):
        vertices = [
            (0.5, 0.5, 0.0), (-0.5, 0.5, 0.0), (-0.5, -0.5, 0.0),
            (0.5, 0.5, 0.0), (-0.5, -0.5, 0.0), (0.5, -0.5, 0.0),
        ]
        colors = [
            (0, 1, 0), (1, 0, 0), (1, 1, 0),
            (0, 1, 0), (1, 1, 0), (0, 0, 1)
        ]
        vertex_data = np.hstack([vertices, colors], dtype='float32')
        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

  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值