官方教程:
帧缓冲
我这里只放自己调通了的代码加注释。
Frame_buffers_vertShader.vert
#version 330 core
layout (location=0) in vec2 aPos;
layout(location=1)in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
gl_Position=vec4(aPos.x,aPos.y,0.0f,1.0f);
TexCoords=aTexCoords;
}
Frame_buffers_fragment.frag
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;//纹理
void main()
{
FragColor=texture(screenTexture,TexCoords);
}
创建帧缓冲的过程
Shader shader = Shader("Space_vertShader.vert", "Blending_fragment.frag");
Shader screenShader = Shader("Frame_buffers_vertShader.vert", "Frame_buffers_fragment.frag");
unsigned int framebuffer;
glGenFramebuffers(1,&framebuffer);//创建帧缓冲
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);//绑定帧缓冲
unsigned int texColorBuffer;
glGenTextures(1, &texColorBuffer);
glBindTexture(GL_TEXTURE_2D, texColorBuffer);//当前的对GL_TEXTURE_2D的所有操作都是对texColorBuffer的
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);//纹理大小为屏幕宽高,data为空
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, texColorBuffer, 0);//绑定颜色附件。该函数1 帧缓冲目标,2附件类型,3纹理类型,4纹理本身,5多级渐远纹理级别
//glDeleteFramebuffers(1, &framebuffer);删除帧缓冲,不过不能在这里删
unsigned int rbo;
glGenRenderbuffers(1, &rbo);//申请渲染缓冲
glBindRenderbuffer(GL_RENDERBUFFER, rbo);//绑定渲染缓冲
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, WIDTH, HEIGHT);//绑定深度和模板附件
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);//把渲染绑定到帧缓冲上
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)//检测帧缓冲是否完整
{
std::cout << "ERROR::FRAMEBUFFER::Framebuffer is not complete!" << std::endl;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);//恢复默认
绘制四边形所需的前置准备
float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// positions // texCoords
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
GLuint quadVBO, quadVAO;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4* sizeof(GLfloat), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
帧缓冲的使用
glfwInput(window);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);//在frambuffer上绘制渲染图形
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
drawcube();//前面有就不写了
drawplane();
glBindFramebuffer(GL_FRAMEBUFFER, 0);//绘制
glDisable(GL_DEPTH_TEST); // disable depth test so screen-space quad isn't discarded due to depth test.
// clear all relevant buffers
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways)
glClear(GL_COLOR_BUFFER_BIT);
screenShader.Use();
glBindVertexArray(quadVAO);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texColorBuffer); // use the color attachment texture as the texture of the quad plane
screenShader.setInt("screenTexture", 2);//这个挺重要的,必须自己手动设置才能确保无错
glDrawArrays(GL_TRIANGLES, 0, 6);
输出效果:
没有看见教程里的那个白框,个人认为前面这一通操作就是为了在自定义的帧缓冲上渲染自己的图形。
接下来开始后期处理
反色
修改Frame_buffers_fragment.frag
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;//纹理
void main()
{
FragColor=vec4(vec3(1.0-texture(screenTexture,TexCoords)),1.0);
}
输出效果:
灰度化
修改Frame_buffers_fragment.frag
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;//纹理
void main()
{
vec4 texColor=texture(screenTexture,TexCoords);
float average=(texColor.r+texColor.g+texColor.b)/3.0;
FragColor=vec4(average,average,average,1.0f);
}
输出效果:
修改Frame_buffers_fragment.frag 采用加权通道
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;//纹理
void main()
{
vec4 texColor=texture(screenTexture,TexCoords);
float average=(0.2126*texColor.r+0.7152*texColor.g+0.0722*texColor.b)/3.0;
FragColor=vec4(average,average,average,1.0f);
}
输出效果:
锐化
修改Frame_buffers_fragment.frag
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;//纹理
const float offset=1.0/300.0;
void main()
{
//核
vec2 offsets[9] = vec2[](
vec2(-offset, offset), // 左上
vec2( 0.0f, offset), // 正上
vec2( offset, offset), // 右上
vec2(-offset, 0.0f), // 左
vec2( 0.0f, 0.0f), // 中
vec2( offset, 0.0f), // 右
vec2(-offset, -offset), // 左下
vec2( 0.0f, -offset), // 正下
vec2( offset, -offset) // 右下
);
float kernel[9]=float[](
-1,-1,-1,
-1,9,-1,
-1,-1,-1
);
vec3 sampleTexs[9];
for(int i=0;i<9;i++)
{
sampleTexs[i]=vec3(texture(screenTexture,TexCoords.st+offsets[i]));
}
vec3 col=vec3(0.0);
for(int i=0;i<9;i++)
col+=sampleTexs[i]*kernel[i];
FragColor=vec4(col,1.0);
}
输出效果:
模糊
float kernel[9] = float[](
1.0 / 16, 2.0 / 16, 1.0 / 16,
2.0 / 16, 4.0 / 16, 2.0 / 16,
1.0 / 16, 2.0 / 16, 1.0 / 16
);
边缘检测
float kernel[9]=float[](
1,1,1,
1,-8,1,
1,1,1
);
输出效果: