zoukankan      html  css  js  c++  java
  • 纹理,这次没用Shader头文件,但是没有报“超出内存”的错误,不知道为什么

      1 #include <iostream>
      2 using namespace std;
      3 //using std::cout;    using std::cin;    using std::endl;
      4 
      5 #define GLEW_STATIC
      6 #include <GL/glew.h>
      7 #include <GLFW/glfw3.h>
      8 
      9 //#define STB_IMAGE_STATIC
     10 //#define STR_IMAGE_IMPLEMENTATION
     11 #include "stb_image.h"
     12 
     13 //#include "stb_image.h"
     14 
     15 void framebuffer_size_callback(GLFWwindow* window, int width, int height);
     16 void processInput(GLFWwindow* window);
     17 
     18 //着色器源码
     19 //明确表示我们使用核心模式,使用in关键字,在顶点着色器中声明所有的输入顶点属性
     20 //由于每个顶点都有一个3D坐标,我们就创建一个vec3输入变量aPos;
     21 //用layout(location = 0)设定了输入变量的位置值
     22 const char *vertexShaderSource = "#version 330 core
    "
     23 "layout (location = 0) in vec3 aPos;
    "
     24 "layout (location = 1) in vec3 aColor;
    "
     25 "layout (location = 2) in vec2 aTexCoord;
    "
     26 
     27 "out vec3 ourColor;
    "
     28 "out vec2 TexCoord;
    "
     29 
     30 "void main()
    "
     31 "{
    "
     32 //aPos.w用在所谓的透视除法上
     33 //我们将gl_Postion设置的值会成为该顶点着色器的输出,由于我们的输入是一个3分量的向量,我们必须把它转换成4分量的
     34 "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    "
     35 "    ourColor = aColor;
    "
     36 "    TexCoord = aTexCoord
    ;"
     37 "}
    ";
     38 
     39 //片段着色器源码
     40 const char* fragmentShaderSource = "#version 330 core
    "
     41 "out vec4 FragColor;
    "
     42 "in vec3 ourColor;
    "
     43 "in vec2 TexCoord;
    "
     44 
     45 //"uniform sampler2D ourTexture;
    "    //采样器
     46 "uniform sampler2D texture1;
    "
     47 "uniform sampler2D texture2;
    "
     48 "void main()
    "
     49 "{
    "
     50 //最终输出的颜色是两个纹理的结合
     51 //"   FragColor = texture(ourTexture, TexCoord);
    "
     52 "     FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.7);
    "
     53 "}
    ";
     54 
     55 
     56 int main()
     57 {
     58     glfwInit();    //初始化glfw                        
     59     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);    //配置glfw,主版本号
     60     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);    //次版本号
     61     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);    //核心模式
     62     GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpengl", NULL, NULL);    //创建glfw窗口
     63     if (window == NULL)
     64     {
     65         cout << "Fail to create window!
    " << endl;
     66         glfwTerminate();
     67         return -1;
     68     }
     69 
     70     //设置当前窗口的上下文
     71     glfwMakeContextCurrent(window);            //context环境、上下文
     72 
     73     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);        //每次改变窗口大小时都调用这个函数
     74 
     75     glewExperimental = GL_TRUE;        //使得glew在管理opengl函数指针时更多使用现代化技术
     76 
     77     if (glewInit() != GLEW_OK)
     78     {
     79         cout << "Fail to initialize GLEW" << endl;
     80         return -1;
     81     }
     82 
     83     //顶点着色器对象
     84     unsigned int vertexShader;    //用id来引导创建一个着色器对象
     85     vertexShader = glCreateShader(GL_VERTEX_SHADER);    //我们把需要创建的的着色器类型以参数形式提供给glCreateShader
     86 
     87                                                         //把这个着色器源码附加到着色器对象上
     88                                                         //glShaderSource函数吧需要编译的着色器对象作为第一个参数,第二个参数指定了传递的源码字符串数量,这里只有一个
     89                                                         //第三个参数是顶点着色器真正的源码,第四个参数我们先设置为NULL
     90     glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
     91 
     92     //编译这个着色器源码
     93     glCompileShader(vertexShader);
     94 
     95     int success;        //定义一个整型变量来表示是否成功编译
     96     char infoLog[512];    //定义一个储存错误消息的容器
     97                         //用glGetShaderiv检查是否编译成功
     98     glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
     99 
    100 
    101     if (!success)    //如果编译失败,用glGetShaderInfoLog获取错误消息,然后打印它
    102     {
    103         glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
    104         cout << "ERROR R::SHADER::VERTEX::COMPILATION_FAILED
    " << infoLog << endl;
    105     }
    106 
    107     //片段着色器对象
    108     unsigned int fragmentShader;        //定义一个片段着色器对象
    109     fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);    //给对象赋予GL_FRAGMENT_SHADER类型
    110     glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);    //将片段着色器的源码绑定到对象上
    111     glCompileShader(fragmentShader);        //编译该对象
    112     glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);        //检查是否编译成功
    113 
    114     if (!success)
    115     {
    116         glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);            //若不成功,获取错误信息,存入infoLog
    117         cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
    " << infoLog << endl;
    118     }
    119 
    120     //着色器对象
    121     unsigned int shaderProgram;        //定义一个用来链接的着色器程序中
    122     shaderProgram = glCreateProgram();    //给对象赋一个实体
    123 
    124     glAttachShader(shaderProgram, vertexShader);    //将Vertex附加到程序对象上
    125     glAttachShader(shaderProgram, fragmentShader);    //将fragment着色器附加到程序对象上
    126     glLinkProgram(shaderProgram);        //用glLinkProgram来连接他们
    127 
    128     glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);    //检查是否链接成功
    129     if (!success)
    130     {
    131         glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);    //若不成功,获取错误信息,存入infoLog
    132         cout << "ERROR::PROGRAM::SHADER::LINK_FAILED
    " << infoLog << endl;
    133     }
    134 
    135     glDeleteShader(vertexShader);    //删除顶点着色器对象,我们不再需要他了
    136     glDeleteShader(fragmentShader);        //删除片段着色器对象,我们也不再需要他了
    137 
    138 
    139     GLfloat vertices[] = {            //输入3个顶点坐标
    140         0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
    141         0.5f, -0.5f, 0.0f,0.0f, 1.0f, 0.0f, 1.0f, 0.0f,        //位置,颜色,纹理坐标
    142         -0.5f, -0.5f, 0.0f,0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    143         -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f
    144         
    145     };
    146 
    147     
    148     unsigned int indices[] = {    //主义索引从0开始
    149         0, 1, 3,    //第一个三角形
    150         1, 2, 3        //第二个三角形
    151     };
    152 
    153     unsigned int VBO, VAO, EBO;        //定义一个顶点缓冲变量
    154     glGenVertexArrays(1, &VAO);        //创建一个VAO对象
    155     glGenBuffers(1, &VBO);    //利用该函数和一个缓冲id生成一个VBO对象
    156     glGenBuffers(1, &EBO);    //创建一个EBO对象
    157 
    158     glBindVertexArray(VAO);    //绑定VAO
    159     glBindBuffer(GL_ARRAY_BUFFER, VBO);    //顶点缓冲对象的缓冲类型为GL_ARRAY_BUFFER, 把新创建的缓冲绑定到GL_ARRAY_BUFFER上
    160     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);    //索引缓冲对象的缓冲类型为GL_ELEMENT_ARRAY_BUFFER, 把新创建的缓冲绑定到GL_ELEMENT_ARRAY_BUFFER上
    161 
    162     //glBufferData是一个专门用来把用户定义的数据复制到当前绑定缓冲的的函数
    163     //它的第一个参数是目标缓冲类型,顶点缓冲对象当前绑定到GL_ARRAY_BUFFER上
    164     //第二个参数指定传输数据的大小,用sizeof函数计算
    165     //第三个参数是我们希望发送的实际数据
    166     //第四个参数指定了我们希望显卡如何管理给定的数据:GL_STATIC_DRAW / GL_DYNAMIC_DRAW / GL_STREAM_DRAW
    167     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    168     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//将EBO对象复制到缓冲区
    169 
    170     //链接顶点属性
    171     //第一个参数表示顶点位置其实位置值,第二个表示每个顶点的维度,第三个参数表示每个数据的数据类型
    172     //第四个参数表示是否希望数据被成标准化,如果是GL_TRUE的话,有符号被映射到(-1, 1),无符号映射到(0, 1)
    173     //第五个参数表示一个顶点(所有维度相加)的数据大小,也称为连续顶点属性组之间的间隔,步长
    174     //第6个参数表示位置数据在缓冲中起始位置的偏移量(offset),由于位置数据再数组的开头,所以这里是0
    175     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);//顶点位置属性
    176     glEnableVertexAttribArray(0);        //启用顶点位置属性,顶点属性默认是禁用的
    177 
    178 
    179     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));//顶点颜色属性
    180     glEnableVertexAttribArray(1);    //启用顶点颜色属性
    181 
    182     glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));    //纹理属性
    183     glEnableVertexAttribArray(2);    //启用纹理属性
    184 
    185     unsigned int texture1, texture2;
    186 
    187     //创建一个纹理对象,第一个参数是生成纹理的数量,然后把它们存储在第二个参数的unsigned in数组中(我们的例子只是一个单独的unsigned int)
    188     glGenTextures(1, &texture1);
    189     //glGenTextures(1, &texture2);
    190 
    191     //glActiveTexture(GL_TEXTURE0);    //在绑定纹理之前先激活纹理单元
    192     glBindTexture(GL_TEXTURE_2D, texture1); //绑定该纹理对象,让之后任何的纹理指令都可以配置当前绑定的纹理
    193     //glActiveTexture(GL_TEXTURE1);
    194     //glBindTexture(GL_TEXTURE_2D, texture2);
    195 
    196 
    197     //为当前绑定的纹理对象设置环绕方式
    198     //
    199     //纹理图像环绕设置
    200     //第一个参数为纹理目标,我们使用的是2D纹理,所以纹理目标为GL_TEXTURE_2D
    201     //第二个参数需要我们指定设置的选项和应用的纹理轴,这里我们是WRAP选项,S 和T轴
    202     //最后一个参数需要我们传递一个环绕方式
    203     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    204     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    205 
    206     ////如果我们选择GL_CLAMP_TO_BOREDER选项,我们还需要指定一个边缘颜色
    207     //float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
    208     //glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
    209 
    210 
    211     //为当前绑定的纹理对象设置过滤方式
    212     //缩小时用临近过滤,放大时用线性过滤
    213     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    214     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    215 
    216     ////多级渐远纹理过滤
    217     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//在两个临近的多级渐远纹理之间使用线性插值,并使用线性插值进行采样
    218     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    219 
    220     int width, height, nrChannels;
    221 
    222     stbi_set_flip_vertically_on_load(true);
    223     //用stbi_load函数加载图片,加载并生成纹理
    224     unsigned char *data = stbi_load("timg.jpg", &width, &height, &nrChannels, 0);
    225 
    226     if (data)
    227     {
    228         //用glTexImage函数来生成纹理,调用之后,当前绑定的纹理对象就会被附加上纹理图像
    229         //第一个参数指定了纹理目标,设置为GL_TEXTURE_2D意味着会生成与当前绑定的纹理对象在同一个目标上的纹理
    230         //第二个参数为纹理指定多级渐远纹理的级别,0就是基本级别
    231         //第三个参数告诉OpenGL我们希望吧纹理存储为何种格式,我们的图像只有RGB值,因此我们也把纹理存储为RGB值
    232         //第四个和第五个参数设置最终纹理的宽度和高度
    233         //下个参数应该总是被设为0
    234         //第七和第八参数定义了源图的格式和数据类型,我们使用RGB值加载这个图像,并把他们存储为char(byte)数组,我们将会传入对应值
    235         //最后一个参数是真正的图像数据
    236         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    237         glGenerateMipmap(GL_TEXTURE_2D);
    238 
    239         //然而,目前只有基本级别(base-level)的纹理图像被加载了,如果要使用多级渐远纹理,我们必须手动设置所有不同的图像(不断递增
    240         //第二个参数),或者,直接在生成纹理之后调用glGenerateMipmap,这会为当前绑定的纹理自动生成所有需要的多级渐远纹理
    241     }
    242     else
    243     {
    244         cout << "Failed to load texture1
    " << endl;
    245     }
    246 
    247     //生成了纹理和相应的多级渐远纹理后,释放图像的内存是一个很好的习惯
    248     stbi_image_free(data);
    249 
    250     glGenTextures(1, &texture2);
    251     glBindTexture(GL_TEXTURE_2D, texture2);
    252     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    253     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    254     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    255     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    256 
    257     data = stbi_load("wall.jpg", &width, &height, &nrChannels, 0);
    258     if (data)
    259     {
    260         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    261         glGenerateMipmap(GL_TEXTURE_2D);
    262     }
    263     else
    264     {
    265         cout << "Failed to load texture2!" << endl;
    266     }
    267 
    268     stbi_image_free(data);
    269 
    270     glUseProgram(shaderProgram);
    271     glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0);
    272     glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1);
    273 
    274 
    275 
    276     glBindBuffer(GL_ARRAY_BUFFER, 0);
    277 
    278     glBindVertexArray(0);
    279 
    280 
    281     while (!glfwWindowShouldClose(window))
    282     {
    283         processInput(window);
    284 
    285         //render
    286         glClearColor(0.2f, 0.4f, 0.5f, 1.0f);
    287         glClear(GL_COLOR_BUFFER_BIT);
    288 
    289         glActiveTexture(GL_TEXTURE0);
    290         glBindTexture(GL_TEXTURE_2D, texture1);
    291         glActiveTexture(GL_TEXTURE1);
    292         glBindTexture(GL_TEXTURE_2D, texture2);
    293 
    294         //glBindTexture(GL_TEXTURE_2D, texture);
    295         //画第一个三角形
    296         glUseProgram(shaderProgram);        //激活这个程序对象
    297 
    298 
    299         glBindVertexArray(VAO);
    300 
    301         //glDrawArrays函数第一个参数是我们打算绘制Opengl图元的类型,这里是三角形GL_TRIANGLES
    302         //第二个参数制定了顶点数组的起始索引,这里填0
    303         //第三个参数指定我们打算绘制多少个顶点
    304         //lDrawArrays(GL_TRIANGLES, 0, 3);    //
    305 
    306 
    307         //绘制这个矩形
    308         //glDrawElements第一个参数指定了我们绘制的图元模式
    309         //第二个参数是需绘制的顶点个数
    310         //第三个参数是索引类型,这里是GL_UNSIGNED_INT
    311         //最后一个参数是我们指定EBO中的偏移量(或者传递一个索引数组)
    312         glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);    
    313 
    314         glfwSwapBuffers(window);    //交换颜色缓冲,用来绘制,显示在屏幕上
    315         glfwPollEvents();        //检查是否触发事件、更新窗口状态
    316     }
    317 
    318     glDeleteVertexArrays(1, &VAO);        //释放顶点数组对象
    319     glDeleteBuffers(1, &VBO);            //释放顶点缓冲对象
    320     glDeleteBuffers(1, &EBO);
    321 
    322     glfwTerminate();    //释放之前分配的资源
    323 
    324     return 0;
    325 }
    326 
    327 void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    328 {
    329     glViewport(0, 0, width, height);
    330 }
    331 
    332 void processInput(GLFWwindow* window)
    333 {
    334     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    335         glfwSetWindowShouldClose(window, true);
    336 }
  • 相关阅读:
    快速登录机器&数据库
    质量报告之我见
    一些 ssh 小技巧
    virtualenv简介以及一个比较折腾的scrapy安装方法
    用scrapy数据抓取实践
    即将到来的5G,我们该做些什么准备?
    浅谈由管理者角色引出的B端产品设计思考点
    CodeForces 707C Pythagorean Triples (数论)
    UVaLive 6625 Diagrams & Tableaux (状压DP 或者 DFS暴力)
    CodeForces 707B Bakery (水题,暴力,贪心)
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/9575385.html
Copyright © 2011-2022 走看看