文章目录[x]
- 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 同上