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

总结

相关推荐
whoispo2 天前
Imgui处理glfw的鼠标键盘的方法
opengl·imgui·gflw·鼠标键盘事件
XZen5 天前
Shadertoy转传统技术实现程序化星球纹理
图形学
Thomas游戏开发5 天前
Unity3D状态管理器实现指南
前端框架·unity3d·游戏开发
阿杰在学习7 天前
基于OpenGL ES实现的Android人体热力图可视化库
android·前端·opengl
彼方卷不动了7 天前
【技术学习】在 Android 上用 Kotlin 实现支持多图层的 OpenGL 渲染管线
android·kotlin·opengl
米芝鱼7 天前
LearnOpenGL(九)自定义转换类
开发语言·c++·算法·游戏·图形渲染·shader·opengl
byxdaz7 天前
OpenGL绘制文本
opengl
非衣居士8 天前
Lua程序设计笔记
lua·游戏开发
龙湾8 天前
OpenGLshader开发实战学习笔记:第一章 初识游戏图形
opengl
stevenzqzq9 天前
openGl片段着色器的含义
opengl·着色器