OpenGL学习————纹理 Texture

纹理坐标 Texture Coordinate
采样 Sampling 使用纹理坐标获取纹理颜色
 
纹理环绕方式
获取纹理是0.0到1.0的范围取值,所以要有个取值纹理像素的方式
比如超出1.0时 1.1取哪个像素
环绕方式
描述
GL_REPEAT
对纹理的默认行为。重复纹理图像。
GL_MIRRORED_REPEAT
GL_REPEAT 一样,但每次重复图片是镜像放置的。
GL_CLAMP_TO_EDGE
纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果。
GL_CLAMP_TO_BORDER
超出的坐标为用户指定的边缘颜色。
 
OpenGL学习————纹理 Texture_第1张图片
 
纹理过滤 Texture Filtering 获取纹理像素的方式
纹理像素 Texture Pixel | Texel 纹理的像素,并不是屏幕分辨率像素
GL_NEAREST 临近过滤 获取绝对的当前纹理坐标上的像素颜色,如果图像放大会有像素感觉 性能较好
OpenGL学习————纹理 Texture_第2张图片
GL_LINERA 线性过滤 获取纹理坐标的附近颜色的插值,看起来过度更平滑,放大感觉是模糊的感觉 性能开销大,每次获取需要做插值计算
OpenGL学习————纹理 Texture_第3张图片
 
多级渐远纹理 Mipmap 同样的纹理,距离远的或者说被缩小显示的他的片元着色就会少,这时使用尺寸小的纹理就可以更真实的显示出效果,并且性能开销会小很多
再配合线性过滤方式,也会有模糊的感觉,正常距离大小显示时用nearest方式获取纹理像素,效果和效率也有保障
过滤方式
描述
GL_NEAREST_MIPMAP_NEAREST
使用最邻近的多级渐远纹理来匹配像素大小,并使用邻近插值进行纹理采样
GL_LINEAR_MIPMAP_NEAREST
使用最邻近的多级渐远纹理级别,并使用线性插值进行采样
GL_NEAREST_MIPMAP_LINEAR
在两个最匹配像素大小的多级渐远纹理之间进行线性插值,使用邻近插值进行采样
GL_LINEAR_MIPMAP_LINEAR
在两个邻近的多级渐远纹理之间使用线性插值,并使用线性插值进行采样

/纹理/

//如果窗口大小改变 回调函数
void framebuffer_size_callback(GLFWwindow* window, int width, int height);

void loadImage(unsigned int VAO);

void processInput(GLFWwindow* window, Shader ourShader);

