Added lens distortion shader

This commit is contained in:
Magnus Norddahl 2016-08-02 17:32:21 +02:00
parent 43e577ce79
commit 6b9529d70f
11 changed files with 236 additions and 2 deletions

View file

@ -1110,6 +1110,7 @@ set( FASTMATH_SOURCES
gl/shaders/gl_bloomshader.cpp gl/shaders/gl_bloomshader.cpp
gl/shaders/gl_blurshader.cpp gl/shaders/gl_blurshader.cpp
gl/shaders/gl_tonemapshader.cpp gl/shaders/gl_tonemapshader.cpp
gl/shaders/gl_lensshader.cpp
gl/system/gl_interface.cpp gl/system/gl_interface.cpp
gl/system/gl_framebuffer.cpp gl/system/gl_framebuffer.cpp
gl/system/gl_menu.cpp gl/system/gl_menu.cpp

View file

@ -68,6 +68,7 @@
#include "gl/shaders/gl_bloomshader.h" #include "gl/shaders/gl_bloomshader.h"
#include "gl/shaders/gl_blurshader.h" #include "gl/shaders/gl_blurshader.h"
#include "gl/shaders/gl_tonemapshader.h" #include "gl/shaders/gl_tonemapshader.h"
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_presentshader.h" #include "gl/shaders/gl_presentshader.h"
//========================================================================== //==========================================================================
@ -95,6 +96,12 @@ CUSTOM_CVAR(Int, gl_bloom_kernel_size, 7, 0)
self = 7; self = 7;
} }
CVAR(Bool, gl_lens, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, gl_lens_k, -0.15f, 0)
CVAR(Float, gl_lens_kcube, 0.15f, 0)
CVAR(Float, gl_lens_chromatic, 1.2f, 0)
EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast) EXTERN_CVAR(Float, vid_contrast)
@ -260,6 +267,70 @@ void FGLRenderer::TonemapScene()
glActiveTexture(activeTex); glActiveTexture(activeTex);
} }
//-----------------------------------------------------------------------------
//
// Apply lens distortion and place the result in the HUD/2D texture
//
//-----------------------------------------------------------------------------
void FGLRenderer::LensDistortScene()
{
if (gl_lens == 0)
return;
GLint activeTex, textureBinding, samplerBinding;
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
glActiveTexture(GL_TEXTURE0);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
if (gl.flags & RFL_SAMPLER_OBJECTS)
{
glGetIntegerv(GL_SAMPLER_BINDING, &samplerBinding);
glBindSampler(0, 0);
}
GLboolean blendEnabled, scissorEnabled;
glGetBooleanv(GL_BLEND, &blendEnabled);
glGetBooleanv(GL_SCISSOR_TEST, &scissorEnabled);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
float k[4] =
{
gl_lens_k,
gl_lens_k * gl_lens_chromatic,
gl_lens_k * gl_lens_chromatic * gl_lens_chromatic,
0.0f
};
float kcube[4] =
{
gl_lens_kcube,
gl_lens_kcube * gl_lens_chromatic,
gl_lens_kcube * gl_lens_chromatic * gl_lens_chromatic,
0.0f
};
mBuffers->BindHudFB();
mBuffers->BindSceneTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mLensShader->Bind();
mLensShader->InputTexture.Set(0);
mLensShader->LensDistortionCoefficient.Set(k);
mLensShader->CubicDistortionValue.Set(kcube);
mVBO->BindVBO();
mVBO->RenderScreenQuad();
if (blendEnabled)
glEnable(GL_BLEND);
if (scissorEnabled)
glEnable(GL_SCISSOR_TEST);
glBindTexture(GL_TEXTURE_2D, textureBinding);
if (gl.flags & RFL_SAMPLER_OBJECTS)
glBindSampler(0, samplerBinding);
glActiveTexture(activeTex);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Gamma correct while copying to frame buffer // Gamma correct while copying to frame buffer
@ -357,6 +428,8 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f)); mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
} }
mBuffers->BindHudTexture(0); mBuffers->BindHudTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
mVBO->BindVBO(); mVBO->BindVBO();
mVBO->RenderScreenQuad(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight()); mVBO->RenderScreenQuad(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight());

View file

