游戏引擎从零开始(33)-2D渲染器支持旋转

前言

这篇做一些小优化,完善Renderer2D的API。

  1. 调整Run()方法的访问属性
  2. 纹理通过参数来控制缩放
  3. 支持创建旋转的矩形

代码优化

Run()方法设成private属性

当前的代码Run()函数在public下,可以被随意访问,这是不安全的。

但放到private下,main()函数就不能访问了,怎么办?

对main函数增加友元属性。

Sandbox/Hazel/src/Hazel/Core/Application.h

c++ 复制代码
...
// 1. 声明一个全局的main函数
// 注意!这里必须声明
int main(int argc, char** argv);

namespace Hazel{
class Application {
private:
    // 2. 优化,将Run()函数放到private下,不对外公开暴露
    void Run();

private:
    static Application* s_Instance;
    // 3. main通过friend的形式调用Run();
    friend int ::main(int argc, char** argv);
    ...
}

Renderer2D接口拓展&支持纹理缩放

用一个uniform代替之前写死的值,便于在代码里控制:

Sandbox/assets/shaders/Texture.glsl

c++ 复制代码
...
#type fragment
#version 330 core
layout(location = 0) out vec4 color;
in vec2 v_TexCoord;

uniform vec4 u_Color;
uniform float u_TilingFactor;
uniform sampler2D u_Texture;

void main()
{
	color = texture(u_Texture, v_TexCoord * u_TilingFactor) * u_Color;
}

shader里增加更新float的方法

Sandbox/Hazel/src/Hazel/Renderer/Shader.h

c++ 复制代码
virtual void SetFloat(const std::string &name, const float value) = 0;

Sandbox/Hazel/src/Hazel/Platform/OpenGL/OpenGLShader.h

c++ 复制代码
void SetFloat(const std::string &name, const float value) override;

Sandbox/Hazel/src/Hazel/Platform/OpenGL/OpenGLShader.cpp

c++ 复制代码
void OpenGLShader::SetFloat(const std::string &name, const float value) {
    HZ_PROFILE_FUNCTION();
    UploadUniformFloat(name, value);
}

Renderer2D也一起更新接口,增加纹理缩放因子,支持旋转,整体有两组API,一组不带旋转,一组代旋转参数,其实也可以合并到一起:

Sandbox/Hazel/src/Hazel/Renderer/Renderer2D.h

c++ 复制代码
namespace Hazel {
    class Renderer2D {
    public:
        static void Init();
        static void Shutdown();
        static void BeginScene(const OrthographicCamera& camera);
        static void EndScene();
        // Primitives
        static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color);
        static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color);
        static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref<Texture2D>& texture,
                             float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
        static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref<Texture2D>& texture,
                             float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));

        static void DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color);
        static void DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color);
        static void DrawRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const Ref<Texture2D>& texture,float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
        static void DrawRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const Ref<Texture2D>& texture,float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
    };

}

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

c++ 复制代码
void Renderer2D::DrawQuad(const glm::vec2 &position, const glm::vec2 &size, const glm::vec4 &color) {
    DrawQuad({position.x, position.y, 0.0f}, size, color);
}
void Renderer2D::DrawQuad(const glm::vec3 &position, const glm::vec2 &size, const glm::vec4 &color) {
    HZ_PROFILE_FUNCTION();

    s_Data->TextureShader->SetFloat4("u_Color", color);
    s_Data->TextureShader->SetFloat("u_TilingFactor", 1.0f);
    s_Data->WhiteTexture->Bind();
    glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) * glm::scale(glm::mat4(1.0), {size.x, size.y, 1.0f});
    s_Data->TextureShader->SetMat4("u_Transform", transform);
    s_Data->QuadVertexArray->Bind();
    RenderCommand::DrawIndexed(s_Data->QuadVertexArray);
}

void Renderer2D::DrawQuad(const glm::vec2 &position, const glm::vec2 &size, const Ref<Texture2D> &texture, float tilingFactor, const glm::vec4& tintColor) {
    DrawQuad({position.x, position.y, 0.f}, size, texture, tilingFactor, tintColor);
}

