OpenGL着色器实现纹理合并显示

   OpenGL着色器实现纹理合并显示

       本文介绍了opengl下实现纹理的装载,同时借助顶点着色器和片源着色器实现两个不同外部纹理的合并显示。


目录

  • 1 opengl下纹理的装载
  • 2 纹理合并效果显示
  • 3 完整的代码

  • 1 opengl下纹理的装载
// 初始化GLFWif (!glfwInit()) {std::cerr << "Failed to initialize GLFW" << std::endl;return -1;}// 创建窗口GLFWwindow* window = glfwCreateWindow(800, 600, "Multiple Textures Example", NULL, NULL);if (!window) {std::cerr << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);// 初始化GLEWif (glewInit() != GLEW_OK) {std::cerr << "Failed to initialize GLEW" << std::endl;return -1;}// 编译顶点着色器GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// 编译片元着色器GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);// 创建着色器程序GLuint shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);glUseProgram(shaderProgram);// 加载纹理1GLuint textureID1 = SOIL_load_OGL_texture("1.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, textureID1);glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0);// 加载纹理2GLuint textureID2 = SOIL_load_OGL_texture("2.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, textureID2);glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1);

        借助glfw实现窗口的创建,借助SOIL库实现纹理的装载,返回加载后的纹理id。

  • 2 纹理合并效果显示
// 设置顶点数据和纹理坐标float vertices[] = {// 位置            // 纹理坐标-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,1.0f, -1.0f, 0.0f, 1.0f, 0.0f,1.0f,  1.0f, 0.0f, 1.0f, 1.0f,- 1.0f, -1.0f, 0.0f, 0.0f, 0.0f,1.0f,  1.0f, 0.0f, 1.0f, 1.0f,-1.0f,  1.0f, 0.0f, 0.0f, 1.0f};// 创建顶点缓冲对象和顶点数组对象unsigned int VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, 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);// 渲染循环while (!glfwWindowShouldClose(window)) {glClear(GL_COLOR_BUFFER_BIT);// 绑定纹理并绘制glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, textureID1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, textureID2);glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 6);glfwSwapBuffers(window);glfwPollEvents();}// 清理资源glDeleteTextures(1, &textureID1);glDeleteTextures(1, &textureID2);glDeleteProgram(shaderProgram);glDeleteShader(vertexShader);glDeleteShader(fragmentShader);glfwTerminate();

        绘制两个三角形,并绑定两个纹理。添加顶点着色器和片元着色器,其代码如下:

const char* vertexShaderSource = R"(
#version 330 corelayout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;out vec2 fragTexCoord;void main() {fragTexCoord = texCoord;gl_Position = vec4(position, 1.0);
}
)";const char* fragmentShaderSource = R"(
#version 330 corein vec2 fragTexCoord;
out vec4 fragColor;uniform sampler2D texture1;
uniform sampler2D texture2;void main() {vec4 color1 = texture(texture1, fragTexCoord);vec4 color2 = texture(texture2, fragTexCoord);// 将两个纹理的颜色进行混合fragColor = mix(color1, color2, 0.5);
}
)";
  • 3 完整的代码

        完整的代码如下所示,需依赖glfw实现窗口显示,依赖SOIL实现纹理装载。需将两个纹理路径换为本地路径,给出的示例代码路径为1.jpg和2.jpg。


