glm这个变换矩阵只会出现在while循环中吗?

张开发
2026/4/9 20:35:06 15 分钟阅读

分享文章

glm这个变换矩阵只会出现在while循环中吗?
一、变换矩阵的三种常见使用场景1.动态变换在while循环中每帧重新计算矩阵实现动画效果while (!glfwWindowShouldClose(window)){// 每帧都重新计算 - 产生动态效果float time glfwGetTime();float xOffset sin(time); // 随时间变化glm::mat4 transform glm::mat4(1.0f);transform glm::translate(transform, glm::vec3(xOffset, 0.0f, 0.0f));// 传递给着色器并绘制...}2.静态变换在while循环外只在程序开始时计算一次之后保持不变int main(){// 初始化...// 在循环外计算一次整个程序运行期间都不变glm::mat4 transform glm::mat4(1.0f);transform glm::translate(transform, glm::vec3(0.5f, 0.5f, 0.0f));transform glm::scale(transform, glm::vec3(0.5f, 0.5f, 1.0f));// 获取uniform位置也可以只做一次unsigned int transformLoc glGetUniformLocation(ourShader.ID, transform);while (!glfwWindowShouldClose(window)){// 清屏、绑定纹理等...ourShader.use();// 使用预先计算好的矩阵每帧都一样glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));glDrawElements(...);}}适用场景场景中静止的物体建筑、地形等。3.混合使用部分静态 部分动态int main(){// 静态部分基础变换只计算一次glm::mat4 baseTransform glm::mat4(1.0f);baseTransform glm::scale(baseTransform, glm::vec3(0.5f, 0.5f, 1.0f));unsigned int transformLoc glGetUniformLocation(ourShader.ID, transform);while (!glfwWindowShouldClose(window)){// 动态部分每帧添加旋转glm::mat4 transform baseTransform; // 从静态矩阵开始float time glfwGetTime();transform glm::rotate(transform, time, glm::vec3(0.0f, 0.0f, 1.0f));ourShader.use();glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));glDrawElements(...);}}适用场景物体本身有固定缩放和位置但还要自转。二、性能考虑每帧都计算矩阵的性能开销// 轻量级操作没问题transform glm::translate(transform, glm::vec3(xOffset, 0.0f, 0.0f));// 重量级操作尽量避免每帧都做transform glm::inverse(someComplexMatrix); // 矩阵求逆很慢transform glm::perspective(...); // 投影矩阵通常只计算一次最佳实践视图矩阵、投影矩阵通常在循环外计算一次除非摄像机在移动模型矩阵如果物体在移动/旋转就在循环内计算三、实际例子对比错误示例不必要的重复计算while (!glfwWindowShouldClose(window)){// 投影矩阵不会变却每帧都计算浪费性能glm::mat4 projection glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.0f);// 视图矩阵也不会变摄像机不动glm::mat4 view glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3.0f));// 只有模型矩阵在变化glm::mat4 model glm::rotate(glm::mat4(1.0f), time, glm::vec3(0.0f, 1.0f, 0.0f));// 传递三个矩阵...}正确示例优化性能int main(){// 在循环外计算一次glm::mat4 projection glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.0f);glm::mat4 view glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3.0f));// 获取uniform位置只做一次unsigned int projectionLoc glGetUniformLocation(shader.ID, projection);unsigned int viewLoc glGetUniformLocation(shader.ID, view);unsigned int modelLoc glGetUniformLocation(shader.ID, model);while (!glfwWindowShouldClose(window)){float time glfwGetTime();// 只有模型矩阵需要每帧更新glm::mat4 model glm::rotate(glm::mat4(1.0f), time, glm::vec3(0.0f, 1.0f, 0.0f));shader.use();glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));glDrawElements(...);}}四、特殊情况响应窗口大小变化投影矩阵通常需要在窗口大小改变时重新计算void framebuffer_size_callback(GLFWwindow* window, int width, int height){glViewport(0, 0, width, height);// 重新计算投影矩阵适应新的宽高比glm::mat4 projection glm::perspective(glm::radians(45.0f), (float)width/height, 0.1f, 100.0f);// 然后需要重新传递给着色器...}用户输入控制根据键盘输入动态更新矩阵glm::mat4 view glm::mat4(1.0f);float cameraX 0.0f, cameraY 0.0f;while (!glfwWindowShouldClose(window)){// 根据按键更新位置if (glfwGetKey(window, GLFW_KEY_A) GLFW_PRESS)cameraX - 0.01f;if (glfwGetKey(window, GLFW_KEY_D) GLFW_PRESS)cameraX 0.01f;// 每帧重新计算视图矩阵因为摄像机在移动view glm::translate(glm::mat4(1.0f), glm::vec3(cameraX, cameraY, -3.0f));// 传递给着色器...}总结情况计算位置原因静态物体while循环外变换不变避免重复计算动画物体while循环内每帧都需要新位置投影矩阵while循环外通常不变除非窗口大小改变跟随鼠标/键盘while循环内需要响应用户输入记住原则变的东西→ 放循环内不变的东西→ 放循环外

更多文章