Better bloom effect

This commit is contained in:
Tomoaki Kawada 2016-11-07 01:37:15 +09:00
parent 2358f30ce2
commit 2db1a22f81
4 changed files with 86 additions and 42 deletions

View File

@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
@ -29,13 +29,13 @@ varying vec4 texCoord1;
varying vec4 texCoord2;
void main() {
vec2 pos = positionAttribute;
vec2 scrPos = pos * 2. - 1.;
gl_Position = vec4(scrPos, 0.5, 1.);
// generated by ./1dgaussGen.rb
// pixelShift is texture coord shift / texture pixel
const float pixelShift = 1.;
@ -47,9 +47,9 @@ void main() {
const float scale3 = 0.321295592929097;
const float shift4 = pixelShift * 2.30654399138844;
const float scale4 = 0.178704407070903;
texCoord1 = pos.xyxy + unitShift.xyxy * vec4(vec2(shift1), vec2(shift2));
texCoord2 = pos.xyxy + unitShift.xyxy * vec4(vec2(shift3), vec2(shift4));
}

View File

@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
@ -38,45 +38,45 @@ void main() {
vec3 dust2 = texture2D(dustTexture, dustTexCoord1.zw).xyz;
vec3 dust3 = texture2D(dustTexture, dustTexCoord2.xy).xyz;
vec3 dust4 = texture2D(dustTexture, dustTexCoord2.zw).xyz;
// linearize
dust1 *= dust1;
dust2 *= dust2;
dust3 *= dust3;
dust4 *= dust4;
// blurred texture (already linearized?)
vec3 blur1 = texture2D(blurTexture1, texCoord).xyz;
vec3 blur2 = texture2D(blurTexture2, texCoord).xyz;
vec3 blur3 = texture2D(blurTexture3, texCoord).xyz;
vec3 blur4 = texture2D(blurTexture4, texCoord).xyz;
vec3 sum = dust1 * blur1;
sum += dust2 * blur2;
sum += dust3 * blur3;
sum += dust4 * blur4;
vec3 final = texture2D(inputTexture, texCoord).xyz;
#if !LINEAR_FRAMEBUFFER
final *= final;
#endif
final *= 0.95;
final += sum * 0.4;
final += sum * 0.8;
// add grain
float grain = texture2D(noiseTexture, noiseTexCoord.xy).x;
grain += texture2D(noiseTexture, noiseTexCoord.zw).x;
grain = fract(grain) - 0.5;
final += grain * 0.003;
// non-linearize
#if !LINEAR_FRAMEBUFFER
final = sqrt(max(final, 0.));
#else
final = max(final, 0.);
#endif
gl_FragColor = vec4(final, 1.);
}

View File

@ -37,8 +37,9 @@ SPADES_SETTING(r_hdr, "");
namespace spades {
namespace draw {
GLLensDustFilter::GLLensDustFilter(GLRenderer *renderer):
renderer(renderer){
thru = renderer->RegisterProgram("Shaders/PostFilters/PassThroughConstAlpha.program");
renderer(renderer){
thru = renderer->RegisterProgram("Shaders/PostFilters/PassThroughConstAlpha.program");
gauss1d = renderer->RegisterProgram("Shaders/PostFilters/Gauss1D.program");
dust = renderer->RegisterProgram("Shaders/PostFilters/LensDust.program");
dustImg = (GLImage *)renderer->RegisterImage("Textures/RealLens.jpg");
@ -81,8 +82,9 @@ namespace spades {
static GLProgramAttribute blur_positionAttribute("positionAttribute");
static GLProgramUniform blur_textureUniform("texture");
static GLProgramUniform blur_colorUniform("colorUniform");
static GLProgramUniform blur_texCoordRangeUniform("texCoordRange");
static GLProgramUniform blur_colorUniform("colorUniform");
static GLProgramUniform blur_texCoordRangeUniform("texCoordRange");
static GLProgramUniform blur_texCoordOffsetUniform("texCoordOffset");
program->Use();
blur_positionAttribute(program);
@ -90,12 +92,17 @@ namespace spades {
blur_textureUniform.SetValue(0);
dev->ActiveTexture(0);
dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture());
blur_texCoordOffsetUniform(program);
blur_texCoordOffsetUniform.SetValue(1.f / w, 1.f / h, -1.f / w, -1.f / h);
blur_colorUniform(program);
blur_colorUniform.SetValue(1.f,1.f,1.f,1.f);
blur_texCoordRangeUniform(program);
blur_texCoordRangeUniform.SetValue(0.f, 0.f, 1.f, 1.f);
blur_texCoordRangeUniform.SetValue(0.f, 0.f,
(float)((w + 1) & ~1) / w,
(float)((h + 1) & ~1) / h);
qr.SetCoordAttributeIndex(blur_positionAttribute());
if(linearize){
@ -112,6 +119,39 @@ namespace spades {
qr.Draw();
return buf2;
}
GLColorBuffer GLLensDustFilter::GaussianBlur(GLColorBuffer tex, bool vertical) {
SPADES_MARK_FUNCTION();
GLProgram *program = gauss1d;
IGLDevice *dev = renderer->GetGLDevice();
GLQuadRenderer qr(dev);
int w = tex.GetWidth();
int h = tex.GetHeight();
static GLProgramAttribute blur_positionAttribute("positionAttribute");
static GLProgramUniform blur_textureUniform("texture");
static GLProgramUniform blur_unitShift("unitShift");
program->Use();
blur_positionAttribute(program);
blur_textureUniform(program);
blur_textureUniform.SetValue(0);
dev->ActiveTexture(0);
dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture());
blur_unitShift(program);
blur_unitShift.SetValue(vertical ? 0.f : 1.f / w,
vertical ? 1.f / h : 0.f);
qr.SetCoordAttributeIndex(blur_positionAttribute());
dev->Enable(IGLDevice::Blend, false);
GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, false);
dev->Viewport(0, 0, buf2.GetWidth(), buf2.GetHeight());
dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer());
qr.Draw();
return buf2;
}
void GLLensDustFilter::UpdateNoise() {
SPADES_MARK_FUNCTION();
@ -162,18 +202,18 @@ namespace spades {
thruTexCoordRange(thru);
GLColorBuffer downSampled = DownSample(input, r_hdr ? false : true);
downSampled = DownSample(downSampled);
downSampled = DownSample(downSampled);
downSampled = GaussianBlur(downSampled, false);
downSampled = GaussianBlur(downSampled, true);
thru->Use();
thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
thruTexture.SetValue(0);
dev->Enable(IGLDevice::Blend, false);
levels.reserve(8);
levels.reserve(10);
// create downsample levels
for(int i = 0; i < 8; i++){
for(int i = 0; i < 10; i++){
GLColorBuffer prevLevel;
if(i == 0){
prevLevel = downSampled;
@ -187,7 +227,9 @@ namespace spades {
int newH = (prevH + 1) / 2;
if(newW <= 1 || newH <= 1)
break;
GLColorBuffer newLevel = DownSample(prevLevel);
GLColorBuffer newLevel = DownSample(prevLevel);
newLevel = GaussianBlur(newLevel, false);
newLevel = GaussianBlur(newLevel, true);
Level lv;
lv.w = newW; lv.h = newH;
@ -205,12 +247,12 @@ namespace spades {
for(int i = (int)levels.size() - 1; i >= 1; i--){
int cnt = (int)levels.size() - i;
float alpha = (float)cnt / (float)(cnt + 1);
alpha = sqrtf(alpha);
alpha = alpha;
GLColorBuffer curLevel = levels[i].buffer;
float sx = .7f / curLevel.GetWidth();
float sy = .7f / curLevel.GetHeight();
float sx = .25f / curLevel.GetWidth();
float sy = .25f / curLevel.GetHeight();
for(int j = 0; j < 4; j++) {
if(i < (int)levels.size() - 1) {

View File

@ -32,13 +32,15 @@ namespace spades {
class GLProgram;
class GLImage;
class GLLensDustFilter {
GLProgram *thru;
GLProgram *dust;
GLProgram *thru;
GLProgram *dust;
GLProgram *gauss1d;
GLImage *dustImg;
GLRenderer *renderer;
IGLDevice::UInteger noiseTex;
std::vector<uint32_t> noise;
GLColorBuffer DownSample(GLColorBuffer, bool linearize = false);
std::vector<uint32_t> noise;
GLColorBuffer DownSample(GLColorBuffer, bool linearize = false);
GLColorBuffer GaussianBlur(GLColorBuffer, bool vertical);
void UpdateNoise();
public:
GLLensDustFilter(GLRenderer *);