游戏引擎从零开始(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...

总结

相关推荐
凌云行者5 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者5 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
凌云行者3 天前
OpenGL入门004——使用EBO绘制矩形
c++·cmake·opengl
Thomas_YXQ3 天前
Unity3D中管理Shader效果详解
开发语言·游戏·unity·unity3d·游戏开发
闲暇部落4 天前
Android OpenGL ES详解——模板Stencil
android·kotlin·opengl·模板测试·stencil·模板缓冲·物体轮廓
凌云行者6 天前
OpenGL入门003——使用Factory设计模式简化渲染流程
c++·cmake·opengl
凌云行者6 天前
OpenGL入门002——顶点着色器和片段着色器
c++·cmake·opengl
Ljw...7 天前
C++游戏开发
c++·c·游戏开发
闲暇部落7 天前
Android OpenGL ES详解——裁剪Scissor
android·kotlin·opengl·窗口·裁剪·scissor·视口
彭祥.12 天前
点云标注工具开发记录(四)之点云根据类别展示与加速渲染
pyqt·opengl