mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-18 07:02:03 +00:00
This commit is contained in:
commit
ed07ff1bdd
27 changed files with 1223 additions and 166 deletions
|
@ -1128,6 +1128,7 @@ set( FASTMATH_SOURCES
|
||||||
gl/shaders/gl_shaderprogram.cpp
|
gl/shaders/gl_shaderprogram.cpp
|
||||||
gl/shaders/gl_presentshader.cpp
|
gl/shaders/gl_presentshader.cpp
|
||||||
gl/shaders/gl_bloomshader.cpp
|
gl/shaders/gl_bloomshader.cpp
|
||||||
|
gl/shaders/gl_ambientshader.cpp
|
||||||
gl/shaders/gl_blurshader.cpp
|
gl/shaders/gl_blurshader.cpp
|
||||||
gl/shaders/gl_colormapshader.cpp
|
gl/shaders/gl_colormapshader.cpp
|
||||||
gl/shaders/gl_tonemapshader.cpp
|
gl/shaders/gl_tonemapshader.cpp
|
||||||
|
|
|
@ -60,6 +60,11 @@ CVAR (Bool, gl_lights_checkside, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, gl_light_math, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
{
|
||||||
|
if (self < 0 || self > 2) self = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Sets up the parameters to render one dynamic light onto one plane
|
// Sets up the parameters to render one dynamic light onto one plane
|
||||||
|
@ -108,10 +113,25 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD
|
||||||
i = 1;
|
i = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float worldPos[4] = { (float)pos.X, (float)pos.Z, (float)pos.Y, 1.0f };
|
||||||
|
float eyePos[4];
|
||||||
|
gl_RenderState.mViewMatrix.multMatrixPoint(worldPos, eyePos);
|
||||||
|
|
||||||
|
if (gl_light_math != 0)
|
||||||
|
{
|
||||||
|
// Move light up because flasks/vials have their light source location at/below the floor.
|
||||||
|
//
|
||||||
|
// If the point is exactly on the wall plane it might cause some acne as some pixels could
|
||||||
|
// be in front and some behind. Move light just a tiny bit to avoid this.
|
||||||
|
eyePos[0] += 0.01f;
|
||||||
|
eyePos[1] += 5.01f;
|
||||||
|
eyePos[2] += 0.01f;
|
||||||
|
}
|
||||||
|
|
||||||
float *data = &ldata.arrays[i][ldata.arrays[i].Reserve(8)];
|
float *data = &ldata.arrays[i][ldata.arrays[i].Reserve(8)];
|
||||||
data[0] = pos.X;
|
data[0] = eyePos[0];
|
||||||
data[1] = pos.Z;
|
data[1] = eyePos[1];
|
||||||
data[2] = pos.Y;
|
data[2] = eyePos[2];
|
||||||
data[3] = radius;
|
data[3] = radius;
|
||||||
data[4] = r;
|
data[4] = r;
|
||||||
data[5] = g;
|
data[5] = g;
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "gl/renderer/gl_postprocessstate.h"
|
#include "gl/renderer/gl_postprocessstate.h"
|
||||||
#include "gl/data/gl_data.h"
|
#include "gl/data/gl_data.h"
|
||||||
#include "gl/data/gl_vertexbuffer.h"
|
#include "gl/data/gl_vertexbuffer.h"
|
||||||
|
#include "gl/shaders/gl_ambientshader.h"
|
||||||
#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"
|
||||||
|
@ -98,6 +99,16 @@ CVAR(Float, gl_lens_k, -0.12f, 0)
|
||||||
CVAR(Float, gl_lens_kcube, 0.1f, 0)
|
CVAR(Float, gl_lens_kcube, 0.1f, 0)
|
||||||
CVAR(Float, gl_lens_chromatic, 1.12f, 0)
|
CVAR(Float, gl_lens_chromatic, 1.12f, 0)
|
||||||
|
|
||||||
|
CVAR(Bool, gl_ssao, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
CVAR(Float, gl_ssao_strength, 0.7, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
CVAR(Bool, gl_ssao_debug, false, 0)
|
||||||
|
CVAR(Float, gl_ssao_bias, 0.5f, 0)
|
||||||
|
CVAR(Float, gl_ssao_radius, 100.0f, 0)
|
||||||
|
CUSTOM_CVAR(Float, gl_ssao_blur_amount, 4.0f, 0)
|
||||||
|
{
|
||||||
|
if (self < 0.1f) self = 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
EXTERN_CVAR(Float, vid_brightness)
|
EXTERN_CVAR(Float, vid_brightness)
|
||||||
EXTERN_CVAR(Float, vid_contrast)
|
EXTERN_CVAR(Float, vid_contrast)
|
||||||
|
|
||||||
|
@ -109,6 +120,136 @@ void FGLRenderer::RenderScreenQuad()
|
||||||
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
|
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGLRenderer::PostProcessScene()
|
||||||
|
{
|
||||||
|
mBuffers->BlitSceneToTexture();
|
||||||
|
UpdateCameraExposure();
|
||||||
|
BloomScene();
|
||||||
|
TonemapScene();
|
||||||
|
ColormapScene();
|
||||||
|
LensDistortScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Adds ambient occlusion to the scene
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FGLRenderer::AmbientOccludeScene()
|
||||||
|
{
|
||||||
|
FGLDebug::PushGroup("AmbientOccludeScene");
|
||||||
|
|
||||||
|
FGLPostProcessState savedState;
|
||||||
|
savedState.SaveTextureBinding1();
|
||||||
|
|
||||||
|
float bias = gl_ssao_bias;
|
||||||
|
float aoRadius = gl_ssao_radius;
|
||||||
|
const float blurAmount = gl_ssao_blur_amount;
|
||||||
|
float aoStrength = gl_ssao_strength;
|
||||||
|
bool multisample = gl_multisample > 1;
|
||||||
|
|
||||||
|
//float tanHalfFovy = tan(fovy * (M_PI / 360.0f));
|
||||||
|
float tanHalfFovy = 1.0f / gl_RenderState.mProjectionMatrix.get()[5];
|
||||||
|
float invFocalLenX = tanHalfFovy * (mBuffers->GetSceneWidth() / (float)mBuffers->GetSceneHeight());
|
||||||
|
float invFocalLenY = tanHalfFovy;
|
||||||
|
float nDotVBias = clamp(bias, 0.0f, 1.0f);
|
||||||
|
float r2 = aoRadius * aoRadius;
|
||||||
|
|
||||||
|
float blurSharpness = 1.0f / blurAmount;
|
||||||
|
|
||||||
|
// Calculate linear depth values
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
|
||||||
|
glViewport(0, 0, mBuffers->AmbientWidth, mBuffers->AmbientHeight);
|
||||||
|
mBuffers->BindSceneDepthTexture(0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
mBuffers->BindSceneColorTexture(1);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
mLinearDepthShader->Bind(multisample);
|
||||||
|
mLinearDepthShader->DepthTexture[multisample].Set(0);
|
||||||
|
mLinearDepthShader->ColorTexture[multisample].Set(1);
|
||||||
|
if (multisample) mLinearDepthShader->SampleCount[multisample].Set(gl_multisample);
|
||||||
|
mLinearDepthShader->LinearizeDepthA[multisample].Set(1.0f / GetZFar() - 1.0f / GetZNear());
|
||||||
|
mLinearDepthShader->LinearizeDepthB[multisample].Set(MAX(1.0f / GetZNear(), 1.e-8f));
|
||||||
|
mLinearDepthShader->InverseDepthRangeA[multisample].Set(1.0f);
|
||||||
|
mLinearDepthShader->InverseDepthRangeB[multisample].Set(0.0f);
|
||||||
|
mLinearDepthShader->Scale[multisample].Set(mBuffers->AmbientWidth * 2.0f / (float)mScreenViewport.width, mBuffers->AmbientHeight * 2.0f / (float)mScreenViewport.height);
|
||||||
|
mLinearDepthShader->Offset[multisample].Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
|
||||||
|
RenderScreenQuad();
|
||||||
|
|
||||||
|
// Apply ambient occlusion
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientRandomTexture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
mSSAOShader->Bind();
|
||||||
|
mSSAOShader->DepthTexture.Set(0);
|
||||||
|
mSSAOShader->RandomTexture.Set(1);
|
||||||
|
mSSAOShader->UVToViewA.Set(2.0f * invFocalLenX, -2.0f * invFocalLenY);
|
||||||
|
mSSAOShader->UVToViewB.Set(-invFocalLenX, invFocalLenY);
|
||||||
|
mSSAOShader->InvFullResolution.Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
|
||||||
|
mSSAOShader->NDotVBias.Set(nDotVBias);
|
||||||
|
mSSAOShader->NegInvR2.Set(-1.0f / r2);
|
||||||
|
mSSAOShader->RadiusToScreen.Set(aoRadius * 0.5 / tanHalfFovy * mBuffers->AmbientHeight);
|
||||||
|
mSSAOShader->AOMultiplier.Set(1.0f / (1.0f - nDotVBias));
|
||||||
|
mSSAOShader->AOStrength.Set(aoStrength);
|
||||||
|
RenderScreenQuad();
|
||||||
|
|
||||||
|
// Blur SSAO texture
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
mDepthBlurShader->Bind(false);
|
||||||
|
mDepthBlurShader->BlurSharpness[false].Set(blurSharpness);
|
||||||
|
mDepthBlurShader->InvFullResolution[false].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
|
||||||
|
RenderScreenQuad();
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture0);
|
||||||
|
mDepthBlurShader->Bind(true);
|
||||||
|
mDepthBlurShader->BlurSharpness[true].Set(blurSharpness);
|
||||||
|
mDepthBlurShader->InvFullResolution[true].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
|
||||||
|
mDepthBlurShader->PowExponent[true].Set(1.8f);
|
||||||
|
RenderScreenQuad();
|
||||||
|
|
||||||
|
// Add SSAO back to scene texture:
|
||||||
|
mBuffers->BindSceneFB(false);
|
||||||
|
GLenum buffers[] = { GL_COLOR_ATTACHMENT0 };
|
||||||
|
glDrawBuffers(1, buffers);
|
||||||
|
glViewport(mSceneViewport.left, mSceneViewport.top, mSceneViewport.width, mSceneViewport.height);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
|
if (gl_ssao_debug)
|
||||||
|
glBlendFunc(GL_ONE, GL_ZERO);
|
||||||
|
else
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
mBuffers->BindSceneDataTexture(1);
|
||||||
|
mSSAOCombineShader->Bind(multisample);
|
||||||
|
mSSAOCombineShader->AODepthTexture[multisample].Set(0);
|
||||||
|
mSSAOCombineShader->SceneDataTexture[multisample].Set(1);
|
||||||
|
if (multisample) mSSAOCombineShader->SampleCount[multisample].Set(gl_multisample);
|
||||||
|
mSSAOCombineShader->Scale[multisample].Set(mBuffers->AmbientWidth * 2.0f / (float)mScreenViewport.width, mBuffers->AmbientHeight * 2.0f / (float)mScreenViewport.height);
|
||||||
|
mSSAOCombineShader->Offset[multisample].Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
|
||||||
|
RenderScreenQuad();
|
||||||
|
|
||||||
|
FGLDebug::PopGroup();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Extracts light average from the scene and updates the camera exposure texture
|
// Extracts light average from the scene and updates the camera exposure texture
|
||||||
|
@ -190,7 +331,7 @@ void FGLRenderer::UpdateCameraExposure()
|
||||||
void FGLRenderer::BloomScene()
|
void FGLRenderer::BloomScene()
|
||||||
{
|
{
|
||||||
// Only bloom things if enabled and no special fixed light mode is active
|
// Only bloom things if enabled and no special fixed light mode is active
|
||||||
if (!gl_bloom || gl_fixedcolormap != CM_DEFAULT)
|
if (!gl_bloom || gl_fixedcolormap != CM_DEFAULT || gl_ssao_debug)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FGLDebug::PushGroup("BloomScene");
|
FGLDebug::PushGroup("BloomScene");
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||||
CVAR(Bool, gl_renderbuffers, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
CVAR(Bool, gl_renderbuffers, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
@ -75,15 +76,16 @@ FGLRenderBuffers::~FGLRenderBuffers()
|
||||||
ClearEyeBuffers();
|
ClearEyeBuffers();
|
||||||
ClearBloom();
|
ClearBloom();
|
||||||
ClearExposureLevels();
|
ClearExposureLevels();
|
||||||
|
ClearAmbientOcclusion();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderBuffers::ClearScene()
|
void FGLRenderBuffers::ClearScene()
|
||||||
{
|
{
|
||||||
DeleteFrameBuffer(mSceneFB);
|
DeleteFrameBuffer(mSceneFB);
|
||||||
DeleteRenderBuffer(mSceneMultisample);
|
DeleteFrameBuffer(mSceneDataFB);
|
||||||
DeleteRenderBuffer(mSceneDepthStencil);
|
DeleteTexture(mSceneMultisample);
|
||||||
DeleteRenderBuffer(mSceneDepth);
|
DeleteTexture(mSceneData);
|
||||||
DeleteRenderBuffer(mSceneStencil);
|
DeleteTexture(mSceneDepthStencil);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderBuffers::ClearPipeline()
|
void FGLRenderBuffers::ClearPipeline()
|
||||||
|
@ -132,6 +134,15 @@ void FGLRenderBuffers::ClearEyeBuffers()
|
||||||
mEyeFBs.Clear();
|
mEyeFBs.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGLRenderBuffers::ClearAmbientOcclusion()
|
||||||
|
{
|
||||||
|
DeleteFrameBuffer(AmbientFB0);
|
||||||
|
DeleteFrameBuffer(AmbientFB1);
|
||||||
|
DeleteTexture(AmbientTexture0);
|
||||||
|
DeleteTexture(AmbientTexture1);
|
||||||
|
DeleteTexture(AmbientRandomTexture);
|
||||||
|
}
|
||||||
|
|
||||||
void FGLRenderBuffers::DeleteTexture(GLuint &handle)
|
void FGLRenderBuffers::DeleteTexture(GLuint &handle)
|
||||||
{
|
{
|
||||||
if (handle != 0)
|
if (handle != 0)
|
||||||
|
@ -203,6 +214,7 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
|
||||||
{
|
{
|
||||||
CreateBloom(sceneWidth, sceneHeight);
|
CreateBloom(sceneWidth, sceneHeight);
|
||||||
CreateExposureLevels(sceneWidth, sceneHeight);
|
CreateExposureLevels(sceneWidth, sceneHeight);
|
||||||
|
CreateAmbientOcclusion(sceneWidth, sceneHeight);
|
||||||
mSceneWidth = sceneWidth;
|
mSceneWidth = sceneWidth;
|
||||||
mSceneHeight = sceneHeight;
|
mSceneHeight = sceneHeight;
|
||||||
}
|
}
|
||||||
|
@ -240,10 +252,19 @@ void FGLRenderBuffers::CreateScene(int width, int height, int samples)
|
||||||
ClearScene();
|
ClearScene();
|
||||||
|
|
||||||
if (samples > 1)
|
if (samples > 1)
|
||||||
mSceneMultisample = CreateRenderBuffer("SceneMultisample", GL_RGBA16F, samples, width, height);
|
{
|
||||||
|
mSceneMultisample = Create2DMultisampleTexture("SceneMultisample", GL_RGBA16F, width, height, samples, false);
|
||||||
|
mSceneDepthStencil = Create2DMultisampleTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height, samples, false);
|
||||||
|
mSceneData = Create2DMultisampleTexture("SceneSSAOData", GL_RGBA8, width, height, samples, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mSceneDepthStencil = Create2DTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height);
|
||||||
|
mSceneData = Create2DTexture("SceneSSAOData", GL_RGBA8, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
mSceneDepthStencil = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, samples, width, height);
|
mSceneFB = CreateFrameBuffer("SceneFB", samples > 1 ? mSceneMultisample : mPipelineTexture[0], 0, mSceneDepthStencil, samples > 1);
|
||||||
mSceneFB = CreateFrameBuffer("SceneFB", samples > 1 ? mSceneMultisample : mPipelineTexture[0], mSceneDepthStencil, samples > 1);
|
mSceneDataFB = CreateFrameBuffer("SSAOSceneFB", samples > 1 ? mSceneMultisample : mPipelineTexture[0], mSceneData, mSceneDepthStencil, samples > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -296,6 +317,47 @@ void FGLRenderBuffers::CreateBloom(int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Creates ambient occlusion working buffers
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height)
|
||||||
|
{
|
||||||
|
ClearAmbientOcclusion();
|
||||||
|
|
||||||
|
if (width <= 0 || height <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AmbientWidth = width / 2;
|
||||||
|
AmbientHeight = height / 2;
|
||||||
|
AmbientTexture0 = Create2DTexture("AmbientTexture0", GL_RG32F, AmbientWidth, AmbientHeight);
|
||||||
|
AmbientTexture1 = Create2DTexture("AmbientTexture1", GL_RG32F, AmbientWidth, AmbientHeight);
|
||||||
|
AmbientFB0 = CreateFrameBuffer("AmbientFB0", AmbientTexture0);
|
||||||
|
AmbientFB1 = CreateFrameBuffer("AmbientFB1", AmbientTexture1);
|
||||||
|
|
||||||
|
int16_t randomValues[16 * 4];
|
||||||
|
std::mt19937 generator(1337);
|
||||||
|
std::uniform_real_distribution<double> distribution(-1.0, 1.0);
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
double num_directions = 8.0; // Must be same as the define in ssao.fp
|
||||||
|
double angle = 2.0 * M_PI * distribution(generator) / num_directions;
|
||||||
|
double x = cos(angle);
|
||||||
|
double y = sin(angle);
|
||||||
|
double z = distribution(generator);
|
||||||
|
double w = distribution(generator);
|
||||||
|
|
||||||
|
randomValues[i * 4 + 0] = (int16_t)clamp(x * 32767.0, -32768.0, 32767.0);
|
||||||
|
randomValues[i * 4 + 1] = (int16_t)clamp(y * 32767.0, -32768.0, 32767.0);
|
||||||
|
randomValues[i * 4 + 2] = (int16_t)clamp(z * 32767.0, -32768.0, 32767.0);
|
||||||
|
randomValues[i * 4 + 3] = (int16_t)clamp(w * 32767.0, -32768.0, 32767.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
AmbientRandomTexture = Create2DTexture("AmbientRandomTexture", GL_RGBA16_SNORM, 4, 4, randomValues);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Creates camera exposure level buffers
|
// Creates camera exposure level buffers
|
||||||
|
@ -368,12 +430,28 @@ void FGLRenderBuffers::CreateEyeBuffers(int eye)
|
||||||
|
|
||||||
GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data)
|
GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data)
|
||||||
{
|
{
|
||||||
GLuint type = (format == GL_RGBA16F || format == GL_R32F) ? GL_FLOAT : GL_UNSIGNED_BYTE;
|
|
||||||
GLuint handle = 0;
|
GLuint handle = 0;
|
||||||
glGenTextures(1, &handle);
|
glGenTextures(1, &handle);
|
||||||
glBindTexture(GL_TEXTURE_2D, handle);
|
glBindTexture(GL_TEXTURE_2D, handle);
|
||||||
FGLDebug::LabelObject(GL_TEXTURE, handle, name);
|
FGLDebug::LabelObject(GL_TEXTURE, handle, name);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format != GL_R32F ? GL_RGBA : GL_RED, type, data);
|
|
||||||
|
GLenum dataformat, datatype;
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case GL_RGBA8: dataformat = GL_RGBA; datatype = GL_UNSIGNED_BYTE; break;
|
||||||
|
case GL_RGBA16: dataformat = GL_RGBA; datatype = GL_UNSIGNED_SHORT; break;
|
||||||
|
case GL_RGBA16F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
|
||||||
|
case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
|
||||||
|
case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break;
|
||||||
|
case GL_RG32F: dataformat = GL_RG; datatype = GL_FLOAT; break;
|
||||||
|
case GL_DEPTH_COMPONENT24: dataformat = GL_DEPTH_COMPONENT; datatype = GL_FLOAT; break;
|
||||||
|
case GL_STENCIL_INDEX8: dataformat = GL_STENCIL_INDEX; datatype = GL_INT; break;
|
||||||
|
case GL_DEPTH24_STENCIL8: dataformat = GL_DEPTH_STENCIL; datatype = GL_UNSIGNED_INT_24_8; break;
|
||||||
|
case GL_RGBA16_SNORM: dataformat = GL_RGBA; datatype = GL_SHORT; break;
|
||||||
|
default: I_FatalError("Unknown format passed to FGLRenderBuffers.Create2DTexture");
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, dataformat, datatype, data);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
@ -381,6 +459,17 @@ GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint FGLRenderBuffers::Create2DMultisampleTexture(const FString &name, GLuint format, int width, int height, int samples, bool fixedSampleLocations)
|
||||||
|
{
|
||||||
|
GLuint handle = 0;
|
||||||
|
glGenTextures(1, &handle);
|
||||||
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, handle);
|
||||||
|
FGLDebug::LabelObject(GL_TEXTURE, handle, name);
|
||||||
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, format, width, height, fixedSampleLocations);
|
||||||
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Creates a render buffer
|
// Creates a render buffer
|
||||||
|
@ -428,34 +517,26 @@ GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuff
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer)
|
GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuffer0, GLuint colorbuffer1, GLuint depthstencil, bool multisample)
|
||||||
{
|
{
|
||||||
GLuint handle = 0;
|
GLuint handle = 0;
|
||||||
glGenFramebuffers(1, &handle);
|
glGenFramebuffers(1, &handle);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, handle);
|
glBindFramebuffer(GL_FRAMEBUFFER, handle);
|
||||||
FGLDebug::LabelObject(GL_FRAMEBUFFER, handle, name);
|
FGLDebug::LabelObject(GL_FRAMEBUFFER, handle, name);
|
||||||
if (colorIsARenderBuffer)
|
if (multisample)
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
|
{
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, colorbuffer0, 0);
|
||||||
|
if (colorbuffer1 != 0)
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, colorbuffer1, 0);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, depthstencil, 0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
|
{
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthstencil);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer0, 0);
|
||||||
if (CheckFrameBufferCompleteness())
|
if (colorbuffer1 != 0)
|
||||||
ClearFrameBuffer(true, true);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, colorbuffer1, 0);
|
||||||
return handle;
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthstencil, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depth, GLuint stencil, bool colorIsARenderBuffer)
|
|
||||||
{
|
|
||||||
GLuint handle = 0;
|
|
||||||
glGenFramebuffers(1, &handle);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, handle);
|
|
||||||
FGLDebug::LabelObject(GL_FRAMEBUFFER, handle, name);
|
|
||||||
if (colorIsARenderBuffer)
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
|
|
||||||
else
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil);
|
|
||||||
if (CheckFrameBufferCompleteness())
|
if (CheckFrameBufferCompleteness())
|
||||||
ClearFrameBuffer(true, true);
|
ClearFrameBuffer(true, true);
|
||||||
return handle;
|
return handle;
|
||||||
|
@ -475,7 +556,8 @@ bool FGLRenderBuffers::CheckFrameBufferCompleteness()
|
||||||
|
|
||||||
FailedCreate = true;
|
FailedCreate = true;
|
||||||
|
|
||||||
#if 0
|
if (gl_debug_level > 0)
|
||||||
|
{
|
||||||
FString error = "glCheckFramebufferStatus failed: ";
|
FString error = "glCheckFramebufferStatus failed: ";
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
|
@ -489,8 +571,8 @@ bool FGLRenderBuffers::CheckFrameBufferCompleteness()
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: error << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; break;
|
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: error << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; break;
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: error << "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; break;
|
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: error << "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; break;
|
||||||
}
|
}
|
||||||
I_FatalError(error);
|
Printf("%s\n", error.GetChars());
|
||||||
#endif
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -595,9 +677,54 @@ void FGLRenderBuffers::BindEyeFB(int eye, bool readBuffer)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FGLRenderBuffers::BindSceneFB()
|
void FGLRenderBuffers::BindSceneFB(bool sceneData)
|
||||||
{
|
{
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB);
|
glBindFramebuffer(GL_FRAMEBUFFER, sceneData ? mSceneDataFB : mSceneFB);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Binds the scene color texture to the specified texture unit
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FGLRenderBuffers::BindSceneColorTexture(int index)
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0 + index);
|
||||||
|
if (mSamples > 1)
|
||||||
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mSceneMultisample);
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mPipelineTexture[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Binds the scene data texture to the specified texture unit
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FGLRenderBuffers::BindSceneDataTexture(int index)
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0 + index);
|
||||||
|
if (mSamples > 1)
|
||||||
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mSceneData);
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mSceneData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Binds the depth texture to the specified texture unit
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FGLRenderBuffers::BindSceneDepthTexture(int index)
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0 + index);
|
||||||
|
if (mSamples > 1)
|
||||||
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mSceneDepthStencil);
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mSceneDepthStencil);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -31,7 +31,10 @@ public:
|
||||||
|
|
||||||
bool Setup(int width, int height, int sceneWidth, int sceneHeight);
|
bool Setup(int width, int height, int sceneWidth, int sceneHeight);
|
||||||
|
|
||||||
void BindSceneFB();
|
void BindSceneFB(bool sceneData);
|
||||||
|
void BindSceneColorTexture(int index);
|
||||||
|
void BindSceneDataTexture(int index);
|
||||||
|
void BindSceneDepthTexture(int index);
|
||||||
void BlitSceneToTexture();
|
void BlitSceneToTexture();
|
||||||
|
|
||||||
void BindCurrentTexture(int index);
|
void BindCurrentTexture(int index);
|
||||||
|
@ -53,28 +56,42 @@ public:
|
||||||
GLuint ExposureFB = 0;
|
GLuint ExposureFB = 0;
|
||||||
bool FirstExposureFrame = true;
|
bool FirstExposureFrame = true;
|
||||||
|
|
||||||
|
// Ambient occlusion buffers
|
||||||
|
GLuint AmbientTexture0 = 0;
|
||||||
|
GLuint AmbientTexture1 = 0;
|
||||||
|
GLuint AmbientFB0 = 0;
|
||||||
|
GLuint AmbientFB1 = 0;
|
||||||
|
int AmbientWidth = 0;
|
||||||
|
int AmbientHeight = 0;
|
||||||
|
GLuint AmbientRandomTexture = 0;
|
||||||
|
|
||||||
static bool IsEnabled();
|
static bool IsEnabled();
|
||||||
|
|
||||||
int GetWidth() const { return mWidth; }
|
int GetWidth() const { return mWidth; }
|
||||||
int GetHeight() const { return mHeight; }
|
int GetHeight() const { return mHeight; }
|
||||||
|
|
||||||
|
int GetSceneWidth() const { return mSceneWidth; }
|
||||||
|
int GetSceneHeight() const { return mSceneHeight; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClearScene();
|
void ClearScene();
|
||||||
void ClearPipeline();
|
void ClearPipeline();
|
||||||
void ClearEyeBuffers();
|
void ClearEyeBuffers();
|
||||||
void ClearBloom();
|
void ClearBloom();
|
||||||
void ClearExposureLevels();
|
void ClearExposureLevels();
|
||||||
|
void ClearAmbientOcclusion();
|
||||||
void CreateScene(int width, int height, int samples);
|
void CreateScene(int width, int height, int samples);
|
||||||
void CreatePipeline(int width, int height);
|
void CreatePipeline(int width, int height);
|
||||||
void CreateBloom(int width, int height);
|
void CreateBloom(int width, int height);
|
||||||
void CreateExposureLevels(int width, int height);
|
void CreateExposureLevels(int width, int height);
|
||||||
void CreateEyeBuffers(int eye);
|
void CreateEyeBuffers(int eye);
|
||||||
|
void CreateAmbientOcclusion(int width, int height);
|
||||||
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data = nullptr);
|
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data = nullptr);
|
||||||
|
GLuint Create2DMultisampleTexture(const FString &name, GLuint format, int width, int height, int samples, bool fixedSampleLocations);
|
||||||
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height);
|
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height);
|
||||||
GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height);
|
GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height);
|
||||||
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer);
|
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer);
|
||||||
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer);
|
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer0, GLuint colorbuffer1, GLuint depthstencil, bool multisample);
|
||||||
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depth, GLuint stencil, bool colorIsARenderBuffer);
|
|
||||||
bool CheckFrameBufferCompleteness();
|
bool CheckFrameBufferCompleteness();
|
||||||
void ClearFrameBuffer(bool stencil, bool depth);
|
void ClearFrameBuffer(bool stencil, bool depth);
|
||||||
void DeleteTexture(GLuint &handle);
|
void DeleteTexture(GLuint &handle);
|
||||||
|
@ -94,9 +111,9 @@ private:
|
||||||
// Buffers for the scene
|
// Buffers for the scene
|
||||||
GLuint mSceneMultisample = 0;
|
GLuint mSceneMultisample = 0;
|
||||||
GLuint mSceneDepthStencil = 0;
|
GLuint mSceneDepthStencil = 0;
|
||||||
GLuint mSceneDepth = 0;
|
GLuint mSceneData = 0;
|
||||||
GLuint mSceneStencil = 0;
|
|
||||||
GLuint mSceneFB = 0;
|
GLuint mSceneFB = 0;
|
||||||
|
GLuint mSceneDataFB = 0;
|
||||||
|
|
||||||
// Effect/HUD buffers
|
// Effect/HUD buffers
|
||||||
GLuint mPipelineTexture[NumPipelineTextures];
|
GLuint mPipelineTexture[NumPipelineTextures];
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "gl/data/gl_vertexbuffer.h"
|
#include "gl/data/gl_vertexbuffer.h"
|
||||||
#include "gl/scene/gl_drawinfo.h"
|
#include "gl/scene/gl_drawinfo.h"
|
||||||
#include "gl/shaders/gl_shader.h"
|
#include "gl/shaders/gl_shader.h"
|
||||||
|
#include "gl/shaders/gl_ambientshader.h"
|
||||||
#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"
|
||||||
|
@ -113,6 +114,10 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
|
||||||
mTonemapPalette = nullptr;
|
mTonemapPalette = nullptr;
|
||||||
mColormapShader = nullptr;
|
mColormapShader = nullptr;
|
||||||
mLensShader = nullptr;
|
mLensShader = nullptr;
|
||||||
|
mLinearDepthShader = nullptr;
|
||||||
|
mDepthBlurShader = nullptr;
|
||||||
|
mSSAOShader = nullptr;
|
||||||
|
mSSAOCombineShader = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gl_LoadModels();
|
void gl_LoadModels();
|
||||||
|
@ -121,6 +126,10 @@ void gl_FlushModels();
|
||||||
void FGLRenderer::Initialize(int width, int height)
|
void FGLRenderer::Initialize(int width, int height)
|
||||||
{
|
{
|
||||||
mBuffers = new FGLRenderBuffers();
|
mBuffers = new FGLRenderBuffers();
|
||||||
|
mLinearDepthShader = new FLinearDepthShader();
|
||||||
|
mDepthBlurShader = new FDepthBlurShader();
|
||||||
|
mSSAOShader = new FSSAOShader();
|
||||||
|
mSSAOCombineShader = new FSSAOCombineShader();
|
||||||
mBloomExtractShader = new FBloomExtractShader();
|
mBloomExtractShader = new FBloomExtractShader();
|
||||||
mBloomCombineShader = new FBloomCombineShader();
|
mBloomCombineShader = new FBloomCombineShader();
|
||||||
mExposureExtractShader = new FExposureExtractShader();
|
mExposureExtractShader = new FExposureExtractShader();
|
||||||
|
@ -184,6 +193,10 @@ FGLRenderer::~FGLRenderer()
|
||||||
}
|
}
|
||||||
if (mBuffers) delete mBuffers;
|
if (mBuffers) delete mBuffers;
|
||||||
if (mPresentShader) delete mPresentShader;
|
if (mPresentShader) delete mPresentShader;
|
||||||
|
if (mLinearDepthShader) delete mLinearDepthShader;
|
||||||
|
if (mDepthBlurShader) delete mDepthBlurShader;
|
||||||
|
if (mSSAOShader) delete mSSAOShader;
|
||||||
|
if (mSSAOCombineShader) delete mSSAOCombineShader;
|
||||||
if (mBloomExtractShader) delete mBloomExtractShader;
|
if (mBloomExtractShader) delete mBloomExtractShader;
|
||||||
if (mBloomCombineShader) delete mBloomCombineShader;
|
if (mBloomCombineShader) delete mBloomCombineShader;
|
||||||
if (mExposureExtractShader) delete mExposureExtractShader;
|
if (mExposureExtractShader) delete mExposureExtractShader;
|
||||||
|
@ -310,7 +323,7 @@ void FGLRenderer::Begin2D()
|
||||||
if (mBuffers->Setup(mScreenViewport.width, mScreenViewport.height, mSceneViewport.width, mSceneViewport.height))
|
if (mBuffers->Setup(mScreenViewport.width, mScreenViewport.height, mSceneViewport.width, mSceneViewport.height))
|
||||||
{
|
{
|
||||||
if (mDrawingScene2D)
|
if (mDrawingScene2D)
|
||||||
mBuffers->BindSceneFB();
|
mBuffers->BindSceneFB(false);
|
||||||
else
|
else
|
||||||
mBuffers->BindCurrentFB();
|
mBuffers->BindCurrentFB();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@ class FLightBuffer;
|
||||||
class FSamplerManager;
|
class FSamplerManager;
|
||||||
class DPSprite;
|
class DPSprite;
|
||||||
class FGLRenderBuffers;
|
class FGLRenderBuffers;
|
||||||
|
class FLinearDepthShader;
|
||||||
|
class FDepthBlurShader;
|
||||||
|
class FSSAOShader;
|
||||||
|
class FSSAOCombineShader;
|
||||||
class FBloomExtractShader;
|
class FBloomExtractShader;
|
||||||
class FBloomCombineShader;
|
class FBloomCombineShader;
|
||||||
class FExposureExtractShader;
|
class FExposureExtractShader;
|
||||||
|
@ -93,6 +97,10 @@ public:
|
||||||
int mOldFBID;
|
int mOldFBID;
|
||||||
|
|
||||||
FGLRenderBuffers *mBuffers;
|
FGLRenderBuffers *mBuffers;
|
||||||
|
FLinearDepthShader *mLinearDepthShader;
|
||||||
|
FSSAOShader *mSSAOShader;
|
||||||
|
FDepthBlurShader *mDepthBlurShader;
|
||||||
|
FSSAOCombineShader *mSSAOCombineShader;
|
||||||
FBloomExtractShader *mBloomExtractShader;
|
FBloomExtractShader *mBloomExtractShader;
|
||||||
FBloomCombineShader *mBloomCombineShader;
|
FBloomCombineShader *mBloomCombineShader;
|
||||||
FExposureExtractShader *mExposureExtractShader;
|
FExposureExtractShader *mExposureExtractShader;
|
||||||
|
@ -171,6 +179,8 @@ public:
|
||||||
void SetFixedColormap (player_t *player);
|
void SetFixedColormap (player_t *player);
|
||||||
void WriteSavePic (player_t *player, FileWriter *file, int width, int height);
|
void WriteSavePic (player_t *player, FileWriter *file, int width, int height);
|
||||||
void EndDrawScene(sector_t * viewsector);
|
void EndDrawScene(sector_t * viewsector);
|
||||||
|
void PostProcessScene();
|
||||||
|
void AmbientOccludeScene();
|
||||||
void UpdateCameraExposure();
|
void UpdateCameraExposure();
|
||||||
void BloomScene();
|
void BloomScene();
|
||||||
void TonemapScene();
|
void TonemapScene();
|
||||||
|
@ -198,6 +208,9 @@ public:
|
||||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel);
|
DAngle rotation, FDynamicColormap *colormap, int lightlevel);
|
||||||
|
|
||||||
int PTM_BestColor (const uint32 *pal_in, int r, int g, int b, int first, int num);
|
int PTM_BestColor (const uint32 *pal_in, int r, int g, int b, int first, int num);
|
||||||
|
|
||||||
|
static float GetZNear() { return 5.f; }
|
||||||
|
static float GetZFar() { return 65536.f; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global functions. Make them members of GLRenderer later?
|
// Global functions. Make them members of GLRenderer later?
|
||||||
|
|
|
@ -105,6 +105,7 @@ void FRenderState::Reset()
|
||||||
mViewMatrix.loadIdentity();
|
mViewMatrix.loadIdentity();
|
||||||
mModelMatrix.loadIdentity();
|
mModelMatrix.loadIdentity();
|
||||||
mTextureMatrix.loadIdentity();
|
mTextureMatrix.loadIdentity();
|
||||||
|
mPassType = NORMAL_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -118,11 +119,11 @@ bool FRenderState::ApplyShader()
|
||||||
static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f };
|
static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f };
|
||||||
if (mSpecialEffect > EFF_NONE)
|
if (mSpecialEffect > EFF_NONE)
|
||||||
{
|
{
|
||||||
activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect);
|
activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect, mPassType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : 4, mAlphaThreshold >= 0.f);
|
activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : 4, mAlphaThreshold >= 0.f, mPassType);
|
||||||
activeShader->Bind();
|
activeShader->Bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +157,7 @@ bool FRenderState::ApplyShader()
|
||||||
activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f);
|
activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f);
|
||||||
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
|
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
|
||||||
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
|
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
|
||||||
|
activeShader->muLightMath.Set(gl_light_math);
|
||||||
activeShader->muClipSplit.Set(mClipSplit);
|
activeShader->muClipSplit.Set(mClipSplit);
|
||||||
|
|
||||||
if (mGlowEnabled)
|
if (mGlowEnabled)
|
||||||
|
@ -342,7 +344,7 @@ void FRenderState::ApplyMatrices()
|
||||||
{
|
{
|
||||||
if (GLRenderer->mShaderManager != NULL)
|
if (GLRenderer->mShaderManager != NULL)
|
||||||
{
|
{
|
||||||
GLRenderer->mShaderManager->ApplyMatrices(&mProjectionMatrix, &mViewMatrix);
|
GLRenderer->mShaderManager->ApplyMatrices(&mProjectionMatrix, &mViewMatrix, mPassType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,13 @@ enum EEffect
|
||||||
MAX_EFFECTS
|
MAX_EFFECTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EPassType
|
||||||
|
{
|
||||||
|
NORMAL_PASS,
|
||||||
|
GBUFFER_PASS,
|
||||||
|
MAX_PASS_TYPES
|
||||||
|
};
|
||||||
|
|
||||||
class FRenderState
|
class FRenderState
|
||||||
{
|
{
|
||||||
bool mTextureEnabled;
|
bool mTextureEnabled;
|
||||||
|
@ -111,6 +118,8 @@ class FRenderState
|
||||||
|
|
||||||
FShader *activeShader;
|
FShader *activeShader;
|
||||||
|
|
||||||
|
EPassType mPassType = NORMAL_PASS;
|
||||||
|
|
||||||
bool ApplyShader();
|
bool ApplyShader();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -459,6 +468,16 @@ public:
|
||||||
return mInterpolationFactor;
|
return mInterpolationFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetPassType(EPassType passType)
|
||||||
|
{
|
||||||
|
mPassType = passType;
|
||||||
|
}
|
||||||
|
|
||||||
|
EPassType GetPassType()
|
||||||
|
{
|
||||||
|
return mPassType;
|
||||||
|
}
|
||||||
|
|
||||||
// Backwards compatibility crap follows
|
// Backwards compatibility crap follows
|
||||||
void ApplyFixedFunction();
|
void ApplyFixedFunction();
|
||||||
void DrawColormapOverlay();
|
void DrawColormapOverlay();
|
||||||
|
|
|
@ -423,14 +423,16 @@ void GLPortal::End(bool usestencil)
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
glDepthRange(0, 1);
|
glDepthRange(0, 1);
|
||||||
{
|
{
|
||||||
ScopedColorMask colorMask(0, 0, 0, 0);
|
ScopedColorMask colorMask(0, 0, 0, 1); // mark portal in alpha channel but don't touch color
|
||||||
// glColorMask(0,0,0,0); // no graphics
|
|
||||||
gl_RenderState.SetEffect(EFF_STENCIL);
|
gl_RenderState.SetEffect(EFF_STENCIL);
|
||||||
gl_RenderState.EnableTexture(false);
|
gl_RenderState.EnableTexture(false);
|
||||||
|
gl_RenderState.BlendFunc(GL_ONE, GL_ZERO);
|
||||||
|
gl_RenderState.BlendEquation(GL_FUNC_ADD);
|
||||||
|
gl_RenderState.Apply();
|
||||||
DrawPortalStencil();
|
DrawPortalStencil();
|
||||||
gl_RenderState.SetEffect(EFF_NONE);
|
gl_RenderState.SetEffect(EFF_NONE);
|
||||||
gl_RenderState.EnableTexture(true);
|
gl_RenderState.EnableTexture(true);
|
||||||
} // glColorMask(1, 1, 1, 1);
|
}
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
}
|
}
|
||||||
PortalAll.Unclock();
|
PortalAll.Unclock();
|
||||||
|
|
|
@ -158,7 +158,11 @@ void FGLRenderer::Set3DViewport(bool mainview)
|
||||||
{
|
{
|
||||||
if (mainview && mBuffers->Setup(mScreenViewport.width, mScreenViewport.height, mSceneViewport.width, mSceneViewport.height))
|
if (mainview && mBuffers->Setup(mScreenViewport.width, mScreenViewport.height, mSceneViewport.width, mSceneViewport.height))
|
||||||
{
|
{
|
||||||
mBuffers->BindSceneFB();
|
mBuffers->BindSceneFB(gl_ssao);
|
||||||
|
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
|
||||||
|
glDrawBuffers(gl_ssao ? 2 : 1, buffers);
|
||||||
|
gl_RenderState.SetPassType(gl_ssao ? GBUFFER_PASS : NORMAL_PASS);
|
||||||
|
gl_RenderState.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always clear all buffers with scissor test disabled.
|
// Always clear all buffers with scissor test disabled.
|
||||||
|
@ -209,7 +213,7 @@ void FGLRenderer::SetProjection(float fov, float ratio, float fovratio)
|
||||||
{
|
{
|
||||||
|
|
||||||
float fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovratio));
|
float fovy = 2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovratio));
|
||||||
gl_RenderState.mProjectionMatrix.perspective(fovy, ratio, 5.f, 65536.f);
|
gl_RenderState.mProjectionMatrix.perspective(fovy, ratio, GetZNear(), GetZFar());
|
||||||
}
|
}
|
||||||
|
|
||||||
// raw matrix input from stereo 3d modes
|
// raw matrix input from stereo 3d modes
|
||||||
|
@ -489,8 +493,31 @@ void FGLRenderer::DrawScene(int drawmode)
|
||||||
}
|
}
|
||||||
GLRenderer->mClipPortal = NULL; // this must be reset before any portal recursion takes place.
|
GLRenderer->mClipPortal = NULL; // this must be reset before any portal recursion takes place.
|
||||||
|
|
||||||
|
// If SSAO is active, switch to gbuffer shaders and use the gbuffer framebuffer
|
||||||
|
bool applySSAO = gl_ssao && FGLRenderBuffers::IsEnabled() && drawmode == DM_MAINVIEW;
|
||||||
|
if (applySSAO)
|
||||||
|
{
|
||||||
|
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
|
||||||
|
glDrawBuffers(2, buffers);
|
||||||
|
gl_RenderState.SetPassType(GBUFFER_PASS);
|
||||||
|
gl_RenderState.Apply();
|
||||||
|
gl_RenderState.ApplyMatrices();
|
||||||
|
}
|
||||||
|
|
||||||
RenderScene(recursion);
|
RenderScene(recursion);
|
||||||
|
|
||||||
|
// Apply ambient occlusion and switch back to shaders without gbuffer output
|
||||||
|
if (applySSAO)
|
||||||
|
{
|
||||||
|
GLenum buffers[] = { GL_COLOR_ATTACHMENT0 };
|
||||||
|
glDrawBuffers(1, buffers);
|
||||||
|
AmbientOccludeScene();
|
||||||
|
mBuffers->BindSceneFB(true);
|
||||||
|
gl_RenderState.SetPassType(NORMAL_PASS);
|
||||||
|
gl_RenderState.Apply();
|
||||||
|
gl_RenderState.ApplyMatrices();
|
||||||
|
}
|
||||||
|
|
||||||
// Handle all portals after rendering the opaque objects but before
|
// Handle all portals after rendering the opaque objects but before
|
||||||
// doing all translucent stuff
|
// doing all translucent stuff
|
||||||
recursion++;
|
recursion++;
|
||||||
|
@ -826,12 +853,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
|
||||||
if (mainview && toscreen) EndDrawScene(lviewsector); // do not call this for camera textures.
|
if (mainview && toscreen) EndDrawScene(lviewsector); // do not call this for camera textures.
|
||||||
if (mainview && FGLRenderBuffers::IsEnabled())
|
if (mainview && FGLRenderBuffers::IsEnabled())
|
||||||
{
|
{
|
||||||
mBuffers->BlitSceneToTexture();
|
PostProcessScene();
|
||||||
UpdateCameraExposure();
|
|
||||||
BloomScene();
|
|
||||||
TonemapScene();
|
|
||||||
ColormapScene();
|
|
||||||
LensDistortScene();
|
|
||||||
|
|
||||||
// This should be done after postprocessing, not before.
|
// This should be done after postprocessing, not before.
|
||||||
mBuffers->BindCurrentFB();
|
mBuffers->BindCurrentFB();
|
||||||
|
|
140
src/gl/shaders/gl_ambientshader.cpp
Normal file
140
src/gl/shaders/gl_ambientshader.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
** gl_bloomshader.cpp
|
||||||
|
** Shaders used for screen space ambient occlusion
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** 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_ambientshader.h"
|
||||||
|
|
||||||
|
void FLinearDepthShader::Bind(bool multisample)
|
||||||
|
{
|
||||||
|
auto &shader = mShader[multisample];
|
||||||
|
if (!shader)
|
||||||
|
{
|
||||||
|
shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
||||||
|
shader.Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", multisample ? "#define MULTISAMPLE\n" : "", 330);
|
||||||
|
shader.SetFragDataLocation(0, "FragColor");
|
||||||
|
shader.Link("shaders/glsl/lineardepth");
|
||||||
|
shader.SetAttribLocation(0, "PositionInProjection");
|
||||||
|
DepthTexture[multisample].Init(shader, "DepthTexture");
|
||||||
|
ColorTexture[multisample].Init(shader, "ColorTexture");
|
||||||
|
SampleCount[multisample].Init(shader, "SampleCount");
|
||||||
|
LinearizeDepthA[multisample].Init(shader, "LinearizeDepthA");
|
||||||
|
LinearizeDepthB[multisample].Init(shader, "LinearizeDepthB");
|
||||||
|
InverseDepthRangeA[multisample].Init(shader, "InverseDepthRangeA");
|
||||||
|
InverseDepthRangeB[multisample].Init(shader, "InverseDepthRangeB");
|
||||||
|
Scale[multisample].Init(shader, "Scale");
|
||||||
|
Offset[multisample].Init(shader, "Offset");
|
||||||
|
}
|
||||||
|
shader.Bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSSAOShader::Bind()
|
||||||
|
{
|
||||||
|
if (!mShader)
|
||||||
|
{
|
||||||
|
const char *defines = R"(
|
||||||
|
#define USE_RANDOM_TEXTURE
|
||||||
|
#define RANDOM_TEXTURE_WIDTH 4.0
|
||||||
|
#define NUM_DIRECTIONS 8.0
|
||||||
|
#define NUM_STEPS 4.0
|
||||||
|
)";
|
||||||
|
|
||||||
|
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
||||||
|
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", defines, 330);
|
||||||
|
mShader.SetFragDataLocation(0, "FragColor");
|
||||||
|
mShader.Link("shaders/glsl/ssao");
|
||||||
|
mShader.SetAttribLocation(0, "PositionInProjection");
|
||||||
|
DepthTexture.Init(mShader, "DepthTexture");
|
||||||
|
RandomTexture.Init(mShader, "RandomTexture");
|
||||||
|
UVToViewA.Init(mShader, "UVToViewA");
|
||||||
|
UVToViewB.Init(mShader, "UVToViewB");
|
||||||
|
InvFullResolution.Init(mShader, "InvFullResolution");
|
||||||
|
NDotVBias.Init(mShader, "NDotVBias");
|
||||||
|
NegInvR2.Init(mShader, "NegInvR2");
|
||||||
|
RadiusToScreen.Init(mShader, "RadiusToScreen");
|
||||||
|
AOMultiplier.Init(mShader, "AOMultiplier");
|
||||||
|
AOStrength.Init(mShader, "AOStrength");
|
||||||
|
}
|
||||||
|
mShader.Bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FDepthBlurShader::Bind(bool vertical)
|
||||||
|
{
|
||||||
|
auto &shader = mShader[vertical];
|
||||||
|
if (!shader)
|
||||||
|
{
|
||||||
|
shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
||||||
|
shader.Compile(FShaderProgram::Fragment, "shaders/glsl/depthblur.fp", vertical ? "#define BLUR_VERTICAL\n" : "#define BLUR_HORIZONTAL\n", 330);
|
||||||
|
shader.SetFragDataLocation(0, "FragColor");
|
||||||
|
shader.Link("shaders/glsl/depthblur");
|
||||||
|
shader.SetAttribLocation(0, "PositionInProjection");
|
||||||
|
AODepthTexture[vertical].Init(shader, "AODepthTexture");
|
||||||
|
BlurSharpness[vertical].Init(shader, "BlurSharpness");
|
||||||
|
InvFullResolution[vertical].Init(shader, "InvFullResolution");
|
||||||
|
PowExponent[vertical].Init(shader, "PowExponent");
|
||||||
|
}
|
||||||
|
shader.Bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSSAOCombineShader::Bind(bool multisample)
|
||||||
|
{
|
||||||
|
auto &shader = mShader[multisample];
|
||||||
|
if (!shader)
|
||||||
|
{
|
||||||
|
shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
||||||
|
shader.Compile(FShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", multisample ? "#define MULTISAMPLE\n" : "", 330);
|
||||||
|
shader.SetFragDataLocation(0, "FragColor");
|
||||||
|
shader.Link("shaders/glsl/ssaocombine");
|
||||||
|
shader.SetAttribLocation(0, "PositionInProjection");
|
||||||
|
AODepthTexture[multisample].Init(shader, "AODepthTexture");
|
||||||
|
SceneDataTexture[multisample].Init(shader, "SceneDataTexture");
|
||||||
|
SampleCount[multisample].Init(shader, "SampleCount");
|
||||||
|
Scale[multisample].Init(shader, "Scale");
|
||||||
|
Offset[multisample].Init(shader, "Offset");
|
||||||
|
}
|
||||||
|
shader.Bind();
|
||||||
|
}
|
74
src/gl/shaders/gl_ambientshader.h
Normal file
74
src/gl/shaders/gl_ambientshader.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef __GL_AMBIENTSHADER_H
|
||||||
|
#define __GL_AMBIENTSHADER_H
|
||||||
|
|
||||||
|
#include "gl_shaderprogram.h"
|
||||||
|
|
||||||
|
class FLinearDepthShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Bind(bool multisample);
|
||||||
|
|
||||||
|
FBufferedUniformSampler DepthTexture[2];
|
||||||
|
FBufferedUniformSampler ColorTexture[2];
|
||||||
|
FBufferedUniform1i SampleCount[2];
|
||||||
|
FBufferedUniform1f LinearizeDepthA[2];
|
||||||
|
FBufferedUniform1f LinearizeDepthB[2];
|
||||||
|
FBufferedUniform1f InverseDepthRangeA[2];
|
||||||
|
FBufferedUniform1f InverseDepthRangeB[2];
|
||||||
|
FBufferedUniform2f Scale[2];
|
||||||
|
FBufferedUniform2f Offset[2];
|
||||||
|
|
||||||
|
private:
|
||||||
|
FShaderProgram mShader[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
class FSSAOShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Bind();
|
||||||
|
|
||||||
|
FBufferedUniformSampler DepthTexture;
|
||||||
|
FBufferedUniformSampler RandomTexture;
|
||||||
|
FBufferedUniform2f UVToViewA;
|
||||||
|
FBufferedUniform2f UVToViewB;
|
||||||
|
FBufferedUniform2f InvFullResolution;
|
||||||
|
FBufferedUniform1f NDotVBias;
|
||||||
|
FBufferedUniform1f NegInvR2;
|
||||||
|
FBufferedUniform1f RadiusToScreen;
|
||||||
|
FBufferedUniform1f AOMultiplier;
|
||||||
|
FBufferedUniform1f AOStrength;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FShaderProgram mShader;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FDepthBlurShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Bind(bool vertical);
|
||||||
|
|
||||||
|
FBufferedUniformSampler AODepthTexture[2];
|
||||||
|
FBufferedUniform1f BlurSharpness[2];
|
||||||
|
FBufferedUniform2f InvFullResolution[2];
|
||||||
|
FBufferedUniform1f PowExponent[2];
|
||||||
|
|
||||||
|
private:
|
||||||
|
FShaderProgram mShader[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
class FSSAOCombineShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Bind(bool multisample);
|
||||||
|
|
||||||
|
FBufferedUniformSampler AODepthTexture[2];
|
||||||
|
FBufferedUniformSampler SceneDataTexture[2];
|
||||||
|
FBufferedUniform1i SampleCount[2];
|
||||||
|
FBufferedUniform2f Scale[2];
|
||||||
|
FBufferedUniform2f Offset[2];
|
||||||
|
|
||||||
|
private:
|
||||||
|
FShaderProgram mShader[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -180,6 +180,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
||||||
glBindAttribLocation(hShader, VATTR_COLOR, "aColor");
|
glBindAttribLocation(hShader, VATTR_COLOR, "aColor");
|
||||||
glBindAttribLocation(hShader, VATTR_VERTEX2, "aVertex2");
|
glBindAttribLocation(hShader, VATTR_VERTEX2, "aVertex2");
|
||||||
|
|
||||||
|
glBindFragDataLocation(hShader, 0, "FragColor");
|
||||||
|
glBindFragDataLocation(hShader, 1, "FragData");
|
||||||
|
|
||||||
glLinkProgram(hShader);
|
glLinkProgram(hShader);
|
||||||
|
|
||||||
glGetShaderInfoLog(hVertProg, 10000, NULL, buffer);
|
glGetShaderInfoLog(hVertProg, 10000, NULL, buffer);
|
||||||
|
@ -216,6 +219,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
||||||
muColormapStart.Init(hShader, "uFixedColormapStart");
|
muColormapStart.Init(hShader, "uFixedColormapStart");
|
||||||
muColormapRange.Init(hShader, "uFixedColormapRange");
|
muColormapRange.Init(hShader, "uFixedColormapRange");
|
||||||
muLightIndex.Init(hShader, "uLightIndex");
|
muLightIndex.Init(hShader, "uLightIndex");
|
||||||
|
muLightMath.Init(hShader, "uLightMath");
|
||||||
muFogColor.Init(hShader, "uFogColor");
|
muFogColor.Init(hShader, "uFogColor");
|
||||||
muDynLightColor.Init(hShader, "uDynLightColor");
|
muDynLightColor.Init(hShader, "uDynLightColor");
|
||||||
muObjectColor.Init(hShader, "uObjectColor");
|
muObjectColor.Init(hShader, "uObjectColor");
|
||||||
|
@ -297,12 +301,13 @@ bool FShader::Bind()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FShader *FShaderManager::Compile (const char *ShaderName, const char *ShaderPath, bool usediscard)
|
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, bool usediscard, EPassType passType)
|
||||||
{
|
{
|
||||||
FString defines;
|
FString defines;
|
||||||
// this can't be in the shader code due to ATI strangeness.
|
// this can't be in the shader code due to ATI strangeness.
|
||||||
if (gl.MaxLights() == 128) defines += "#define MAXLIGHTS128\n";
|
if (gl.MaxLights() == 128) defines += "#define MAXLIGHTS128\n";
|
||||||
if (!usediscard) defines += "#define NO_ALPHATEST\n";
|
if (!usediscard) defines += "#define NO_ALPHATEST\n";
|
||||||
|
if (passType == GBUFFER_PASS) defines += "#define GBUFFER_PASS\n";
|
||||||
|
|
||||||
FShader *shader = NULL;
|
FShader *shader = NULL;
|
||||||
try
|
try
|
||||||
|
@ -385,27 +390,75 @@ static const FEffectShader effectshaders[]=
|
||||||
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", NULL, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", NULL, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
FShaderManager::FShaderManager()
|
FShaderManager::FShaderManager()
|
||||||
{
|
{
|
||||||
if (!gl.legacyMode) CompileShaders();
|
if (!gl.legacyMode)
|
||||||
|
{
|
||||||
|
for (int passType = 0; passType < MAX_PASS_TYPES; passType++)
|
||||||
|
mPassShaders.Push(new FShaderCollection((EPassType)passType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
FShaderManager::~FShaderManager()
|
FShaderManager::~FShaderManager()
|
||||||
{
|
{
|
||||||
if (!gl.legacyMode) Clean();
|
if (!gl.legacyMode)
|
||||||
|
{
|
||||||
|
glUseProgram(0);
|
||||||
|
mActiveShader = NULL;
|
||||||
|
|
||||||
|
for (auto collection : mPassShaders)
|
||||||
|
delete collection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FShaderManager::SetActiveShader(FShader *sh)
|
||||||
|
{
|
||||||
|
if (mActiveShader != sh)
|
||||||
|
{
|
||||||
|
glUseProgram(sh!= NULL? sh->GetHandle() : 0);
|
||||||
|
mActiveShader = sh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FShader *FShaderManager::BindEffect(int effect, EPassType passType)
|
||||||
|
{
|
||||||
|
if (passType < mPassShaders.Size())
|
||||||
|
return mPassShaders[passType]->BindEffect(effect);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
|
||||||
|
{
|
||||||
|
if (passType < mPassShaders.Size())
|
||||||
|
return mPassShaders[passType]->Get(eff, alphateston);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FShaderManager::ApplyMatrices(VSMatrix *proj, VSMatrix *view, EPassType passType)
|
||||||
|
{
|
||||||
|
if (gl.legacyMode)
|
||||||
|
{
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadMatrixf(proj->get());
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadMatrixf(view->get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (passType < mPassShaders.Size())
|
||||||
|
mPassShaders[passType]->ApplyMatrices(proj, view);
|
||||||
|
|
||||||
|
if (mActiveShader)
|
||||||
|
mActiveShader->Bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FShaderManager::ResetFixedColormap()
|
||||||
|
{
|
||||||
|
for (auto &collection : mPassShaders)
|
||||||
|
collection->ResetFixedColormap();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -414,10 +467,30 @@ FShaderManager::~FShaderManager()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FShaderManager::CompileShaders()
|
FShaderCollection::FShaderCollection(EPassType passType)
|
||||||
{
|
{
|
||||||
mActiveShader = NULL;
|
CompileShaders(passType);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FShaderCollection::~FShaderCollection()
|
||||||
|
{
|
||||||
|
Clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FShaderCollection::CompileShaders(EPassType passType)
|
||||||
|
{
|
||||||
mTextureEffects.Clear();
|
mTextureEffects.Clear();
|
||||||
mTextureEffectsNAT.Clear();
|
mTextureEffectsNAT.Clear();
|
||||||
for (int i = 0; i < MAX_EFFECTS; i++)
|
for (int i = 0; i < MAX_EFFECTS; i++)
|
||||||
|
@ -427,11 +500,11 @@ void FShaderManager::CompileShaders()
|
||||||
|
|
||||||
for(int i=0;defaultshaders[i].ShaderName != NULL;i++)
|
for(int i=0;defaultshaders[i].ShaderName != NULL;i++)
|
||||||
{
|
{
|
||||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, true);
|
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, true, passType);
|
||||||
mTextureEffects.Push(shc);
|
mTextureEffects.Push(shc);
|
||||||
if (i <= 3)
|
if (i <= 3)
|
||||||
{
|
{
|
||||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, false);
|
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, false, passType);
|
||||||
mTextureEffectsNAT.Push(shc);
|
mTextureEffectsNAT.Push(shc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,7 +514,7 @@ void FShaderManager::CompileShaders()
|
||||||
FString name = ExtractFileBase(usershaders[i]);
|
FString name = ExtractFileBase(usershaders[i]);
|
||||||
FName sfn = name;
|
FName sfn = name;
|
||||||
|
|
||||||
FShader *shc = Compile(sfn, usershaders[i], true);
|
FShader *shc = Compile(sfn, usershaders[i], true, passType);
|
||||||
mTextureEffects.Push(shc);
|
mTextureEffects.Push(shc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,11 +536,8 @@ void FShaderManager::CompileShaders()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FShaderManager::Clean()
|
void FShaderCollection::Clean()
|
||||||
{
|
{
|
||||||
glUseProgram(0);
|
|
||||||
mActiveShader = NULL;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mTextureEffectsNAT.Size(); i++)
|
for (unsigned int i = 0; i < mTextureEffectsNAT.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mTextureEffectsNAT[i] != NULL) delete mTextureEffectsNAT[i];
|
if (mTextureEffectsNAT[i] != NULL) delete mTextureEffectsNAT[i];
|
||||||
|
@ -491,7 +561,7 @@ void FShaderManager::Clean()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int FShaderManager::Find(const char * shn)
|
int FShaderCollection::Find(const char * shn)
|
||||||
{
|
{
|
||||||
FName sfn = shn;
|
FName sfn = shn;
|
||||||
|
|
||||||
|
@ -505,21 +575,6 @@ int FShaderManager::Find(const char * shn)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FShaderManager::SetActiveShader(FShader *sh)
|
|
||||||
{
|
|
||||||
if (mActiveShader != sh)
|
|
||||||
{
|
|
||||||
glUseProgram(sh!= NULL? sh->GetHandle() : 0);
|
|
||||||
mActiveShader = sh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -527,7 +582,7 @@ void FShaderManager::SetActiveShader(FShader *sh)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FShader *FShaderManager::BindEffect(int effect)
|
FShader *FShaderCollection::BindEffect(int effect)
|
||||||
{
|
{
|
||||||
if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[effect] != NULL)
|
if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[effect] != NULL)
|
||||||
{
|
{
|
||||||
|
@ -545,17 +600,8 @@ FShader *FShaderManager::BindEffect(int effect)
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
EXTERN_CVAR(Int, gl_fuzztype)
|
EXTERN_CVAR(Int, gl_fuzztype)
|
||||||
|
|
||||||
void FShaderManager::ApplyMatrices(VSMatrix *proj, VSMatrix *view)
|
void FShaderCollection::ApplyMatrices(VSMatrix *proj, VSMatrix *view)
|
||||||
{
|
{
|
||||||
if (gl.legacyMode)
|
|
||||||
{
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadMatrixf(proj->get());
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadMatrixf(view->get());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
mTextureEffects[i]->ApplyMatrices(proj, view);
|
mTextureEffects[i]->ApplyMatrices(proj, view);
|
||||||
|
@ -574,8 +620,6 @@ void FShaderManager::ApplyMatrices(VSMatrix *proj, VSMatrix *view)
|
||||||
{
|
{
|
||||||
mEffectShaders[i]->ApplyMatrices(proj, view);
|
mEffectShaders[i]->ApplyMatrices(proj, view);
|
||||||
}
|
}
|
||||||
if (mActiveShader != NULL) mActiveShader->Bind();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -37,6 +37,7 @@ enum
|
||||||
VATTR_NORMAL = 4
|
VATTR_NORMAL = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FShaderCollection;
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -248,7 +249,7 @@ public:
|
||||||
|
|
||||||
class FShader
|
class FShader
|
||||||
{
|
{
|
||||||
friend class FShaderManager;
|
friend class FShaderCollection;
|
||||||
friend class FRenderState;
|
friend class FRenderState;
|
||||||
|
|
||||||
unsigned int hShader;
|
unsigned int hShader;
|
||||||
|
@ -265,6 +266,7 @@ class FShader
|
||||||
FUniform1i muFixedColormap;
|
FUniform1i muFixedColormap;
|
||||||
FUniform4f muColormapStart;
|
FUniform4f muColormapStart;
|
||||||
FUniform4f muColormapRange;
|
FUniform4f muColormapRange;
|
||||||
|
FBufferedUniform1i muLightMath;
|
||||||
FBufferedUniform1i muLightIndex;
|
FBufferedUniform1i muLightIndex;
|
||||||
FBufferedUniformPE muFogColor;
|
FBufferedUniformPE muFogColor;
|
||||||
FBufferedUniform4f muDynLightColor;
|
FBufferedUniform4f muDynLightColor;
|
||||||
|
@ -322,7 +324,6 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// The global shader manager
|
// The global shader manager
|
||||||
|
@ -330,26 +331,40 @@ public:
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
class FShaderManager
|
class FShaderManager
|
||||||
{
|
{
|
||||||
TArray<FShader*> mTextureEffects;
|
|
||||||
TArray<FShader*> mTextureEffectsNAT;
|
|
||||||
FShader *mActiveShader;
|
|
||||||
FShader *mEffectShaders[MAX_EFFECTS];
|
|
||||||
|
|
||||||
void Clean();
|
|
||||||
void CompileShaders();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FShaderManager();
|
FShaderManager();
|
||||||
~FShaderManager();
|
~FShaderManager();
|
||||||
FShader *Compile(const char *ShaderName, const char *ShaderPath, bool usediscard);
|
|
||||||
|
void SetActiveShader(FShader *sh);
|
||||||
|
FShader *GetActiveShader() const { return mActiveShader; }
|
||||||
|
|
||||||
|
FShader *BindEffect(int effect, EPassType passType);
|
||||||
|
FShader *Get(unsigned int eff, bool alphateston, EPassType passType);
|
||||||
|
void ApplyMatrices(VSMatrix *proj, VSMatrix *view, EPassType passType);
|
||||||
|
|
||||||
|
void ResetFixedColormap();
|
||||||
|
|
||||||
|
private:
|
||||||
|
FShader *mActiveShader = nullptr;
|
||||||
|
TArray<FShaderCollection*> mPassShaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FShaderCollection
|
||||||
|
{
|
||||||
|
TArray<FShader*> mTextureEffects;
|
||||||
|
TArray<FShader*> mTextureEffectsNAT;
|
||||||
|
FShader *mEffectShaders[MAX_EFFECTS];
|
||||||
|
|
||||||
|
void Clean();
|
||||||
|
void CompileShaders(EPassType passType);
|
||||||
|
|
||||||
|
public:
|
||||||
|
FShaderCollection(EPassType passType);
|
||||||
|
~FShaderCollection();
|
||||||
|
FShader *Compile(const char *ShaderName, const char *ShaderPath, bool usediscard, EPassType passType);
|
||||||
int Find(const char *mame);
|
int Find(const char *mame);
|
||||||
FShader *BindEffect(int effect);
|
FShader *BindEffect(int effect);
|
||||||
void SetActiveShader(FShader *sh);
|
|
||||||
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
|
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
|
||||||
FShader *GetActiveShader() const
|
|
||||||
{
|
|
||||||
return mActiveShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResetFixedColormap()
|
void ResetFixedColormap()
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,7 +41,7 @@ VSMatrix EyePose::GetProjection(float fov, float aspectRatio, float fovRatio) co
|
||||||
|
|
||||||
// Lifted from gl_scene.cpp FGLRenderer::SetProjection()
|
// Lifted from gl_scene.cpp FGLRenderer::SetProjection()
|
||||||
float fovy = (float)(2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)));
|
float fovy = (float)(2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)));
|
||||||
result.perspective(fovy, aspectRatio, 5.f, 65536.f);
|
result.perspective(fovy, aspectRatio, FGLRenderer::GetZNear(), FGLRenderer::GetZFar());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ EXTERN_CVAR (Bool, gl_attachedlights);
|
||||||
EXTERN_CVAR (Bool, gl_lights_checkside);
|
EXTERN_CVAR (Bool, gl_lights_checkside);
|
||||||
EXTERN_CVAR (Bool, gl_light_sprites);
|
EXTERN_CVAR (Bool, gl_light_sprites);
|
||||||
EXTERN_CVAR (Bool, gl_light_particles);
|
EXTERN_CVAR (Bool, gl_light_particles);
|
||||||
|
EXTERN_CVAR (Int, gl_light_math);
|
||||||
|
|
||||||
EXTERN_CVAR(Int, gl_fogmode)
|
EXTERN_CVAR(Int, gl_fogmode)
|
||||||
EXTERN_CVAR(Int, gl_lightmode)
|
EXTERN_CVAR(Int, gl_lightmode)
|
||||||
|
@ -50,6 +51,12 @@ EXTERN_CVAR(Bool, gl_lens)
|
||||||
EXTERN_CVAR(Float, gl_lens_k)
|
EXTERN_CVAR(Float, gl_lens_k)
|
||||||
EXTERN_CVAR(Float, gl_lens_kcube)
|
EXTERN_CVAR(Float, gl_lens_kcube)
|
||||||
EXTERN_CVAR(Float, gl_lens_chromatic)
|
EXTERN_CVAR(Float, gl_lens_chromatic)
|
||||||
|
EXTERN_CVAR(Bool, gl_ssao)
|
||||||
|
EXTERN_CVAR(Float, gl_ssao_strength)
|
||||||
|
EXTERN_CVAR(Bool, gl_ssao_debug)
|
||||||
|
EXTERN_CVAR(Float, gl_ssao_bias)
|
||||||
|
EXTERN_CVAR(Float, gl_ssao_radius)
|
||||||
|
EXTERN_CVAR(Float, gl_ssao_blur_amount)
|
||||||
|
|
||||||
EXTERN_CVAR(Int, gl_debug_level)
|
EXTERN_CVAR(Int, gl_debug_level)
|
||||||
EXTERN_CVAR(Bool, gl_debug_breakpoint)
|
EXTERN_CVAR(Bool, gl_debug_breakpoint)
|
||||||
|
|
|
@ -2612,6 +2612,7 @@ GLLIGHTMNU_LIGHTDEFS = "Enable light definitions";
|
||||||
GLLIGHTMNU_CLIPLIGHTS = "Clip lights";
|
GLLIGHTMNU_CLIPLIGHTS = "Clip lights";
|
||||||
GLLIGHTMNU_LIGHTSPRITES = "Lights affect sprites";
|
GLLIGHTMNU_LIGHTSPRITES = "Lights affect sprites";
|
||||||
GLLIGHTMNU_LIGHTPARTICLES = "Lights affect particles";
|
GLLIGHTMNU_LIGHTPARTICLES = "Lights affect particles";
|
||||||
|
GLLIGHTMNU_LIGHTMATH = "Light quality";
|
||||||
|
|
||||||
// OpenGL Preferences
|
// OpenGL Preferences
|
||||||
GLPREFMNU_TITLE = "OPENGL PREFERENCES";
|
GLPREFMNU_TITLE = "OPENGL PREFERENCES";
|
||||||
|
@ -2637,6 +2638,7 @@ GLPREFMNU_MULTISAMPLE = "Multisample";
|
||||||
GLPREFMNU_TONEMAP = "Tonemap Mode";
|
GLPREFMNU_TONEMAP = "Tonemap Mode";
|
||||||
GLPREFMNU_BLOOM = "Bloom effect";
|
GLPREFMNU_BLOOM = "Bloom effect";
|
||||||
GLPREFMNU_LENS = "Lens distortion effect";
|
GLPREFMNU_LENS = "Lens distortion effect";
|
||||||
|
GLPREFMNU_SSAO = "Ambient occlusion";
|
||||||
|
|
||||||
// Option Values
|
// Option Values
|
||||||
OPTVAL_SMART = "Smart";
|
OPTVAL_SMART = "Smart";
|
||||||
|
@ -2712,3 +2714,6 @@ OPTVAL_UNCHARTED2 = "Uncharted 2";
|
||||||
OPTVAL_HEJLDAWSON = "Hejl Dawson";
|
OPTVAL_HEJLDAWSON = "Hejl Dawson";
|
||||||
OPTVAL_REINHARD = "Reinhard";
|
OPTVAL_REINHARD = "Reinhard";
|
||||||
OPTVAL_PALETTE = "Palette";
|
OPTVAL_PALETTE = "Palette";
|
||||||
|
OPTVAL_LOW = "Low";
|
||||||
|
OPTVAL_MEDIUM = "Medium";
|
||||||
|
OPTVAL_HIGH = "High";
|
||||||
|
|
|
@ -25,6 +25,13 @@ OptionValue "FilterModes"
|
||||||
4, "$OPTVAL_TRILINEAR"
|
4, "$OPTVAL_TRILINEAR"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OptionValue "LightMathModes"
|
||||||
|
{
|
||||||
|
0, "$OPTVAL_LOW"
|
||||||
|
1, "$OPTVAL_MEDIUM"
|
||||||
|
2, "$OPTVAL_HIGH"
|
||||||
|
}
|
||||||
|
|
||||||
OptionValue "HWGammaModes"
|
OptionValue "HWGammaModes"
|
||||||
{
|
{
|
||||||
0, "$OPTVAL_ON"
|
0, "$OPTVAL_ON"
|
||||||
|
@ -199,6 +206,7 @@ OptionMenu "GLLightOptions"
|
||||||
Option "$GLLIGHTMNU_CLIPLIGHTS", gl_lights_checkside, "YesNo"
|
Option "$GLLIGHTMNU_CLIPLIGHTS", gl_lights_checkside, "YesNo"
|
||||||
Option "$GLLIGHTMNU_LIGHTSPRITES", gl_light_sprites, "YesNo"
|
Option "$GLLIGHTMNU_LIGHTSPRITES", gl_light_sprites, "YesNo"
|
||||||
Option "$GLLIGHTMNU_LIGHTPARTICLES", gl_light_particles, "YesNo"
|
Option "$GLLIGHTMNU_LIGHTPARTICLES", gl_light_particles, "YesNo"
|
||||||
|
Option "$GLLIGHTMNU_LIGHTMATH", gl_light_math, "LightMathModes"
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionMenu "GLPrefOptions"
|
OptionMenu "GLPrefOptions"
|
||||||
|
@ -226,4 +234,5 @@ OptionMenu "GLPrefOptions"
|
||||||
Option "$GLPREFMNU_TONEMAP", gl_tonemap, "TonemapModes"
|
Option "$GLPREFMNU_TONEMAP", gl_tonemap, "TonemapModes"
|
||||||
Option "$GLPREFMNU_BLOOM", gl_bloom, "OnOff"
|
Option "$GLPREFMNU_BLOOM", gl_bloom, "OnOff"
|
||||||
Option "$GLPREFMNU_LENS", gl_lens, "OnOff"
|
Option "$GLPREFMNU_LENS", gl_lens, "OnOff"
|
||||||
|
Option "$GLPREFMNU_SSAO", gl_ssao, "OnOff"
|
||||||
}
|
}
|
||||||
|
|
69
wadsrc/static/shaders/glsl/depthblur.fp
Normal file
69
wadsrc/static/shaders/glsl/depthblur.fp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D AODepthTexture;
|
||||||
|
uniform float BlurSharpness;
|
||||||
|
uniform vec2 InvFullResolution;
|
||||||
|
uniform float PowExponent;
|
||||||
|
|
||||||
|
#define KERNEL_RADIUS 7.0
|
||||||
|
|
||||||
|
float CrossBilateralWeight(float r, float sampleDepth, float centerDepth)
|
||||||
|
{
|
||||||
|
const float blurSigma = KERNEL_RADIUS * 0.5;
|
||||||
|
const float blurFalloff = 1.0 / (2.0 * blurSigma * blurSigma);
|
||||||
|
|
||||||
|
float deltaZ = (sampleDepth - centerDepth) * BlurSharpness;
|
||||||
|
|
||||||
|
return exp2(-r * r * blurFalloff - deltaZ * deltaZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessSample(float ao, float z, float r, float centerDepth, inout float totalAO, inout float totalW)
|
||||||
|
{
|
||||||
|
float w = CrossBilateralWeight(r, z, centerDepth);
|
||||||
|
totalAO += w * ao;
|
||||||
|
totalW += w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRadius(vec2 deltaUV, float centerDepth, inout float totalAO, inout float totalW)
|
||||||
|
{
|
||||||
|
for (float r = 1; r <= KERNEL_RADIUS; r += 1.0)
|
||||||
|
{
|
||||||
|
vec2 uv = r * deltaUV + TexCoord;
|
||||||
|
vec2 aoZ = texture(AODepthTexture, uv).xy;
|
||||||
|
ProcessSample(aoZ.x, aoZ.y, r, centerDepth, totalAO, totalW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 ComputeBlur(vec2 deltaUV)
|
||||||
|
{
|
||||||
|
vec2 aoZ = texture(AODepthTexture, TexCoord).xy;
|
||||||
|
|
||||||
|
float totalAO = aoZ.x;
|
||||||
|
float totalW = 1.0;
|
||||||
|
|
||||||
|
ProcessRadius(deltaUV, aoZ.y, totalAO, totalW);
|
||||||
|
ProcessRadius(-deltaUV, aoZ.y, totalAO, totalW);
|
||||||
|
|
||||||
|
return vec2(totalAO / totalW, aoZ.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 BlurX()
|
||||||
|
{
|
||||||
|
return ComputeBlur(vec2(InvFullResolution.x, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float BlurY()
|
||||||
|
{
|
||||||
|
return pow(clamp(ComputeBlur(vec2(0.0, InvFullResolution.y)).x, 0.0, 1.0), PowExponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
#if defined(BLUR_HORIZONTAL)
|
||||||
|
FragColor = vec4(BlurX(), 0.0, 1.0);
|
||||||
|
#else
|
||||||
|
FragColor = vec4(BlurY(), 0.0, 0.0, 1.0);
|
||||||
|
#endif
|
||||||
|
}
|
46
wadsrc/static/shaders/glsl/lineardepth.fp
Normal file
46
wadsrc/static/shaders/glsl/lineardepth.fp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
uniform sampler2DMS DepthTexture;
|
||||||
|
uniform sampler2DMS ColorTexture;
|
||||||
|
uniform int SampleCount;
|
||||||
|
#else
|
||||||
|
uniform sampler2D DepthTexture;
|
||||||
|
uniform sampler2D ColorTexture;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform float LinearizeDepthA;
|
||||||
|
uniform float LinearizeDepthB;
|
||||||
|
uniform float InverseDepthRangeA;
|
||||||
|
uniform float InverseDepthRangeB;
|
||||||
|
uniform vec2 Scale;
|
||||||
|
uniform vec2 Offset;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 uv = Offset + TexCoord * Scale;
|
||||||
|
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
ivec2 texSize = textureSize(DepthTexture);
|
||||||
|
#else
|
||||||
|
ivec2 texSize = textureSize(DepthTexture, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use floor here because as we downscale the sampling error has to remain uniform to prevent
|
||||||
|
// noise in the depth values.
|
||||||
|
ivec2 ipos = ivec2(max(floor(uv * vec2(texSize) - 0.75), vec2(0.0)));
|
||||||
|
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
float depth = 0.0;
|
||||||
|
for (int i = 0; i < SampleCount; i++)
|
||||||
|
depth += texelFetch(ColorTexture, ipos, i).a != 0.0 ? texelFetch(DepthTexture, ipos, i).x : 1.0;
|
||||||
|
depth /= float(SampleCount);
|
||||||
|
#else
|
||||||
|
float depth = texelFetch(ColorTexture, ipos, 0).a != 0.0 ? texelFetch(DepthTexture, ipos, 0).x : 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float normalizedDepth = clamp(InverseDepthRangeA * depth + InverseDepthRangeB, 0.0, 1.0);
|
||||||
|
FragColor = vec4(1.0 / (normalizedDepth * LinearizeDepthA + LinearizeDepthB), 0.0, 0.0, 1.0);
|
||||||
|
}
|
|
@ -5,6 +5,9 @@ in vec4 vTexCoord;
|
||||||
in vec4 vColor;
|
in vec4 vColor;
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
#ifdef GBUFFER_PASS
|
||||||
|
out vec4 FragData;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SHADER_STORAGE_LIGHTS
|
#ifdef SHADER_STORAGE_LIGHTS
|
||||||
layout(std430, binding = 1) buffer LightBufferSSO
|
layout(std430, binding = 1) buffer LightBufferSSO
|
||||||
|
@ -25,6 +28,88 @@ vec4 Process(vec4 color);
|
||||||
vec4 ProcessTexel();
|
vec4 ProcessTexel();
|
||||||
vec4 ProcessLight(vec4 color);
|
vec4 ProcessLight(vec4 color);
|
||||||
|
|
||||||
|
// Smoothed normal used for the face, in eye space. Should be converted to an 'in' variable in the future.
|
||||||
|
vec3 pixelnormal;
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Calculates the face normal vector for the fragment, in eye space
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
vec3 calculateFaceNormal()
|
||||||
|
{
|
||||||
|
#if __VERSION__ < 450
|
||||||
|
vec3 dFdxPos = dFdx(pixelpos.xyz);
|
||||||
|
vec3 dFdyPos = dFdy(pixelpos.xyz);
|
||||||
|
#else
|
||||||
|
vec3 dFdxPos = dFdxCoarse(pixelpos.xyz);
|
||||||
|
vec3 dFdyPos = dFdyCoarse(pixelpos.xyz);
|
||||||
|
#endif
|
||||||
|
return normalize(cross(dFdxPos,dFdyPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Standard lambertian diffuse light calculation
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
float diffuseContribution(vec3 eyeLightDirection, vec3 eyeNormal)
|
||||||
|
{
|
||||||
|
return max(dot(eyeNormal, eyeLightDirection), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Blinn specular light calculation
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
float blinnSpecularContribution(float diffuseContribution, vec3 eyeLightDirection, vec3 eyePosition, vec3 eyeNormal, float glossiness, float specularLevel)
|
||||||
|
{
|
||||||
|
if (diffuseContribution > 0.0f)
|
||||||
|
{
|
||||||
|
vec3 viewDir = normalize(-eyePosition);
|
||||||
|
vec3 halfDir = normalize(eyeLightDirection + viewDir);
|
||||||
|
float specAngle = max(dot(halfDir, eyeNormal), 0.0f);
|
||||||
|
float phExp = glossiness * 4.0f;
|
||||||
|
return specularLevel * pow(specAngle, phExp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Calculates the brightness of a dynamic point light
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
float pointLightAttenuation(vec4 lightpos)
|
||||||
|
{
|
||||||
|
float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
|
||||||
|
if (uLightMath == 0)
|
||||||
|
{
|
||||||
|
return attenuation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
|
||||||
|
float diffuseAmount = diffuseContribution(lightDirection, pixelnormal);
|
||||||
|
if (uLightMath == 1)
|
||||||
|
{
|
||||||
|
return attenuation * diffuseAmount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float specularAmount = blinnSpecularContribution(diffuseAmount, lightDirection, pixelpos.xyz, pixelnormal, 3.0, 1.2);
|
||||||
|
return attenuation * (diffuseAmount + specularAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -196,7 +281,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
||||||
vec4 lightpos = lights[i];
|
vec4 lightpos = lights[i];
|
||||||
vec4 lightcolor = lights[i+1];
|
vec4 lightcolor = lights[i+1];
|
||||||
|
|
||||||
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
|
lightcolor.rgb *= pointLightAttenuation(lightpos);
|
||||||
dynlight.rgb += lightcolor.rgb;
|
dynlight.rgb += lightcolor.rgb;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -207,7 +292,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
||||||
vec4 lightpos = lights[i];
|
vec4 lightpos = lights[i];
|
||||||
vec4 lightcolor = lights[i+1];
|
vec4 lightcolor = lights[i+1];
|
||||||
|
|
||||||
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
|
lightcolor.rgb *= pointLightAttenuation(lightpos);
|
||||||
dynlight.rgb -= lightcolor.rgb;
|
dynlight.rgb -= lightcolor.rgb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,6 +315,32 @@ vec4 applyFog(vec4 frag, float fogfactor)
|
||||||
return vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
|
return vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// The color of the fragment if it is fully occluded by ambient lighting
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
vec3 AmbientOcclusionColor()
|
||||||
|
{
|
||||||
|
float fogdist;
|
||||||
|
float fogfactor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// calculate fog factor
|
||||||
|
//
|
||||||
|
if (uFogEnabled == -1)
|
||||||
|
{
|
||||||
|
fogdist = pixelpos.w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fogdist = max(16.0, length(pixelpos.xyz));
|
||||||
|
}
|
||||||
|
fogfactor = exp2 (uFogDensity * fogdist);
|
||||||
|
|
||||||
|
return mix(uFogColor.rgb, vec3(0.0), fogfactor);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -241,6 +352,13 @@ void main()
|
||||||
{
|
{
|
||||||
vec4 frag = ProcessTexel();
|
vec4 frag = ProcessTexel();
|
||||||
|
|
||||||
|
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
||||||
|
if (uLightMath != 0) // Remove this if pixelnormal is converted to an 'in' variable
|
||||||
|
{
|
||||||
|
pixelnormal = calculateFaceNormal();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef NO_ALPHATEST
|
#ifndef NO_ALPHATEST
|
||||||
if (frag.a <= uAlphaThreshold) discard;
|
if (frag.a <= uAlphaThreshold) discard;
|
||||||
#endif
|
#endif
|
||||||
|
@ -265,12 +383,11 @@ void main()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
|
fogdist = max(16.0, length(pixelpos.xyz));
|
||||||
}
|
}
|
||||||
fogfactor = exp2 (uFogDensity * fogdist);
|
fogfactor = exp2 (uFogDensity * fogdist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
frag *= getLightColor(fogdist, fogfactor);
|
frag *= getLightColor(fogdist, fogfactor);
|
||||||
|
|
||||||
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
||||||
|
@ -289,7 +406,7 @@ void main()
|
||||||
vec4 lightpos = lights[i];
|
vec4 lightpos = lights[i];
|
||||||
vec4 lightcolor = lights[i+1];
|
vec4 lightcolor = lights[i+1];
|
||||||
|
|
||||||
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
|
lightcolor.rgb *= pointLightAttenuation(lightpos);
|
||||||
addlight.rgb += lightcolor.rgb;
|
addlight.rgb += lightcolor.rgb;
|
||||||
}
|
}
|
||||||
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
|
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
|
||||||
|
@ -336,7 +453,7 @@ void main()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
|
fogdist = max(16.0, length(pixelpos.xyz));
|
||||||
}
|
}
|
||||||
fogfactor = exp2 (uFogDensity * fogdist);
|
fogfactor = exp2 (uFogDensity * fogdist);
|
||||||
|
|
||||||
|
@ -345,5 +462,8 @@ void main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FragColor = frag;
|
FragColor = frag;
|
||||||
|
#ifdef GBUFFER_PASS
|
||||||
|
FragData = vec4(AmbientOcclusionColor(), 1.0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ void main()
|
||||||
vColor = aColor;
|
vColor = aColor;
|
||||||
|
|
||||||
#ifndef SIMPLE
|
#ifndef SIMPLE
|
||||||
pixelpos.xyz = worldcoord.xyz;
|
pixelpos.xyz = eyeCoordPos.xyz;
|
||||||
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
|
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
|
||||||
|
|
||||||
glowdist.x = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z) - worldcoord.y;
|
glowdist.x = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z) - worldcoord.y;
|
||||||
|
|
|
@ -44,6 +44,7 @@ uniform int uFogEnabled;
|
||||||
|
|
||||||
// dynamic lights
|
// dynamic lights
|
||||||
uniform int uLightIndex;
|
uniform int uLightIndex;
|
||||||
|
uniform int uLightMath; // 0, when using only attenuation, 1 for diffuse light, 2 for blinn specular light
|
||||||
|
|
||||||
// quad drawer stuff
|
// quad drawer stuff
|
||||||
#ifdef USE_QUAD_DRAWER
|
#ifdef USE_QUAD_DRAWER
|
||||||
|
|
112
wadsrc/static/shaders/glsl/ssao.fp
Normal file
112
wadsrc/static/shaders/glsl/ssao.fp
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform vec2 UVToViewA;
|
||||||
|
uniform vec2 UVToViewB;
|
||||||
|
uniform vec2 InvFullResolution;
|
||||||
|
|
||||||
|
uniform float NDotVBias;
|
||||||
|
uniform float NegInvR2;
|
||||||
|
uniform float RadiusToScreen;
|
||||||
|
uniform float AOMultiplier;
|
||||||
|
|
||||||
|
uniform float AOStrength;
|
||||||
|
|
||||||
|
uniform sampler2D DepthTexture;
|
||||||
|
|
||||||
|
#if defined(USE_RANDOM_TEXTURE)
|
||||||
|
uniform sampler2D RandomTexture;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PI 3.14159265358979323846
|
||||||
|
|
||||||
|
// Calculate eye space position for the specified texture coordinate
|
||||||
|
vec3 FetchViewPos(vec2 uv)
|
||||||
|
{
|
||||||
|
float z = texture(DepthTexture, uv).x;
|
||||||
|
return vec3((UVToViewA * uv + UVToViewB) * z, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 MinDiff(vec3 p, vec3 pr, vec3 pl)
|
||||||
|
{
|
||||||
|
vec3 v1 = pr - p;
|
||||||
|
vec3 v2 = p - pl;
|
||||||
|
return (dot(v1, v1) < dot(v2, v2)) ? v1 : v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconstruct eye space normal from nearest neighbors
|
||||||
|
vec3 ReconstructNormal(vec3 p)
|
||||||
|
{
|
||||||
|
vec3 pr = FetchViewPos(TexCoord + vec2(InvFullResolution.x, 0));
|
||||||
|
vec3 pl = FetchViewPos(TexCoord + vec2(-InvFullResolution.x, 0));
|
||||||
|
vec3 pt = FetchViewPos(TexCoord + vec2(0, InvFullResolution.y));
|
||||||
|
vec3 pb = FetchViewPos(TexCoord + vec2(0, -InvFullResolution.y));
|
||||||
|
return normalize(cross(MinDiff(p, pr, pl), MinDiff(p, pt, pb)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute normalized 2D direction
|
||||||
|
vec2 RotateDirection(vec2 dir, vec2 cossin)
|
||||||
|
{
|
||||||
|
return vec2(dir.x * cossin.x - dir.y * cossin.y, dir.x * cossin.y + dir.y * cossin.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 GetJitter()
|
||||||
|
{
|
||||||
|
#if !defined(USE_RANDOM_TEXTURE)
|
||||||
|
return vec4(1,0,1,1);
|
||||||
|
//vec3 rand = noise3(TexCoord.x + TexCoord.y);
|
||||||
|
//float angle = 2.0 * PI * rand.x / NUM_DIRECTIONS;
|
||||||
|
//return vec4(cos(angle), sin(angle), rand.y, rand.z);
|
||||||
|
#else
|
||||||
|
return texture(RandomTexture, gl_FragCoord.xy / RANDOM_TEXTURE_WIDTH);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the ambient occlusion of a sample
|
||||||
|
float ComputeSampleAO(vec3 kernelPos, vec3 normal, vec3 samplePos)
|
||||||
|
{
|
||||||
|
vec3 v = samplePos - kernelPos;
|
||||||
|
float distanceSquare = dot(v, v);
|
||||||
|
float nDotV = dot(normal, v) * inversesqrt(distanceSquare);
|
||||||
|
return clamp(nDotV - NDotVBias, 0.0, 1.0) * clamp(distanceSquare * NegInvR2 + 1.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the total ambient occlusion for the entire fragment
|
||||||
|
float ComputeAO(vec3 viewPosition, vec3 viewNormal)
|
||||||
|
{
|
||||||
|
vec4 rand = GetJitter();
|
||||||
|
|
||||||
|
float radiusPixels = RadiusToScreen / viewPosition.z;
|
||||||
|
float stepSizePixels = radiusPixels / (NUM_STEPS + 1.0);
|
||||||
|
|
||||||
|
const float directionAngleStep = 2.0 * PI / NUM_DIRECTIONS;
|
||||||
|
float ao = 0.0;
|
||||||
|
|
||||||
|
for (float directionIndex = 0.0; directionIndex < NUM_DIRECTIONS; ++directionIndex)
|
||||||
|
{
|
||||||
|
float angle = directionAngleStep * directionIndex;
|
||||||
|
|
||||||
|
vec2 direction = RotateDirection(vec2(cos(angle), sin(angle)), rand.xy);
|
||||||
|
float rayPixels = (rand.z * stepSizePixels + 1.0);
|
||||||
|
|
||||||
|
for (float StepIndex = 0.0; StepIndex < NUM_STEPS; ++StepIndex)
|
||||||
|
{
|
||||||
|
vec2 sampleUV = round(rayPixels * direction) * InvFullResolution + TexCoord;
|
||||||
|
vec3 samplePos = FetchViewPos(sampleUV);
|
||||||
|
ao += ComputeSampleAO(viewPosition, viewNormal, samplePos);
|
||||||
|
rayPixels += stepSizePixels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ao *= AOMultiplier / (NUM_DIRECTIONS * NUM_STEPS);
|
||||||
|
return clamp(1.0 - ao * 2.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 viewPosition = FetchViewPos(TexCoord);
|
||||||
|
vec3 viewNormal = ReconstructNormal(viewPosition);
|
||||||
|
float occlusion = ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength);
|
||||||
|
FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0);
|
||||||
|
}
|
38
wadsrc/static/shaders/glsl/ssaocombine.fp
Normal file
38
wadsrc/static/shaders/glsl/ssaocombine.fp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D AODepthTexture;
|
||||||
|
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
uniform sampler2DMS SceneDataTexture;
|
||||||
|
uniform int SampleCount;
|
||||||
|
#else
|
||||||
|
uniform sampler2D SceneDataTexture;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform vec2 Scale;
|
||||||
|
uniform vec2 Offset;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 uv = Offset + TexCoord * Scale;
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
ivec2 texSize = textureSize(SceneDataTexture);
|
||||||
|
#else
|
||||||
|
ivec2 texSize = textureSize(SceneDataTexture, 0);
|
||||||
|
#endif
|
||||||
|
ivec2 ipos = ivec2(max(floor(uv * vec2(texSize) - 0.75), vec2(0.0)));
|
||||||
|
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
vec3 fogColor = vec3(0.0);
|
||||||
|
for (int i = 0; i < SampleCount; i++)
|
||||||
|
fogColor += texelFetch(SceneDataTexture, ipos, i).rgb;
|
||||||
|
fogColor /= float(SampleCount);
|
||||||
|
#else
|
||||||
|
vec3 fogColor = texelFetch(SceneDataTexture, ipos, 0).rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float attenutation = texture(AODepthTexture, TexCoord).x;
|
||||||
|
FragColor = vec4(fogColor, 1.0 - attenutation);
|
||||||
|
}
|
|
@ -3,6 +3,6 @@ out vec4 FragColor;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
FragColor = vec4(1.0);
|
FragColor = vec4(1.0, 1.0, 1.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue