opengl日记10-opengl使用多个纹理示例


在这里插入图片描述

环境

  • 系统:ubuntu20.04
  • opengl版本:4.6
  • glfw版本:3.3
  • glad版本:4.6
  • cmake版本:3.16.3
  • gcc版本:10.3.0

在<opengl学习日记9-opengl使用纹理示例>的基础上,拓展使用多个纹理。

代码

CMakeLists.txt文件内容不变。

fragmentShaderSource.fs

#version 330 core
out 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) ;
}

vertexShaderSource.vs

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

out vec3 ourColor;
out vec2 TexCoord;

void main()
{
        gl_Position = vec4(aPos, 1.0);
        ourColor = aColor;
        TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

main.cpp

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include "stbimage.h"

//#include <glm/glm.hpp>
//#include <glm/gtc/matrix_transform.hpp>
//#include <glm/gtc/type_ptr.hpp>

#include <iostream>
#include <fstream>
#include <iosfwd>
#include <sstream>
#include <string>

//定义窗口大小
int SCR_WIDTH = 800;
int SCR_HEIGHT = 600;

std::string readFile(const std::string filename)
{
    std::string data;
    data = readFile(filename.c_str());
    return data;
}

std::string readFile(const char* filename)
{
    std::string data;
    std::ifstream infile;
    infile.open(filename);
    std::stringstream neirong;
    neirong << infile.rdbuf();
    infile.close();
    data = neirong.str();
    return data;
}

int main()
{
    std::cout << "Hello World!" << std::endl;

    std::cout << "初始化" << std::endl;
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "transformtions", NULL, NULL);
    if (window == NULL) {
        std::cout << "创建窗口失败" << std::endl;
        return -1;
    }

    glfwMakeContextCurrent(window);
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "初始化glad失败" << std::endl;
        return -1;
    }

    std::cout << "顶点定义,VAO,VBO,EBO" << std::endl;
    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};

    //索引缓冲区
    unsigned int indices[] = {0, 1, 3,
                              1, 2, 3};

    unsigned int VAO, VBO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    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);

    //定位点关系
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) 0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    std::cout << "着色器定义" << std::endl;
    std::cout << "着色器定义:顶点着色器" << std::endl;
    std::string vertexShaderSource = readFile("vertexShaderSource.vs");
    const char *vertexShaderSourceCtr = vertexShaderSource.c_str();
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSourceCtr, NULL);
    glCompileShader(vertexShader);

    int success;
    char infolog[512] = {0};
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, NULL, infolog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infolog << std::endl;
    }

    std::cout << "着色器定义:片段着色器" << std::endl;
    std::string fragmentShaderSource = readFile("fragmentShaderSource.fs");
    const char *fragmentShaderSourceCtr = fragmentShaderSource.c_str();
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSourceCtr, NULL);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infolog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infolog << std::endl;
    }

    std::cout << "着色器定义:启用着色器程序" << std::endl;
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infolog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infolog << std::endl;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);


    std::cout << "纹理定义" << std::endl;
    unsigned 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);

    stbi_set_flip_vertically_on_load(true);
    std::cout << "读取纹理图片" << std::endl;
    int width, height, nrChannels;
    unsigned char* texturesData = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
    if (texturesData) {
        //绑定和纹理图片数据结合
        glTexImage2D(GL_TEXTURE_2D,
            0,
            GL_RGB,
            width,
            height,
            0,
            GL_RGB,
            GL_UNSIGNED_BYTE,
            texturesData);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "读取图片数据错误" << std::endl;
    }
    stbi_image_free(texturesData);

    std::cout << "纹理定义2" << std::endl;
    unsigned 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);

    std::cout << "读取纹理图片" << std::endl;
    //        int width, height, nrChannels;
    texturesData = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
    if (texturesData) {
        //绑定和纹理图片数据结合
        glTexImage2D(GL_TEXTURE_2D,
            0,
            GL_RGBA,
            width,
            height,
            0,
            GL_RGBA,
            GL_UNSIGNED_BYTE,
            texturesData);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "读取图片数据错误" << std::endl;
    }
    stbi_image_free(texturesData);

    glUseProgram(shaderProgram);
    glUniform1i(glGetUniformLocation((GLuint)shaderProgram,"texture1"),0);
    glUniform1i(glGetUniformLocation((GLuint)shaderProgram,"texture2"),1);

    std::cout << "绘制" << std::endl;
    while (!glfwWindowShouldClose(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);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const GLvoid *) 0);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    std::cout << "内存释放" << std::endl;
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);
    glfwTerminate();

    return 0;
}

