LearnOpenGL - 纹理贴图 源代码
生活随笔
收集整理的這篇文章主要介紹了
LearnOpenGL - 纹理贴图 源代码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? 為了方便使用與代碼觀看,將Shader抽出來作為一個單獨的Shader類,叫ShaderTex。其次,將vs與fs的代碼寫成單獨的shader文件。
Shader類:將Shader構建代碼抽出,文件名 shader_textures.h
#ifndef _SHADER_TEXTURES_H_ #define _SHADER_TEXTURES_H_ //紋理器#include <glad/glad.h> #include <string> #include <fstream> #include <sstream> #include <iostream>class ShaderTex { public:unsigned int ID; //程序id 即前文代碼中的shaderProgramShaderTex(const GLchar* vertexPath, const GLchar* fragmentPath){std::string vertexCode;std::string fragmentCode;std::ifstream vShaderFile;std::ifstream fShaderFile;//保證可以拋出異常vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);try{vShaderFile.open(vertexPath);fShaderFile.open(fragmentPath);std::stringstream vShaderStream, fShaderStream;//讀取文件vShaderStream << vShaderFile.rdbuf();fShaderStream << fShaderFile.rdbuf();//關閉文件處理器vShaderFile.close();fShaderFile.close();//轉換數據到stringvertexCode = vShaderStream.str();fragmentCode = fShaderStream.str();}catch (std::ifstream::failure e){std::cout << "error: shader file read failed " << std::endl;return;}const char* vShaderCode = vertexCode.c_str();const char* fShaderCode = fragmentCode.c_str();int vertexShader = glCreateShader(GL_VERTEX_SHADER); //創建vsglShaderSource(vertexShader, 1, &vShaderCode, NULL); //shader源碼附加到shader身上glCompileShader(vertexShader); //編譯int success;glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); //獲得編譯結果if (!success){char infoLog[512];glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);std::cout << "error: vertexshader compilation failed " << infoLog << std::endl;return;}int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //創建fsglShaderSource(fragmentShader, 1, &fShaderCode, NULL);glCompileShader(fragmentShader);glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success){char infoLog[512];glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;return;}ID = glCreateProgram(); //創建程序對象glAttachShader(ID, vertexShader); //shader附加到程序對象glAttachShader(ID, fragmentShader); //shader附加到程序對象glLinkProgram(ID); //鏈接他們glGetProgramiv(ID, GL_LINK_STATUS, &success); //獲得鏈接結果if (!success){char infoLog[512];glGetProgramInfoLog(ID, 512, NULL, infoLog);std::cout << "error: programshader link failed " << infoLog << std::endl;return;}glDeleteShader(vertexShader); //附加完畢,已經沒用了glDeleteShader(fragmentShader);}void use(){glUseProgram(ID);}void setBool(const std::string& name, bool value) const{glUniform1i(glGetUniformLocation(ID, name.c_str()), int(value));}void setInt(const std::string& name, int value) const{glUniform1i(glGetUniformLocation(ID, name.c_str()), value);}void setFloat(const std::string& name, float value) const{glUniform1f(glGetUniformLocation(ID, name.c_str()), value);} };#endifshader代碼:文件名,shader_textures.fs 、shader_textures.vs
#version 330 coreout vec4 FragColor;in vec3 ourColor; in vec2 TexCoord;uniform sampler2D ourTexture;void main() {FragColor = texture(ourTexture, TexCoord); } #version 330 corelayout(location = 0) in vec3 pos; layout(location = 1) in vec3 color; layout(location = 2) in vec2 texcoord;out vec3 ourColor; out vec2 TexCoord;void main() {gl_Position = vec4(pos, 1.0);ourColor = color;TexCoord = texcoord; }使用文件:
#include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> #include "shader.h" #include "shader_textures.h" #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h"void processInput(GLFWwindow* window); void framebuffer_size_callback(GLFWwindow* window, int width, int height); int main() {glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);if (!window){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return 0;}glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to init GLAD" << std::endl;return 0;}ShaderTex ourShader("shader_textures.vs", "shader_textures.fs");//前三個數表示坐標,后三個數表示顏色,最后是紋理坐標float vertices[] = {-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};int indices[] = {0,1,2,0,3,2};unsigned int VBO, VAO, EBO;glGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glGenVertexArrays(1, &VAO);glBindVertexArray(VAO);glGenBuffers(1, &EBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//位置屬性0的繼續配置 讀取三個,步長6*float,偏移0glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);//位置屬性1的 讀取三個,步長6*float,偏移3*float 位置屬性的含義對應 vShader中的locationglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);//位置屬性2的 讀取兩個glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float)));glEnableVertexAttribArray(2);stbi_set_flip_vertically_on_load(true); //翻轉y軸//texture 1unsigned int texture;glGenTextures(1, &texture);glBindTexture(GL_TEXTURE_2D, texture);//為綁定的紋理對象設置環繞、過濾方式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_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);int width, height, nrChannels;unsigned char* data = stbi_load("aaa.jpg", &width, &height, &nrChannels, 0);if (!data) {std::cout << "error: stbi_load failed" << std::endl;return 0;}//教程里這里都用的GL_RGB 我用的圖片需要使用GL_RGBA,否則最后渲染很奇怪glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);//釋放內存stbi_image_free(data);while (!glfwWindowShouldClose(window)){processInput(window); //輸入glClearColor(0.2f, 0.3f, 0.4f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glActiveTexture(GL_TEXTURE0); //激活紋理單元glBindTexture(GL_TEXTURE_2D, texture); //綁定ourShader.use();glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);glfwSwapBuffers(window); //雙緩沖BufferglfwPollEvents(); //檢查事件觸發 是否結束渲染}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glfwTerminate();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); }結果圖:
?
將顏色與最終背景圖融合,只需要改動shader_textures.fs文件,增加vec4的顏色輸出,如下:
#version 330 coreout vec4 FragColor;in vec3 ourColor; in vec2 TexCoord;uniform sampler2D ourTexture;void main() {FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 1.0f); }最終效果圖:
?
組合兩張貼圖,修改shader_textures.fs代碼如下:
#version 330 coreout vec4 FragColor;in vec3 ourColor; in vec2 TexCoord;uniform sampler2D texture1; uniform sampler2D texture2;void main() {FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2) *vec4(ourColor, 1.0f); }修改主程序:
#include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> #include "shader.h" #include "shader_textures.h" #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h"void processInput(GLFWwindow* window); void framebuffer_size_callback(GLFWwindow* window, int width, int height); int main() {glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);if (!window){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return 0;}glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to init GLAD" << std::endl;return 0;}ShaderTex ourShader("shader_textures.vs", "shader_textures.fs");//前三個數表示坐標,后三個數表示顏色,最后是紋理坐標float vertices[] = {0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f};int indices[] = {0,1,3,1,2,3};unsigned int VBO, VAO, EBO;glGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glGenVertexArrays(1, &VAO);glBindVertexArray(VAO);glGenBuffers(1, &EBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//位置屬性0的繼續配置 讀取三個,步長6*float,偏移0glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);//位置屬性1的 讀取三個,步長6*float,偏移3*float 位置屬性的含義對應 vShader中的locationglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);//位置屬性2的 讀取兩個glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float)));glEnableVertexAttribArray(2);stbi_set_flip_vertically_on_load(true); //翻轉y軸//texture 1unsigned int texture1;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;unsigned char* data = stbi_load("aaa.jpg", &width, &height, &nrChannels, 0);if (!data) {std::cout << "error: stbi_load failed" << std::endl;return 0;}else{//教程里這里都用的GL_RGB 我用的圖片需要使用GL_RGBA,否則最后渲染很奇怪glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);}//釋放內存stbi_image_free(data);//texture 2unsigned int texture2;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);data = stbi_load("bbb.png", &width, &height, &nrChannels, 0);if (!data){std::cout << "error: stbi_load failed111" << std::endl;return 0;}else{glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);}//釋放內存stbi_image_free(data);ourShader.use();glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);ourShader.setInt("texture2", 1);while (!glfwWindowShouldClose(window)){processInput(window); //輸入glClearColor(0.2f, 0.3f, 0.4f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glActiveTexture(GL_TEXTURE0); //激活紋理單元glBindTexture(GL_TEXTURE_2D, texture1); //綁定glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);ourShader.use();glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);glfwSwapBuffers(window); //雙緩沖BufferglfwPollEvents(); //檢查事件觸發 是否結束渲染}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glfwTerminate();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); }最終效果如下:
總結
以上是生活随笔為你收集整理的LearnOpenGL - 纹理贴图 源代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用SHELLEXECUTEINFO 和
- 下一篇: FPGA 20个例程篇:7.FLASH读