#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <SOIL/SOIL.h>
#include <iostream>const char* vertexShaderSource = R"(
#version 330 corelayout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;out vec2 fragTexCoord;void main() {fragTexCoord = texCoord;gl_Position = vec4(position, 1.0);
}
)";const char* fragmentShaderSource = R"(
#version 330 corein vec2 fragTexCoord;
out vec4 fragColor;uniform sampler2D texture1;
uniform sampler2D texture2;void main() {vec4 color1 = texture(texture1, fragTexCoord);vec4 color2 = texture(texture2, fragTexCoord);// 将两个纹理的颜色进行混合fragColor = mix(color1, color2, 0.5);
}
)";int main() {// 初始化GLFWif (!glfwInit()) {std::cerr << "Failed to initialize GLFW" << std::endl;return -1;}// 创建窗口GLFWwindow* window = glfwCreateWindow(800, 600, "Multiple Textures Example", NULL, NULL);if (!window) {std::cerr << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);// 初始化GLEWif (glewInit() != GLEW_OK) {std::cerr << "Failed to initialize GLEW" << std::endl;return -1;}// 编译顶点着色器GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// 编译片元着色器GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);// 创建着色器程序GLuint shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);glUseProgram(shaderProgram);// 加载纹理1GLuint textureID1 = SOIL_load_OGL_texture("1.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, textureID1);glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0);// 加载纹理2GLuint textureID2 = SOIL_load_OGL_texture("2.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, textureID2);glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1);// 设置顶点数据和纹理坐标float vertices[] = {// 位置            // 纹理坐标-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,1.0f, -1.0f, 0.0f, 1.0f, 0.0f,1.0f,  1.0f, 0.0f, 1.0f, 1.0f,- 1.0f, -1.0f, 0.0f, 0.0f, 0.0f,1.0f,  1.0f, 0.0f, 1.0f, 1.0f,-1.0f,  1.0f, 0.0f, 0.0f, 1.0f};// 创建顶点缓冲对象和顶点数组对象unsigned int VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, 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);// 渲染循环while (!glfwWindowShouldClose(window)) {glClear(GL_COLOR_BUFFER_BIT);// 绑定纹理并绘制glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, textureID1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, textureID2);glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 6);glfwSwapBuffers(window);glfwPollEvents();}// 清理资源glDeleteTextures(1, &textureID1);glDeleteTextures(1, &textureID2);glDeleteProgram(shaderProgram);glDeleteShader(vertexShader);glDeleteShader(fragmentShader);glfwTerminate();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/808316.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从建表语句带你学习doris_数据类型

