其他分享
首页 > 其他分享> > OpenGL贴图、小图片叠加(10)

OpenGL贴图、小图片叠加(10)

作者:互联网

基于前边两篇博文:OpenGL多层纹理叠加_部分区域(九-2) - 邗影 - 博客园 (cnblogs.com)

OpenGL多层纹理叠加MIX(九-1) - 邗影 - 博客园 (cnblogs.com)

本篇文章效果类似,也是一个贴图,但是是一个完整小图贴到一张大图上;我们经常看视频的时候会有logo贴图的那种效果;或者像看电视,角落上有电视台小图;但是目前本博客的程序还做不到透明贴图(如图,彩虹中的透明部分是黑色的,而不是透明的)

 

 

 

 本博客仅展示个人实现效果(不代表真实原理、机制);通过使用多个VBO进行实现;

  1 #include "stdafx.h"
  2 #include<windows.h>
  3 #include <glad/glad.h>
  4 #include <GLFW/glfw3.h>
  5 #define STB_IMAGE_IMPLEMENTATION
  6 #include <stb_image.h>
  7 #include<string>
  8 #include<fstream>
  9 #include<sstream>
 10 #include<iostream>
 11 
 12 #include <stdio.h>
 13 
 14 // settings
 15 const unsigned int SCR_WIDTH = 800;
 16 const unsigned int SCR_HEIGHT = 600;
 17 unsigned int VBO = 0;
 18 unsigned int VBO2 = 0;
 19 unsigned int VAO = 0;
 20 unsigned int VAO2 = 0;
 21 unsigned int EBO = 0;
 22 unsigned int texturePIC = 0;
 23 unsigned int texturePIC2 = 0;
 24 int shaderProgram = 0;
 25 GLuint texId_bottom = 99;
 26 GLuint texId_top = 99;
 27 
 28 //本地文件夹下有个图片加载到项目上(注意参数列表中的引用表示变量本身,不要用变量的副本)
 29 void LoadPicture(unsigned int& textureIndex,unsigned int& textureIndex2)
 30 {
 31     //返回不同采样器的序号
 32     glUseProgram(shaderProgram);
 33     texId_bottom = glGetUniformLocation(shaderProgram, " ourTextureB");
 34     texId_top = glGetUniformLocation(shaderProgram, "ourTextureT");
 35 
 36     glGenTextures(1, &textureIndex);
 37     glActiveTexture(GL_TEXTURE0);
 38     glBindTexture(GL_TEXTURE_2D, textureIndex);
 39     
 40     //为bind的纹理设置环绕,过滤方式
 41     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 42     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 43     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 44     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 45 
 46     //加载图片生成纹理 :
 47     stbi_set_flip_vertically_on_load(true);
 48     //stbi是一个图片载入的开源组件,文件名,宽高,通道数,你期望的通道数(使用的是宽大于高的图片,如果是高>宽,程序需要改否则渲染异常)
 49     int W, H, channels_in_file, desired_channels = 3;
 50     unsigned char* data = stbi_load("./F.jpg ", &W, &H, &channels_in_file, desired_channels);
 51     if (channels_in_file == 3)
 52     {
 53         //数据生成纹理;根据指定的参数,把输入数据生成一张2D纹理
 54         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, W, H, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
 55         glUniform1i(texId_bottom,0);
 56         //生成mipmap数组
 57         glGenerateMipmap(GL_TEXTURE_2D);
 58     }
 59     stbi_image_free(data);
 60     data = nullptr;
 61 
 62     //加载图片2
 63     glGenTextures(1, &textureIndex2);
 64 
 65     glActiveTexture(GL_TEXTURE1);
 66     glBindTexture(GL_TEXTURE_2D, textureIndex2);
 67     //为bind的纹理设置环绕,过滤方式
 68     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 69     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 70     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 71     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 72     //加载图片生成纹理 :
 73     stbi_set_flip_vertically_on_load(true);
 74     //stbi是一个图片载入的开源组件,文件名,宽高,通道数,你期望的通道数
 75     int W2, H2, channels_in_file2, desired_channels2 = 3;
 76     unsigned char* data2 = stbi_load("./lyf.jpg", &W2, &H2, &channels_in_file2, desired_channels2);
 77     if (channels_in_file2 == 3)
 78     {
 79         //数据生成纹理;根据指定的参数,把输入数据生成一张2D纹理
 80         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, W2, H2, 0, GL_RGB, GL_UNSIGNED_BYTE, data2);
 81         glUniform1i(texId_top, 1);
 82         //生成mipmap数组
 83         glGenerateMipmap(GL_TEXTURE_2D);
 84     }
 85     stbi_image_free(data2);
 86     data2 = nullptr;
 87 
 88     glUseProgram(0);
 89 }
 90 
 91 
 92 void render()
 93 {
 94     
 95     glBindVertexArray(VAO);
 96     glUseProgram(shaderProgram);
 97     glUniform1i(glGetUniformLocation(shaderProgram, "mixValue"), 1);//要先启用着色器程序咋,再指定变量的值
 98     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
 99     glUseProgram(0);
100     glBindVertexArray(0);
101 
102     //不同的图片要画两次
103     
104     glBindVertexArray(VAO2);
105     glUseProgram(shaderProgram);
106     glUniform1i(glGetUniformLocation(shaderProgram, "mixValue"), 2);//为了给片元着色器区分采样
107     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
108     glUseProgram(0);
109     glBindVertexArray(0);
110 }
111 
112 void initmodule()
113 {
114     //做个一模型;正方形;映射了顶点坐标和纹理坐标的对应关系
115     float vertexs[] = {
116         //顶点坐标-------纹理坐标
117         1.0f,  1.0f, 0.0f,  1.0f, 1.0f,   // 右上
118         1.0f, -1.0f, 0.0f,  1.0f, 0.0f,   // 右下
119         -1.0f, -1.0f, 0.0f,  0.0f, 0.0f,   // 左下
120         -1.0f,  1.0f, 0.0f,  0.0f, 1.0f    // 左上
121 
122 
123     };
124 
125     float vertexs2[] = {
126         //顶点坐标-------纹理坐标
127         0.9f,  1.0f, 0.0f,  1.0f, 1.0f,   // 右上
128         0.9f, 0.5f, 0.0f,   1.0f, 0.0f,   // 右下
129         -0.1f, 0.5f, 0.0f,  0.0f, 0.0f,   // 左下
130         -0.1f,  1.0f, 0.0f,  0.0f, 1.0f    // 左上
131 
132 
133     };
134 
135 
136 
137     //一个正方形是由两个三角形得来的;记录顶点的索引顺序
138     unsigned int indexs[] = {
139         0,1,3,
140         1,2,3,
141     };
142 
143     
144     //加载纹理图片,生成纹理
145     LoadPicture(texturePIC, texturePIC2);
146 
147     //做VAO
148     glGenVertexArrays(1, &VAO);
149     glBindVertexArray(VAO);
150 
151     //做VBO
152 
153     glGenBuffers(1, &VBO);
154     glBindBuffer(GL_ARRAY_BUFFER, VBO);
155     //创建显存空间
156     glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);
157 
158     glGenBuffers(1, &EBO);
159     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
160     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexs), indexs, GL_STATIC_DRAW);
161 
162 
163     //设置第0个锚点,3个点,不需要归一化,跨度5个float可以读下一个点
164     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
165     //打开顶点
166     glEnableVertexAttribArray(0);
167     //纹理属性设置,纹理在第一个锚点上(指定顶点数据)你在顶点着色器程序中制定了锚点1的位置对应的是纹理坐标
168     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
169     //打开纹理
170     glEnableVertexAttribArray(1);
171 
172     //解除绑定VBO
173     glBindBuffer(GL_ARRAY_BUFFER, 0);
174 
175     //解绑VAO
176     glBindVertexArray(0);
177 
178 
179     //叠图的VAO,VBO,EBO--------------注意不能用同一个VAO(VBO),
180     //对每个VAO可以使用同样的EBO,但是一定要在每个VAO下都写一次EBO以及glVertexAttribPointer
181     glGenVertexArrays(1, &VAO2);
182     glBindVertexArray(VAO2);
183 
184     glGenBuffers(1, &VBO2);
185     glBindBuffer(GL_ARRAY_BUFFER, VBO2);
186     //创建显存空间
187     glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs2), vertexs2, GL_STATIC_DRAW);
188 
189 
190     //设置索引缓冲
191     glGenBuffers(1, &EBO);
192     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
193     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexs), indexs, GL_STATIC_DRAW);
194     
195     //绑定纹理,OpenGL至少保证有16个纹理单元供你使用,也就是说你可以激活从GL_TEXTURE0到GL_TEXTRUE15
196     
197     //设置第0个锚点,3个点,不需要归一化,跨度5个float可以读下一个点
198     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
199     //打开顶点
200     glEnableVertexAttribArray(0);
201     //纹理属性设置,纹理在第一个锚点上(指定顶点数据)你在顶点着色器程序中制定了锚点1的位置对应的是纹理坐标
202     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
203     //打开纹理
204     glEnableVertexAttribArray(1);
205 
206     //解除绑定VBO
207     glBindBuffer(GL_ARRAY_BUFFER, 0);
208 
209     //解绑VAO
210     glBindVertexArray(0);
211 
212 }
213 
214 void initshader(const char* verpath, const char* fragpath)
215 {
216     //编译shader,并记录shaderID
217     std::string VerCode("");
218     std::string fregCode("");
219     //读文件
220     std::ifstream  vShaderFile;
221     std::ifstream  fShaderFile;
222 
223     vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
224     fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
225 
226     try
227     {
228         vShaderFile.open(verpath);
229         fShaderFile.open(fragpath);
230 
231         std::stringstream vsstream, fsstream;
232         vsstream << vShaderFile.rdbuf();
233         fsstream << fShaderFile.rdbuf();
234         VerCode = vsstream.str();
235         fregCode = fsstream.str();
236 
237     }
238     catch (const std::exception&)
239     {
240         std::cout << "read file error" << std::endl;
241     }
242 
243     const char* vshader = VerCode.c_str();
244     const char* fshader = fregCode.c_str();
245 
246     //shader 编译连接
247     unsigned int vertexID = 0, fragID = 0;
248     char infoLog[512];//存储错误信息
249     int  successflag = 0;
250     vertexID = glCreateShader(GL_VERTEX_SHADER);
251     glShaderSource(vertexID, 1, &vshader, NULL);
252     glCompileShader(vertexID);
253     //获取编译是否成功
254     glGetShaderiv(vertexID, GL_COMPILE_STATUS, &successflag);
255     if (!successflag)
256     {
257         glGetShaderInfoLog(vertexID, 512, NULL, infoLog);
258         std::string errstr(infoLog);
259         std::cout << "v shader err" << infoLog;
260     }
261     //frag
262     fragID = glCreateShader(GL_FRAGMENT_SHADER);
263     glShaderSource(fragID, 1, &fshader, NULL);
264     glCompileShader(fragID);
265     //获取编译是否成功
266     glGetShaderiv(fragID, GL_COMPILE_STATUS, &successflag);
267     if (!successflag)
268     {
269         glGetShaderInfoLog(fragID, 512, NULL, infoLog);
270         std::string errstr(infoLog);
271         std::cout << "f shader err" << infoLog;
272     }
273     //链接
274     shaderProgram = glCreateProgram();
275     glAttachShader(shaderProgram, vertexID);
276     glAttachShader(shaderProgram, fragID);
277     glLinkProgram(shaderProgram);
278     glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successflag);
279     if (!successflag)
280     {
281         glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
282         std::string errstr(infoLog);
283         std::cout << "link error";
284     }
285 
286     //编译完成后,可以把中间的步骤程序删除
287     glDeleteShader(vertexID);
288     glDeleteShader(fragID);
289 }
290 void processInput(GLFWwindow *window)
291 {
292     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
293     {
294         //将窗口设置为关闭,跳出循环
295         glfwSetWindowShouldClose(window, true);
296     }
297 }
298 
299 void framebuffer_size_callback(GLFWwindow* window, int width, int height)
300 {
301     glViewport(0, 0, width, height);
302 }
303 
304 int main()
305 {
306     //glfw初始化
307     glfwInit();
308     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
309     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
310     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
311 
312     //glfw创建窗口
313     GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
314     if (window == NULL)
315     {
316         printf("创建窗口失败");
317         //终止
318         glfwTerminate();
319         return -1;
320     }
321     //显示窗口
322     glfwMakeContextCurrent(window);
323 
324     //设置回调,当窗口大小调整后将调用该回调函数
325     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
326 
327     // glad初始化
328     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
329     {
330         printf("加载失败");
331         return -1;
332     }
333     
334     initshader("vertexShader.glsl", "fragmentShader.glsl");
335     initmodule();
336     // 使用循环达到循环渲染效果
337     while (!glfwWindowShouldClose(window))
338     {
339         //自定义输入事件
340         processInput(window);
341         glEnable(GL_BLEND);
342         glClearColor(0.5f, 0.5f, 0.3f, 1.0f);
343         glClear(GL_COLOR_BUFFER_BIT);
344         render();
345         //交互缓冲区,否则显示空白
346         glfwSwapBuffers(window);
347         //输入输出事件,否则无法对窗口进行交互
348         glfwPollEvents();
349     }
350 
351     //终止渲染 关闭并清理glfw本地资源
352     glfwTerminate();
353     return 0;
354 }

片元着色器:

#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
float alpha;

uniform int mixValue;
uniform sampler2D ourTextureB;
uniform sampler2D ourTextureT;
void main()
{
  
    if(mixValue == 1)
    {
        FragColor = texture(ourTextureB, TexCoord);
    }else{
      FragColor = texture(ourTextureT, TexCoord);
    }
   

};

顶点着色器:

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 texCoord; 

out vec2 TexCoord;
void main()
{
   gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);
   TexCoord = texCoord;
};

效果展示:

 

标签:贴图,10,1.0,OpenGL,0.0,TEXTURE,纹理,2D,GL
来源: https://www.cnblogs.com/8335IT/p/16414875.html