Browse Source

feat: 添加帧缓冲测试(有Bug版本)

NiceTry12138 10 months ago
parent
commit
04878eaff6

+ 4 - 0
图形学/OpenGL学习/src/OpenGLDemo/OpenGLDemo/OpenGLDemo.vcxproj

@@ -136,6 +136,7 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="src\testModule\TestFrameBuffer.cpp" />
     <ClCompile Include="src\Util\BaseLight.cpp" />
     <ClCompile Include="src\testModule\TestModelV1.cpp" />
     <ClCompile Include="src\Util\Model.cpp" />
@@ -166,6 +167,7 @@
     <ClCompile Include="src\Util\Texture.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="src\testModule\TestFrameBuffer.h" />
     <ClInclude Include="src\Util\BaseLight.h" />
     <ClInclude Include="src\testModule\TestModelV1.h" />
     <ClInclude Include="src\Util\Model.h" />
@@ -479,6 +481,8 @@
     <ClInclude Include="src\Util\UtilTemplate.h" />
   </ItemGroup>
   <ItemGroup>
+    <None Include="res\shader\FrameBuffer\fb.frag" />
+    <None Include="res\shader\FrameBuffer\fb.vert" />
     <None Include="res\shader\Light\Cube.frag" />
     <None Include="res\shader\Light\Cube.vert" />
     <None Include="res\shader\Light\Fragment.frag" />

+ 10 - 2
图形学/OpenGL学习/src/OpenGLDemo/OpenGLDemo/OpenGLDemo.vcxproj.filters

@@ -99,6 +99,9 @@
     <ClCompile Include="src\Util\BaseLight.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
+    <ClCompile Include="src\testModule\TestFrameBuffer.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\third\imgui\imstb_truetype.h">
@@ -1034,10 +1037,11 @@
     <ClInclude Include="src\Util\BaseLight.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="src\testModule\TestFrameBuffer.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <None Include="res\shader\TextPosition\Vertex.vert" />
-    <None Include="res\shader\TextPosition\Fragment.frag" />
     <None Include="src\third\glm\detail\func_common.inl">
       <Filter>头文件</Filter>
     </None>
@@ -1454,6 +1458,10 @@
     <None Include="res\shader\Light\Cube.vert" />
     <None Include="res\shader\model\model.frag" />
     <None Include="res\shader\model\model.vert" />
+    <None Include="res\shader\FrameBuffer\fb.frag" />
+    <None Include="res\shader\FrameBuffer\fb.vert" />
+    <None Include="res\shader\TextPosition\Fragment.frag" />
+    <None Include="res\shader\TextPosition\Vertex.vert" />
   </ItemGroup>
   <ItemGroup>
     <Image Include="res\textures\test.jpg">

+ 3 - 3
图形学/OpenGL学习/src/OpenGLDemo/OpenGLDemo/imgui.ini

@@ -10,7 +10,7 @@ Collapsed=0
 
 [Window][Common Test Title]
 Pos=6,6
-Size=141,196
+Size=144,205
 Collapsed=0
 
 [Window][ClearColor]
@@ -29,7 +29,7 @@ Size=418,267
 Collapsed=0
 
 [Window][Model]
-Pos=399,35
-Size=392,127
+Pos=459,52
+Size=396,162
 Collapsed=0
 

+ 11 - 0
图形学/OpenGL学习/src/OpenGLDemo/OpenGLDemo/res/shader/FrameBuffer/fb.frag

@@ -0,0 +1,11 @@
+#version 330 core
+
+layout(location = 0) out vec4 o_color;
+
+in vec2 v_TexCoord;
+
+uniform sampler2D screenTexture;
+
+void main() {
+    o_color = vec4(v_TexCoord, 0.0f, 1.0f); 
+}

+ 12 - 0
图形学/OpenGL学习/src/OpenGLDemo/OpenGLDemo/res/shader/FrameBuffer/fb.vert