1、前言概述 1.1、doris建表模板 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [DATABASE.]table_name (column_definition1[,column_deinition2,......][,index_definition1,[,index_definition2,]] ) [ENGINE = [olap|mysql|broker|hive]] [key_desc] [COMMENT "table co…

共享低碳未来!科士达新一代工商业储能产品引爆ESIE 2024

4月11日&#xff0c;第十二届储能国际峰会暨展览会&#xff08;ESIE 2024&#xff09;在北京首钢会展中心盛大开幕&#xff0c;科士达以“数智光储&#xff0c;共享低碳未来”为主题&#xff0c;携多款工商业储能产品及解决方案惊艳亮相本次盛会。 展会首日&#xff0c;科士达展…

C/C++基础----运算符

算数运算符 运算符 描述 例子 两个数字相加 两个变量a b得到两个变量之和 - 两个数字相减 - * 两个数字相乘 - / 两个数字相除 - % 两个数字相除后取余数 8 % 3 2 -- 一个数字递减 变量a&#xff1a;a-- 、--a 一个数字递增 变量a: a 、 a 其中递…

VSCode中调试C++程序

目录 一、准备工作&#xff1a;安装插件 1、C/C插件 ​编辑 2、CMake插件 3、CMake tool插件 二、调试过程 1、debug 2、打断点 3、调C/C文件 每次重新调试的时候都忘了具体步骤&#xff0c;直接给自己写个备忘录好了。 一、准备工作&#xff1a;安装插件 1、C/C插件…

java二叉树前中后序遍历

代码随想录解题思路&#x1f192;力扣前序题目&#x1f192;力扣中序题目&#x1f192;力扣后序题目 递归遍历 // 前序遍历 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> res new ArrayList<>();preorder(root…

zabbix“专家坐诊”第236期问答

问题一 Q&#xff1a;我的trap里已经可以收到信息了&#xff0c;后续要怎么创建监控项呀&#xff1f; A&#xff1a;参考&#xff1a; 问题二 Q&#xff1a;snmp和snmp trap咋搞&#xff1f; A&#xff1a;你指的是如何开启这些协议还是如何做监控项&#xff1f; Q&#xff1…

Opentelemetry——Observability Primer

Observability Primer 可观测性入门 Core observability concepts. 可观测性核心概念。 What is Observability? 什么是可观测性&#xff1f; Observability lets us understand a system from the outside, by letting us ask questions about that system without know…

动态开辟字符串malloc

1. 定义一个指针 int *p; 直接给指针赋值会产生段错误 &#xff1a;*p c malloc 函数原型 void *malloc(size_t size) &#xff08;开辟的内容大小&#xff09; C库函数 void *malloc(size_t size)分配所需的内存空间&#xff0c;并返回一个指向它的指针。 作用&…

Java——数组练习

目录 一.数组转字符串 二.数组拷贝 三.求数组中元素的平均值 四.查找数组中指定元素(顺序查找) 五.查找数组中指定元素(二分查找) 六.数组排序(冒泡排序) 七.数组逆序 一.数组转字符串 代码示例&#xff1a; import java.util.Arrays int[] arr {1,2,3,4,5,6}; String…

数据分析——数据规范化

数据规范化是数据分析中的一个重要步骤&#xff0c;其目的在于确保数据的一致性和可比性&#xff0c;提高数据质量和分析结果的准确性。以下是一些数据规范化的常见方法和技术&#xff1a; 数据清洗&#xff1a;此步骤主要清除数据中的重复项、空格、格式错误等&#xff0c;确…

【二分与前缀和】python例题详解

文章目录 1、数的范围 2、数的三次方根 3、前缀和 4、子矩阵的和 5、机器人跳跃问题 1、数的范围 题目 给定一个按照升序排列的长度为 n 的整数数组&#xff0c;以及 q 个查询。对于每个查询&#xff0c;返回一个元素 k的起始位置和终止位置&#xff08;位置从 00 开始计…

批归一化(BN)在神经网络中的作用与原理

文章目录 1. 批归一化&#xff08;BN&#xff09;在神经网络中的作用与原理1.1 作用与优势1.2 原理与推导 2. 将BN应用于神经网络的方法2.1 训练时的BN 2. 将BN应用于神经网络的方法2.1 训练时的BN2.2 测试时的BN代码示例&#xff08;Python&#xff09;&#xff1a; 3. BN的优…

工厂方法模式(Factory Method Pattern)在JAVA中的应用

JAVA设计模式是一套被广泛认可的解决特定问题的最佳实践。在面向对象的软件设计中&#xff0c;设计模式可以帮助开发者构建可维护、可扩展和灵活的软件系统。本文将介绍工厂方法模式&#xff0c;这是一种创建型设计模式&#xff0c;它提供了一种创建对象的最佳方式。 ## 1. 工…

Day8:学习尚上优选项目

学习计划&#xff1a;完成尚硅谷的尚上优选项目 学习进度&#xff1a;尚上优选项目 知识点&#xff1a; 五、尚上优选微信小程序端 商品详情页 需求分析 页面效果功能分析对应接口 CompletableFuture异步编排 ⅰ. 问题引入并发、串行和并行CompletableFuture概述创建异步对象…

编程规范(保姆级教程)

文章目录 为什么需要编程规范&#xff1f;&#x1f4a1;代码检测工具 ESLint&#x1f4a1;代码格式化 Prettier&#x1f4a1;ESLint 与 Prettier 配合解决代码格式问题eslint支持ts约定式提交规范Commitizen助你规范化提交代码什么是 Git Hooks使用 husky commitlint 检查提交…

探索设计模式的魅力:MVVM模式在AI大模型领域的创新应用-打破传统,迎接智能未来

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 MVVM模式在AI大模型领域的创新应用-打破传统迎接智能未来 &#x1f680; “在人工智能的领域里&a…

算法训练营第37天|LeetCode 738.单调递增的数字 968.监控二叉树

LeetCode 738.单调递增的数字 题目链接&#xff1a; LeetCode 738.单调递增的数字 解题思路&#xff1a; 从后向前遍历&#xff0c;当不满足递增条件时&#xff0c;当前位置赋值为9&#xff0c;前一位减一。之后记录不满足位置&#xff0c;将后续全部赋值为9. 代码&#x…

【springboot】项目启动时打印全部接口方法

方法&#xff1a;在你springboot项目的基础上&#xff0c;创建下面的类&#xff1a; package com.llq.wahaha.listener;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework…

【Entity Framework】如何使用EF中的生成值

【Entity Framework】如何使用EF中的生成值 文章目录 【Entity Framework】如何使用EF中的生成值一、概述二、默认值三、计算列四、设置主键五、显示配置值生成六、设置日期/时间值生成6.1 创建时间戳6.2 更新时间戳 七、替代值生成八、无值生成九、总结 一、概述 数据库列的值…

DHCP抓包分析

DHCP动态路由配置协议&#xff0c;是C/S架构&#xff0c;由DHCP服务器为客户端动态分配IP信息。 DHCP客户端首次接入网络数据交互过程&#xff1a; 如何解决IP地址的冲突&#xff1a; ▫ DHCP服务器端&#xff1a;收到DHCP DISCOVER报文时&#xff0c;给客户端分配IP地址前会发…