@ -432,7 +432,7 @@ void FGLRenderBuffers::BindSceneTextureFB()
void FGLRenderBuffers::BindHudFB() void FGLRenderBuffers::BindHudFB()
{ {
if (gl_tonemap != 0) if (gl_tonemap != 0 || gl_lens)
glBindFramebuffer(GL_FRAMEBUFFER, mHudFB); glBindFramebuffer(GL_FRAMEBUFFER, mHudFB);
else else
glBindFramebuffer(GL_FRAMEBUFFER, mSceneTextureFB); glBindFramebuffer(GL_FRAMEBUFFER, mSceneTextureFB);
@ -470,7 +470,7 @@ void FGLRenderBuffers::BindSceneTexture(int index)
void FGLRenderBuffers::BindHudTexture(int index) void FGLRenderBuffers::BindHudTexture(int index)
{ {
glActiveTexture(GL_TEXTURE0 + index); glActiveTexture(GL_TEXTURE0 + index);
if (gl_tonemap != 0) if (gl_tonemap != 0 || gl_lens)
glBindTexture(GL_TEXTURE_2D, mHudTexture); glBindTexture(GL_TEXTURE_2D, mHudTexture);
else else
glBindTexture(GL_TEXTURE_2D, mSceneTexture); glBindTexture(GL_TEXTURE_2D, mSceneTexture);

View file

@ -65,6 +65,7 @@
#include "gl/shaders/gl_bloomshader.h" #include "gl/shaders/gl_bloomshader.h"
#include "gl/shaders/gl_blurshader.h" #include "gl/shaders/gl_blurshader.h"
#include "gl/shaders/gl_tonemapshader.h" #include "gl/shaders/gl_tonemapshader.h"
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_presentshader.h" #include "gl/shaders/gl_presentshader.h"
#include "gl/textures/gl_texture.h" #include "gl/textures/gl_texture.h"
#include "gl/textures/gl_translate.h" #include "gl/textures/gl_translate.h"
@ -117,6 +118,7 @@ void FGLRenderer::Initialize()
mBloomCombineShader = new FBloomCombineShader(); mBloomCombineShader = new FBloomCombineShader();
mBlurShader = new FBlurShader(); mBlurShader = new FBlurShader();
mTonemapShader = new FTonemapShader(); mTonemapShader = new FTonemapShader();
mLensShader = new FLensShader();
mPresentShader = new FPresentShader(); mPresentShader = new FPresentShader();
// Only needed for the core profile, because someone decided it was a good idea to remove the default VAO. // Only needed for the core profile, because someone decided it was a good idea to remove the default VAO.
@ -171,6 +173,7 @@ FGLRenderer::~FGLRenderer()
if (mBloomCombineShader) delete mBloomCombineShader; if (mBloomCombineShader) delete mBloomCombineShader;
if (mBlurShader) delete mBlurShader; if (mBlurShader) delete mBlurShader;
if (mTonemapShader) delete mTonemapShader; if (mTonemapShader) delete mTonemapShader;
if (mLensShader) delete mLensShader;
} }
//========================================================================== //==========================================================================

View file

@ -23,6 +23,7 @@ class FBloomExtractShader;
class FBloomCombineShader; class FBloomCombineShader;
class FBlurShader; class FBlurShader;
class FTonemapShader; class FTonemapShader;
class FLensShader;
class FPresentShader; class FPresentShader;
inline float DEG2RAD(float deg) inline float DEG2RAD(float deg)
@ -90,6 +91,7 @@ public:
FBloomCombineShader *mBloomCombineShader; FBloomCombineShader *mBloomCombineShader;
FBlurShader *mBlurShader; FBlurShader *mBlurShader;
FTonemapShader *mTonemapShader; FTonemapShader *mTonemapShader;
FLensShader *mLensShader;
FPresentShader *mPresentShader; FPresentShader *mPresentShader;
FTexture *gllight; FTexture *gllight;
@ -160,6 +162,7 @@ public:
void EndDrawScene(sector_t * viewsector); void EndDrawScene(sector_t * viewsector);
void BloomScene(); void BloomScene();
void TonemapScene(); void TonemapScene();
void LensDistortScene();
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma); void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
void Flush() { CopyToBackbuffer(nullptr, true); } void Flush() { CopyToBackbuffer(nullptr, true); }

View file

@ -864,6 +864,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
if (FGLRenderBuffers::IsEnabled()) mBuffers->BlitSceneToTexture(); if (FGLRenderBuffers::IsEnabled()) mBuffers->BlitSceneToTexture();
BloomScene(); BloomScene();
TonemapScene(); TonemapScene();
LensDistortScene();
} }
mDrawingScene2D = false; mDrawingScene2D = false;
eye->TearDown(); eye->TearDown();