总结

  1. 使用多个纹理,则需要定义多个纹理,读取多个图片数据
std::cout << "纹理定义" << std::endl;
    unsigned 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);

    stbi_set_flip_vertically_on_load(true);
    std::cout << "读取纹理图片" << std::endl;
    int width, height, nrChannels;
    unsigned char* texturesData = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
    if (texturesData) {
        //绑定和纹理图片数据结合
        glTexImage2D(GL_TEXTURE_2D,
            0,
            GL_RGB,
            width,
            height,
            0,
            GL_RGB,
            GL_UNSIGNED_BYTE,
            texturesData);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "读取图片数据错误" << std::endl;
    }
    stbi_image_free(texturesData);

    std::cout << "纹理定义2" << std::endl;
    unsigned 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);

    std::cout << "读取纹理图片" << std::endl;
    //        int width, height, nrChannels;
    texturesData = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
    if (texturesData) {
        //绑定和纹理图片数据结合
        glTexImage2D(GL_TEXTURE_2D,
            0,
            GL_RGBA,
            width,
            height,
            0,
            GL_RGBA,
            GL_UNSIGNED_BYTE,
            texturesData);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "读取图片数据错误" << std::endl;
    }
    stbi_image_free(texturesData);
  1. 一张图片纹理叠加在另一张图片纹理上,需要有透明通道,图片格式是png,所以在绑定png纹理图片是需要注意参数变化
glTexImage2D(GL_TEXTURE_2D,
            0,
            GL_RGBA,
            width,
            height,
            0,
            GL_RGBA,
            GL_UNSIGNED_BYTE,
            texturesData);

注意第三个参数和第七个参数,由GL_RGB变为GL_RGBA
3. 在绘制之前需要手动设置一次纹理对应的采样器

glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation((GLuint)shaderProgram,"texture1"),0);
glUniform1i(glGetUniformLocation((GLuint)shaderProgram,"texture2"),1);

这里需要注意,glUniform1i函数的书写是数字1,不是字母l
4. 在读取纹理之前,设置一下,可保持加载图像不上下颠倒

stbi_set_flip_vertically_on_load(true);

相关推荐

  1. 使用OpenGLopengl ES 渲染YUV图片文件的QT示例

    2024-03-21 09:14:05       58 阅读
  2. OpenGL着色器实现纹理合并显示

    2024-03-21 09:14:05       30 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-21 09:14:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-21 09:14:05       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-21 09:14:05       82 阅读
  4. Python语言-面向对象

    2024-03-21 09:14:05       91 阅读

热门阅读

  1. 汽车信息安全--密钥管理系统初探(1)

    2024-03-21 09:14:05       38 阅读
  2. HTML:浏览器CSS样式前缀

    2024-03-21 09:14:05       43 阅读
  3. vue html里面使用全局引入的scss变量

    2024-03-21 09:14:05       43 阅读
  4. 批量更新或者新增

    2024-03-21 09:14:05       43 阅读
  5. html面试题

    2024-03-21 09:14:05       41 阅读
  6. HTML世界之标签Ⅴ

    2024-03-21 09:14:05       38 阅读
  7. 利用opencv获取系统时间

    2024-03-21 09:14:05       46 阅读