当前位置: 首页 > news >正文

【OpenGL学习】(八)图形变换

OpenGL图形变换介绍:https://learnopengl-cn.github.io/01%20Getting%20started/07%20Transformations

【OpenGL学习】(八)图形变换


本项目将通过变换矩阵,对【OpenGL学习】(七)纹理单元 中的图形进行缩放,旋转和平移。

项目链接: https://github.com/BinaryAI-1024/OpenGLPorjects/tree/master/transformations

顶点着色器transform.vs:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;out vec2 TexCoord;uniform mat4 transform;void main()
{gl_Position = transform * vec4(aPos, 1.0); // 坐标变换TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

片段着色器transform.fs:

#version 330 core
out vec4 FragColor;in vec3 ourColor;
in vec2 TexCoord;// texture samplers
uniform sampler2D texSampler1;
uniform sampler2D texSampler2;void main()
{// 在两个纹理之间进行线性插值 (80% container, 20% awesomeface)FragColor = mix(texture(texSampler1, TexCoord), texture(texSampler2, TexCoord), 0.2);
}

transfomations.cpp

#define STB_IMAGE_IMPLEMENTATION
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>#include <filesystem.h>
#include <shader_s.h>#include <iostream>void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;int main()
{// 初始化GLFW并配置glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac OS X需要前向兼容
#endif// 创建窗口GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window); //  设置为当前上下文glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // 注册窗口大小变化回调// 初始化GLAD(加载OpenGL函数指针)if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}// 编译着色器程序Shader ourShader("transform.vs", "transform.fs");// 顶点数据和缓冲区设置float vertices[] = {// 位置              // 纹理坐标0.5f,  0.5f, 0.0f,   1.0f, 1.0f, // 右上0.5f, -0.5f, 0.0f,   1.0f, 0.0f, // 右下-0.5f, -0.5f, 0.0f,   0.0f, 0.0f, // 左下-0.5f,  0.5f, 0.0f,   0.0f, 1.0f  // 左上 };unsigned int indices[] = {0, 1, 3, // 第一个三角形1, 2, 3  // 第二个三角形};// 生成缓冲区对象unsigned int VBO, VAO, EBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);// 绑定VAOglBindVertexArray(VAO);// 绑定VBO并传输顶点数据glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 绑定EBO并传输索引数据glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);// 设置位置属性指针glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// 设置纹理坐标属性指针glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);// 加载并创建纹理unsigned int texture1, texture2;// 纹理1 - 容器纹理glGenTextures(1, &texture1);glBindTexture(GL_TEXTURE_2D, texture1);// 设置纹理环绕方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);// 设置纹理过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 加载图像数据int width, height, nrChannels;stbi_set_flip_vertically_on_load(true); // 翻转y轴unsigned char* data = stbi_load(FileSystem::getPath("resources/container.jpg").c_str(), &width, &height, &nrChannels, 0);if (data){glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);}else{std::cout << "Failed to load texture" << std::endl;}stbi_image_free(data);// 纹理2 - 笑脸纹理glGenTextures(1, &texture2);glBindTexture(GL_TEXTURE_2D, texture2);// 设置纹理参数(同上)glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 加载图像数据(注意这是PNG有透明通道)data = stbi_load(FileSystem::getPath("resources/awesomeface.png").c_str(), &width, &height, &nrChannels, 0);if (data){glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);}else{std::cout << "Failed to load texture" << std::endl;}stbi_image_free(data);// 设置着色器中的采样器对应的纹理单元ourShader.use();ourShader.setInt("texSampler1", 0); // 纹理单元0ourShader.setInt("texSampler2", 1); // 纹理单元1// 渲染循环while (!glfwWindowShouldClose(window)){// 输入处理processInput(window);// 渲染指令glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);// 绑定纹理到对应的纹理单元glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);// ========== 矩阵变换部分 ==========// 1. 创建变换矩阵(初始化为单位矩阵)glm::mat4 transform = glm::mat4(1.0f);// 2. 应用平移变换(向右0.5单位,向下0.5单位)transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));// 3. 应用旋转变换(绕z轴旋转,旋转角度基于当前时间)// glfwGetTime()返回程序运行时间(秒)transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));// 4. 图形每个轴都缩放为0.5倍transform = glm::scale(transform, glm::vec3(0.5, 0.5, 0.5));// 矩阵变换的执行顺序是反向的:// 实际效果是:物体先缩小,再旋转,最后平移// 使用着色器程序并设置变换矩阵uniformourShader.use();unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");// 将矩阵传输给着色器glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));// 渲染四边形glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);// 交换缓冲区并查询IO事件glfwSwapBuffers(window);glfwPollEvents();}// 清理资源glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);// 终止GLFWglfwTerminate();return 0;
}void processInput(GLFWwindow* window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true);
}void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height); 
}

运行结果:

在这里插入图片描述

http://www.lryc.cn/news/576821.html

相关文章:

  • Oauth2 自定义设置token过期时间
  • 状态机编程实战 | 如何更优雅地处理字符串
  • 全新大模型开源,腾讯(int4能打DeepSeek) Vs 谷歌(2GB运行多模态)
  • Gemini-CLI:谷歌开源的命令行AI工具,重新定义开发者工作流
  • Ubuntu22 安装 RTX 5070 Ti Nvidia Driver 驱动
  • 自学嵌入式 day27 进程
  • mac系统快捷键及命令安装
  • 状态模式 - Flutter中的状态变身术,让对象随“状态“自由切换行为!
  • 边界的艺术:支持向量机与统计学习时代的王者
  • 设计模式-外观模式、适配器模式
  • 【数据挖掘】聚类算法学习—K-Means
  • YOLOv12_ultralytics-8.3.145_2025_5_27部分代码阅读笔记-conv.py
  • 设备预测性维护和异常检测系统设计方案
  • 【HuggingFace】模型下载至本地访问
  • Git安装全攻略:避坑指南与最佳实践
  • C++ 格式化输入输出
  • 人工智能时代的职业替代风险与应对策略分析
  • MySQL技巧
  • 性能分析专栏 -- top命令
  • 【修电脑的小记录】连不上网
  • 打造地基: App拉起基础小程序容器
  • 疏通经脉: Bridge 联通逻辑层和渲染层
  • 深入理解 Dubbo 负载均衡:原理、源码与实践
  • RK3588集群服务器性能优化案例:电网巡检集群、云手机集群、工业质检集群
  • [Python 基础课程]PyCharm 的安装
  • 大数据Hadoop之——Flume安装与使用(详细)
  • Dify私有化知识库搭建并通过ChatFlow智能机器人使用知识库的详细操作步骤
  • AlpineLinux安装部署MariaDB
  • 怎样优化HDFS的网络传输
  • WireShark网络取证分析第一集到第五集和dvwa靶场环境分析漏洞