游戏引擎从零开始(37)-Batch Rendering(3)

批渲染中的旋转处理

这章我们继续完善批渲染,支持旋转处理。

回顾下通用的顶点着色器的代码:

c++ 复制代码
void main()
{
	v_Color = a_Color;
	v_TexCoord = a_TexCoord;
	v_TexIndex = a_TexIndex;
	gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
}

一个顶点的坐标计算依赖"投影矩阵(u_ViewProjection)"、"移动变换(u_Transform)"、"原始坐标(a_Position)",其中u_Transform是由程序中传进来的通用变量,一个完整的网格有一个u_Transform,多个网格就对应多个u_Transform,

如果要实现多个网格批渲染,就需要类似color一样,将u_Transform作为顶点属性传进来,以实现每个顶点的u_Transform都不一样。

另一个方法是,在shader外面将transform提前乘到position上,即传到shader中的顶点已经计算过旋转、缩放、位移了。shader修改为:

c++ 复制代码
void main()
{
	v_Color = a_Color;
	v_TexCoord = a_TexCoord;
	v_TexIndex = a_TexIndex;
	v_TilingFactor = a_TilingFactor;
	// gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
	gl_Position = u_ViewProjection * vec4(a_Position, 1.0);
}

最终的实现效果如下,demo中增加旋转的矩形:

代码实现

整体思路是,在draw函数中,将旋转乘到position上

Sandbox/Hazel/src/Hazel/Renderer/Renderer2D.cpp

c++ 复制代码
// 1. 增加单位矩阵的顶点

struct Renderer2DData{
....
  std::array<Ref<Texture2D>, MaxTexturesSlots> TextureSlots;
  uint32_t TextureSlotIndex = 1; // 0 = white texture

  glm::vec4 QuadVertexPositions[4]; // 矩形的四个顶点
}

// 2. 初始化单位矩阵的顶点
void Renderer2D::Init() {
....
  // Set all texture slots to 0
  // 安全起见,将数组中的每个值都初始化成一个默认的纹理,即单像素纹理
  for (int i = 0; i < s_Data->MaxTexturesSlots; i++) {
      s_Data->TextureSlots[i] = s_Data->WhiteTexture;
  }

  // 初始化单位矩阵的顶点坐标
  s_Data->QuadVertexPositions[0] = {-0.5f, -0.5f, 0.0f, 1.0f};
  s_Data->QuadVertexPositions[1] = {0.5f, -0.5f, 0.0f, 1.0f};
  s_Data->QuadVertexPositions[2] = {0.5f, 0.5f, 0.0f, 1.0f};
  s_Data->QuadVertexPositions[3] = {-0.5f, 0.5f, 0.0f, 1.0f};
}

// 3. DrawQuad函数中增加旋转处理

void Renderer2D::DrawQuad(const glm::vec3 &position, const glm::vec2 &size, float rotation,
                                 const glm::vec4 &color) {
    HZ_PROFILE_FUNCTION();
    const float texIndex = 0.0f; // white Texture
    const float tilingFactor = 1.0f;

    glm::mat4 transform = glm::translate(glm::mat4(1.0f), position)
            * glm::rotate(glm::mat4(1.0f), glm::radians(rotation), {0.0f, 0.0f, 1.0f})
            * glm::scale(glm::mat4(1.0f), {size.x, size.y, 1.0f});


    s_Data->TextureShader->SetFloat4("u_Color", color);
    s_Data->TextureShader->SetFloat("u_TilingFactor", 1.0f);
    s_Data->WhiteTexture->Bind();


    s_Data->QuadVertexBufferPtr->Position = transform * s_Data->QuadVertexPositions[0];
    ...
    
    s_Data->QuadVertexBufferPtr->Position = transform * s_Data->QuadVertexPositions[1];
    
    ...
    s_Data->QuadVertexBufferPtr->Position = transform * s_Data->QuadVertexPositions[2];
    
    ...
    s_Data->QuadVertexBufferPtr->Position = transform * s_Data->QuadVertexPositions[3];

}

...

一共有4个重载的Renderer2D::DrawQuad函数,都需要改进,将transform提前计算好,乘到position上。此处仅说明实现思路,完整代码参考文末github地址

demo中增加旋转的矩阵,此处我们根据update的时间,动态的增加旋转角度

Sandbox/src/Sandbox2D.cpp

c++ 复制代码
{
    HZ_PROFILE_SCOPE("Renderer Draw");

    static float rotation = 0.f;
    rotation += ts * 50.0f;

    Hazel::Renderer2D::BeginScene(m_CameraController.GetCamera());

    // 旋转45°
    Hazel::Renderer2D::DrawQuad({1.0f, 0.0f}, {0.8f, 0.8f}, -45, {0.8f, 0.2f, 0.3f, 1.0f});

    // 静态矩形
    Hazel::Renderer2D::DrawQuad({-1.0f, 0.0f}, {0.8f, 0.8f}, {0.8f, 0.2f, 0.3f, 1.0f});
    Hazel::Renderer2D::DrawQuad({0.5f, -0.5f}, {0.5f, 0.75f}, {0.2f, 0.3f, 0.8f, 1.0f});
    Hazel::Renderer2D::DrawQuad({0.0f, 0.0f, -0.1f}, {10.0f, 10.0f}, m_CheckerboardTexture, 10.0f);

    // 持续旋转45°
    Hazel::Renderer2D::DrawQuad({1.f, 0.5f, 0.1f}, {0.8f, 0.8f}, rotation, m_CoverTexture, 1.0f);

    Hazel::Renderer2D::EndScene();

}

完整代码 & 总结

完整代码

github.com/summer-go/H...

总结

批渲染的核心,就是将所有要绘制的数据尽量统一起来,去异求同,将不同的地方提前处理好或者在shader中按参数动态计算,以达到使用同一个shader,不切换状态,一次绘制上屏。

最近工作有点累,加上流感盛行,娃老生病,有点干不动了。加油💪🏻

相关推荐
Jooolin1 天前
什么语言最适合用来游戏开发?
游戏·ai编程·游戏开发
byxdaz3 天前
在Qt中使用OpenGL显示大量点(点云)
opengl
二进制人工智能3 天前
【OpenGL学习】(四)统一着色和插值着色
c++·opengl
技术小甜甜4 天前
[Blender] 高质量材质推荐第四弹:25-30号精选纹理资源详解
blender·游戏开发·材质·建模·资源
Thomas游戏开发9 天前
Unity3D 自动化游戏框架设计
前端框架·unity3d·游戏开发
oyishyi9 天前
从零开始独立游戏开发学习笔记(七十八)--绘画/像素画学习笔记(十五)--V大预科3.0(五)-第三,四周理论
游戏·游戏开发
LeeAt10 天前
《谁杀死了比尔?》:使用Trae完成的一个推理游戏项目!!
前端·游戏开发·trae
龙智DevSecOps解决方案10 天前
游戏开发中的CI/CD优化案例:知名游戏公司Gearbox使用TeamCity简化CI/CD流程
ci/cd·游戏开发·jetbrains·teamcity
一名用户10 天前
unity实现自定义粒子系统
c#·unity3d·游戏开发
技术小甜甜12 天前
【Blender Texture】【游戏开发】高质感 Blender 4K 材质资源推荐合集 —— 提升场景真实感与美术表现力
blender·游戏开发·材质·texture