[OpenGL]变换Transform

文章目录[x]
  1. 1:新建主测试类

新建主测试类


#pragma once
#include "../TestBed.h"

class HelloTransform: public TestBed
{

public:
    HelloTransform()
    {
    }

private:
    virtual const std::string GetShaderPath(const std::string shaderPath) const override
    {
        return "SandBox/05_HelloTransform/" + shaderPath;
    }
};

 

OrthoMVPMatrix

经过了上一张绘制了纹理后,发现虽然显示了纹理,但是比例不对,原图是一张正方形的图片,而在屏幕上却被拉成了长方形。
这是因为我使用的是4:3的分辨率1024x768,更别提现在占主流的16:9的屏幕了。所以第一件事就是要让纹理显示正常。

class OrthoMVPMatrix : public SubTestBed
{
protected:
    glm::mat4 proj;
public:
    OrthoMVPMatrix(const std::string& shaderPath) : SubTestBed(shaderPath) { }

    virtual void Setup() override
    {
        float vertices[] = {
            // --- 位置 ---   -- 纹理坐标 ---
            -0.5f, -0.5f, 0,  0.0f, 0.0f,
            +0.5f, -0.5f, 0,  1.0f, 0.0f,
            +0.5f, +0.5f, 0,  1.0f, 1.0f,
            -0.5f, +0.5f, 0,  0.0f, 1.0f
        };

        unsigned int indices[] = {
            0, 1, 2,
            2, 3, 0
        };

        m_VA[0] = new VertexArray();
        m_VB[0] = new VertexBuffer(vertices, sizeof(vertices));
        VertexBufferLayout layout;
        layout.Push<float>(3);
        layout.Push<float>(2);
        m_VA[0]->AddBuffer(*m_VB[0], layout);
        m_IB[0] = new IndexBuffer(indices, 6);
        m_Texture[0] = new Texture("Resources/Textures/container.jpg");
        m_Texture[1] = new Texture("Resources/Textures/awesomeface.png");

        proj = glm::ortho(-1.6f, 1.6f, -1.2f, 1.2f, -1.0f, 1.0f); // 1.6 : 1.2 = 4 : 3,所以这里填写这两个数字显示的比例就是正常的

        m_VB[0]->UnBind();
        m_VA[0]->UnBind();
        m_IB[0]->UnBind();
        m_Texture[0]->UnBind();
        m_Texture[1]->UnBind();
    }


    virtual void Render() override
    {
        m_Texture[0]->Bind(190);
        m_Texture[1]->Bind(191);
        this->m_Renderer.Draw(*m_VA[0], *m_IB[0], *m_Shader[0]);
        m_Shader[0]->SetUniform1i("u_Texture190", 190);
        m_Shader[0]->SetUniform1i("u_Texture191", 191);
        m_Shader[0]->SetUniformMat4f("u_MVP", proj);
    }
};
#Shader Vertex
#version 330 core

layout(location = 0) in vec4 a_position;
layout(location = 1) in vec2 a_TexCoord;

out vec2 v_TexCoord;

uniform mat4 u_MVP;

void main()
{
    gl_Position = u_MVP * a_position;
    v_TexCoord = a_TexCoord;
}

#Shader Fragment
#version 330 core

out vec4 fragColor;

in vec2 v_TexCoord;

uniform sampler2D u_Texture190;
uniform sampler2D u_Texture191;

void main()
{
    vec4 texColor190 = texture(u_Texture190, v_TexCoord);
    vec4 texColor191 = texture(u_Texture191, v_TexCoord);
    fragColor = mix(texColor190, texColor191, 0.2);
};

可以看到这里显示比例对啦。

 

缩放+旋转
class RotateScale : public OrthoMVPMatrix
{
    glm::mat4 transform = glm::identity<glm::mat4>();
public:
    RotateScale(const std::string& shaderPath) : OrthoMVPMatrix(shaderPath) { }

    virtual void Setup() override
    {
        OrthoMVPMatrix::Setup();

        transform = glm::rotate(transform, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0)); // 沿着vector3.forward旋转90度
        transform = glm::scale(transform, glm::vec3(0.5, 0.5, 0.5)); // 缩放0.5倍

        m_Shader[0]->Bind();
        m_Shader[0]->SetUniformMat4f("u_Transform", transform);
    }
};
#Shader Vertex
#version 330 core

layout(location = 0) in vec4 a_position;
layout(location = 1) in vec2 a_TexCoord;

out vec2 v_TexCoord;

uniform mat4 u_Transform;
uniform mat4 u_MVP;

void main()
{
    gl_Position = u_MVP * u_Transform * a_position;
    v_TexCoord = a_TexCoord;
}

// Fragment Shader 同上

 

练习题1: 使用应用在箱子上的最后一个变换,尝试将其改变为先旋转,后位移。看看发生了什么,试着想想为什么会发生这样的事情
class GameLoopRotate : public OrthoMVPMatrix
{
public:
    GameLoopRotate(const std::string& shaderPath) : OrthoMVPMatrix(shaderPath) { }

    virtual void Render() override
    {
        OrthoMVPMatrix::Render();

        glm::mat4 transform = glm::identity<glm::mat4>();
        transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f)); // 再平移
        transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0, 0.0, 1.0)); // 先旋转

        m_Shader[0]->Bind();
        m_Shader[0]->SetUniformMat4f("u_Transform", transform);
    }
};

// Shader 同上

如果是先平移再旋转,就会出现箱子绕原点旋转的现象。因为我们在glm::rotate的第二个参数填的glm::vec3(0.0, 0.0, 1.0) 也就是绕点(0, 0, 1)来旋转。

 

练习题2: 尝试再次调用glDrawElements画出第二个箱子,只使用变换将其摆放在不同的位置。让这个箱子被摆放在窗口的左上角,并且会不断的缩放
class TwoBox : public OrthoMVPMatrix
{
public:
    TwoBox(const std::string& shaderPath) : OrthoMVPMatrix(shaderPath)
    {
        m_Shader[1] = new Shader(shaderPath);
    }

    virtual void Setup() override
    {
        OrthoMVPMatrix::Setup();
    }

    virtual void Render() override
    {
        // first box
        OrthoMVPMatrix::Render();
        glm::mat4 transform = glm::identity<glm::mat4>();
        transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));
        float timeValue = (float)glfwGetTime();
        transform = glm::rotate(transform, timeValue, glm::vec3(0.0, 0.0, 1.0));
        m_Shader[0]->SetUniformMat4f("u_Transform", transform);

        // second box
        this->m_Renderer.Draw(*m_VA[0], *m_IB[0], *m_Shader[1]);
        float scale = Lerp(1.0f, 0.2f, glm::sin(timeValue) / 2 + 0.5f);
        transform = glm::identity<glm::mat4>();
        transform = glm::translate(transform, glm::vec3(-0.7f, 0.5f, 0.0f));
        transform = glm::scale(transform, glm::vec3(scale, scale, 1.0)); 
        m_Shader[1]->SetUniform1i("u_Texture190", 190); 
        m_Shader[1]->SetUniform1i("u_Texture191", 191);
        m_Shader[1]->SetUniformMat4f("u_Transform", transform);
        m_Shader[1]->SetUniformMat4f("u_MVP", proj);
    }

    inline float Lerp(float a, float b, float t)
    {
        return a + t * (b - a);
    }
};

// Shader 同上

 

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像