【PyOpenGL】5.自由移动的相机
0.简介
距离上次更新已经两个多月了,这段时间对整个框架做了一些调整。主要有一下几个方面:
统一的资源管理
: 增加了load和unload接口,加载图片时自动创建Texture(但不创建GPU资源),不再使用加载图片和手动创建Texture的两步方式。渲染重构
: 将Mesh生成的OpenGL VAO/VBO/EBO保存在Mesh组件中,将Texture ID依旧保存在Texture类中,在需要时手动load/unload GPU资源,不再每次Render重新生成,大幅提升了渲染速度。场景管理
: 增加Scene类,用来管理场景中的Actor。相机组件
: 增加相机组件以实现场景中的主相机MainCamera。相机的Input组件
: 暂时是给相机Actor使用的,用来处理用户输入,从而控制相机移动。- WASDQE控制相机在场景中移动
- 按住右键旋转相机视角
一些临时更改
: 尝试使用四元数实现相机的旋转控制,还挺好用。
1.创建Actor
1.1.创建Cube Actor
python
def create_cube(self, i, pos):
# 1.创建渲染Actor
new_actor = Actor()
new_actor.name = new_actor.name + str(i)
transform_comp = TransformComponent()
transform_comp.position = pos
transform_comp.angle = 20.0 * i
transform_comp.rotation_axis = glm.vec3(1.0, 0.3, 0.5)
transform_comp.update_matrix()
new_actor.add_component(transform_comp)
# 2.创建Mesh组件
mesh_comp = MeshComponent()
mesh_comp.use_default_cube()
new_actor.add_component(mesh_comp)
# 3.创建Material组件
mat_comp = MaterialComponent()
shader_name = 'camera_shader'
mat_shader = self._asset_manager.get_shader(shader_name)
mat_comp.set_shader(mat_shader)
new_tex = self._asset_manager.get_texture('keqing')
mat_comp.bind_texture('icon_tex', new_tex)
new_actor.add_component(mat_comp)
self._scene.add_actor(new_actor)
1.2.创建Camera Actor
python
# 相机Actor
self._cam_actor = Actor()
self._cam_actor.name = 'MainCamera'
self._cam_actor.set_visible(False)
# 相机的Transform
transform_comp = TransformComponent()
transform_comp.position = glm.vec3(0.0, 0.0, 10.0)
transform_comp.update_matrix()
self._cam_actor.add_component(transform_comp)
# 相机组件
camera_comp = CameraComponent()
camera_comp.set_screen_size(800, 600)
self._cam_actor.add_component(camera_comp)
# 输入组件
input_comp = CameraInputComponent()
self._cam_actor.add_component(input_comp)
self._scene.add_actor(self._cam_actor)
self._scene.set_camera(self._cam_actor)
2.Scene场景管理
python
class Scene(object):
def __init__(self) -> None:
self._name = 'Default'
self._actors = []
self._main_camera = None
self._renderer = RenderSystem()
def set_name(self, name):
self._name = name
def add_actor(self, actor):
self._actors.append(actor)
def remove_actor(self, actor):
self._actors.remove(actor)
def set_camera(self, camera):
self._main_camera = camera
self._renderer.set_camera(camera)
def get_camera(self):
return self._main_camera
def load(self):
for actor in self._actors:
actor.init()
if actor.visible():
self._renderer.load_gpu_resources(self, actor)
def unload(self):
for actor in self._actors:
actor.shutdown()
if actor.visible():
self._renderer.unload_gpu_resources(self, actor)
def process_input(self, event):
for actor in self._actors:
actor.process_input(event)
def update(self, frame_time):
for actor in self._actors:
actor.update(frame_time)
def render(self):
for actor in self._actors:
if actor.visible():
self._renderer.render(self, actor)
3.渲染重构
3.1.手动控制GPU资源load/unload
class RenderSystem
加载与卸载GPU资源pythondef load_gpu_resources(self, scene, actor: Actor): if not actor.visible(): return mesh_comp: MeshComponent = actor.get_component('MeshComponent') mesh_comp.load_gpu_resource() material: MaterialComponent = actor.get_component('MaterialComponent') material.load_gpu_resources() def unload_gpu_resources(self, scene, actor: Actor): mesh_comp: MeshComponent = actor.get_component('MeshComponent') mesh_comp.unload_gpu_resource() material: MaterialComponent = actor.get_component('MaterialComponent') material.unload_gpu_resources()
mesh_comp.load_gpu_resource()
和 material.load_gpu_resources()
就是上文提到的渲染重构部分。
3.2.渲染方法
目前渲染功能在RenderSystem类的 def render(self, scene, actor: Actor)
方法中。但是,这部分很明显需要重构。(TODO +1)
python
def render(self, scene, actor: Actor):
GL.glEnable(GL.GL_DEPTH_TEST)
GL.glEnable(GL.GL_BLEND)
GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
# ......
GL.glBindVertexArray(vao)
GL.glUseProgram(mat_shader.get_program())
GL.glUniformMatrix4fv(location, 1, GL.GL_FALSE, glm.value_ptr(param_value))
# ......
GL.glActiveTexture(MeshRendererComponent.INDEX_TO_GL_TEXTURE_LOCATION[gl_texture_index])
GL.glBindTexture(GL.GL_TEXTURE_2D, mat_tex.get_texture_id())
# ......
GL.glDrawArrays(GL.GL_TRIANGLES, 0, vertex_num)
# ......
GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0)
GL.glBindVertexArray(0)
GL.glUseProgram(0)
4.结果展示
5.总结
到这里,基本完成了OpenGL的基础使用,接下来会有两个方向可以选择:
OpenGL进阶
: 深度测试、模板测试、GPU实例化等。真正的图形学入门
: 光照、阴影、PBR、后处理等。
原本,以上这两部分都会按部就班进行,但是最近计划被打乱,又刚好OpenGL基础系列结束,所以接下来可能会很久之后才会继续了。伤心一秒钟:(