Better bloom effect
This commit is contained in:
parent
2358f30ce2
commit
2db1a22f81
@ -1,21 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2013 yvt
|
Copyright (c) 2013 yvt
|
||||||
|
|
||||||
This file is part of OpenSpades.
|
This file is part of OpenSpades.
|
||||||
|
|
||||||
OpenSpades is free software: you can redistribute it and/or modify
|
OpenSpades is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
OpenSpades is distributed in the hope that it will be useful,
|
OpenSpades is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -29,13 +29,13 @@ varying vec4 texCoord1;
|
|||||||
varying vec4 texCoord2;
|
varying vec4 texCoord2;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
vec2 pos = positionAttribute;
|
vec2 pos = positionAttribute;
|
||||||
|
|
||||||
vec2 scrPos = pos * 2. - 1.;
|
vec2 scrPos = pos * 2. - 1.;
|
||||||
|
|
||||||
gl_Position = vec4(scrPos, 0.5, 1.);
|
gl_Position = vec4(scrPos, 0.5, 1.);
|
||||||
|
|
||||||
// generated by ./1dgaussGen.rb
|
// generated by ./1dgaussGen.rb
|
||||||
// pixelShift is texture coord shift / texture pixel
|
// pixelShift is texture coord shift / texture pixel
|
||||||
const float pixelShift = 1.;
|
const float pixelShift = 1.;
|
||||||
@ -47,9 +47,9 @@ void main() {
|
|||||||
const float scale3 = 0.321295592929097;
|
const float scale3 = 0.321295592929097;
|
||||||
const float shift4 = pixelShift * 2.30654399138844;
|
const float shift4 = pixelShift * 2.30654399138844;
|
||||||
const float scale4 = 0.178704407070903;
|
const float scale4 = 0.178704407070903;
|
||||||
|
|
||||||
texCoord1 = pos.xyxy + unitShift.xyxy * vec4(vec2(shift1), vec2(shift2));
|
texCoord1 = pos.xyxy + unitShift.xyxy * vec4(vec2(shift1), vec2(shift2));
|
||||||
texCoord2 = pos.xyxy + unitShift.xyxy * vec4(vec2(shift3), vec2(shift4));
|
texCoord2 = pos.xyxy + unitShift.xyxy * vec4(vec2(shift3), vec2(shift4));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2013 yvt
|
Copyright (c) 2013 yvt
|
||||||
|
|
||||||
This file is part of OpenSpades.
|
This file is part of OpenSpades.
|
||||||
|
|
||||||
OpenSpades is free software: you can redistribute it and/or modify
|
OpenSpades is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
OpenSpades is distributed in the hope that it will be useful,
|
OpenSpades is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
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 dust2 = texture2D(dustTexture, dustTexCoord1.zw).xyz;
|
||||||
vec3 dust3 = texture2D(dustTexture, dustTexCoord2.xy).xyz;
|
vec3 dust3 = texture2D(dustTexture, dustTexCoord2.xy).xyz;
|
||||||
vec3 dust4 = texture2D(dustTexture, dustTexCoord2.zw).xyz;
|
vec3 dust4 = texture2D(dustTexture, dustTexCoord2.zw).xyz;
|
||||||
|
|
||||||
// linearize
|
// linearize
|
||||||
dust1 *= dust1;
|
dust1 *= dust1;
|
||||||
dust2 *= dust2;
|
dust2 *= dust2;
|
||||||
dust3 *= dust3;
|
dust3 *= dust3;
|
||||||
dust4 *= dust4;
|
dust4 *= dust4;
|
||||||
|
|
||||||
// blurred texture (already linearized?)
|
// blurred texture (already linearized?)
|
||||||
vec3 blur1 = texture2D(blurTexture1, texCoord).xyz;
|
vec3 blur1 = texture2D(blurTexture1, texCoord).xyz;
|
||||||
vec3 blur2 = texture2D(blurTexture2, texCoord).xyz;
|
vec3 blur2 = texture2D(blurTexture2, texCoord).xyz;
|
||||||
vec3 blur3 = texture2D(blurTexture3, texCoord).xyz;
|
vec3 blur3 = texture2D(blurTexture3, texCoord).xyz;
|
||||||
vec3 blur4 = texture2D(blurTexture4, texCoord).xyz;
|
vec3 blur4 = texture2D(blurTexture4, texCoord).xyz;
|
||||||
|
|
||||||
vec3 sum = dust1 * blur1;
|
vec3 sum = dust1 * blur1;
|
||||||
sum += dust2 * blur2;
|
sum += dust2 * blur2;
|
||||||
sum += dust3 * blur3;
|
sum += dust3 * blur3;
|
||||||
sum += dust4 * blur4;
|
sum += dust4 * blur4;
|
||||||
|
|
||||||
vec3 final = texture2D(inputTexture, texCoord).xyz;
|
vec3 final = texture2D(inputTexture, texCoord).xyz;
|
||||||
#if !LINEAR_FRAMEBUFFER
|
#if !LINEAR_FRAMEBUFFER
|
||||||
final *= final;
|
final *= final;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
final *= 0.95;
|
final *= 0.95;
|
||||||
final += sum * 0.4;
|
final += sum * 0.8;
|
||||||
|
|
||||||
// add grain
|
// add grain
|
||||||
float grain = texture2D(noiseTexture, noiseTexCoord.xy).x;
|
float grain = texture2D(noiseTexture, noiseTexCoord.xy).x;
|
||||||
grain += texture2D(noiseTexture, noiseTexCoord.zw).x;
|
grain += texture2D(noiseTexture, noiseTexCoord.zw).x;
|
||||||
grain = fract(grain) - 0.5;
|
grain = fract(grain) - 0.5;
|
||||||
final += grain * 0.003;
|
final += grain * 0.003;
|
||||||
|
|
||||||
// non-linearize
|
// non-linearize
|
||||||
#if !LINEAR_FRAMEBUFFER
|
#if !LINEAR_FRAMEBUFFER
|
||||||
final = sqrt(max(final, 0.));
|
final = sqrt(max(final, 0.));
|
||||||
#else
|
#else
|
||||||
final = max(final, 0.);
|
final = max(final, 0.);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gl_FragColor = vec4(final, 1.);
|
gl_FragColor = vec4(final, 1.);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +37,9 @@ SPADES_SETTING(r_hdr, "");
|
|||||||
namespace spades {
|
namespace spades {
|
||||||
namespace draw {
|
namespace draw {
|
||||||
GLLensDustFilter::GLLensDustFilter(GLRenderer *renderer):
|
GLLensDustFilter::GLLensDustFilter(GLRenderer *renderer):
|
||||||
renderer(renderer){
|
renderer(renderer){
|
||||||
thru = renderer->RegisterProgram("Shaders/PostFilters/PassThroughConstAlpha.program");
|
thru = renderer->RegisterProgram("Shaders/PostFilters/PassThroughConstAlpha.program");
|
||||||
|
gauss1d = renderer->RegisterProgram("Shaders/PostFilters/Gauss1D.program");
|
||||||
dust = renderer->RegisterProgram("Shaders/PostFilters/LensDust.program");
|
dust = renderer->RegisterProgram("Shaders/PostFilters/LensDust.program");
|
||||||
dustImg = (GLImage *)renderer->RegisterImage("Textures/RealLens.jpg");
|
dustImg = (GLImage *)renderer->RegisterImage("Textures/RealLens.jpg");
|
||||||
|
|
||||||
@ -81,8 +82,9 @@ namespace spades {
|
|||||||
|
|
||||||
static GLProgramAttribute blur_positionAttribute("positionAttribute");
|
static GLProgramAttribute blur_positionAttribute("positionAttribute");
|
||||||
static GLProgramUniform blur_textureUniform("texture");
|
static GLProgramUniform blur_textureUniform("texture");
|
||||||
static GLProgramUniform blur_colorUniform("colorUniform");
|
static GLProgramUniform blur_colorUniform("colorUniform");
|
||||||
static GLProgramUniform blur_texCoordRangeUniform("texCoordRange");
|
static GLProgramUniform blur_texCoordRangeUniform("texCoordRange");
|
||||||
|
static GLProgramUniform blur_texCoordOffsetUniform("texCoordOffset");
|
||||||
program->Use();
|
program->Use();
|
||||||
blur_positionAttribute(program);
|
blur_positionAttribute(program);
|
||||||
|
|
||||||
@ -90,12 +92,17 @@ namespace spades {
|
|||||||
blur_textureUniform.SetValue(0);
|
blur_textureUniform.SetValue(0);
|
||||||
dev->ActiveTexture(0);
|
dev->ActiveTexture(0);
|
||||||
dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture());
|
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(program);
|
||||||
blur_colorUniform.SetValue(1.f,1.f,1.f,1.f);
|
blur_colorUniform.SetValue(1.f,1.f,1.f,1.f);
|
||||||
|
|
||||||
blur_texCoordRangeUniform(program);
|
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());
|
qr.SetCoordAttributeIndex(blur_positionAttribute());
|
||||||
if(linearize){
|
if(linearize){
|
||||||
@ -112,6 +119,39 @@ namespace spades {
|
|||||||
qr.Draw();
|
qr.Draw();
|
||||||
return buf2;
|
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() {
|
void GLLensDustFilter::UpdateNoise() {
|
||||||
SPADES_MARK_FUNCTION();
|
SPADES_MARK_FUNCTION();
|
||||||
@ -162,18 +202,18 @@ namespace spades {
|
|||||||
thruTexCoordRange(thru);
|
thruTexCoordRange(thru);
|
||||||
|
|
||||||
GLColorBuffer downSampled = DownSample(input, r_hdr ? false : true);
|
GLColorBuffer downSampled = DownSample(input, r_hdr ? false : true);
|
||||||
downSampled = DownSample(downSampled);
|
downSampled = GaussianBlur(downSampled, false);
|
||||||
downSampled = DownSample(downSampled);
|
downSampled = GaussianBlur(downSampled, true);
|
||||||
|
|
||||||
thru->Use();
|
thru->Use();
|
||||||
thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
|
thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
|
||||||
thruTexture.SetValue(0);
|
thruTexture.SetValue(0);
|
||||||
dev->Enable(IGLDevice::Blend, false);
|
dev->Enable(IGLDevice::Blend, false);
|
||||||
|
|
||||||
levels.reserve(8);
|
levels.reserve(10);
|
||||||
|
|
||||||
// create downsample levels
|
// create downsample levels
|
||||||
for(int i = 0; i < 8; i++){
|
for(int i = 0; i < 10; i++){
|
||||||
GLColorBuffer prevLevel;
|
GLColorBuffer prevLevel;
|
||||||
if(i == 0){
|
if(i == 0){
|
||||||
prevLevel = downSampled;
|
prevLevel = downSampled;
|
||||||
@ -187,7 +227,9 @@ namespace spades {
|
|||||||
int newH = (prevH + 1) / 2;
|
int newH = (prevH + 1) / 2;
|
||||||
if(newW <= 1 || newH <= 1)
|
if(newW <= 1 || newH <= 1)
|
||||||
break;
|
break;
|
||||||
GLColorBuffer newLevel = DownSample(prevLevel);
|
GLColorBuffer newLevel = DownSample(prevLevel);
|
||||||
|
newLevel = GaussianBlur(newLevel, false);
|
||||||
|
newLevel = GaussianBlur(newLevel, true);
|
||||||
|
|
||||||
Level lv;
|
Level lv;
|
||||||
lv.w = newW; lv.h = newH;
|
lv.w = newW; lv.h = newH;
|
||||||
@ -205,12 +247,12 @@ namespace spades {
|
|||||||
for(int i = (int)levels.size() - 1; i >= 1; i--){
|
for(int i = (int)levels.size() - 1; i >= 1; i--){
|
||||||
int cnt = (int)levels.size() - i;
|
int cnt = (int)levels.size() - i;
|
||||||
float alpha = (float)cnt / (float)(cnt + 1);
|
float alpha = (float)cnt / (float)(cnt + 1);
|
||||||
alpha = sqrtf(alpha);
|
alpha = alpha;
|
||||||
|
|
||||||
GLColorBuffer curLevel = levels[i].buffer;
|
GLColorBuffer curLevel = levels[i].buffer;
|
||||||
|
|
||||||
float sx = .7f / curLevel.GetWidth();
|
float sx = .25f / curLevel.GetWidth();
|
||||||
float sy = .7f / curLevel.GetHeight();
|
float sy = .25f / curLevel.GetHeight();
|
||||||
|
|
||||||
for(int j = 0; j < 4; j++) {
|
for(int j = 0; j < 4; j++) {
|
||||||
if(i < (int)levels.size() - 1) {
|
if(i < (int)levels.size() - 1) {
|
||||||
|
@ -32,13 +32,15 @@ namespace spades {
|
|||||||
class GLProgram;
|
class GLProgram;
|
||||||
class GLImage;
|
class GLImage;
|
||||||
class GLLensDustFilter {
|
class GLLensDustFilter {
|
||||||
GLProgram *thru;
|
GLProgram *thru;
|
||||||
GLProgram *dust;
|
GLProgram *dust;
|
||||||
|
GLProgram *gauss1d;
|
||||||
GLImage *dustImg;
|
GLImage *dustImg;
|
||||||
GLRenderer *renderer;
|
GLRenderer *renderer;
|
||||||
IGLDevice::UInteger noiseTex;
|
IGLDevice::UInteger noiseTex;
|
||||||
std::vector<uint32_t> noise;
|
std::vector<uint32_t> noise;
|
||||||
GLColorBuffer DownSample(GLColorBuffer, bool linearize = false);
|
GLColorBuffer DownSample(GLColorBuffer, bool linearize = false);
|
||||||
|
GLColorBuffer GaussianBlur(GLColorBuffer, bool vertical);
|
||||||
void UpdateNoise();
|
void UpdateNoise();
|
||||||
public:
|
public:
|
||||||
GLLensDustFilter(GLRenderer *);
|
GLLensDustFilter(GLRenderer *);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user