@@ -0,0 +1,12 @@
+#version 330 core
+
+layout(location = 0) in vec3 inPosition;
+layout(location = 1) in vec3 inNormal;
+layout(location = 2) in vec2 inTexCoord;
+
+out vec2 v_TexCoord;
+
+void main() {
+	v_TexCoord = inTexCoord;
+	gl_Position = vec4(inPosition, 1.0f);
+}

+ 231 - 0
图形学/OpenGL学习/src/OpenGLDemo/OpenGLDemo/src/testModule/TestFrameBuffer.cpp

@@ -0,0 +1,231 @@
+#include "TestFrameBuffer.h"
+#include "../Util/RenderSettings.h"
+
+TestFrameBuffer TestFrameBuffer::_self;
+
+void TestFrameBuffer::OnEnter(GLFWwindow* window)
+{
+	// 启动深度测试
+	glEnable(GL_DEPTH_TEST);
+
+	// 初始化 shader
+	m_Shader.Init("res/shader/model/model.vert", "res/shader/model/model.frag");
+	m_Shader.UnBind();
+
+	m_LightShader.Init("res/shader/Light/LightVertex.vert", "res/shader/Light/LightFragment.frag");
+	m_LightShader.UnBind();
+
+	//m_packageModel.Init("res/model/armor-set/armor 2021.obj");
+	m_packageModel.Init("res/model/Miku/miku_prefab.fbx");
+
+	m_Camera.SetLocation(glm::vec3(0.0f, 0.0f, 3.0f));
+	BindMouse(window);
+
+	m_planeShader.Init("res/shader/FrameBuffer/fb.vert", "res/shader/FrameBuffer/fb.frag");
+	m_planeShader.SetUniform1i("screenTexture", 10);
+	m_planeShader.UnBind();
+
+	m_Light.Init();
+	m_LightPos = glm::vec3(5.0f);
+}
+
+void TestFrameBuffer::OnExit(GLFWwindow* window)
+{
+	// 删除帧缓冲
+	glDeleteFramebuffers(1, &m_FBO);
+
+	glfwSetWindowUserPointer(window, nullptr);
+	UnBindMouse(window);
+}
+
+void TestFrameBuffer::UpdateLogic(float delayTime)
+{
+	m_view = m_Camera.GetView();
+	m_Camera.SetMoveSpeed(m_CameraMoveSpeed);
+	m_Camera.SetRotateSpeed(m_CameraRotateSpeed);
+
+	m_Light.SetLocation(m_LightPos);
+
+	// 可能会更新窗口视口大小 每帧更新一下
+	m_proj = glm::perspective(glm::radians(45.0f), (float)RSI->ViewportHeight / (float)RSI->ViewportWidth, 0.1f, 100.0f);
+}
+
+void TestFrameBuffer::ClearRender(GLFWwindow* window)
+{
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void TestFrameBuffer::Render(GLFWwindow* window)
+{
+	if (m_ShowFBO)
+	{
+		glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
+	}
+
+	glEnable(GL_DEPTH_TEST);
+	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+	ClearRender(window);
+	RenderModel();
+
+	if (m_ShowFBO)
+	{
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glDisable(GL_DEPTH_TEST);
+		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+		glClear(GL_COLOR_BUFFER_BIT);
+
+		glBindVertexArray(m_VAOPlane);
+		glActiveTexture(GL_TEXTURE10);
+		glBindTexture(GL_TEXTURE_2D, m_textureBuffer);
+		glDrawArrays(GL_TRIANGLES, 0, 6);
+	}
+}
+
+void TestFrameBuffer::UpdateImGUI(GLFWwindow* window)
+{
+	const auto& io = ImGui::GetIO();
+
+	ImGui::Begin("Model");
+
+	ImGui::SliderFloat3("Light Position", &m_LightPos.x, -10.0f, 10.0f);
+	ImGui::SliderFloat("Model Scale", &m_ModelScale, 0.1f, 2.0f);
+	ImGui::SliderFloat3("Model Rotate", &m_ModelRotate.x, -180.0f, 180.0f);
+	ImGui::SliderInt("Model Shineness", &m_Shineness, 0, 64);
+	ImGui::Checkbox("Show FBO Plane?", &m_ShowFBO);
+
+	if (ImGui::Button("Close Window"))
+		glfwSetWindowShouldClose(window, true);
+
+	ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
+	ImGui::End();
+}
+
+void TestFrameBuffer::InputProcess(GLFWwindow* window)
+{
+	TestWithMouseBase::InputProcess(window);
+	
+	m_Camera.InputProcess(window);
+	
+	if (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS)
+	{
+		m_bLeftAltPress = true;
+		UnBindMouse(window);
+	}
+	else if(m_bLeftAltPress) {
+		// 因为当前状况 如果不按下 左 alt,每帧都会导致该函数触发,加个判断防止重复触发
+		m_bLeftAltPress = false;
+		BindMouse(window);
+	}
+}
+
+void TestFrameBuffer::MouseCallback(GLFWwindow* window, double xpos, double ypos)
+{
+	m_Camera.MouseCallback(window, xpos, ypos);
+}
+
+void TestFrameBuffer::BindMouse(GLFWwindow* window)
+{
+	m_Camera.SetFirstMouse(true);
+	TestWithMouseBase::BindMouse(window);
+}
+
+void TestFrameBuffer::UnBindMouse(GLFWwindow* window)
+{
+	m_Camera.SetFirstMouse(false);
+	TestWithMouseBase::UnBindMouse(window);
+}
+
+void TestFrameBuffer::InitFBO()
+{
+	std::vector<Vertex_v2> planeVerteices = {
+		{-1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+		{-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+		{ 1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f},
+
+		{-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+		{ 1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f},
+		{ 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
+	};
+
+	// 渲染用 Plane 的效果
+	GLuint planeVBO;
+
+	glGenVertexArrays(1, &m_VAOPlane);
+	glBindVertexArray(m_VAOPlane);
+
+	glGenBuffers(1, &planeVBO);
+	glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
+	glBufferData(GL_ARRAY_BUFFER, planeVerteices.size() * sizeof(Vertex_v2), planeVerteices.data(), GL_STATIC_DRAW);
+
+	glEnableVertexAttribArray(0);
+	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex_v2), (void*)offsetof(Vertex_v2, position));
+	glEnableVertexAttribArray(1);
+	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex_v2), (void*)offsetof(Vertex_v2, normal));
+	glEnableVertexAttribArray(2);
+	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex_v2), (void*)offsetof(Vertex_v2, texCoords));
+
+	glBindVertexArray(GL_ZERO);
+
+	// 创建 Frame Buffer Obejct
+	glGenFramebuffers(1, &m_FBO);
+	glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
+
+	// 创建贴图 用于承接帧缓冲并传递给 Shader 绘制
+	glGenTextures(1, &m_textureBuffer);
+	glBindTexture(GL_TEXTURE_2D, m_textureBuffer);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, RSI->ViewportWidth, RSI->ViewportHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureBuffer, 0);
+	
+	// 添加深度缓冲
+	GLuint rbo;
+	glGenRenderbuffers(1, &rbo);
+	glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, RSI->ViewportWidth, RSI->ViewportHeight);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+	{
+		std::cout << "Error: FrameBuffer Is Not Compelete" << std::endl;
+	}
+
+	// 重置设置帧缓冲为 0,默认绘制到屏幕上
+	glBindFramebuffer(GL_FRAMEBUFFER, GL_ZERO);
+	glBindTexture(GL_TEXTURE_2D, GL_ZERO);
+}
+
+void TestFrameBuffer::RenderModel()
+{
+	m_Shader.Bind();
+
+	auto CameraLocation = m_Camera.GetCameraLocation();
+
+	auto model = glm::mat4(1.0f);
+	model = glm::rotate(model, glm::radians(m_ModelRotate.x), glm::vec3(1, 0, 0));
+	model = glm::rotate(model, glm::radians(m_ModelRotate.y), glm::vec3(0, 1, 0));
+	model = glm::rotate(model, glm::radians(m_ModelRotate.z), glm::vec3(0, 0, 1));
+	model = glm::scale(model, glm::vec3(m_ModelScale, m_ModelScale, m_ModelScale));
+
+	m_Shader.SetUniformMat4f("model", model);
+	m_Shader.SetUniformMat4f("view", m_view);
+	m_Shader.SetUniformMat4f("projection", m_proj);
+	m_Shader.SetUniform3f("lightPos", m_LightPos.x, m_LightPos.y, m_LightPos.z);
+	m_Shader.SetUniform3f("viewPos", CameraLocation.x, CameraLocation.y, CameraLocation.z);
+	m_Shader.SetUniform1i("shineness", m_Shineness);
+
+	m_packageModel.Draw(m_Shader);
+
+	glBindVertexArray(m_LightVAO);
+	glDrawArrays(GL_TRIANGLES, 0, 6 * 6);
+
+	auto lightModule = glm::mat4(1.0f);
+	lightModule = glm::translate(lightModule, m_LightPos);
+	lightModule = glm::scale(lightModule, glm::vec3(0.2f)); // a smaller cube
+
+	m_LightShader.Bind();
+	m_LightShader.SetUniformMat4f("model", lightModule);
+	m_LightShader.SetUniformMat4f("view", m_view);
+	m_LightShader.SetUniformMat4f("projection", m_proj);
+	m_Light.Draw();
+}