float mixnum = 0.2f;
int main()
{
    glfwInit();//初始化 glfw
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//确定使用的版本号 major minor
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//确定使用的核心模式 core-profile
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT);  MAC平台使用的版本号
    stbi_set_flip_vertically_on_load(true);//颠倒Y 轴


    GLFWwindow* window = glfwCreateWindow(800, 600, "learnOpenGL", NULL, NULL);//生成一个窗口对象
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW windows" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);//设置当前主窗口对象

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))//初始化 GLAD
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    //glViewport(1,1,10,10);//告诉opengl  窗口的位置和大小 前俩参数是左下角 位置 后俩就是窗口宽高

    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);//注册窗口大小改变回调事件

    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    // 左上
        -0.5f,-0.5f,0.0f,  1.0f, 0.0f, 0.0f,  0.0f, 0.0f,  // 左下
        -0.5f,0.5f,0.0f,  0.0f, 1.0f, 0.0f,  0.0f,1.0f, // 顶部
        0.5f,-0.5f,0.0f,  0.0f, 0.0f, 1.0f,  1.0f,0.0f,  // 右下

        0.5f,-0.5f,0.0f, 1.0f, 0.0f, 0.0f,     1.0f,0.0f,  // 左下
        -0.5f,0.5f,0.0f,0.0f, 1.0f, 0.0f,     0.0f,1.0f, // 顶部
        0.5f,0.5f,0.0f,    0.0f, 0.0f, 1.0f,     1.0f,1.0f  // 右下
    };

    float texCoords[] = {
        0.0f,0.0f,//左下角
        1.0f,0.0f,//右下角
        0.5f,1.0f//上中
    };

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

    glGenBuffers(1, &VBO);//申请一个顶点缓冲区
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//把顶点缓冲区绑定到 array_buffer 缓冲区上
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把顶点数据复制到内存上

    int nrAttributes;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes);
    std::cout << "Maximum nr of vertex attirbutes supported : " << nrAttributes << std::endl;

    

    Shader ourShader("C:/Users/Hoolai/source/repos/OpenGl_1/OpenGl_1/shaders/vs.glsl", "C:/Users/Hoolai/source/repos/OpenGl_1/OpenGl_1/shaders/fs.glsl");

    //告诉opengl 该如何解析顶点数据
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    //告诉opengl 该如何解析顶点数据
    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);

    //loadImage(VAO);
    unsigned int texture1, texture2;
    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("C:/Users/Hoolai/source/repos/OpenGl_1/OpenGl_1/images/container.jpg", &width, &height, &nrChannels, 0);

    if (data)
    {
        /*参数1 渲染的目标鸟类型
        参数2 mipmap等级 0就是基础等级
        参数3 纹理的存储格式 RGB
        参数4 5 就是纹理的高度和宽度
        参数6 0 不要问为什么 就是这么任性
        参数7 原图的格式和数据类型, 储存到 char byte数组内 传入对应值
        参数8 图像数据传入*/
        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);

    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);


    // 为当前绑定的纹理对象设置环绕、过滤方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);    // set texture wrapping to GL_REPEAT (default wrapping method)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    // set texture filtering parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    data = stbi_load("C:/Users/Hoolai/source/repos/OpenGl_1/OpenGl_1/images/awesomeface.png", &width, &height, &nrChannels, 0);

    if (data)
    {
        /*参数1 渲染的目标鸟类型
        参数2 mipmap等级 0就是基础等级
        参数3 纹理的存储格式 RGB
        参数4 5 就是纹理的高度和宽度
        参数6 0 不要问为什么 就是这么任性
        参数7 原图的格式和数据类型, 储存到 char byte数组内 传入对应值
        参数8 图像数据传入*/
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }

    //使用完数据 释放下数据
    stbi_image_free(data);

    // render container
    ourShader.use();
    ourShader.setInt("texture1", 0);

    //glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);
    // or set it via the texture class
    ourShader.setInt("texture2", 1);
    ourShader.setInt("mixnum", mixnum);


    //做一个渲染循环,保证程序不直接退出 Renderer Loop
    while (!glfwWindowShouldClose(window))//每次循环检查下 GLFW是否需求要推出 返回True就会跳出循环 程序结束
    {
        processInput(window, ourShader);//每次循环检查下输入

        glClear(GL_COLOR_BUFFER_BIT);
        //ourShader.use();

        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);

        //glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0,6);//使用顶点数组渲染 第一个是渲染图形,第二 三个参数是 数组索引 开始和结束值

        glfwSwapBuffers(window);//GLFW的渲染函数 储存窗口的每个像素 输出到屏幕上
        glfwPollEvents();//检查函数有没有触发什么事件 键盘输入 鼠标点击等
    }

    glfwTerminate();//如果退出程序 清理下glfw的资源


    return 0;

}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);//感觉没有生效
}
bool up = false;
bool down = false;
void processInput(GLFWwindow *window, Shader ourShader)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)//是否按下 ESC建
    {
        glfwSetWindowShouldClose(window, true);//执行关闭窗口
    }
    if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS)
    {
        ourShader.setFloat("offset", 0.5f);
    }
    if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS)
    {
        ourShader.setFloat("offset", 0.0f);

        /*    glClearColor(0.4f, 0.6f, 0.1f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);*/
    }
    if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
    {
        up = true;
    }
    if (up&&glfwGetKey(window, GLFW_KEY_UP) == GLFW_RELEASE)
    {
        up = false;
        mixnum = mixnum + 0.1f;
        if (mixnum > 1.0f)
        {
            mixnum = 1.0f;
        }
        ourShader.setFloat("mixnum", mixnum);
        std::cout << "aaaaa  " << mixnum << std::endl;
    }
    if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
    {
        down = true;
    }
    if (down&&glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_RELEASE)
    {
        down = false;
        mixnum = mixnum - 0.1f;
        if (mixnum < 0.0f)
        {
            mixnum = 0.0f;
        }
        ourShader.setFloat("mixnum", mixnum);
        std::cout << "bbbbb  " << mixnum << std::endl;
        /*    glClearColor(0.4f, 0.6f, 0.1f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);*/
    }

你可能感兴趣的:(OpenGL学习笔记,opengl)