From 0f5bebbdadb3670f03dcd9369c3e76c4ab25e2e3 Mon Sep 17 00:00:00 2001 From: iridiumR Date: Sat, 3 Jun 2023 20:48:51 +0800 Subject: [PATCH] feat(OpenGL): lab 3 --- OpenGL/hello/Makefile | 2 + OpenGL/hello/include/model.h | 15 ++++ OpenGL/hello/include/source.h | 54 +----------- OpenGL/hello/src/cube.fs | 32 ------- OpenGL/hello/src/cube.vs | 18 ---- OpenGL/hello/src/light.fs | 7 -- OpenGL/hello/src/light.vs | 11 --- OpenGL/hello/src/main.cpp | 147 ++++++++++++++++++++++++++++++- OpenGL/hello/src/simple.vs | 8 -- OpenGL/hello/src/text.fs | 12 +++ OpenGL/hello/src/text.vs | 11 +++ OpenGL/hello/src/uniformcolor.fs | 9 -- 12 files changed, 186 insertions(+), 140 deletions(-) delete mode 100644 OpenGL/hello/src/cube.fs delete mode 100644 OpenGL/hello/src/cube.vs delete mode 100644 OpenGL/hello/src/light.fs delete mode 100644 OpenGL/hello/src/light.vs delete mode 100644 OpenGL/hello/src/simple.vs create mode 100644 OpenGL/hello/src/text.fs create mode 100644 OpenGL/hello/src/text.vs delete mode 100644 OpenGL/hello/src/uniformcolor.fs diff --git a/OpenGL/hello/Makefile b/OpenGL/hello/Makefile index 13610ee..69ffda2 100644 --- a/OpenGL/hello/Makefile +++ b/OpenGL/hello/Makefile @@ -2,6 +2,7 @@ SRC_DIR := ./src #头文件目录 INC_DIR := ./include +INC_DIR += /usr/include/freetype2 #输出文件目录 OUT_DIR := ./build #目标文件(中间文件)目录 @@ -9,6 +10,7 @@ OBJ_DIR :=./build #链接选项 LDFLAGS := $(shell pkg-config --static --libs glfw3) LDFLAGS += $(shell pkg-config --static --libs assimp) +LDFLAGS += $(shell pkg-config --static -libs freetype2) # 调试符号 LDFLAGS += -g #编译工具链 diff --git a/OpenGL/hello/include/model.h b/OpenGL/hello/include/model.h index 84c4f28..52e430a 100644 --- a/OpenGL/hello/include/model.h +++ b/OpenGL/hello/include/model.h @@ -28,6 +28,11 @@ unsigned int TextureFromFile(const char *path, const string &directory, bool gam class Model { public: + + unsigned long vertexCount = 0; + unsigned long triangleCount = 0; + unsigned long textureCount = 0; + // model data vector textures_loaded; // stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once. vector meshes; @@ -60,6 +65,12 @@ private: cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl; return; } + + for(unsigned int i = 0; i < scene->mNumMaterials; i++){ + const aiMaterial* material = scene->mMaterials[i]; + textureCount += material->GetTextureCount(aiTextureType_DIFFUSE); + } + // retrieve the directory path of the filepath directory = path.substr(0, path.find_last_of('/')); @@ -76,6 +87,10 @@ private: // the node object only contains indices to index the actual objects in the scene. // the scene contains all the data, node is just to keep stuff organized (like relations between nodes). aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + + vertexCount += mesh->mNumVertices; + triangleCount += mesh->mNumFaces; + meshes.push_back(processMesh(mesh, scene)); } // after we've processed all of the meshes (if any) we then recursively process each of the children nodes diff --git a/OpenGL/hello/include/source.h b/OpenGL/hello/include/source.h index 999c8d9..7970073 100644 --- a/OpenGL/hello/include/source.h +++ b/OpenGL/hello/include/source.h @@ -10,57 +10,8 @@ #include #include #include "model.h" - - float vertices[] = { - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f - }; - -glm::vec3 cubePositions[] = { - glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(2.0f, 5.0f, -15.0f), - glm::vec3(-1.5f, -2.2f, -2.5f), glm::vec3(-3.8f, -2.0f, -12.3f), - glm::vec3(2.4f, -0.4f, -3.5f), glm::vec3(-1.7f, 3.0f, -7.5f), - glm::vec3(1.3f, -2.0f, -2.5f), glm::vec3(1.5f, 2.0f, -2.5f), - glm::vec3(1.5f, 0.2f, -1.5f), glm::vec3(-1.3f, 1.0f, -1.5f)}; +#include +#include FT_FREETYPE_H float deltaTime = 0.0f; // 当前帧与上一帧的时间差 float lastFrame = 0.0f; // 上一帧的时间 @@ -68,7 +19,6 @@ float lastFrame = 0.0f; // 上一帧的时间 // settings const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 800; -glm::vec3 lightPos(1.2f, 1.0f, 2.0f); // 创建摄像机 Camera camera = Camera(SCR_HEIGHT / 2.0f, SCR_HEIGHT / 2.0f); diff --git a/OpenGL/hello/src/cube.fs b/OpenGL/hello/src/cube.fs deleted file mode 100644 index 835b4fa..0000000 --- a/OpenGL/hello/src/cube.fs +++ /dev/null @@ -1,32 +0,0 @@ -#version 330 core -out vec4 FragColor; - -in vec3 Normal; -in vec3 FragPos; - -uniform vec3 lightPos; -uniform vec3 lightColor; -uniform vec3 objectColor; -uniform vec3 viewPos; - -void main() { - // 环境 - float ambientStrength = 0.1; - vec3 ambient = ambientStrength * lightColor; - - // 漫反射 - vec3 norm = normalize(Normal); - vec3 lightDir = normalize(lightPos - FragPos); - float diff = max(dot(norm, lightDir), 0.0); - vec3 diffuse = diff * lightColor; - - // 镜面 - float specularStrength = 0.5; - vec3 viewDir = normalize(viewPos - FragPos); - vec3 reflectDir = reflect(-lightDir, norm); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), 64); - vec3 specular = specularStrength * spec * lightColor; - -vec3 result = (ambient + diffuse + specular) * objectColor; - FragColor = vec4(result, 1.0); -} \ No newline at end of file diff --git a/OpenGL/hello/src/cube.vs b/OpenGL/hello/src/cube.vs deleted file mode 100644 index d7ade7b..0000000 --- a/OpenGL/hello/src/cube.vs +++ /dev/null @@ -1,18 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aNormal; - -out vec3 FragPos; -out vec3 Normal; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - -void main() -{ - FragPos = vec3(model * vec4(aPos, 1.0)); - Normal = aNormal; - - gl_Position = projection * view * vec4(FragPos, 1.0); -} \ No newline at end of file diff --git a/OpenGL/hello/src/light.fs b/OpenGL/hello/src/light.fs deleted file mode 100644 index 1c649f4..0000000 --- a/OpenGL/hello/src/light.fs +++ /dev/null @@ -1,7 +0,0 @@ -#version 330 core -out vec4 FragColor; - -void main() -{ - FragColor = vec4(1.0); // set all 4 vector values to 1.0 -} \ No newline at end of file diff --git a/OpenGL/hello/src/light.vs b/OpenGL/hello/src/light.vs deleted file mode 100644 index 752ce21..0000000 --- a/OpenGL/hello/src/light.vs +++ /dev/null @@ -1,11 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 aPos; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - -void main() -{ - gl_Position = projection * view * model * vec4(aPos, 1.0); -} \ No newline at end of file diff --git a/OpenGL/hello/src/main.cpp b/OpenGL/hello/src/main.cpp index 9420177..4d1d68b 100644 --- a/OpenGL/hello/src/main.cpp +++ b/OpenGL/hello/src/main.cpp @@ -8,6 +8,18 @@ void processInput(GLFWwindow *window); void mouse_callback(GLFWwindow *window, double xpos, double ypos); void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); +struct Character { + GLuint TextureID; // 字形纹理的ID + glm::ivec2 Size; // 字形大小 + glm::ivec2 Bearing; // 从基准线到字形左部/顶部的偏移值 + GLuint Advance; // 原点距下一个字形原点的距离 +}; +std::map Characters; +GLuint VAO, VBO; + +void RenderText(Shader &shader, std::string text, GLfloat x, GLfloat y, + GLfloat scale, glm::vec3 color); + int main() { // 设置 glfw @@ -39,11 +51,77 @@ int main() { glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); - // 反转y轴 - // stbi_set_flip_vertically_on_load(true); + // FreeType + FT_Library ft; + // All functions return a value different than 0 whenever an error occurred + if (FT_Init_FreeType(&ft)) + std::cout << "ERROR::FREETYPE: Could not init FreeType Library" + << std::endl; + + // Load font as face + FT_Face face; + if (FT_New_Face(ft, "/usr/share/fonts/TTF/Hack-Regular.ttf", 0, &face)) + std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl; + + // Set size to load glyphs as + FT_Set_Pixel_Sizes(face, 0, 48); + + // Disable byte-alignment restriction + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // Load first 128 characters of ASCII set + for (GLubyte c = 0; c < 128; c++) { + // Load character glyph + if (FT_Load_Char(face, c, FT_LOAD_RENDER)) { + std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl; + continue; + } + // Generate texture + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, face->glyph->bitmap.width, + face->glyph->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE, + face->glyph->bitmap.buffer); + // Set texture options + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // Now store character for later use + Character character = { + texture, + glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows), + glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top), + face->glyph->advance.x}; + Characters.insert(std::pair(c, character)); + } + glBindTexture(GL_TEXTURE_2D, 0); + // Destroy FreeType once we're finished + FT_Done_Face(face); + FT_Done_FreeType(ft); + + // Configure VAO/VBO for texture quads + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); // 加载着色器 Shader ourShader("src/model.vs", "src/model.fs"); + + // Compile and setup the shader + Shader shader("src/text.vs", "src/text.fs"); + glm::mat4 projection = glm::ortho(0.0f, static_cast(SCR_WIDTH), 0.0f, + static_cast(SCR_HEIGHT)); + shader.use(); + shader.setMat4("projection", projection); + // 加载模型 Model Model1("resources/models/nanosuit/nanosuit.obj"); // Model ourModel("resources/models/bugatti/bugatti.obj"); @@ -75,6 +153,23 @@ int main() { glClearColor(0.8f, 0.8f, 0.8f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // 绘制文字 + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + RenderText(shader, std::to_string(1.0f / deltaTime), float(SCR_WIDTH - 150), + float(SCR_HEIGHT - 50), 0.5f, glm::vec3(0.0, 0.0f, 0.0f)); + std::string info = + "Vertex Count: " + std::to_string(ourModel->vertexCount) + + " Triangle Count:" + std::to_string(ourModel->vertexCount / 3) + + " Texture Count: " + std::to_string(ourModel->textureCount); + + RenderText(shader, info, float(5), float(25), 0.3f, + glm::vec3(0.0, 0.0f, 0.0f)); + + // 关闭混合 + glDisable(GL_BLEND); + if (mode) // 线框模式 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -96,7 +191,8 @@ int main() { glm::mat4 model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); - model = glm::rotate(model, glm::radians(float(10*glfwGetTime())), glm::vec3(0.0f, 1.0f, 0.0f)); + model = glm::rotate(model, glm::radians(float(10 * glfwGetTime())), + glm::vec3(0.0f, 1.0f, 0.0f)); ourShader.setMat4("model", model); ourModel->Draw(ourShader); @@ -143,4 +239,49 @@ void mouse_callback(GLFWwindow *window, double xpos, double ypos) { void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) { camera.ProcessMouseScroll(yoffset); +} + +void RenderText(Shader &shader, std::string text, GLfloat x, GLfloat y, + GLfloat scale, glm::vec3 color) { + // Activate corresponding render state + shader.use(); + shader.setVec3("textColor", color); + glActiveTexture(GL_TEXTURE0); + glBindVertexArray(VAO); + + // Iterate through all characters + std::string::const_iterator c; + for (c = text.begin(); c != text.end(); c++) { + Character ch = Characters[*c]; + + GLfloat xpos = x + ch.Bearing.x * scale; + GLfloat ypos = y - (ch.Size.y - ch.Bearing.y) * scale; + + GLfloat w = ch.Size.x * scale; + GLfloat h = ch.Size.y * scale; + // Update VBO for each character + GLfloat vertices[6][4] = { + {xpos, ypos + h, 0.0, 0.0}, {xpos, ypos, 0.0, 1.0}, + {xpos + w, ypos, 1.0, 1.0}, + + {xpos, ypos + h, 0.0, 0.0}, {xpos + w, ypos, 1.0, 1.0}, + {xpos + w, ypos + h, 1.0, 0.0}}; + // Render glyph texture over quad + glBindTexture(GL_TEXTURE_2D, ch.TextureID); + // Update content of VBO memory + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferSubData( + GL_ARRAY_BUFFER, 0, sizeof(vertices), + vertices); // Be sure to use glBufferSubData and not glBufferData + glBindBuffer(GL_ARRAY_BUFFER, 0); + // Render quad + glDrawArrays(GL_TRIANGLES, 0, 6); + // Now advance cursors for next glyph (note that advance is number of 1/64 + // pixels) + x += (ch.Advance >> 6) * + scale; // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount + // of 1/64th pixels by 64 to get amount of pixels)) + } + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); } \ No newline at end of file diff --git a/OpenGL/hello/src/simple.vs b/OpenGL/hello/src/simple.vs deleted file mode 100644 index e924e3e..0000000 --- a/OpenGL/hello/src/simple.vs +++ /dev/null @@ -1,8 +0,0 @@ -#version 330 core -layout(location = 0) in vec3 aPos; // 位置变量的属性位置值为0 -uniform float xOffset; -uniform float yOffset; -void main() { - gl_Position = vec4(aPos.x + xOffset, aPos.y + yOffset, aPos.z, - 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数 -} diff --git a/OpenGL/hello/src/text.fs b/OpenGL/hello/src/text.fs new file mode 100644 index 0000000..bbd0c17 --- /dev/null +++ b/OpenGL/hello/src/text.fs @@ -0,0 +1,12 @@ +#version 330 core +in vec2 TexCoords; +out vec4 color; + +uniform sampler2D text; +uniform vec3 textColor; + +void main() +{ + vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r); + color = vec4(textColor, 1.0) * sampled; +} \ No newline at end of file diff --git a/OpenGL/hello/src/text.vs b/OpenGL/hello/src/text.vs new file mode 100644 index 0000000..94b6118 --- /dev/null +++ b/OpenGL/hello/src/text.vs @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec4 vertex; // +out vec2 TexCoords; + +uniform mat4 projection; + +void main() +{ + gl_Position = projection * vec4(vertex.xy, 0.0, 1.0); + TexCoords = vertex.zw; +} \ No newline at end of file diff --git a/OpenGL/hello/src/uniformcolor.fs b/OpenGL/hello/src/uniformcolor.fs deleted file mode 100644 index 07cfe17..0000000 --- a/OpenGL/hello/src/uniformcolor.fs +++ /dev/null @@ -1,9 +0,0 @@ -#version 330 core -out vec4 FragColor; - -uniform vec4 ourColor; // 在OpenGL程序代码中设定这个变量 - -void main() -{ - FragColor = ourColor; -} \ No newline at end of file