一、先简单说一下OpenGL的纹理使用
本质上还是状态机,要把加载的图片放到插槽里面,然后着色器通过访问插槽去拿到纹理。因此纹理从加载到使用需要经历如下步骤(1-5可以写成一个纹理加载函数):
1.先绑定纹理,告诉opengl接下来的操作在这个id上:glBindTexture(GL_TEXTURE_2D, textureID);
2.上传纹理数据:glTexImage2D(GL_TEXTURE_2D, 0, format,
width, height, 0,
format, GL_UNSIGNED_BYTE, data);
3.设置mimap(自动生成多级纹理):glGenerateMipmap(GL_TEXTURE_2D);
4.设置纹理环绕方式(横向和竖向,也就是超过0-1的坐标如何重复去做):
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
5.设置放大缩小的过滤方式(一般是mimap+线性插值算法): glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6.渲染时一定要先激活纹理单元,并绑定纹理上去:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
7.此时在Fragment shader里面才可以通过sampler2D + 变量名 去访问到纹理:
sampler2D diffuse;
sampler2D specular;
vec3 ambient = light.ambient * texture(diffuse, TexCoords).rgb;
二、OpenGL帧缓冲(FBO)
帧缓冲顾名思义,就是自己创建一个缓冲来存放临时数据。帧缓冲其实只是一个容器,不能单独使用,必须绑定颜色附件或者再加上一个深度/模板缓冲,颜色附件其实就是一个纹理,只不过这个纹理不是读进来的,而是创建一个空白的内存。深度和模板缓冲一般用渲染缓冲对象(rbo),这个没有什么特别的,只是因为这两个东西不需要采样,因此换了一个高效的数据格式,如果需要采样深度,其实也可以用纹理附件去存深度。
下面是帧缓冲的创建:
//1.创建帧缓冲 unsigned int framebuffer; glGenFramebuffers(1, &framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); //2.创建并添加纹理附件 unsigned int textureColorbuffer; glGenTextures(1, &textureColorbuffer); glBindTexture(GL_TEXTURE_2D, textureColorbuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); //创建空白的纹理内存 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0); // 3.创建rbo用来做深度缓冲 unsigned int rbo; glGenRenderbuffers(1, &rbo); glBindRenderbuffer(GL_RENDERBUFFER, rbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);下面是帧缓冲的使用:
//1.绑定缓冲为自己创建的帧缓冲,保证接下来渲染的内容放到帧缓冲 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad) //渲染前清理一下buffer glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //渲染 . . . //2.切换绑定的缓冲到默认缓冲 glBindFramebuffer(GL_FRAMEBUFFER, 0); //同样清理一下缓冲 glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //接下来绑定纹理附件到纹理,此时去fragment shader操作就相当于是对纹理后处理 glBindTexture(GL_TEXTURE_2D, textureColorbuffer); //渲染 . . .