Vertex Shader:
attribute vec4 rm_Vertex;
varying vec2 vTexCoord;
void main(void)
{
// Clean up inaccuracies
vec2 Position;
Position.xy = sign(rm_Vertex.xy);
gl_Position = vec4(Position.xy, 0.0, 1.0);
vTexCoord = Position.xy *.5 + .5;
}
Godray Fragment Shader:
#ifdef GL_FRAGMENT_PRECISION_HIGH
// Default precision
precision highp float;
#else
precision mediump float;
#endif
uniform mat4 matViewProjection;
uniform sampler2D Accum;
uniform sampler2D Noise;
uniform vec3 sunPos;
uniform float decal;
uniform float decal0;
uniform int numSamples;
varying vec2 vTexCoord;
vec4 godray(vec2 tc)
{
vec2 delta = (tc - vTexCoord) / float(numSamples);
vec2 curTc;
vec3 accumColor = vec3(0.0);
int i;
for(i = 0; i <= numSamples; ++i)
{
curTc = vTexCoord + delta * float(i);
if(curTc.x < 0.0 || curTc.x > 1.0 || curTc.y < 0.0 || curTc.y > 1.0)
break;
vec4 texel = texture2D(Accum, curTc);
if (texel.xyz == 0.0)
{
accumColor += clamp(vec3(1.0/length(tc - curTc) * decal), 0.0, 1.0);
}
}
return vec4(accumColor / (float(i)*decal0+0.01), 0.0);
}
vec4 godray_noise(vec2 tc)
{
vec2 delta = (tc - vTexCoord) / float(numSamples);
vec2 curTc = vTexCoord;
vec3 accumColor = vec3(0.0);
int i;
for(i = 0; i <= numSamples+1; ++i)
{
if(curTc.x < 0.0 || curTc.x > 1.0 || curTc.y < 0.0 || curTc.y > 1.0)
break;
vec4 texel = texture2D(Accum, curTc);
if (texel.xyz == 0.0)
{
accumColor += clamp(vec3(1.0/length(tc - curTc) * decal), 0.0, 1.0);
}
float noise = texture2D(Noise, curTc).x;
curTc += delta * noise;
}
return vec4(accumColor / (float(i)*decal0+0.01), 0.0);
}
void main(void)
{
vec4 clipPos = matViewProjection * vec4(sunPos, 1.0);
vec2 tc = clipPos.xy/clipPos.w * 0.5 + 0.5;
vec4 c = godray(tc);
gl_FragColor = c;
}
Radial Blur Fragment Shader:
#ifdef GL_FRAGMENT_PRECISION_HIGH
// Default precision
precision highp float;
#else
precision mediump float;
#endif
uniform mat4 matViewProjection;
uniform sampler2D Accum;
uniform sampler2D GodRay;
uniform vec3 sunPos;
uniform int numBlurSamples;
uniform float scale;
varying vec2 vTexCoord;
void main(void)
{
vec4 clipPos = matViewProjection * vec4(sunPos, 1.0);
vec2 tc = clipPos.xy/clipPos.w * 0.5 + 0.5;
vec2 delta = (tc - vTexCoord) * scale;
vec2 curTc = vTexCoord;
vec3 accumColor = vec3(0.0);
int i;
for(i = 0; i <= numBlurSamples; ++i)
{
if(curTc.x < 0.0 || curTc.x > 1.0 || curTc.y < 0.0 || curTc.y > 1.0)
break;
accumColor += texture2D(GodRay, curTc).xyz;
curTc += delta;
}
gl_FragColor = texture2D(Accum, vTexCoord) + vec4(accumColor/float(i), 1.0);
}
运行结果:下面是没有采用Noise,10个采样点,无Blur的结果,可以看到有很多Aliasing。
下图是采用Noise,10个采样点,带Blur-10个采样点和不带Blur的结果。效果上提升了不少。
Shader中的一些参数设置:
numSamples: 10 numBlurSamples: 10 decal: 0.03794 decal0: 0.96000 scale: 0.01820
Noise纹理:
转载自原文链接, 如需删除请联系管理员。
原文链接:神光GodRay的简单实现,转载请注明来源!