如何加快pyglet渲染速度?

如何解决如何加快pyglet渲染速度?

下面是渲染代码。我只渲染了约300个块,但速度很慢

async def render(self):
    time_start = time.time()
    self.batch = pyglet.graphics.Batch()
    for block in self.blocks_to_be_rendered:
        self.draw_block(block)
    print("Time to render 1 chunk " + str(time_start-time.time()))


def Create_chunk(cx,cz):
    thr = threading.Thread(target=_Create_chunk,args=(cx,cz))
    thr.start()
    thr.join()
    asyncio.run(Chunks[cx][cz].render())
def draw_block(self,block):

    position = (block.x,block.y,block.z)
    if block._type == "grass":
        block = Grass
    else:
        print("HOLD ON A SEC")
        block = Grass
    vertices = get_vertices(*position)
    faces = ("left","right","top","bottom","front","back")
    for vertex,face in zip(vertices,faces):
        self.batch.add(
            4,gl.GL_QUADS,block.textures[face],("v3f/static",vertex),("t2f/static",(0,1,1)),

我尝试将“ render”作为异步函数运行,因为渲染每个块需要0.3秒!!!! 这意味着fps接近0

任何对优化/关键缺陷的帮助将不胜感激!

编辑:这段代码可能没有意义,因为我将它与主要代码拼接起来会很长,但是这里只是以防万一:

import pyglet
from pyglet.gl import *
from pyglet.window import key
from pyglet import gl,window
import math
import numpy as np
import random
import noise
import threading
import asyncio
from multiprocessing import Pool
import time
#AVOID FROM KEEPING GL FUNCTIONS IN CLASS BLOCK AND CLASS CHUNK BECAUSE THESE WILL BE EXECUTED FROM A DIFFERENT THREAD
def get_tex(file):
    tex = pyglet.image.load(file).get_texture()
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
    return pyglet.graphics.TextureGroup(tex)


def make_textures(textures):
    result = {}
    base = "imgs/"
    faces = ("left","back")
    for face in faces:
        file_name = textures.get(face,textures.get("side"))
        result[face] = get_tex(base + file_name)
    return result

def get_vertices(x,y,z):
    dx,dy,dz = x + 1,y + 1,z + 1
    return [
        (x,z,x,dz,z),# side
        (dx,dx,dz),# side
        (x,# top
        (x,# bottom
        (dx,# side
    ]
class Grass:
    textures = make_textures({"side": "grass_side.png","top": "grass_top.png","bottom": "dirt.png"})

class Block():
    def __init__(self,z):
        #for testing sake _type = dirt
        self._type = "grass"
        self.x = x
        self.y = y
        self.z = z
        self.width = 1
        self.height = 1
        self.length = 1


np.seed = random.randint(1,10000)
Chunks = {-1:{},0:{},1:{}}
class Chunk():
    def prepare_for_rendering(self):
        #Im too lazy to do actual faces so i will only render the nesecary blocks
        #MUST BE DONE IN A DIFFERENT THREAD OR FPS = -1
        time_start = time.time()
        self.blocks_to_be_rendered = []
        for x in range(0,16):
            for z in range(0,16):
                #Gives us an unspecified length dictionary
                for key in self.Chunk_blocks[x][z].keys():
                    #key is an integer
                    #block is Chunk_blocks[x][z][key]
                    try:
                        if self.Chunk_blocks[x-1][z][key] and self.Chunk_blocks[x+1][z][key] and self.Chunk_blocks[x][z+1][key] and self.Chunk_blocks[x][z-1][key] and self.Chunk_blocks[x][z][key+1] and self.Chunk_blocks[x][z][key-1]:
                            pass
                    except:
                        self.blocks_to_be_rendered.append(self.Chunk_blocks[x][z][key])
        print(time_start-time.time())
    def draw_block(self,block):

        position = (block.x,block.z)
        if block._type == "grass":
            block = Grass
        else:
            print("HOLD ON A SEC")
            block = Grass
        vertices = get_vertices(*position)
        faces = ("left","back")
        for vertex,faces):
            self.batch.add(
                4,)
    def __init__(self,Cx,Cz):
    #C means chunk x and chunk y aka top left
        self.Chunk_blocks = {}
        self.batch = pyglet.graphics.Batch()
        self.blocks_to_be_rendered = []
        x =0
        z=0
        for x in range(0,16):
            Chunk_row ={}
            for z in range(0,16):
                top_y = round(noise.pnoise2((Cx*16+x)/16,(Cz*16+z)/16)*10)
                Chunk_collumn = {}
                Chunk_collumn[top_y] = Block(Cx*16+x,top_y,Cz*16+z)
                #print(top_y)
                for y in range(-top_y,30):
                    Chunk_collumn[top_y-y-1] = Block(Cx*16+x,top_y-y-1,Cz*16+z)
                Chunk_row[z]= Chunk_collumn
            self.Chunk_blocks[x] = Chunk_row
        thr = threading.Thread(target=self.prepare_for_rendering)
        thr.start()
    async def render(self):
        time_start = time.time()
        self.batch = pyglet.graphics.Batch()
        for block in self.blocks_to_be_rendered:
            self.draw_block(block)
        print("Time to render 1 chunk " + str(time_start-time.time()))


def Create_chunk(cx,cz))
    thr.start()
    thr.join()
    asyncio.run(Chunks[cx][cz].render())
def _Create_chunk(cx,cz):
    time_start = time.time()
    if cx in Chunks.keys():
        Chunks[cx][cz] = Chunk(cx,cz)
    else:
        Chunks[cx] = {cz:Chunk(cx,cz)}
    print(time_start-time.time())


#THIS IS WHERE THE PYGLET/GL SEGMENT STARTS
#I AM TRYING TO SPERATE THIS SO WE CAN MUTLI TRHEAD
#WITHOUT ACCIDENTILY CALLING GL FUNCTIONS IN A SEPERATE THREAD OTHER THEN THE MAIN THREAD
#

Create_chunk(0,0)

class Player:
    def __init__(self,position=(8,8),rotation=(0,0)):
        self.position = position
        self.rotation = rotation
        self.strafe = [0,0]  # forward,up,left

    def mouse_motion(self,dy):
        x,y = self.rotation
        sensitivity = 0.15
        x += dx * sensitivity
        y += dy * sensitivity
        y = max(-90,min(90,y))
        self.rotation = x % 360,y

    def update(self,dt):
        motion_vector = self.get_motion_vector()
        speed = dt * 5
        self.position = [x + y * speed for x,y in zip(self.position,motion_vector)]

    def get_motion_vector(self):
        x,z = self.strafe
        if x or z:
            strafe = math.degrees(math.atan2(x,z))
            yaw = self.rotation[0]
            x_angle = math.radians(yaw + strafe)
            x = math.cos(x_angle)
            z = math.sin(x_angle)
        return x,z


def draw_camera(position,rotation):
    yaw,pitch = rotation
    gl.glRotatef(yaw,0)
    gl.glRotatef(-pitch,math.cos(math.radians(yaw)),math.sin(math.radians(yaw)))
    x,z = position
    gl.glTranslatef(-x,-y,-z)


def set_3d(width,height):
    gl.glEnable(gl.GL_DEPTH_TEST)
    gl.glMatrixMode(gl.GL_PROJECTION)
    gl.glLoadIdentity()
    gl.gluPerspective(65,width / height,0.1,60)
    gl.glMatrixMode(gl.GL_MODELVIEW)
    gl.glLoadIdentity()


class Window(pyglet.window.Window):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.player = Player()
        self.set_exclusive_mouse(True)
        pyglet.clock.schedule(self.update)

    def on_mouse_motion(self,dy):
        self.player.mouse_motion(dx,dy)

    def on_key_press(self,symbol,modifiers):
        if symbol == window.key.ESCAPE:
            self.close()
        speed = 1
        if symbol == window.key.W:
            self.player.strafe[0] = -speed
        elif symbol == window.key.S:
            self.player.strafe[0] = speed
        elif symbol == window.key.A:
            self.player.strafe[2] = -speed
        elif symbol == window.key.D:
            self.player.strafe[2] = speed
        elif symbol == window.key.SPACE:
            self.player.strafe[1] = speed
        elif symbol == window.key.LSHIFT:
            self.player.strafe[1] = -speed

    def on_key_release(self,modifiers):
        if symbol == window.key.W:
            self.player.strafe[0] = 0
        elif symbol == window.key.S:
            self.player.strafe[0] = 0
        elif symbol == window.key.A:
            self.player.strafe[2] = 0
        elif symbol == window.key.D:
            self.player.strafe[2] = 0
        elif symbol == window.key.SPACE:
            self.player.strafe[1] = 0
        elif symbol == window.key.LSHIFT:
            self.player.strafe[1] = 0
                
    def update(self,dt):
        self.player.update(dt)
        chunk_x_player = round(self.player.position[0]/16)
        chunk_z_player = round(self.player.position[2]/16)
        for x in range(-2,2):
            for z in range(-2,2):
                try:
                    if Chunks[chunk_x_player+x][chunk_z_player+z]:
                        pass
                except:
                    Create_chunk(chunk_x_player+x,chunk_z_player+z)

    def on_draw(self):
        self.clear()
        time_start = time.time()
        set_3d(*self.get_size())
        draw_camera(self.player.position,self.player.rotation)
        #for block in self.model.blocks_to_be_rendered:
        #    self.model.draw_block(block)
        chunk_x_player = round(self.player.position[0]/16)
        chunk_z_player = round(self.player.position[2]/16)
        for x in range(-2,2):
                try:
                    Chunks[chunk_x_player+x][chunk_z_player+z].batch.draw()
                except:
                    print("ERROR")
                    pass
        print(time_start-time.time())


if __name__ == "__main__":
    Window(width=800,height=480,resizable=True)
    gl.glClearColor(0.5,0.7,1)  # sky color
    pyglet.app.run()

解决方法

到目前为止,这还不是一个完整的答案,但是要发表评论太久了,它可能包含一些有用的信息。我建议您尝试避免使用线程,并避免使用异步。主要是因为将其正确设置可能很棘手,并且asynciopyglet都有自己的主事件循环。您可以 创建自己的事件循环,所以这并非不可能-但也许在这种情况下,它正在尝试解决可以用更少的代码解决的问题-而不是更多。

您还每次render迭代,或者至少我认为尽可能多的每次render调用都替换批次(我认为)。 / p>

class Chunk():
    def __init__(self,Cx,Cz):
        self.batch = pyglet.graphics.Batch()
    def render(self):
        self.batch = pyglet.graphics.Batch()

您还应该在self.blocks_to_be_rendered函数中创建__init__,并使其正常运行。除非您习惯于创建材料/对象加载器并创建加载屏幕,或者预先准备好它们并更快地加载它们,否则请跳过它,只将创建部分保留在__init__部分中。这样就避免了线程,并确保不必每次渲染都这样做:

    def render(self):
        for block in self.blocks_to_be_rendered:
            self.draw_block(block)

翻译为:

    def render(self):
        # Delete the entire old batch
        self.batch = pyglet.graphics.Batch()
    
        # Wait for thread lock in case there is one
        # because the resouces is being created out of main thread
        for block in self.blocks_to_be_rendered:
            position = (block.x,block.y,block.z)
            if block._type == "grass":
                block = Grass
            else:
                print("HOLD ON A SEC")
                block = Grass

            x,y,z = position
            dx,dy,dz = x + 1,y + 1,z + 1
            vertices = [
                (x,z,x,dz,z),# side
                (dx,dx,dz),# side
                (x,# top
                (x,# bottom
                (dx,# side
            ]

            faces = ("left","right","top","bottom","front","back")
            for vertex,face in zip(vertices,faces):
                # Recreating the batch objects again,one by one
                self.batch.add(
                    4,gl.GL_QUADS,block.textures[face],("v3f/static",vertex),("t2f/static",(0,1,1)),)
        print("Time to render 1 chunk " + str(time_start-time.time()))

(我扩展了代码,因此您将了解在渲染逻辑中进行的大量调用,循环和逻辑。在图形渲染中,每个时钟周期都很重要)

相反,整个渲染逻辑可以归结为:

    def render(self):
        self.batch.draw()

假设您改为在__init__函数中创建批次。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res