View file

@ -0,0 +1,66 @@
/*
** gl_lensshader.cpp
** Lens distortion with chromatic aberration shader
**
**---------------------------------------------------------------------------
** Copyright 2016 Magnus Norddahl
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be
** covered by the terms of the GNU Lesser General Public License as published
** by the Free Software Foundation; either version 2.1 of the License, or (at
** your option) any later version.
** 5. Full disclosure of the entire project's source code, except for third
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "gl/system/gl_system.h"
#include "files.h"
#include "m_swap.h"
#include "v_video.h"
#include "gl/gl_functions.h"
#include "vectors.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_lensshader.h"
void FLensShader::Bind()
{
if (!mShader)
{
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/lensdistortion.vp", "", 330);
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/lensdistortion.fp", "", 330);
mShader.SetFragDataLocation(0, "FragColor");
mShader.Link("shaders/glsl/lensdistortion");
mShader.SetAttribLocation(0, "PositionInProjection");
InputTexture.Init(mShader, "InputTexture");
LensDistortionCoefficient.Init(mShader, "k");
CubicDistortionValue.Init(mShader, "kcube");
}
mShader.Bind();
}

View file

@ -0,0 +1,19 @@
#ifndef __GL_LENSSHADER_H
#define __GL_LENSSHADER_H
#include "gl_shaderprogram.h"
class FLensShader
{
public:
void Bind();
FBufferedUniform1i InputTexture;
FBufferedUniform4f LensDistortionCoefficient;
FBufferedUniform4f CubicDistortionValue;
private:
FShaderProgram mShader;
};
#endif

View file

@ -49,5 +49,9 @@ EXTERN_CVAR(Float, gl_bloom_amount)
EXTERN_CVAR(Int, gl_bloom_kernel_size) EXTERN_CVAR(Int, gl_bloom_kernel_size)
EXTERN_CVAR(Int, gl_tonemap) EXTERN_CVAR(Int, gl_tonemap)
EXTERN_CVAR(Float, gl_exposure) EXTERN_CVAR(Float, gl_exposure)
EXTERN_CVAR(Bool, gl_lens)
EXTERN_CVAR(Float, gl_lens_k)
EXTERN_CVAR(Float, gl_lens_kcube)
EXTERN_CVAR(Float, gl_lens_chromatic)
#endif // _GL_INTERN_H #endif // _GL_INTERN_H

View file

@ -0,0 +1,55 @@
/*
Original Lens Distortion Algorithm from SSontech
http://www.ssontech.com/content/lensalg.htm
If (u,v) are the coordinates of a feature in the undistorted perfect
image plane, then (u', v') are the coordinates of the feature on the
distorted image plate, ie the scanned or captured image from the
camera. The distortion occurs radially away from the image center,
with correction for the image aspect ratio (image_aspect = physical
image width/height), as follows:
r2 = image_aspect*image_aspect*u*u + v*v
f = 1 + r2*(k + kcube*sqrt(r2))
u' = f*u
v' = f*v
The constant k is the distortion coefficient that appears on the lens
panel and through Sizzle. It is generally a small positive or negative
number under 1%. The constant kcube is the cubic distortion value found
on the image preprocessor's lens panel: it can be used to undistort or
redistort images, but it does not affect or get computed by the solver.
When no cubic distortion is needed, neither is the square root, saving
time.
Chromatic Aberration example,
using red distord channel with green and blue undistord channel:
k = vec3(-0.15, 0.0, 0.0);
kcube = vec3(0.15, 0.0, 0.0);
*/
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D InputTexture;
uniform vec4 k; // lens distortion coefficient
uniform vec4 kcube; // cubic distortion value
void main()
{
vec2 position = TexCoord - vec2(0.5);
float r2 = dot(position, position);
vec3 f = vec3(1.0) + r2 * (k.rgb + kcube.rgb * sqrt(r2));
vec3 x = f * position.x + 0.5;
vec3 y = f * position.y + 0.5;
vec3 c;
c.r = texture(InputTexture, vec2(x.r, y.r)).r;
c.g = texture(InputTexture, vec2(x.g, y.g)).g;
c.b = texture(InputTexture, vec2(x.b, y.b)).b;
FragColor = vec4(c, 1.0);
}

View file

@ -0,0 +1,9 @@
in vec4 PositionInProjection;
out vec2 TexCoord;
void main()
{
gl_Position = PositionInProjection;
TexCoord = PositionInProjection.xy * 0.5 + 0.5;
}