+ 75 - 0
图形学/OpenGL学习/src/OpenGLDemo/OpenGLDemo/src/testModule/TestFrameBuffer.h

@@ -0,0 +1,75 @@
+#pragma once
+#include "TestWithMouseBase.h"
+#include "../Util/CommonData.h"
+
+#include "../Util/Shader.h"
+#include "../Util/Texture.h"
+#include "../Util/Camera.h"
+#include "../Util/Model.h"
+
+#include "../Util/BaseLight.h"
+
+class TestFrameBuffer : public TestWithMouseBase
+{
+public:
+	TestFrameBuffer() : TestWithMouseBase("TestFrameBuffer") {}
+
+public:
+	virtual void OnEnter(GLFWwindow* window) override;
+	virtual void OnExit(GLFWwindow* window) override;
+
+	virtual void UpdateLogic(float delayTime) override;
+	virtual void ClearRender(GLFWwindow* window) override;
+	virtual void Render(GLFWwindow* window) override;
+	virtual void UpdateImGUI(GLFWwindow* window) override;
+
+	virtual void InputProcess(GLFWwindow* window) override;
+
+	virtual void MouseCallback(GLFWwindow* window, double xpos, double ypos) override;
+
+	virtual void BindMouse(GLFWwindow* window) override;
+	virtual void UnBindMouse(GLFWwindow* window) override;
+
+protected:
+	void InitFBO();
+
+	void RenderModel();
+
+private:
+	GLuint m_LightVAO{ GL_ZERO };
+	
+	GLuint m_FBO{ GL_ZERO };					// Frame Buffer Object 帧缓冲对象
+	GLuint m_VAOPlane{ GL_ZERO };				// 一个平面的 VAO 用于绘制帧缓冲效果
+	GLuint m_textureBuffer{ GL_ZERO };			// 用于存储帧缓冲的 贴图
+	Shader m_planeShader;
+	
+	bool m_ShowFBO{ true };						// 是否渲染到 FBO 上
+
+	Shader m_Shader;
+	Shader m_LightShader;
+
+	glm::mat4 m_model = glm::mat4(1.0f);		// 模型矩阵
+	glm::mat4 m_view = glm::mat4(1.0f);			// 视图矩阵
+	glm::mat4 m_proj = glm::mat4(1.0f);			// 投影矩阵
+
+	//glm::vec3 m_modelRotate = glm::vec3(0.0f);
+
+	float m_CameraMoveSpeed = 0.1f;
+	float m_CameraRotateSpeed = 0.1f;
+
+	Model m_packageModel;
+
+	Camera m_Camera;
+	bool m_bLeftAltPress = false;
+
+	BaseLight m_Light;
+	glm::vec3 m_LightPos;
+
+	float m_ModelScale = 1.0f;
+	glm::vec3 m_ModelRotate;
+
+	int m_Shineness = 4;
+
+	static TestFrameBuffer _self;
+};
+