OpenGL 纹理学习总结

Posted --zz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL 纹理学习总结相关的知识,希望对你有一定的参考价值。

技术分享图片

 

这里总结下左右颠倒的方法:

就是更改片段着色器

FragColor = mix(texture(texture1,TexCoord), texture(texture2,vec2(1.0 - TexCoord.x, TexCoord.y)),0.78f);

这段代码的意思就是更改图片的纹理坐标

比如:

(0,0) -> (1,0)

(1,0) -> (0,0)

(0,1) -> (1,1)

(1,1) -> (0,1)

 

 

OpenGLDemo.cpp

// OpenGLDemo.cpp: 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <cstring>
#include "Shader.h"
#include <stb_image/stb_image.h>
#include<filesystem>

using namespace std;

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
char* readTheFile(string strSource);


int main()
{
    //glfw: 初始化
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
    
    //glfw: 窗口创建
    GLFWwindow* window = glfwCreateWindow(800, 600, "Oh!I see you!", NULL, NULL);
    if (window == NULL) {
        std::cout << "Failed to create the windows" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    glfwSwapInterval(1);

    //glad: 加载OpenGL 函数指针
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    
    Shader shader("vertexShaderSource.vert", "fragmentShaderSource.frag");

    float vertices[] = {
        //第一个三角形
    //  ----位置----   ----颜色----     --纹理坐标-
        -.5f,.5f,0.0f, 1.0f,0.0f,0.0f,  0.0f,1.0f,       //左上   
        -.5f,-.5f,.0f, 0.0f,1.0f,0.0f,  0.0f,0.0f,       //左下
         .5f,-.5f,.0f, 0.0f,0.0f,1.0f,  1.0f,0.0f,       //右下
         .5f, .5f,.0f, 0.0f,0.0f,1.0f,  1.0f,1.0f        //右上
    };

    unsigned int indices[] = {
        0,1,2,
        0,3,2
    };

    unsigned int VBO, VAO, 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);

    //texture 1
    //---------
    unsigned int texture1,texture2;
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    //// 为当前绑定的纹理对象设置环绕、过滤方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    float borderColor[] = { 1.0f,1.0f,0.0f,1.0f };
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
    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("container.jpg", &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);

    //texture 2
    //---------
    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    stbi_set_flip_vertically_on_load(true);
    data = stbi_load("LJW.png", &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);

    shader.use();
    shader.setInt("texture1", 0);
    shader.setInt("texture2", 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);

        shader.use();
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT
            , 0);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES,0,3);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();
    return 0;
}

void framebuffer_size_callback(GLFWwindow* windows, int width, int height) {
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow* window) {
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, true);
    }
}

//.frag .vert文件读取
char* readTheFile(string strSource) {
    //fstream 中判断是否成功打开文件
    //https://blog.csdn.net/fruitz/article/details/41624921
    std::ifstream myfile(strSource);
    //打开失败
    if (myfile.fail()) {
        std::cout << "Can not open it " << std::endl;
        throw new runtime_error("IO stream corrupted");
    }
    //转换成字符串
    std::string str((std::istreambuf_iterator<char>(myfile)),
        std::istreambuf_iterator<char>());
    //关闭文件处理器
    myfile.close();
    //str数组长度一定要 +1,
    /*原因: https://blog.csdn.net/ShiQW5696/article/details/80676290 */
    int len = str.length();
    char* result = new char[len];
    strcpy_s(result, len + 1, str.c_str());
    return result;
}

  

fragmentShaderSource.frag

#version 330 core
out vec4 FragColor;

in vec2 TexCoord;
in vec3 outColor;

uniform sampler2D texture1;
uniform sampler2D texture2;

void main()
{
    FragColor = mix(texture(texture1,TexCoord), texture(texture2,vec2(1.0 - TexCoord.x, TexCoord.y)),0.78f);
}

 

vertexShaderSource.vert

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

out vec3 outColor;
out vec2 TexCoord;

void main()
{
	gl_Position = vec4(aPos, 1.0);
	outColor = aColor;
	TexCoord = aTexCoord;
}

  

以上是关于OpenGL 纹理学习总结的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL、GLSL 片段着色器无法读取 Sampler2D 纹理

纹理中的 OpenGL 片段着色器

我的OpenGL学习进阶之旅关于OpenGL ES 绘制纹理,因为加载纹理坐标设置错误,导致纹理无法渲染的问题

我的OpenGL学习进阶之旅关于OpenGL ES 绘制纹理,因为加载纹理坐标设置错误,导致纹理无法渲染的问题

openGL 纹理05

片段着色器究竟如何用于纹理?