OpenGL中的动态图块显示优化

如何解决OpenGL中的动态图块显示优化

| 我正在研究具有动态生成地形的基于图块的自上而下的2D游戏,并开始(重新)编写OpenGL中的图形引擎。该游戏使用LWJGL用Java编写,我希望它保持相对独立于平台的状态,并且可以在较旧的计算机上玩。 目前,我正在使用即时模式进行绘制,但是对于最简单的场景,这显然太慢了。 绘制的对象有两种基本类型:“图块”(即世界)和“雪碧”(几乎所有其他东西)(实体,项目,效果等)。 这些图块的大小为20 * 20像素,并以大块形式存储(40 * 40个图块)。像Minecraft一样,地形生成是完全完成的。 我现在使用的方法是遍历播放器附近的9个块,然后遍历内部的每个图块,为图块纹理绘制一个四边形,并根据材料选择附加的四边形。 结束时速度很慢,但是简单的视线检查可以将FPS提升5-10倍。 为了优化这一点,我研究了使用VBO和四方带,但是当地形变化时我遇到了一个问题。这并非在每一帧都发生,但也不是非常罕见的事件。 一种简单的方法是在每次更改时删除并重建块的VBO。不过,这似乎并不是最好的方法。我读到VBO可以是“动态的”,可以更改其内容。如何做到这一点,以及可以在其中有效地更改哪些数据?还有其他有效绘制世界的方法吗? 目前,另一种类型的精灵是使用四边形绘制的,该四边形具有从精灵表映射的纹理。因此,通过更改纹理坐标,我什至可以为它们设置动画。这是做ania杀的正确方法吗? 目前,即使是非常大量的精灵也不会降低游戏速度,而且通过了解VBO,我可以进一步提高它们的速度,但是我还没有看到任何可靠的教程有效的方法。有人知道吗? 谢谢您的帮助!     

解决方法

目前,我正在使用即时模式进行绘制,但是对于最简单的场景,这显然太慢了。 我不同意。除非您要绘制很多图块(每帧数以万计),否则即时模式对您来说就很好了。 无论如何,关键是您必须要做的就是获得良好的性能:纹理图集。您所有的图块都应存储在单个纹理中。渲染时,可以使用纹理坐标将不同的图块从该纹理中拉出。因此,如果这是您的渲染循环现在的样子:
for(tile in tileList) //Pseudocode. Not actual C++
{
    glBindTexture(GL_TEXTURE_2D,tile.texture);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f,0.0f);
        glVertex2fv(tile.lowerLeft);
        glTexCoord2f(0.0f,1.0f);
        glVertex2fv(tile.upperLeft);
        glTexCoord2f(1.0f,1.0f);
        glVertex2fv(tile.upperRight);
        glTexCoord2f(1.0f,0.0f);
        glVertex2fv(tile.lowerRight);
    glEnd();
}
您可以将其转换为:
glBindTexture(GL_TEXTURE_2D,allTilesTexture);
glBegin(GL_QUADS);
for(tile in tileList) //Still pseudocode.
{
    glTexCoord2f(tile.texCoord.lowerLeft);
    glVertex2fv(tile.lowerLeft);
    glTexCoord2f(tile.texCoord.upperLeft);
    glVertex2fv(tile.upperLeft);
    glTexCoord2f(tile.texCoord.upperRight);
    glVertex2fv(tile.upperRight);
    glTexCoord2f(tile.texCoord.lowerRight);
    glVertex2fv(tile.lowerRight);
}
glEnd();
如果您已经在使用纹理图集,但仍无法获得令人满意的性能,则可以继续缓冲对象等。但是,如果不先执行此操作,则缓冲对象将无法获得更好的性能。 如果您的所有图块都无法适合单个纹理,则您需要执行以下两项操作之一:使用多个纹理(在一个glBegin / glEnd对中为每个纹理渲染尽可能多的图块),或使用纹理数组。纹理数组仅在OpenGL 3.0级别的硬件中可用。这意味着任何Radeon HDxxxx或GeForce 8xxxx或更高版本。 您提到您有时会在图块的顶部渲染“功能”。这些功能可能会使用混合和不同于常规图块的glTexEnv模式。在这种情况下,您需要找到将相似功能组合到单个glBegin / glEnd对中的方法。 正如您可能从中收集到的那样,性能的关键是使调用glBindTexture和glBegin / glEnd的次数最小化。在每个glBegin / glEnd中做尽可能多的工作。 如果您希望继续使用基于缓冲区的方法(并且仅当纹理图集方法不能使您的性能达到标准时就应该打扰),这非常简单。将所有图块“块”放入单个缓冲区对象中。不要为每个缓冲区创建缓冲区;没有真正的理由这样做,而且40x40瓦片的顶点数据值只有12,800字节。您可以在单个1MB缓冲区中放入81个这样的块。这样,您只需为地形调用glBindBuffer。同样,这可以节省您的性能。 我将需要更多地了解您有时用来建议优化它们的“功能”。但是对于动态缓冲区,我不会担心。只需使用glBufferSubData更新有问题的缓冲区的一部分即可。如果事实证明这很慢,则可以使用多种方法来加快速度。但是除非您知道这是必要的,否则您不应该打扰,因为它们很复杂。 Sprite可能从缓冲区对象方法中受益最少。在即时模式下,它实际上没有任何收获。即使您要渲染数百个,每个对象也将具有自己的转换矩阵。这意味着每个人都必须是一个单独的抽奖电话。因此也可能是glBegin / glEnd。     

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

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地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-