后处理中的 模糊、眩光、投影纹理:Blur,Bloom&ShadowMappingt in PostProcess - MartinRGB/GLES30_ProgrammingGuide_NDK GitHub Wiki
后处理
一般结合 FBO 和 Shader,处理上一般处理的 Pass。
一般来说,Post Process 有以下经典模式:
1.将场景渲染到屏幕外 FBO 中
2.将 FBO 绑定一个来源,在屏幕上渲染
3.执行 FragmentShader,在屏幕范围内进行过滤
模糊
偏移 4 次取平均
void main(void)
{
vec4 sample0,
sample1,
sample2,
sample3;
float fStep = u_blurStep / 100.0;
sample0 = texture2D ( renderTexture,
vec2 ( v_texCoord.x - fStep, v_texCoord.y - fStep ) );
sample1 = texture2D ( renderTexture,
vec2 ( v_texCoord.x + fStep, v_texCoord.y + fStep ) );
sample2 = texture2D ( renderTexture,
vec2 ( v_texCoord.x + fStep, v_texCoord.y - fStep ) );
sample3 = texture2D ( renderTexture,
vec2 ( v_texCoord.x - fStep, v_texCoord.y + fStep) );
outColor = (sample0 + sample1 + sample2 + sample3) / 4.0;
}
眩光
较暗的表面生成比较明亮的光线,处理步骤如下供参考:
1.清除屏幕外渲染目标 rt0 绘制黑色物体
2.模糊步长 1.0 将屏幕外渲染目标 rt0 模糊到另一个渲染目标 rt1
3.模糊步长 1.0 将 rt1 模糊到 rt0
4.将对象渲染到后台缓冲区
5.将加光照的渲染目标与后台缓冲区混合
投影纹理
使用投影纹理,可以提供更高的性能。
1.读取投影纹理:
textureProj
通俗来讲,使用投影纹理是使用 3D 纹理坐标在 2D 纹理图形中查找,(s,t) 除以 r 坐标,使用 (s/r,t/r) 读取纹素。
2.投影纹理所用的矩阵
照明矩阵
—— 使用 景深(FOV)
纵横比(aspect)
远近平面距离(zNear|zFar)
的光源投影矩阵
照明视图
—— 定义视图轴的 3个主轴方向和照明位置构造
偏置矩阵
—— 将坐标转换为投影纹理坐标,通过在照明空间中位置(x,y,z)分量上使用 3x3 偏置矩阵实现。
上述转换一般在 CPU 中实现
3.着色器解析:
vert:
#version 300
uniform float u_time_0_X;
uniform mat4 u_matProjection;
uniform mat4 u_matViewProjection;
in vec4 a_vertex;
in vec2 a_texCoord0;
in vec3 a_normal;
out vec2 v_texCoord;
out vec3 v_projTexCoord;
out vec3 v_normal;
out vec3 v_lightDir;
void main( void )
{
gl_Position = u_matViewProjection * a_vertex;
v_texCoord = a_texCoord0.xy;
// 根据时间计算照明位置,一般 CPU 中完成
vec3 lightPos;
lightPos.x = cos(u_time_0_X);
lightPos.z = sin(u_time_0_X);
lightPos.xz = 200.0 * normalize(lightPos.xz);
lightPos.y = 200.0;
// Compute the light coordinate axes
vec3 look = -normalize( lightPos );
vec3 right = cross( vec3( 0.0, 0.0, 1.0), look );
vec3 up = cross( look, right );
// Create a view matrix for the light - 照明视图矩阵
mat4 lightView = mat4( right, dot( right, -lightPos ),
up, dot( up, -lightPos ),
look, dot( look, -lightPos),
0.0, 0.0, 0.0, 1.0 );
// Transform position into light view space
vec4 objPosLight = a_vertex * lightView;
// Transform position into projective light view space 利用视野矩阵,将照明空间矩阵转换到投影照明空间中国年
objPosLight = u_matProjection * objPosLight;
// Create bias matrix 变换到投影纹理矩阵
mat3 biasMatrix = mat3( 0.5, 0.0, 0.5,
0.0, -0.5, 0.5,
0.0, 0.0, 1.0 );
// Compute projective texture coordinates
v_projTexCoord = objPosLight.xyz * biasMatrix;
v_lightDir = normalize(a_vertex.xyz - lightPos);
v_normal = a_normal;
}
frag:
version 300
precision mediump float;
uniform sampler2D baseMap;
uniform sampler2D spotLight;
in vec2 v_texCoord;
in vec3 v_projTexCoord;
in vec3 v_normal;
in vec3 v_lightDir;
out vec4 outColor;
void main( void )
{
// Projective fetch of spotlight 读取投影纹理
vec4 spotLightColor = textureProj( spotLight, v_projTexCoord );
// Basemap 基础材质颜色
vec4 baseColor = texture( baseMap, v_texCoord );
// Compute N.L 计算照明方向和法线的 点积,用来衰减颜色
float nDotL = max( 0.0, -dot( v_normal, v_lightDir ) );
outColor = spotLightColor * baseColor * 2.0 * nDotL;
}