void Renderer2D::DrawQuad(const glm::vec3 &position, const glm::vec2 &size, const Ref<Texture2D> &texture, float tilingFactor, const glm::vec4& tintColor) {
    HZ_PROFILE_FUNCTION();

    s_Data->TextureShader->Bind();
    s_Data->TextureShader->SetFloat4("u_Color", glm::vec4(1.0f));
    s_Data->TextureShader->SetFloat("u_TilingFactor", tilingFactor);
    texture->Bind();

    glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) * glm::scale(glm::mat4(1.0), {size.x, size.y, 1.0f});
    s_Data->TextureShader->SetMat4("u_Transform", transform);

    s_Data->QuadVertexArray->Bind();
    RenderCommand::DrawIndexed(s_Data->QuadVertexArray);
}

void Renderer2D::DrawRotatedQuad(const glm::vec2 &position, const glm::vec2 &size, float rotation,
                                 const glm::vec4 &color) {
    DrawRotatedQuad({position.x, position.y, 0.0f}, size, rotation, color);
}

void Renderer2D::DrawRotatedQuad(const glm::vec3 &position, const glm::vec2 &size, float rotation,
                                 const glm::vec4 &color) {
    HZ_PROFILE_FUNCTION();

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

    glm::mat4 transform = glm::translate(glm::mat4(1.0f), position)
            * glm::rotate(glm::mat4(1.0), rotation, {0.0f, 0.0f, 1.0f})
            * glm::scale(glm::mat4(1.0f), {size.x, size.y, 1.0f});
    s_Data->TextureShader->SetMat4("u_Transform", transform);
    RenderCommand::DrawIndexed(s_Data->QuadVertexArray);
}

void Renderer2D::DrawRotatedQuad(const glm::vec2 &position, const glm::vec2 &size, float rotation,
                                 const Ref<Texture2D> &texture, float tilingFactor, const glm::vec4 &tintColor) {
    DrawRotatedQuad({position.x, position.y, 0.0f}, size, rotation, texture, tilingFactor, tintColor);
}

void Renderer2D::DrawRotatedQuad(const glm::vec3 &position, const glm::vec2 &size, float rotation,
                                 const Ref<Texture2D> &texture, float tilingFactor, const glm::vec4 &tintColor) {
    HZ_PROFILE_FUNCTION();

    s_Data->TextureShader->SetFloat4("u_Color", tintColor);
    s_Data->TextureShader->SetFloat("u_TilingFactor", tilingFactor);
    texture->Bind();

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

    s_Data->TextureShader->SetMat4("u_Transform", transform);
    s_Data->QuadVertexArray->Bind();
}

更新Sandbox2D

Sandbox/src/Sandbox2D.cpp

c++ 复制代码
{
    HZ_PROFILE_SCOPE("Renderer Draw");
    Hazel::Renderer2D::BeginScene(m_CameraController.GetCamera());
    Hazel::Renderer2D::DrawRotatedQuad({-1.0f, 0.0f}, {0.8f, 0.8f}, glm::radians(-45.0f), {0.8f, 0.2f, 0.3f, 1.0f});
    Hazel::Renderer2D::DrawQuad({0.5f, -0.5f}, {0.5f, 0.5f}, {0.2f, 0.3f, 0.8f, 1.0f});
    Hazel::Renderer2D::DrawQuad({0.0f, 0.0f, -0.1f}, {5.f, 5.f}, m_CheckerboardTexture, 10.0f);
    Hazel::Renderer2D::EndScene();
}

如果运行正常,能看到下面

代码 & 总结

完整代码

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

总结

相关推荐
小-黯16 小时前
VSCode + XMake搭建OpenGL开发环境
vscode·opengl·xmake
陈尕六2 天前
从零开始的 Godot 之旅 — EP8:角色移动和动画切换
godot·游戏开发
Setsuna_F_Seiei2 天前
CocosCreator 游戏开发 - 利用 AssetsBundle 技术对小游戏包体积进行优化
前端·cocos creator·游戏开发
gopyer3 天前
Go语言2D游戏开发入门004:零基础打造射击游戏《太空大战》3
golang·go·游戏开发
芝麻粒儿4 天前
天龙八部TLBB系列 - 客户端技术整体性分析
游戏开发·天龙八部·网单·引擎脚本
吃饺子不吃馅4 天前
如何设计一个 Canvas 事件系统?
前端·canvas·图形学
cjzcjl6 天前
在安卓中基于OpenGL ES实现随风飘荡3D动画效果
3d·opengl·三角函数·波浪·
UWA7 天前
有什么指标可以判断手机是否降频
人工智能·智能手机·性能优化·memory·游戏开发
onthewaying8 天前
Android SurfaceTexture 深度解析
android·opengl