mirror of
https://github.com/ZDoom/Raze.git
synced 2025-05-30 00:41:24 +00:00
- renamed 'common' to 'core'.
We'll need 'common' for something else.
This commit is contained in:
parent
736337979b
commit
e2f5e8fe34
280 changed files with 187 additions and 187 deletions
|
@ -1,83 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
class FRenderState;
|
||||
|
||||
// The low level code needs to know which attributes exist.
|
||||
// OpenGL needs to change the state of all of them per buffer binding.
|
||||
// VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want.
|
||||
enum
|
||||
{
|
||||
VATTR_VERTEX,
|
||||
VATTR_TEXCOORD,
|
||||
VATTR_COLOR,
|
||||
VATTR_VERTEX2,
|
||||
VATTR_NORMAL,
|
||||
VATTR_NORMAL2,
|
||||
|
||||
VATTR_MAX
|
||||
};
|
||||
|
||||
enum EVertexAttributeFormat
|
||||
{
|
||||
VFmt_Float4,
|
||||
VFmt_Float3,
|
||||
VFmt_Float2,
|
||||
VFmt_Float,
|
||||
VFmt_Byte4,
|
||||
VFmt_Packed_A2R10G10B10,
|
||||
};
|
||||
|
||||
struct FVertexBufferAttribute
|
||||
{
|
||||
int binding;
|
||||
int location;
|
||||
int format;
|
||||
int offset;
|
||||
};
|
||||
|
||||
class IBuffer
|
||||
{
|
||||
protected:
|
||||
size_t buffersize = 0;
|
||||
void *map = nullptr;
|
||||
public:
|
||||
IBuffer() = default;
|
||||
IBuffer(const IBuffer &) = delete;
|
||||
IBuffer &operator=(const IBuffer &) = delete;
|
||||
virtual ~IBuffer() = default;
|
||||
|
||||
virtual void SetData(size_t size, const void *data, bool staticdata = true) = 0;
|
||||
virtual void SetSubData(size_t offset, size_t size, const void *data) = 0;
|
||||
virtual void *Lock(unsigned int size) = 0;
|
||||
virtual void Unlock() = 0;
|
||||
virtual void Resize(size_t newsize) = 0;
|
||||
virtual void Map() {} // Only needed by old OpenGL but this needs to be in the interface.
|
||||
virtual void Unmap() {}
|
||||
void *Memory() { assert(map); return map; }
|
||||
size_t Size() { return buffersize; }
|
||||
};
|
||||
|
||||
class IVertexBuffer : virtual public IBuffer
|
||||
{
|
||||
public:
|
||||
virtual void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) = 0;
|
||||
};
|
||||
|
||||
// This merely exists to have a dedicated type for index buffers to inherit from.
|
||||
class IIndexBuffer : virtual public IBuffer
|
||||
{
|
||||
// Element size is fixed to 4, thanks to OpenGL requiring this info to be coded into the glDrawElements call.
|
||||
// This mostly prohibits a more flexible buffer setup but GZDoom doesn't use any other format anyway.
|
||||
// Ob Vulkam, element size is a buffer property and of no concern to the drawing functions (as it should be.)
|
||||
};
|
||||
|
||||
class IDataBuffer : virtual public IBuffer
|
||||
{
|
||||
// Can be either uniform or shader storage buffer, depending on its needs.
|
||||
public:
|
||||
virtual void BindRange(FRenderState *state, size_t start, size_t length) = 0;
|
||||
|
||||
};
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
** hw_flatvertices.cpp
|
||||
** Creates flat vertex data for hardware rendering.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2010-2020 Christoph Oelckers
|
||||
** 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.
|
||||
**
|
||||
** 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 "c_cvars.h"
|
||||
#include "flatvertices.h"
|
||||
#include "v_video.h"
|
||||
#include "cmdlib.h"
|
||||
#include "printf.h"
|
||||
#include "hwrenderer/data/buffers.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
|
||||
{
|
||||
vbo_shadowdata.Resize(NUM_RESERVED);
|
||||
|
||||
// the first quad is reserved for handling coordinates through uniforms.
|
||||
vbo_shadowdata[0].Set(0, 0, 0, 0, 0);
|
||||
vbo_shadowdata[1].Set(1, 0, 0, 0, 0);
|
||||
vbo_shadowdata[2].Set(2, 0, 0, 0, 0);
|
||||
vbo_shadowdata[3].Set(3, 0, 0, 0, 0);
|
||||
|
||||
// and the second one for the fullscreen quad used for blend overlays.
|
||||
vbo_shadowdata[4].Set(0, 0, 0, 0, 0);
|
||||
vbo_shadowdata[5].Set(0, (float)height, 0, 0, 1);
|
||||
vbo_shadowdata[6].Set((float)width, 0, 0, 1, 0);
|
||||
vbo_shadowdata[7].Set((float)width, (float)height, 0, 1, 1);
|
||||
|
||||
// and this is for the postprocessing copy operation
|
||||
vbo_shadowdata[8].Set(-1.0f, -1.0f, 0, 0.0f, 0.0f);
|
||||
vbo_shadowdata[9].Set(-1.0f, 1.0f, 0, 0.0f, 1.f);
|
||||
vbo_shadowdata[10].Set(1.0f, -1.0f, 0, 1.f, 0.0f);
|
||||
vbo_shadowdata[11].Set(1.0f, 1.0f, 0, 1.f, 1.f);
|
||||
|
||||
// The next two are the stencil caps.
|
||||
vbo_shadowdata[12].Set(-32767.0f, 32767.0f, -32767.0f, 0, 0);
|
||||
vbo_shadowdata[13].Set(-32767.0f, 32767.0f, 32767.0f, 0, 0);
|
||||
vbo_shadowdata[14].Set(32767.0f, 32767.0f, 32767.0f, 0, 0);
|
||||
vbo_shadowdata[15].Set(32767.0f, 32767.0f, -32767.0f, 0, 0);
|
||||
|
||||
vbo_shadowdata[16].Set(-32767.0f, -32767.0f, -32767.0f, 0, 0);
|
||||
vbo_shadowdata[17].Set(-32767.0f, -32767.0f, 32767.0f, 0, 0);
|
||||
vbo_shadowdata[18].Set(32767.0f, -32767.0f, 32767.0f, 0, 0);
|
||||
vbo_shadowdata[19].Set(32767.0f, -32767.0f, -32767.0f, 0, 0);
|
||||
|
||||
mVertexBuffer = screen->CreateVertexBuffer();
|
||||
mIndexBuffer = screen->CreateIndexBuffer();
|
||||
|
||||
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
|
||||
mVertexBuffer->SetData(bytesize, nullptr, false);
|
||||
|
||||
static const FVertexBufferAttribute format[] = {
|
||||
{ 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) },
|
||||
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }
|
||||
};
|
||||
mVertexBuffer->SetFormat(1, 2, sizeof(FFlatVertex), format);
|
||||
|
||||
mIndex = mCurIndex = NUM_RESERVED;
|
||||
mNumReserved = NUM_RESERVED;
|
||||
Copy(0, NUM_RESERVED);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FFlatVertexBuffer::~FFlatVertexBuffer()
|
||||
{
|
||||
delete mIndexBuffer;
|
||||
delete mVertexBuffer;
|
||||
mIndexBuffer = nullptr;
|
||||
mVertexBuffer = nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FFlatVertexBuffer::OutputResized(int width, int height)
|
||||
{
|
||||
vbo_shadowdata[4].Set(0, 0, 0, 0, 0);
|
||||
vbo_shadowdata[5].Set(0, (float)height, 0, 0, 1);
|
||||
vbo_shadowdata[6].Set((float)width, 0, 0, 1, 0);
|
||||
vbo_shadowdata[7].Set((float)width, (float)height, 0, 1, 1);
|
||||
Copy(4, 4);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
std::pair<FFlatVertex *, unsigned int> FFlatVertexBuffer::AllocVertices(unsigned int count)
|
||||
{
|
||||
FFlatVertex *p = GetBuffer();
|
||||
auto index = mCurIndex.fetch_add(count);
|
||||
auto offset = index;
|
||||
if (index + count >= BUFFER_SIZE_TO_USE)
|
||||
{
|
||||
// If a single scene needs 2'000'000 vertices there must be something very wrong.
|
||||
I_FatalError("Out of vertex memory. Tried to allocate more than %u vertices for a single frame", index + count);
|
||||
}
|
||||
return std::make_pair(p, index);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FFlatVertexBuffer::Copy(int start, int count)
|
||||
{
|
||||
Map();
|
||||
memcpy(GetBuffer(start), &vbo_shadowdata[0], count * sizeof(FFlatVertex));
|
||||
Unmap();
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
|
||||
#ifndef _HW__VERTEXBUFFER_H
|
||||
#define _HW__VERTEXBUFFER_H
|
||||
|
||||
#include "tarray.h"
|
||||
#include "hwrenderer/data/buffers.h"
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
class FRenderState;
|
||||
struct secplane_t;
|
||||
struct subsector_t;
|
||||
|
||||
struct FFlatVertex
|
||||
{
|
||||
float x, z, y; // world position
|
||||
float u, v; // texture coordinates
|
||||
|
||||
void Set(float xx, float zz, float yy, float uu, float vv)
|
||||
{
|
||||
x = xx;
|
||||
z = zz;
|
||||
y = yy;
|
||||
u = uu;
|
||||
v = vv;
|
||||
}
|
||||
|
||||
void SetVertex(float _x, float _y, float _z = 0)
|
||||
{
|
||||
x = _x;
|
||||
z = _y;
|
||||
y = _z;
|
||||
}
|
||||
|
||||
void SetTexCoord(float _u = 0, float _v = 0)
|
||||
{
|
||||
u = _u;
|
||||
v = _v;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FFlatVertexBuffer
|
||||
{
|
||||
TArray<FFlatVertex> vbo_shadowdata;
|
||||
TArray<uint32_t> ibo_data;
|
||||
|
||||
IVertexBuffer *mVertexBuffer;
|
||||
IIndexBuffer *mIndexBuffer;
|
||||
|
||||
unsigned int mIndex;
|
||||
std::atomic<unsigned int> mCurIndex;
|
||||
unsigned int mNumReserved;
|
||||
|
||||
|
||||
static const unsigned int BUFFER_SIZE = 4000000; // Was upped from 2000000 to account for voxels not being implemented with a separate vertex buffer.
|
||||
static const unsigned int BUFFER_SIZE_TO_USE = BUFFER_SIZE-500;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
QUAD_INDEX = 0,
|
||||
FULLSCREEN_INDEX = 4,
|
||||
PRESENT_INDEX = 8,
|
||||
STENCILTOP_INDEX = 12,
|
||||
STENCILBOTTOM_INDEX = 16,
|
||||
|
||||
NUM_RESERVED = 20
|
||||
};
|
||||
|
||||
FFlatVertexBuffer(int width, int height);
|
||||
~FFlatVertexBuffer();
|
||||
|
||||
void OutputResized(int width, int height);
|
||||
std::pair<IVertexBuffer *, IIndexBuffer *> GetBufferObjects() const
|
||||
{
|
||||
return std::make_pair(mVertexBuffer, mIndexBuffer);
|
||||
}
|
||||
|
||||
void Copy(int start, int count);
|
||||
|
||||
FFlatVertex *GetBuffer(int index) const
|
||||
{
|
||||
FFlatVertex *ff = (FFlatVertex*)mVertexBuffer->Memory();
|
||||
return &ff[index];
|
||||
}
|
||||
|
||||
FFlatVertex *GetBuffer() const
|
||||
{
|
||||
return GetBuffer(mCurIndex);
|
||||
}
|
||||
|
||||
std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count);
|
||||
|
||||
void Reset()
|
||||
{
|
||||
mCurIndex = mIndex;
|
||||
}
|
||||
|
||||
void Map()
|
||||
{
|
||||
mVertexBuffer->Map();
|
||||
}
|
||||
|
||||
void Unmap()
|
||||
{
|
||||
mVertexBuffer->Unmap();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "tflags.h"
|
||||
|
||||
// A render queue is what contains all render commands.
|
||||
// On Vulkan there can be several of them so this interface is needed to allow for the needed parallelism.
|
||||
// On OpenGL the render state is global so all this will do is to translate the system independent calls into OpenGL API calls.
|
||||
|
||||
enum class ColormaskBits
|
||||
{
|
||||
RED = 1,
|
||||
GREEN = 2,
|
||||
BLUE = 4,
|
||||
ALPHA = 8
|
||||
};
|
||||
|
||||
typedef TFlags<ColormaskBits, uint8_t> Colormask;
|
||||
|
||||
class IRenderQueue
|
||||
{
|
||||
Colormask mColorMask;
|
||||
|
||||
|
||||
Colormask GetColorMask() const
|
||||
{
|
||||
return mColorMask;
|
||||
}
|
||||
|
||||
virtual void SetColorMask(Colormask mask) = 0;
|
||||
|
||||
|
||||
};
|
|
@ -1,154 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "hwrenderer/data/buffers.h"
|
||||
#include "v_video.h"
|
||||
|
||||
enum
|
||||
{
|
||||
LIGHTBUF_BINDINGPOINT = 1,
|
||||
POSTPROCESS_BINDINGPOINT = 2,
|
||||
VIEWPOINT_BINDINGPOINT = 3,
|
||||
LIGHTNODES_BINDINGPOINT = 4,
|
||||
LIGHTLINES_BINDINGPOINT = 5,
|
||||
LIGHTLIST_BINDINGPOINT = 6
|
||||
};
|
||||
|
||||
enum class UniformType
|
||||
{
|
||||
Int,
|
||||
UInt,
|
||||
Float,
|
||||
Vec2,
|
||||
Vec3,
|
||||
Vec4,
|
||||
IVec2,
|
||||
IVec3,
|
||||
IVec4,
|
||||
UVec2,
|
||||
UVec3,
|
||||
UVec4,
|
||||
Mat4
|
||||
};
|
||||
|
||||
class UniformFieldDesc
|
||||
{
|
||||
public:
|
||||
UniformFieldDesc() { }
|
||||
UniformFieldDesc(const char *name, UniformType type, std::size_t offset) : Name(name), Type(type), Offset(offset) { }
|
||||
|
||||
const char *Name;
|
||||
UniformType Type;
|
||||
std::size_t Offset;
|
||||
};
|
||||
|
||||
class UniformBlockDecl
|
||||
{
|
||||
public:
|
||||
static FString Create(const char *name, const std::vector<UniformFieldDesc> &fields, int bindingpoint)
|
||||
{
|
||||
FString decl;
|
||||
FString layout;
|
||||
if (bindingpoint == -1)
|
||||
{
|
||||
layout = "push_constant";
|
||||
}
|
||||
else if (screen->glslversion < 4.20)
|
||||
{
|
||||
layout = "std140";
|
||||
}
|
||||
else
|
||||
{
|
||||
layout.Format("std140, binding = %d", bindingpoint);
|
||||
}
|
||||
decl.Format("layout(%s) uniform %s\n{\n", layout.GetChars(), name);
|
||||
for (size_t i = 0; i < fields.size(); i++)
|
||||
{
|
||||
decl.AppendFormat("\t%s %s;\n", GetTypeStr(fields[i].Type), fields[i].Name);
|
||||
}
|
||||
decl += "};\n";
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
private:
|
||||
static const char *GetTypeStr(UniformType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case UniformType::Int: return "int";
|
||||
case UniformType::UInt: return "uint";
|
||||
case UniformType::Float: return "float";
|
||||
case UniformType::Vec2: return "vec2";
|
||||
case UniformType::Vec3: return "vec3";
|
||||
case UniformType::Vec4: return "vec4";
|
||||
case UniformType::IVec2: return "ivec2";
|
||||
case UniformType::IVec3: return "ivec3";
|
||||
case UniformType::IVec4: return "ivec4";
|
||||
case UniformType::UVec2: return "uvec2";
|
||||
case UniformType::UVec3: return "uvec3";
|
||||
case UniformType::UVec4: return "uvec4";
|
||||
case UniformType::Mat4: return "mat4";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int bindingpoint>
|
||||
class ShaderUniforms
|
||||
{
|
||||
public:
|
||||
ShaderUniforms()
|
||||
{
|
||||
memset(&Values, 0, sizeof(Values));
|
||||
}
|
||||
|
||||
~ShaderUniforms()
|
||||
{
|
||||
if (mBuffer != nullptr)
|
||||
delete mBuffer;
|
||||
}
|
||||
|
||||
int BindingPoint() const
|
||||
{
|
||||
return bindingpoint;
|
||||
}
|
||||
|
||||
FString CreateDeclaration(const char *name, const std::vector<UniformFieldDesc> &fields)
|
||||
{
|
||||
mFields = fields;
|
||||
return UniformBlockDecl::Create(name, fields, bindingpoint);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
if (mBuffer == nullptr)
|
||||
mBuffer = screen->CreateDataBuffer(bindingpoint, false, false);
|
||||
}
|
||||
|
||||
void SetData()
|
||||
{
|
||||
if (mBuffer != nullptr)
|
||||
mBuffer->SetData(sizeof(T), &Values);
|
||||
}
|
||||
|
||||
IDataBuffer* GetBuffer() const
|
||||
{
|
||||
// OpenGL needs to mess around with this in ways that should not be part of the interface.
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
T *operator->() { return &Values; }
|
||||
const T *operator->() const { return &Values; }
|
||||
|
||||
T Values;
|
||||
|
||||
private:
|
||||
ShaderUniforms(const ShaderUniforms &) = delete;
|
||||
ShaderUniforms &operator=(const ShaderUniforms &) = delete;
|
||||
|
||||
IDataBuffer *mBuffer = nullptr;
|
||||
std::vector<UniformFieldDesc> mFields;
|
||||
};
|
||||
|
||||
|
|
@ -1,846 +0,0 @@
|
|||
/*
|
||||
** Postprocessing framework
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "v_video.h"
|
||||
#include "hw_postprocess.h"
|
||||
#include "gamecvars.h"
|
||||
#include "stats.h"
|
||||
#include "imagehelpers.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
||||
#include <random>
|
||||
|
||||
Postprocess hw_postprocess;
|
||||
|
||||
PPResource *PPResource::First = nullptr;
|
||||
|
||||
bool gpuStatActive = false;
|
||||
bool keepGpuStatActive = false;
|
||||
FString gpuStatOutput;
|
||||
|
||||
ADD_STAT(gpu)
|
||||
{
|
||||
keepGpuStatActive = true;
|
||||
return gpuStatOutput;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PPBloom::UpdateTextures(int width, int height)
|
||||
{
|
||||
if (width == lastWidth && height == lastHeight)
|
||||
return;
|
||||
|
||||
int bloomWidth = (width + 1) / 2;
|
||||
int bloomHeight = (height + 1) / 2;
|
||||
|
||||
for (int i = 0; i < NumBloomLevels; i++)
|
||||
{
|
||||
auto &blevel = levels[i];
|
||||
blevel.Viewport.left = 0;
|
||||
blevel.Viewport.top = 0;
|
||||
blevel.Viewport.width = (bloomWidth + 1) / 2;
|
||||
blevel.Viewport.height = (bloomHeight + 1) / 2;
|
||||
blevel.VTexture = { blevel.Viewport.width, blevel.Viewport.height, PixelFormat::Rgba16f };
|
||||
blevel.HTexture = { blevel.Viewport.width, blevel.Viewport.height, PixelFormat::Rgba16f };
|
||||
|
||||
bloomWidth = blevel.Viewport.width;
|
||||
bloomHeight = blevel.Viewport.height;
|
||||
}
|
||||
|
||||
lastWidth = width;
|
||||
lastHeight = height;
|
||||
}
|
||||
|
||||
void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneHeight, int fixedcm)
|
||||
{
|
||||
// Only bloom things if enabled and no special fixed light mode is active
|
||||
if (!gl_bloom || sceneWidth <= 0 || sceneHeight <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
renderstate->PushGroup("bloom");
|
||||
|
||||
UpdateTextures(sceneWidth, sceneHeight);
|
||||
|
||||
ExtractUniforms extractUniforms;
|
||||
extractUniforms.Scale = screen->SceneScale();
|
||||
extractUniforms.Offset = screen->SceneOffset();
|
||||
|
||||
auto &level0 = levels[0];
|
||||
|
||||
// Extract blooming pixels from scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomExtract;
|
||||
renderstate->Uniforms.Set(extractUniforms);
|
||||
renderstate->Viewport = level0.Viewport;
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->SetInputTexture(1, &hw_postprocess.exposure.CameraTexture);
|
||||
renderstate->SetOutputTexture(&level0.VTexture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
const float blurAmount = gl_bloom_amount;
|
||||
BlurUniforms blurUniforms;
|
||||
ComputeBlurSamples(7, blurAmount, blurUniforms.SampleWeights);
|
||||
|
||||
// Blur and downscale:
|
||||
for (int i = 0; i < NumBloomLevels - 1; i++)
|
||||
{
|
||||
auto &blevel = levels[i];
|
||||
auto &next = levels[i + 1];
|
||||
|
||||
BlurStep(renderstate, blurUniforms, blevel.VTexture, blevel.HTexture, blevel.Viewport, false);
|
||||
BlurStep(renderstate, blurUniforms, blevel.HTexture, blevel.VTexture, blevel.Viewport, true);
|
||||
|
||||
// Linear downscale:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = next.Viewport;
|
||||
renderstate->SetInputTexture(0, &blevel.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&next.VTexture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
}
|
||||
|
||||
// Blur and upscale:
|
||||
for (int i = NumBloomLevels - 1; i > 0; i--)
|
||||
{
|
||||
auto &blevel = levels[i];
|
||||
auto &next = levels[i - 1];
|
||||
|
||||
BlurStep(renderstate, blurUniforms, blevel.VTexture, blevel.HTexture, blevel.Viewport, false);
|
||||
BlurStep(renderstate, blurUniforms, blevel.HTexture, blevel.VTexture, blevel.Viewport, true);
|
||||
|
||||
// Linear upscale:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = next.Viewport;
|
||||
renderstate->SetInputTexture(0, &blevel.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&next.VTexture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
}
|
||||
|
||||
BlurStep(renderstate, blurUniforms, level0.VTexture, level0.HTexture, level0.Viewport, false);
|
||||
BlurStep(renderstate, blurUniforms, level0.HTexture, level0.VTexture, level0.Viewport, true);
|
||||
|
||||
// Add bloom back to scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = screen->mSceneViewport;
|
||||
renderstate->SetInputTexture(0, &level0.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputCurrent();
|
||||
renderstate->SetAdditiveBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
||||
void PPBloom::RenderBlur(PPRenderState *renderstate, int sceneWidth, int sceneHeight, float gameinfobluramount)
|
||||
{
|
||||
// No scene, no blur!
|
||||
if (sceneWidth <= 0 || sceneHeight <= 0)
|
||||
return;
|
||||
|
||||
UpdateTextures(sceneWidth, sceneHeight);
|
||||
|
||||
// first, respect the CVar
|
||||
float blurAmount = gl_menu_blur;
|
||||
|
||||
// if CVar is negative, use the gameinfo entry
|
||||
if (gl_menu_blur < 0)
|
||||
blurAmount = gameinfobluramount;
|
||||
|
||||
// if blurAmount == 0 or somehow still returns negative, exit to prevent a crash, clearly we don't want this
|
||||
if (blurAmount <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
renderstate->PushGroup("blur");
|
||||
|
||||
int numLevels = 3;
|
||||
assert(numLevels <= NumBloomLevels);
|
||||
|
||||
auto &level0 = levels[0];
|
||||
|
||||
// Grab the area we want to bloom:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = level0.Viewport;
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&level0.VTexture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
BlurUniforms blurUniforms;
|
||||
ComputeBlurSamples(7, blurAmount, blurUniforms.SampleWeights);
|
||||
|
||||
// Blur and downscale:
|
||||
for (int i = 0; i < numLevels - 1; i++)
|
||||
{
|
||||
auto &blevel = levels[i];
|
||||
auto &next = levels[i + 1];
|
||||
|
||||
BlurStep(renderstate, blurUniforms, blevel.VTexture, blevel.HTexture, blevel.Viewport, false);
|
||||
BlurStep(renderstate, blurUniforms, blevel.HTexture, blevel.VTexture, blevel.Viewport, true);
|
||||
|
||||
// Linear downscale:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = next.Viewport;
|
||||
renderstate->SetInputTexture(0, &blevel.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&next.VTexture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
}
|
||||
|
||||
// Blur and upscale:
|
||||
for (int i = numLevels - 1; i > 0; i--)
|
||||
{
|
||||
auto &blevel = levels[i];
|
||||
auto &next = levels[i - 1];
|
||||
|
||||
BlurStep(renderstate, blurUniforms, blevel.VTexture, blevel.HTexture, blevel.Viewport, false);
|
||||
BlurStep(renderstate, blurUniforms, blevel.HTexture, blevel.VTexture, blevel.Viewport, true);
|
||||
|
||||
// Linear upscale:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = next.Viewport;
|
||||
renderstate->SetInputTexture(0, &blevel.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&next.VTexture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
}
|
||||
|
||||
BlurStep(renderstate, blurUniforms, level0.VTexture, level0.HTexture, level0.Viewport, false);
|
||||
BlurStep(renderstate, blurUniforms, level0.HTexture, level0.VTexture, level0.Viewport, true);
|
||||
|
||||
// Copy blur back to scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = screen->mScreenViewport;
|
||||
renderstate->SetInputTexture(0, &level0.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputCurrent();
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
||||
void PPBloom::BlurStep(PPRenderState *renderstate, const BlurUniforms &blurUniforms, PPTexture &input, PPTexture &output, PPViewport viewport, bool vertical)
|
||||
{
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = vertical ? &BlurVertical : &BlurHorizontal;
|
||||
renderstate->Uniforms.Set(blurUniforms);
|
||||
renderstate->Viewport = viewport;
|
||||
renderstate->SetInputTexture(0, &input);
|
||||
renderstate->SetOutputTexture(&output);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
}
|
||||
|
||||
float PPBloom::ComputeBlurGaussian(float n, float theta) // theta = Blur Amount
|
||||
{
|
||||
return (float)((1.0f / sqrtf(2 * (float)M_PI * theta)) * expf(-(n * n) / (2.0f * theta * theta)));
|
||||
}
|
||||
|
||||
void PPBloom::ComputeBlurSamples(int sampleCount, float blurAmount, float *sampleWeights)
|
||||
{
|
||||
sampleWeights[0] = ComputeBlurGaussian(0, blurAmount);
|
||||
|
||||
float totalWeights = sampleWeights[0];
|
||||
|
||||
for (int i = 0; i < sampleCount / 2; i++)
|
||||
{
|
||||
float weight = ComputeBlurGaussian(i + 1.0f, blurAmount);
|
||||
|
||||
sampleWeights[i * 2 + 1] = weight;
|
||||
sampleWeights[i * 2 + 2] = weight;
|
||||
|
||||
totalWeights += weight * 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
{
|
||||
sampleWeights[i] /= totalWeights;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PPLensDistort::Render(PPRenderState *renderstate)
|
||||
{
|
||||
if (gl_lens == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float k[4] =
|
||||
{
|
||||
gl_lens_k,
|
||||
gl_lens_k * gl_lens_chromatic,
|
||||
gl_lens_k * gl_lens_chromatic * gl_lens_chromatic,
|
||||
0.0f
|
||||
};
|
||||
float kcube[4] =
|
||||
{
|
||||
gl_lens_kcube,
|
||||
gl_lens_kcube * gl_lens_chromatic,
|
||||
gl_lens_kcube * gl_lens_chromatic * gl_lens_chromatic,
|
||||
0.0f
|
||||
};
|
||||
|
||||
float aspect = screen->mSceneViewport.width / (float)screen->mSceneViewport.height;
|
||||
|
||||
// Scale factor to keep sampling within the input texture
|
||||
float r2 = aspect * aspect * 0.25f + 0.25f;
|
||||
float sqrt_r2 = sqrt(r2);
|
||||
float f0 = 1.0f + std::max(r2 * (k[0] + kcube[0] * sqrt_r2), 0.0f);
|
||||
float f2 = 1.0f + std::max(r2 * (k[2] + kcube[2] * sqrt_r2), 0.0f);
|
||||
float f = std::max(f0, f2);
|
||||
float scale = 1.0f / f;
|
||||
|
||||
LensUniforms uniforms;
|
||||
uniforms.AspectRatio = aspect;
|
||||
uniforms.Scale = scale;
|
||||
uniforms.LensDistortionCoefficient = k;
|
||||
uniforms.CubicDistortionValue = kcube;
|
||||
|
||||
renderstate->PushGroup("lens");
|
||||
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &Lens;
|
||||
renderstate->Uniforms.Set(uniforms);
|
||||
renderstate->Viewport = screen->mScreenViewport;
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->SetOutputNext();
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PPFXAA::Render(PPRenderState *renderstate)
|
||||
{
|
||||
if (0 == gl_fxaa)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateShaders();
|
||||
|
||||
FXAAUniforms uniforms;
|
||||
uniforms.ReciprocalResolution = { 1.0f / screen->mScreenViewport.width, 1.0f / screen->mScreenViewport.height };
|
||||
|
||||
renderstate->PushGroup("fxaa");
|
||||
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &FXAALuma;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = screen->mScreenViewport;
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Nearest);
|
||||
renderstate->SetOutputNext();
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->Shader = &FXAA;
|
||||
renderstate->Uniforms.Set(uniforms);
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
||||
int PPFXAA::GetMaxVersion()
|
||||
{
|
||||
return screen->glslversion >= 4.f ? 400 : 330;
|
||||
}
|
||||
|
||||
void PPFXAA::CreateShaders()
|
||||
{
|
||||
if (LastQuality == gl_fxaa)
|
||||
return;
|
||||
|
||||
FXAALuma = { "engine/shaders/pp/fxaa.fp", "#define FXAA_LUMA_PASS\n", {} };
|
||||
FXAA = { "engine/shaders/pp/fxaa.fp", GetDefines(), FXAAUniforms::Desc(), GetMaxVersion() };
|
||||
LastQuality = gl_fxaa;
|
||||
}
|
||||
|
||||
FString PPFXAA::GetDefines()
|
||||
{
|
||||
int quality;
|
||||
|
||||
switch (gl_fxaa)
|
||||
{
|
||||
default:
|
||||
case IFXAAShader::Low: quality = 10; break;
|
||||
case IFXAAShader::Medium: quality = 12; break;
|
||||
case IFXAAShader::High: quality = 29; break;
|
||||
case IFXAAShader::Extreme: quality = 39; break;
|
||||
}
|
||||
|
||||
const int gatherAlpha = GetMaxVersion() >= 400 ? 1 : 0;
|
||||
|
||||
// TODO: enable FXAA_GATHER4_ALPHA on OpenGL earlier than 4.0
|
||||
// when GL_ARB_gpu_shader5/GL_NV_gpu_shader5 extensions are supported
|
||||
|
||||
FString result;
|
||||
result.Format(
|
||||
"#define FXAA_QUALITY__PRESET %i\n"
|
||||
"#define FXAA_GATHER4_ALPHA %i\n",
|
||||
quality, gatherAlpha);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sceneHeight)
|
||||
{
|
||||
if (!gl_bloom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
renderstate->PushGroup("exposure");
|
||||
|
||||
UpdateTextures(sceneWidth, sceneHeight);
|
||||
|
||||
ExposureExtractUniforms extractUniforms;
|
||||
extractUniforms.Scale = screen->SceneScale();
|
||||
extractUniforms.Offset = screen->SceneOffset();
|
||||
|
||||
ExposureCombineUniforms combineUniforms;
|
||||
combineUniforms.ExposureBase = gl_exposure_base;
|
||||
combineUniforms.ExposureMin = gl_exposure_min;
|
||||
combineUniforms.ExposureScale = gl_exposure_scale;
|
||||
combineUniforms.ExposureSpeed = gl_exposure_speed;
|
||||
|
||||
auto &level0 = ExposureLevels[0];
|
||||
|
||||
// Extract light blevel from scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &ExposureExtract;
|
||||
renderstate->Uniforms.Set(extractUniforms);
|
||||
renderstate->Viewport = level0.Viewport;
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&level0.Texture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
// Find the average value:
|
||||
for (size_t i = 0; i + 1 < ExposureLevels.size(); i++)
|
||||
{
|
||||
auto &blevel = ExposureLevels[i];
|
||||
auto &next = ExposureLevels[i + 1];
|
||||
|
||||
renderstate->Shader = &ExposureAverage;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = next.Viewport;
|
||||
renderstate->SetInputTexture(0, &blevel.Texture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&next.Texture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
}
|
||||
|
||||
// Combine average value with current camera exposure:
|
||||
renderstate->Shader = &ExposureCombine;
|
||||
renderstate->Uniforms.Set(combineUniforms);
|
||||
renderstate->Viewport.left = 0;
|
||||
renderstate->Viewport.top = 0;
|
||||
renderstate->Viewport.width = 1;
|
||||
renderstate->Viewport.height = 1;
|
||||
renderstate->SetInputTexture(0, &ExposureLevels.back().Texture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&CameraTexture);
|
||||
if (!FirstExposureFrame)
|
||||
renderstate->SetAlphaBlend();
|
||||
else
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->PopGroup();
|
||||
|
||||
FirstExposureFrame = false;
|
||||
}
|
||||
|
||||
void PPCameraExposure::UpdateTextures(int width, int height)
|
||||
{
|
||||
int firstwidth = std::max(width / 2, 1);
|
||||
int firstheight = std::max(height / 2, 1);
|
||||
|
||||
if (ExposureLevels.size() > 0 && ExposureLevels[0].Viewport.width == firstwidth && ExposureLevels[0].Viewport.height == firstheight)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ExposureLevels.clear();
|
||||
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
width = std::max(width / 2, 1);
|
||||
height = std::max(height / 2, 1);
|
||||
|
||||
PPExposureLevel blevel;
|
||||
blevel.Viewport.left = 0;
|
||||
blevel.Viewport.top = 0;
|
||||
blevel.Viewport.width = width;
|
||||
blevel.Viewport.height = height;
|
||||
blevel.Texture = { blevel.Viewport.width, blevel.Viewport.height, PixelFormat::R32f };
|
||||
ExposureLevels.push_back(std::move(blevel));
|
||||
|
||||
i++;
|
||||
|
||||
} while (width > 1 || height > 1);
|
||||
|
||||
FirstExposureFrame = true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PPTonemap::UpdateTextures()
|
||||
{
|
||||
if (gl_tonemap == Palette && !PaletteTexture.Data)
|
||||
{
|
||||
std::shared_ptr<void> data(new uint32_t[512 * 512], [](void *p) { delete[](uint32_t*)p; });
|
||||
|
||||
uint8_t *lut = (uint8_t *)data.get();
|
||||
for (int r = 0; r < 64; r++)
|
||||
{
|
||||
for (int g = 0; g < 64; g++)
|
||||
{
|
||||
for (int b = 0; b < 64; b++)
|
||||
{
|
||||
PalEntry color = ImageHelpers::BasePalette[(uint8_t)ImageHelpers::PTM_BestColor((r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4),
|
||||
gl_paltonemap_reverselookup, gl_paltonemap_powtable, 0, 256)];
|
||||
int index = ((r * 64 + g) * 64 + b) * 4;
|
||||
lut[index] = color.r;
|
||||
lut[index + 1] = color.g;
|
||||
lut[index + 2] = color.b;
|
||||
lut[index + 3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PaletteTexture = { 512, 512, PixelFormat::Rgba8, data };
|
||||
}
|
||||
}
|
||||
|
||||
void PPTonemap::Render(PPRenderState *renderstate)
|
||||
{
|
||||
if (gl_tonemap == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateTextures();
|
||||
|
||||
PPShader *shader = nullptr;
|
||||
switch (gl_tonemap)
|
||||
{
|
||||
default:
|
||||
case Linear: shader = &LinearShader; break;
|
||||
case Reinhard: shader = &ReinhardShader; break;
|
||||
case HejlDawson: shader = &HejlDawsonShader; break;
|
||||
case Uncharted2: shader = &Uncharted2Shader; break;
|
||||
case Palette: shader = &PaletteShader; break;
|
||||
}
|
||||
|
||||
renderstate->PushGroup("tonemap");
|
||||
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = shader;
|
||||
renderstate->Viewport = screen->mScreenViewport;
|
||||
renderstate->SetInputCurrent(0);
|
||||
if (gl_tonemap == Palette)
|
||||
renderstate->SetInputTexture(1, &PaletteTexture);
|
||||
renderstate->SetOutputNext();
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PPAmbientOcclusion::PPAmbientOcclusion()
|
||||
{
|
||||
// Must match quality enum in PPAmbientOcclusion::DeclareShaders
|
||||
double numDirections[NumAmbientRandomTextures] = { 2.0, 4.0, 8.0 };
|
||||
|
||||
std::mt19937 generator(1337);
|
||||
std::uniform_real_distribution<double> distribution(0.0, 1.0);
|
||||
for (int quality = 0; quality < NumAmbientRandomTextures; quality++)
|
||||
{
|
||||
std::shared_ptr<void> data(new int16_t[16 * 4], [](void *p) { delete[](int16_t*)p; });
|
||||
int16_t *randomValues = (int16_t *)data.get();
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
double angle = 2.0 * M_PI * distribution(generator) / numDirections[quality];
|
||||
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[quality] = { 4, 4, PixelFormat::Rgba16_snorm, data };
|
||||
}
|
||||
}
|
||||
|
||||
void PPAmbientOcclusion::CreateShaders()
|
||||
{
|
||||
if (gl_ssao == LastQuality)
|
||||
return;
|
||||
|
||||
// Must match quality values in PPAmbientOcclusion::UpdateTextures
|
||||
int numDirections, numSteps;
|
||||
switch (gl_ssao)
|
||||
{
|
||||
default:
|
||||
case LowQuality: numDirections = 2; numSteps = 4; break;
|
||||
case MediumQuality: numDirections = 4; numSteps = 4; break;
|
||||
case HighQuality: numDirections = 8; numSteps = 4; break;
|
||||
}
|
||||
|
||||
FString defines;
|
||||
defines.Format(R"(
|
||||
#define USE_RANDOM_TEXTURE
|
||||
#define RANDOM_TEXTURE_WIDTH 4.0
|
||||
#define NUM_DIRECTIONS %d.0
|
||||
#define NUM_STEPS %d.0
|
||||
)", numDirections, numSteps);
|
||||
|
||||
LinearDepth = { "engine/shaders/pp/lineardepth.fp", "", LinearDepthUniforms::Desc() };
|
||||
LinearDepthMS = { "engine/shaders/pp/lineardepth.fp", "#define MULTISAMPLE\n", LinearDepthUniforms::Desc() };
|
||||
AmbientOcclude = { "engine/shaders/pp/ssao.fp", defines, SSAOUniforms::Desc() };
|
||||
AmbientOccludeMS = { "engine/shaders/pp/ssao.fp", defines + "\n#define MULTISAMPLE\n", SSAOUniforms::Desc() };
|
||||
BlurVertical = { "engine/shaders/pp/depthblur.fp", "#define BLUR_VERTICAL\n", DepthBlurUniforms::Desc() };
|
||||
BlurHorizontal = { "engine/shaders/pp/depthblur.fp", "#define BLUR_HORIZONTAL\n", DepthBlurUniforms::Desc() };
|
||||
Combine = { "engine/shaders/pp/ssaocombine.fp", "", AmbientCombineUniforms::Desc() };
|
||||
CombineMS = { "engine/shaders/pp/ssaocombine.fp", "#define MULTISAMPLE\n", AmbientCombineUniforms::Desc() };
|
||||
|
||||
LastQuality = gl_ssao;
|
||||
}
|
||||
|
||||
void PPAmbientOcclusion::UpdateTextures(int width, int height)
|
||||
{
|
||||
if ((width <= 0 || height <= 0) || (width == LastWidth && height == LastHeight))
|
||||
return;
|
||||
|
||||
AmbientWidth = (width + 1) / 2;
|
||||
AmbientHeight = (height + 1) / 2;
|
||||
|
||||
LinearDepthTexture = { AmbientWidth, AmbientHeight, PixelFormat::R32f };
|
||||
Ambient0 = { AmbientWidth, AmbientHeight, PixelFormat::Rg16f };
|
||||
Ambient1 = { AmbientWidth, AmbientHeight, PixelFormat::Rg16f };
|
||||
|
||||
LastWidth = width;
|
||||
LastHeight = height;
|
||||
}
|
||||
|
||||
void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneWidth, int sceneHeight)
|
||||
{
|
||||
if (gl_ssao == 0 || sceneWidth == 0 || sceneHeight == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateShaders();
|
||||
UpdateTextures(sceneWidth, sceneHeight);
|
||||
|
||||
float bias = gl_ssao_bias;
|
||||
float aoRadius = gl_ssao_radius;
|
||||
const float blurAmount = gl_ssao_blur;
|
||||
float aoStrength = gl_ssao_strength;
|
||||
|
||||
//float tanHalfFovy = tan(fovy * (M_PI / 360.0f));
|
||||
float tanHalfFovy = 1.0f / m5;
|
||||
float invFocalLenX = tanHalfFovy * (sceneWidth / (float)sceneHeight);
|
||||
float invFocalLenY = tanHalfFovy;
|
||||
float nDotVBias = clamp(bias, 0.0f, 1.0f);
|
||||
float r2 = aoRadius * aoRadius;
|
||||
|
||||
float blurSharpness = 1.0f / blurAmount;
|
||||
|
||||
auto sceneScale = screen->SceneScale();
|
||||
auto sceneOffset = screen->SceneOffset();
|
||||
|
||||
int randomTexture = clamp(gl_ssao - 1, 0, NumAmbientRandomTextures - 1);
|
||||
|
||||
LinearDepthUniforms linearUniforms;
|
||||
linearUniforms.SampleIndex = 0;
|
||||
linearUniforms.LinearizeDepthA = 1.0f / screen->GetZFar() - 1.0f / screen->GetZNear();
|
||||
linearUniforms.LinearizeDepthB = std::max(1.0f / screen->GetZNear(), 1.e-8f);
|
||||
linearUniforms.InverseDepthRangeA = 1.0f;
|
||||
linearUniforms.InverseDepthRangeB = 0.0f;
|
||||
linearUniforms.Scale = sceneScale;
|
||||
linearUniforms.Offset = sceneOffset;
|
||||
|
||||
SSAOUniforms ssaoUniforms;
|
||||
ssaoUniforms.SampleIndex = 0;
|
||||
ssaoUniforms.UVToViewA = { 2.0f * invFocalLenX, 2.0f * invFocalLenY };
|
||||
ssaoUniforms.UVToViewB = { -invFocalLenX, -invFocalLenY };
|
||||
ssaoUniforms.InvFullResolution = { 1.0f / AmbientWidth, 1.0f / AmbientHeight };
|
||||
ssaoUniforms.NDotVBias = nDotVBias;
|
||||
ssaoUniforms.NegInvR2 = -1.0f / r2;
|
||||
ssaoUniforms.RadiusToScreen = aoRadius * 0.5f / tanHalfFovy * AmbientHeight;
|
||||
ssaoUniforms.AOMultiplier = 1.0f / (1.0f - nDotVBias);
|
||||
ssaoUniforms.AOStrength = aoStrength;
|
||||
ssaoUniforms.Scale = sceneScale;
|
||||
ssaoUniforms.Offset = sceneOffset;
|
||||
|
||||
DepthBlurUniforms blurUniforms;
|
||||
blurUniforms.BlurSharpness = blurSharpness;
|
||||
blurUniforms.PowExponent = gl_ssao_exponent;
|
||||
|
||||
AmbientCombineUniforms combineUniforms;
|
||||
combineUniforms.SampleCount = gl_multisample;
|
||||
combineUniforms.Scale = screen->SceneScale();
|
||||
combineUniforms.Offset = screen->SceneOffset();
|
||||
combineUniforms.DebugMode = gl_ssao_debug;
|
||||
|
||||
IntRect ambientViewport;
|
||||
ambientViewport.left = 0;
|
||||
ambientViewport.top = 0;
|
||||
ambientViewport.width = AmbientWidth;
|
||||
ambientViewport.height = AmbientHeight;
|
||||
|
||||
renderstate->PushGroup("ssao");
|
||||
|
||||
// Calculate linear depth values
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = gl_multisample > 1 ? &LinearDepthMS : &LinearDepth;
|
||||
renderstate->Uniforms.Set(linearUniforms);
|
||||
renderstate->Viewport = ambientViewport;
|
||||
renderstate->SetInputSceneDepth(0);
|
||||
renderstate->SetInputSceneColor(1);
|
||||
renderstate->SetOutputTexture(&LinearDepthTexture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
// Apply ambient occlusion
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = gl_multisample > 1 ? &AmbientOccludeMS : &AmbientOcclude;
|
||||
renderstate->Uniforms.Set(ssaoUniforms);
|
||||
renderstate->Viewport = ambientViewport;
|
||||
renderstate->SetInputTexture(0, &LinearDepthTexture);
|
||||
renderstate->SetInputSceneNormal(1);
|
||||
renderstate->SetInputTexture(2, &AmbientRandomTexture[randomTexture], PPFilterMode::Nearest, PPWrapMode::Repeat);
|
||||
renderstate->SetOutputTexture(&Ambient0);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
// Blur SSAO texture
|
||||
if (gl_ssao_debug < 2)
|
||||
{
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BlurHorizontal;
|
||||
renderstate->Uniforms.Set(blurUniforms);
|
||||
renderstate->Viewport = ambientViewport;
|
||||
renderstate->SetInputTexture(0, &Ambient0);
|
||||
renderstate->SetOutputTexture(&Ambient1);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BlurVertical;
|
||||
renderstate->Uniforms.Set(blurUniforms);
|
||||
renderstate->Viewport = ambientViewport;
|
||||
renderstate->SetInputTexture(0, &Ambient1);
|
||||
renderstate->SetOutputTexture(&Ambient0);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
}
|
||||
|
||||
// Add SSAO back to scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = gl_multisample > 1 ? &CombineMS : &Combine;
|
||||
renderstate->Uniforms.Set(combineUniforms);
|
||||
renderstate->Viewport = screen->mSceneViewport;
|
||||
if (gl_ssao_debug < 4)
|
||||
renderstate->SetInputTexture(0, &Ambient0, PPFilterMode::Linear);
|
||||
else
|
||||
renderstate->SetInputSceneNormal(0, PPFilterMode::Linear);
|
||||
renderstate->SetInputSceneFog(1);
|
||||
renderstate->SetOutputSceneColor();
|
||||
if (gl_ssao_debug != 0)
|
||||
renderstate->SetNoBlend();
|
||||
else
|
||||
renderstate->SetAlphaBlend();
|
||||
renderstate->Draw();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PPPresent::PPPresent()
|
||||
{
|
||||
static const float data[64] =
|
||||
{
|
||||
.0078125, .2578125, .1328125, .3828125, .0234375, .2734375, .1484375, .3984375,
|
||||
.7578125, .5078125, .8828125, .6328125, .7734375, .5234375, .8984375, .6484375,
|
||||
.0703125, .3203125, .1953125, .4453125, .0859375, .3359375, .2109375, .4609375,
|
||||
.8203125, .5703125, .9453125, .6953125, .8359375, .5859375, .9609375, .7109375,
|
||||
.0390625, .2890625, .1640625, .4140625, .0546875, .3046875, .1796875, .4296875,
|
||||
.7890625, .5390625, .9140625, .6640625, .8046875, .5546875, .9296875, .6796875,
|
||||
.1015625, .3515625, .2265625, .4765625, .1171875, .3671875, .2421875, .4921875,
|
||||
.8515625, .6015625, .9765625, .7265625, .8671875, .6171875, .9921875, .7421875,
|
||||
};
|
||||
|
||||
std::shared_ptr<void> pixels(new float[64], [](void *p) { delete[](float*)p; });
|
||||
memcpy(pixels.get(), data, 64 * sizeof(float));
|
||||
Dither = { 8, 8, PixelFormat::R32f, pixels };
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Postprocess::Pass1(PPRenderState* state, int fixedcm, int sceneWidth, int sceneHeight)
|
||||
{
|
||||
exposure.Render(state, sceneWidth, sceneHeight);
|
||||
bloom.RenderBloom(state, sceneWidth, sceneHeight, fixedcm);
|
||||
}
|
||||
|
||||
void Postprocess::Pass2(PPRenderState* state, int fixedcm, int sceneWidth, int sceneHeight)
|
||||
{
|
||||
tonemap.Render(state);
|
||||
lens.Render(state);
|
||||
fxaa.Render(state);
|
||||
}
|
|
@ -1,771 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "hwrenderer/data/shaderuniforms.h"
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
struct PostProcessShader;
|
||||
|
||||
typedef FRenderStyle PPBlendMode;
|
||||
typedef IntRect PPViewport;
|
||||
|
||||
class PPTexture;
|
||||
class PPShader;
|
||||
|
||||
enum class PPFilterMode { Nearest, Linear };
|
||||
enum class PPWrapMode { Clamp, Repeat };
|
||||
enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth, SwapChain, ShadowMap };
|
||||
|
||||
class PPTextureInput
|
||||
{
|
||||
public:
|
||||
PPFilterMode Filter = PPFilterMode::Nearest;
|
||||
PPWrapMode Wrap = PPWrapMode::Clamp;
|
||||
PPTextureType Type = PPTextureType::CurrentPipelineTexture;
|
||||
PPTexture *Texture = nullptr;
|
||||
};
|
||||
|
||||
class PPOutput
|
||||
{
|
||||
public:
|
||||
PPTextureType Type = PPTextureType::NextPipelineTexture;
|
||||
PPTexture *Texture = nullptr;
|
||||
};
|
||||
|
||||
class PPUniforms
|
||||
{
|
||||
public:
|
||||
PPUniforms()
|
||||
{
|
||||
}
|
||||
|
||||
PPUniforms(const PPUniforms &src)
|
||||
{
|
||||
Data = src.Data;
|
||||
}
|
||||
|
||||
~PPUniforms()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
PPUniforms &operator=(const PPUniforms &src)
|
||||
{
|
||||
Data = src.Data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Data.Clear();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Set(const T &v)
|
||||
{
|
||||
if (Data.Size() != (int)sizeof(T))
|
||||
{
|
||||
Data.Resize(sizeof(T));
|
||||
memcpy(Data.Data(), &v, Data.Size());
|
||||
}
|
||||
}
|
||||
|
||||
TArray<uint8_t> Data;
|
||||
};
|
||||
|
||||
class PPRenderState
|
||||
{
|
||||
public:
|
||||
virtual ~PPRenderState() = default;
|
||||
|
||||
virtual void PushGroup(const FString &name) = 0;
|
||||
virtual void PopGroup() = 0;
|
||||
|
||||
virtual void Draw() = 0;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Shader = nullptr;
|
||||
Textures = TArray<PPTextureInput>();
|
||||
Uniforms = PPUniforms();
|
||||
Viewport = PPViewport();
|
||||
BlendMode = PPBlendMode();
|
||||
Output = PPOutput();
|
||||
ShadowMapBuffers = false;
|
||||
}
|
||||
|
||||
void SetInputTexture(int index, PPTexture *texture, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
||||
{
|
||||
if ((int)Textures.Size() < index + 1)
|
||||
Textures.Resize(index + 1);
|
||||
auto &tex = Textures[index];
|
||||
tex.Filter = filter;
|
||||
tex.Wrap = wrap;
|
||||
tex.Type = PPTextureType::PPTexture;
|
||||
tex.Texture = texture;
|
||||
}
|
||||
|
||||
void SetInputCurrent(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
||||
{
|
||||
SetInputSpecialType(index, PPTextureType::CurrentPipelineTexture, filter, wrap);
|
||||
}
|
||||
|
||||
void SetInputSceneColor(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
||||
{
|
||||
SetInputSpecialType(index, PPTextureType::SceneColor, filter, wrap);
|
||||
}
|
||||
|
||||
void SetInputSceneFog(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
||||
{
|
||||
SetInputSpecialType(index, PPTextureType::SceneFog, filter, wrap);
|
||||
}
|
||||
|
||||
void SetInputSceneNormal(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
||||
{
|
||||
SetInputSpecialType(index, PPTextureType::SceneNormal, filter, wrap);
|
||||
}
|
||||
|
||||
void SetInputSceneDepth(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
||||
{
|
||||
SetInputSpecialType(index, PPTextureType::SceneDepth, filter, wrap);
|
||||
}
|
||||
|
||||
void SetInputSpecialType(int index, PPTextureType type, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
||||
{
|
||||
if ((int)Textures.Size() < index + 1)
|
||||
Textures.Resize(index + 1);
|
||||
auto &tex = Textures[index];
|
||||
tex.Filter = filter;
|
||||
tex.Wrap = wrap;
|
||||
tex.Type = type;
|
||||
tex.Texture = nullptr;
|
||||
}
|
||||
|
||||
void SetShadowMapBuffers(bool enable)
|
||||
{
|
||||
ShadowMapBuffers = enable;
|
||||
}
|
||||
|
||||
void SetOutputTexture(PPTexture *texture)
|
||||
{
|
||||
Output.Type = PPTextureType::PPTexture;
|
||||
Output.Texture = texture;
|
||||
}
|
||||
|
||||
void SetOutputCurrent()
|
||||
{
|
||||
Output.Type = PPTextureType::CurrentPipelineTexture;
|
||||
Output.Texture = nullptr;
|
||||
}
|
||||
|
||||
void SetOutputNext()
|
||||
{
|
||||
Output.Type = PPTextureType::NextPipelineTexture;
|
||||
Output.Texture = nullptr;
|
||||
}
|
||||
|
||||
void SetOutputSceneColor()
|
||||
{
|
||||
Output.Type = PPTextureType::SceneColor;
|
||||
Output.Texture = nullptr;
|
||||
}
|
||||
|
||||
void SetOutputSwapChain()
|
||||
{
|
||||
Output.Type = PPTextureType::SwapChain;
|
||||
Output.Texture = nullptr;
|
||||
}
|
||||
|
||||
void SetOutputShadowMap()
|
||||
{
|
||||
Output.Type = PPTextureType::ShadowMap;
|
||||
Output.Texture = nullptr;
|
||||
}
|
||||
|
||||
void SetNoBlend()
|
||||
{
|
||||
BlendMode.BlendOp = STYLEOP_Add;
|
||||
BlendMode.SrcAlpha = STYLEALPHA_One;
|
||||
BlendMode.DestAlpha = STYLEALPHA_Zero;
|
||||
BlendMode.Flags = 0;
|
||||
}
|
||||
|
||||
void SetAdditiveBlend()
|
||||
{
|
||||
BlendMode.BlendOp = STYLEOP_Add;
|
||||
BlendMode.SrcAlpha = STYLEALPHA_One;
|
||||
BlendMode.DestAlpha = STYLEALPHA_One;
|
||||
BlendMode.Flags = 0;
|
||||
}
|
||||
|
||||
void SetAlphaBlend()
|
||||
{
|
||||
BlendMode.BlendOp = STYLEOP_Add;
|
||||
BlendMode.SrcAlpha = STYLEALPHA_Src;
|
||||
BlendMode.DestAlpha = STYLEALPHA_InvSrc;
|
||||
BlendMode.Flags = 0;
|
||||
}
|
||||
|
||||
PPShader *Shader;
|
||||
TArray<PPTextureInput> Textures;
|
||||
PPUniforms Uniforms;
|
||||
PPViewport Viewport;
|
||||
PPBlendMode BlendMode;
|
||||
PPOutput Output;
|
||||
bool ShadowMapBuffers = false;
|
||||
};
|
||||
|
||||
enum class PixelFormat
|
||||
{
|
||||
Rgba8,
|
||||
Rgba16f,
|
||||
R32f,
|
||||
Rg16f,
|
||||
Rgba16_snorm
|
||||
};
|
||||
|
||||
class PPResource
|
||||
{
|
||||
public:
|
||||
PPResource()
|
||||
{
|
||||
Next = First;
|
||||
First = this;
|
||||
if (Next) Next->Prev = this;
|
||||
}
|
||||
|
||||
PPResource(const PPResource &)
|
||||
{
|
||||
Next = First;
|
||||
First = this;
|
||||
if (Next) Next->Prev = this;
|
||||
}
|
||||
|
||||
virtual ~PPResource()
|
||||
{
|
||||
if (Next) Next->Prev = Prev;
|
||||
if (Prev) Prev->Next = Next;
|
||||
else First = Next;
|
||||
}
|
||||
|
||||
PPResource &operator=(const PPResource &other)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
static void ResetAll()
|
||||
{
|
||||
for (PPResource *cur = First; cur; cur = cur->Next)
|
||||
cur->ResetBackend();
|
||||
}
|
||||
|
||||
virtual void ResetBackend() = 0;
|
||||
|
||||
private:
|
||||
static PPResource *First;
|
||||
PPResource *Prev = nullptr;
|
||||
PPResource *Next = nullptr;
|
||||
};
|
||||
|
||||
class PPTextureBackend
|
||||
{
|
||||
public:
|
||||
virtual ~PPTextureBackend() = default;
|
||||
};
|
||||
|
||||
class PPTexture : public PPResource
|
||||
{
|
||||
public:
|
||||
PPTexture() = default;
|
||||
PPTexture(int width, int height, PixelFormat format, std::shared_ptr<void> data = {}) : Width(width), Height(height), Format(format), Data(data) { }
|
||||
|
||||
void ResetBackend() override { Backend.reset(); }
|
||||
|
||||
int Width;
|
||||
int Height;
|
||||
PixelFormat Format;
|
||||
std::shared_ptr<void> Data;
|
||||
|
||||
std::unique_ptr<PPTextureBackend> Backend;
|
||||
};
|
||||
|
||||
class PPShaderBackend
|
||||
{
|
||||
public:
|
||||
virtual ~PPShaderBackend() = default;
|
||||
};
|
||||
|
||||
class PPShader : public PPResource
|
||||
{
|
||||
public:
|
||||
PPShader() = default;
|
||||
PPShader(const FString &fragment, const FString &defines, const std::vector<UniformFieldDesc> &uniforms, int version = 330) : FragmentShader(fragment), Defines(defines), Uniforms(uniforms), Version(version) { }
|
||||
|
||||
void ResetBackend() override { Backend.reset(); }
|
||||
|
||||
FString VertexShader = "engine/shaders/pp/screenquad.vp";
|
||||
FString FragmentShader;
|
||||
FString Defines;
|
||||
std::vector<UniformFieldDesc> Uniforms;
|
||||
int Version = 330;
|
||||
|
||||
std::unique_ptr<PPShaderBackend> Backend;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ExtractUniforms
|
||||
{
|
||||
FVector2 Scale;
|
||||
FVector2 Offset;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "Scale", UniformType::Vec2, offsetof(ExtractUniforms, Scale) },
|
||||
{ "Offset", UniformType::Vec2, offsetof(ExtractUniforms, Offset) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct BlurUniforms
|
||||
{
|
||||
float SampleWeights[8];
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "SampleWeights0", UniformType::Float, offsetof(BlurUniforms, SampleWeights[0]) },
|
||||
{ "SampleWeights1", UniformType::Float, offsetof(BlurUniforms, SampleWeights[1]) },
|
||||
{ "SampleWeights2", UniformType::Float, offsetof(BlurUniforms, SampleWeights[2]) },
|
||||
{ "SampleWeights3", UniformType::Float, offsetof(BlurUniforms, SampleWeights[3]) },
|
||||
{ "SampleWeights4", UniformType::Float, offsetof(BlurUniforms, SampleWeights[4]) },
|
||||
{ "SampleWeights5", UniformType::Float, offsetof(BlurUniforms, SampleWeights[5]) },
|
||||
{ "SampleWeights6", UniformType::Float, offsetof(BlurUniforms, SampleWeights[6]) },
|
||||
{ "SampleWeights7", UniformType::Float, offsetof(BlurUniforms, SampleWeights[7]) },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
enum { NumBloomLevels = 4 };
|
||||
|
||||
class PPBlurLevel
|
||||
{
|
||||
public:
|
||||
PPViewport Viewport;
|
||||
PPTexture VTexture;
|
||||
PPTexture HTexture;
|
||||
};
|
||||
|
||||
class PPBloom
|
||||
{
|
||||
public:
|
||||
void RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneHeight, int fixedcm);
|
||||
void RenderBlur(PPRenderState *renderstate, int sceneWidth, int sceneHeight, float gameinfobluramount);
|
||||
|
||||
private:
|
||||
void BlurStep(PPRenderState *renderstate, const BlurUniforms &blurUniforms, PPTexture &input, PPTexture &output, PPViewport viewport, bool vertical);
|
||||
void UpdateTextures(int width, int height);
|
||||
|
||||
static float ComputeBlurGaussian(float n, float theta);
|
||||
static void ComputeBlurSamples(int sampleCount, float blurAmount, float *sampleWeights);
|
||||
|
||||
PPBlurLevel levels[NumBloomLevels];
|
||||
int lastWidth = 0;
|
||||
int lastHeight = 0;
|
||||
|
||||
PPShader BloomCombine = { "engine/shaders/pp/bloomcombine.fp", "", {} };
|
||||
PPShader BloomExtract = { "engine/shaders/pp/bloomextract.fp", "", ExtractUniforms::Desc() };
|
||||
PPShader BlurVertical = { "engine/shaders/pp/blur.fp", "#define BLUR_VERTICAL\n", BlurUniforms::Desc() };
|
||||
PPShader BlurHorizontal = { "engine/shaders/pp/blur.fp", "#define BLUR_HORIZONTAL\n", BlurUniforms::Desc() };
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct LensUniforms
|
||||
{
|
||||
float AspectRatio;
|
||||
float Scale;
|
||||
float Padding0, Padding1;
|
||||
FVector4 LensDistortionCoefficient;
|
||||
FVector4 CubicDistortionValue;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "Aspect", UniformType::Float, offsetof(LensUniforms, AspectRatio) },
|
||||
{ "Scale", UniformType::Float, offsetof(LensUniforms, Scale) },
|
||||
{ "Padding0", UniformType::Float, offsetof(LensUniforms, Padding0) },
|
||||
{ "Padding1", UniformType::Float, offsetof(LensUniforms, Padding1) },
|
||||
{ "k", UniformType::Vec4, offsetof(LensUniforms, LensDistortionCoefficient) },
|
||||
{ "kcube", UniformType::Vec4, offsetof(LensUniforms, CubicDistortionValue) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class PPLensDistort
|
||||
{
|
||||
public:
|
||||
void Render(PPRenderState *renderstate);
|
||||
|
||||
private:
|
||||
PPShader Lens = { "engine/shaders/pp/lensdistortion.fp", "", LensUniforms::Desc() };
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct FXAAUniforms
|
||||
{
|
||||
FVector2 ReciprocalResolution;
|
||||
float Padding0, Padding1;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "ReciprocalResolution", UniformType::Vec2, offsetof(FXAAUniforms, ReciprocalResolution) },
|
||||
{ "Padding0", UniformType::Float, offsetof(FXAAUniforms, Padding0) },
|
||||
{ "Padding1", UniformType::Float, offsetof(FXAAUniforms, Padding1) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class PPFXAA
|
||||
{
|
||||
public:
|
||||
void Render(PPRenderState *renderstate);
|
||||
|
||||
private:
|
||||
void CreateShaders();
|
||||
int GetMaxVersion();
|
||||
FString GetDefines();
|
||||
|
||||
PPShader FXAALuma;
|
||||
PPShader FXAA;
|
||||
int LastQuality = -1;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ExposureExtractUniforms
|
||||
{
|
||||
FVector2 Scale;
|
||||
FVector2 Offset;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "Scale", UniformType::Vec2, offsetof(ExposureExtractUniforms, Scale) },
|
||||
{ "Offset", UniformType::Vec2, offsetof(ExposureExtractUniforms, Offset) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct ExposureCombineUniforms
|
||||
{
|
||||
float ExposureBase;
|
||||
float ExposureMin;
|
||||
float ExposureScale;
|
||||
float ExposureSpeed;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "ExposureBase", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureBase) },
|
||||
{ "ExposureMin", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureMin) },
|
||||
{ "ExposureScale", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureScale) },
|
||||
{ "ExposureSpeed", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureSpeed) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class PPExposureLevel
|
||||
{
|
||||
public:
|
||||
PPViewport Viewport;
|
||||
PPTexture Texture;
|
||||
};
|
||||
|
||||
class PPCameraExposure
|
||||
{
|
||||
public:
|
||||
void Render(PPRenderState *renderstate, int sceneWidth, int sceneHeight);
|
||||
|
||||
PPTexture CameraTexture = { 1, 1, PixelFormat::R32f };
|
||||
|
||||
private:
|
||||
void UpdateTextures(int width, int height);
|
||||
|
||||
std::vector<PPExposureLevel> ExposureLevels;
|
||||
bool FirstExposureFrame = true;
|
||||
|
||||
PPShader ExposureExtract = { "engine/shaders/pp/exposureextract.fp", "", ExposureExtractUniforms::Desc() };
|
||||
PPShader ExposureAverage = { "engine/shaders/pp/exposureaverage.fp", "", {}, 400 };
|
||||
PPShader ExposureCombine = { "engine/shaders/pp/exposurecombine.fp", "", ExposureCombineUniforms::Desc() };
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ColormapUniforms
|
||||
{
|
||||
FVector4 MapStart;
|
||||
FVector4 MapRange;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "uFixedColormapStart", UniformType::Vec4, offsetof(ColormapUniforms, MapStart) },
|
||||
{ "uFixedColormapRange", UniformType::Vec4, offsetof(ColormapUniforms, MapRange) },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PPTonemap
|
||||
{
|
||||
public:
|
||||
void Render(PPRenderState *renderstate);
|
||||
void ClearTonemapPalette() { PaletteTexture = {}; }
|
||||
|
||||
private:
|
||||
void UpdateTextures();
|
||||
|
||||
PPTexture PaletteTexture;
|
||||
|
||||
PPShader LinearShader = { "engine/shaders/pp/tonemap.fp", "#define LINEAR\n", {} };
|
||||
PPShader ReinhardShader = { "engine/shaders/pp/tonemap.fp", "#define REINHARD\n", {} };
|
||||
PPShader HejlDawsonShader = { "engine/shaders/pp/tonemap.fp", "#define HEJLDAWSON\n", {} };
|
||||
PPShader Uncharted2Shader = { "engine/shaders/pp/tonemap.fp", "#define UNCHARTED2\n", {} };
|
||||
PPShader PaletteShader = { "engine/shaders/pp/tonemap.fp", "#define PALETTE\n", {} };
|
||||
|
||||
enum TonemapMode
|
||||
{
|
||||
None,
|
||||
Uncharted2,
|
||||
HejlDawson,
|
||||
Reinhard,
|
||||
Linear,
|
||||
Palette,
|
||||
NumTonemapModes
|
||||
};
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct LinearDepthUniforms
|
||||
{
|
||||
int SampleIndex;
|
||||
float LinearizeDepthA;
|
||||
float LinearizeDepthB;
|
||||
float InverseDepthRangeA;
|
||||
float InverseDepthRangeB;
|
||||
float Padding0, Padding1, Padding2;
|
||||
FVector2 Scale;
|
||||
FVector2 Offset;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "SampleIndex", UniformType::Int, offsetof(LinearDepthUniforms, SampleIndex) },
|
||||
{ "LinearizeDepthA", UniformType::Float, offsetof(LinearDepthUniforms, LinearizeDepthA) },
|
||||
{ "LinearizeDepthB", UniformType::Float, offsetof(LinearDepthUniforms, LinearizeDepthB) },
|
||||
{ "InverseDepthRangeA", UniformType::Float, offsetof(LinearDepthUniforms, InverseDepthRangeA) },
|
||||
{ "InverseDepthRangeB", UniformType::Float, offsetof(LinearDepthUniforms, InverseDepthRangeB) },
|
||||
{ "Padding0", UniformType::Float, offsetof(LinearDepthUniforms, Padding0) },
|
||||
{ "Padding1", UniformType::Float, offsetof(LinearDepthUniforms, Padding1) },
|
||||
{ "Padding2", UniformType::Float, offsetof(LinearDepthUniforms, Padding2) },
|
||||
{ "Scale", UniformType::Vec2, offsetof(LinearDepthUniforms, Scale) },
|
||||
{ "Offset", UniformType::Vec2, offsetof(LinearDepthUniforms, Offset) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct SSAOUniforms
|
||||
{
|
||||
FVector2 UVToViewA;
|
||||
FVector2 UVToViewB;
|
||||
FVector2 InvFullResolution;
|
||||
float NDotVBias;
|
||||
float NegInvR2;
|
||||
float RadiusToScreen;
|
||||
float AOMultiplier;
|
||||
float AOStrength;
|
||||
int SampleIndex;
|
||||
float Padding0, Padding1;
|
||||
FVector2 Scale;
|
||||
FVector2 Offset;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "UVToViewA", UniformType::Vec2, offsetof(SSAOUniforms, UVToViewA) },
|
||||
{ "UVToViewB", UniformType::Vec2, offsetof(SSAOUniforms, UVToViewB) },
|
||||
{ "InvFullResolution", UniformType::Vec2, offsetof(SSAOUniforms, InvFullResolution) },
|
||||
{ "NDotVBias", UniformType::Float, offsetof(SSAOUniforms, NDotVBias) },
|
||||
{ "NegInvR2", UniformType::Float, offsetof(SSAOUniforms, NegInvR2) },
|
||||
{ "RadiusToScreen", UniformType::Float, offsetof(SSAOUniforms, RadiusToScreen) },
|
||||
{ "AOMultiplier", UniformType::Float, offsetof(SSAOUniforms, AOMultiplier) },
|
||||
{ "AOStrength", UniformType::Float, offsetof(SSAOUniforms, AOStrength) },
|
||||
{ "SampleIndex", UniformType::Int, offsetof(SSAOUniforms, SampleIndex) },
|
||||
{ "Padding0", UniformType::Float, offsetof(SSAOUniforms, Padding0) },
|
||||
{ "Padding1", UniformType::Float, offsetof(SSAOUniforms, Padding1) },
|
||||
{ "Scale", UniformType::Vec2, offsetof(SSAOUniforms, Scale) },
|
||||
{ "Offset", UniformType::Vec2, offsetof(SSAOUniforms, Offset) },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct DepthBlurUniforms
|
||||
{
|
||||
float BlurSharpness;
|
||||
float PowExponent;
|
||||
float Padding0, Padding1;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "BlurSharpness", UniformType::Float, offsetof(DepthBlurUniforms, BlurSharpness) },
|
||||
{ "PowExponent", UniformType::Float, offsetof(DepthBlurUniforms, PowExponent) },
|
||||
{ "Padding0", UniformType::Float, offsetof(DepthBlurUniforms, Padding0) },
|
||||
{ "Padding1", UniformType::Float, offsetof(DepthBlurUniforms, Padding1) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct AmbientCombineUniforms
|
||||
{
|
||||
int SampleCount;
|
||||
int DebugMode, Padding1, Padding2;
|
||||
FVector2 Scale;
|
||||
FVector2 Offset;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "SampleCount", UniformType::Int, offsetof(AmbientCombineUniforms, SampleCount) },
|
||||
{ "DebugMode", UniformType::Int, offsetof(AmbientCombineUniforms, DebugMode) },
|
||||
{ "Padding1", UniformType::Int, offsetof(AmbientCombineUniforms, Padding1) },
|
||||
{ "Padding2", UniformType::Int, offsetof(AmbientCombineUniforms, Padding2) },
|
||||
{ "Scale", UniformType::Vec2, offsetof(AmbientCombineUniforms, Scale) },
|
||||
{ "Offset", UniformType::Vec2, offsetof(AmbientCombineUniforms, Offset) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class PPAmbientOcclusion
|
||||
{
|
||||
public:
|
||||
PPAmbientOcclusion();
|
||||
void Render(PPRenderState *renderstate, float m5, int sceneWidth, int sceneHeight);
|
||||
|
||||
private:
|
||||
void CreateShaders();
|
||||
void UpdateTextures(int width, int height);
|
||||
|
||||
enum Quality
|
||||
{
|
||||
Off,
|
||||
LowQuality,
|
||||
MediumQuality,
|
||||
HighQuality,
|
||||
NumQualityModes
|
||||
};
|
||||
|
||||
int AmbientWidth = 0;
|
||||
int AmbientHeight = 0;
|
||||
|
||||
int LastQuality = -1;
|
||||
int LastWidth = 0;
|
||||
int LastHeight = 0;
|
||||
|
||||
PPShader LinearDepth;
|
||||
PPShader LinearDepthMS;
|
||||
PPShader AmbientOcclude;
|
||||
PPShader AmbientOccludeMS;
|
||||
PPShader BlurVertical;
|
||||
PPShader BlurHorizontal;
|
||||
PPShader Combine;
|
||||
PPShader CombineMS;
|
||||
|
||||
PPTexture LinearDepthTexture;
|
||||
PPTexture Ambient0;
|
||||
PPTexture Ambient1;
|
||||
|
||||
enum { NumAmbientRandomTextures = 3 };
|
||||
PPTexture AmbientRandomTexture[NumAmbientRandomTextures];
|
||||
};
|
||||
|
||||
struct PresentUniforms
|
||||
{
|
||||
float InvGamma;
|
||||
float Contrast;
|
||||
float Brightness;
|
||||
float Saturation;
|
||||
int GrayFormula;
|
||||
int WindowPositionParity; // top-of-window might not be top-of-screen
|
||||
FVector2 Scale;
|
||||
FVector2 Offset;
|
||||
float ColorScale;
|
||||
int HdrMode;
|
||||
|
||||
static std::vector<UniformFieldDesc> Desc()
|
||||
{
|
||||
return
|
||||
{
|
||||
{ "InvGamma", UniformType::Float, offsetof(PresentUniforms, InvGamma) },
|
||||
{ "Contrast", UniformType::Float, offsetof(PresentUniforms, Contrast) },
|
||||
{ "Brightness", UniformType::Float, offsetof(PresentUniforms, Brightness) },
|
||||
{ "Saturation", UniformType::Float, offsetof(PresentUniforms, Saturation) },
|
||||
{ "GrayFormula", UniformType::Int, offsetof(PresentUniforms, GrayFormula) },
|
||||
{ "WindowPositionParity", UniformType::Int, offsetof(PresentUniforms, WindowPositionParity) },
|
||||
{ "UVScale", UniformType::Vec2, offsetof(PresentUniforms, Scale) },
|
||||
{ "UVOffset", UniformType::Vec2, offsetof(PresentUniforms, Offset) },
|
||||
{ "ColorScale", UniformType::Float, offsetof(PresentUniforms, ColorScale) },
|
||||
{ "HdrMode", UniformType::Int, offsetof(PresentUniforms, HdrMode) }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class PPPresent
|
||||
{
|
||||
public:
|
||||
PPPresent();
|
||||
|
||||
PPTexture Dither;
|
||||
|
||||
PPShader Present = { "engine/shaders/pp/present.fp", "", PresentUniforms::Desc() };
|
||||
PPShader Checker3D = { "engine/shaders/pp/present_checker3d.fp", "", PresentUniforms::Desc() };
|
||||
PPShader Column3D = { "engine/shaders/pp/present_column3d.fp", "", PresentUniforms::Desc() };
|
||||
PPShader Row3D = { "engine/shaders/pp/present_row3d.fp", "", PresentUniforms::Desc() };
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Postprocess
|
||||
{
|
||||
public:
|
||||
PPBloom bloom;
|
||||
PPLensDistort lens;
|
||||
PPFXAA fxaa;
|
||||
PPCameraExposure exposure;
|
||||
PPTonemap tonemap;
|
||||
PPAmbientOcclusion ssao;
|
||||
PPPresent present;
|
||||
|
||||
|
||||
void Pass1(PPRenderState *state, int fixedcm, int sceneWidth, int sceneHeight);
|
||||
void Pass2(PPRenderState* state, int fixedcm, int sceneWidth, int sceneHeight);
|
||||
};
|
||||
|
||||
extern Postprocess hw_postprocess;
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
** Postprocessing framework
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "hw_postprocess_cvars.h"
|
||||
#include "v_video.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CVARs
|
||||
//
|
||||
//==========================================================================
|
||||
CVAR(Bool, gl_bloom, false, CVAR_ARCHIVE);
|
||||
CUSTOM_CVAR(Float, gl_bloom_amount, 1.4f, CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0.1f) self = 0.1f;
|
||||
}
|
||||
|
||||
CVAR(Float, gl_exposure_scale, 1.3f, CVAR_ARCHIVE)
|
||||
CVAR(Float, gl_exposure_min, 0.35f, CVAR_ARCHIVE)
|
||||
CVAR(Float, gl_exposure_base, 0.35f, CVAR_ARCHIVE)
|
||||
CVAR(Float, gl_exposure_speed, 0.05f, CVAR_ARCHIVE)
|
||||
|
||||
CUSTOM_CVAR(Int, gl_tonemap, 0, CVAR_ARCHIVE)
|
||||
{
|
||||
if (self < 0 || self > 5)
|
||||
self = 0;
|
||||
}
|
||||
|
||||
CVAR(Bool, gl_lens, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
CVAR(Float, gl_lens_k, -0.12f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Float, gl_lens_kcube, 0.1f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Float, gl_lens_chromatic, 1.12f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
CUSTOM_CVAR(Int, gl_fxaa, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
if (self < 0 || self >= IFXAAShader::Count)
|
||||
{
|
||||
self = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, gl_ssao, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
if (self < 0 || self > 3)
|
||||
self = 0;
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, gl_ssao_portals, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
if (self < 0)
|
||||
self = 0;
|
||||
}
|
||||
|
||||
CVAR(Float, gl_ssao_strength, 0.7f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Int, gl_ssao_debug, 0, 0)
|
||||
CVAR(Float, gl_ssao_bias, 0.2f, 0)
|
||||
CVAR(Float, gl_ssao_radius, 80.0f, 0)
|
||||
CUSTOM_CVAR(Float, gl_ssao_blur, 16.0f, 0)
|
||||
{
|
||||
if (self < 0.1f) self = 0.1f;
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Float, gl_ssao_exponent, 1.8f, 0)
|
||||
{
|
||||
if (self < 0.1f) self = 0.1f;
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Float, gl_paltonemap_powtable, 2.0f, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
||||
{
|
||||
screen->UpdatePalette();
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Bool, gl_paltonemap_reverselookup, true, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
||||
{
|
||||
screen->UpdatePalette();
|
||||
}
|
||||
|
||||
CVAR(Float, gl_menu_blur, -1.0f, CVAR_ARCHIVE)
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "c_cvars.h"
|
||||
|
||||
class IFXAAShader
|
||||
{
|
||||
public:
|
||||
enum Quality
|
||||
{
|
||||
None,
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
Extreme,
|
||||
Count
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CVARs
|
||||
//
|
||||
//==========================================================================
|
||||
EXTERN_CVAR(Bool, gl_bloom)
|
||||
EXTERN_CVAR(Float, gl_bloom_amount)
|
||||
EXTERN_CVAR(Float, gl_exposure_scale)
|
||||
EXTERN_CVAR(Float, gl_exposure_min)
|
||||
EXTERN_CVAR(Float, gl_exposure_base)
|
||||
EXTERN_CVAR(Float, gl_exposure_speed)
|
||||
EXTERN_CVAR(Int, gl_tonemap)
|
||||
EXTERN_CVAR(Int, gl_bloom_kernel_size)
|
||||
EXTERN_CVAR(Bool, gl_lens)
|
||||
EXTERN_CVAR(Float, gl_lens_k)
|
||||
EXTERN_CVAR(Float, gl_lens_kcube)
|
||||
EXTERN_CVAR(Float, gl_lens_chromatic)
|
||||
EXTERN_CVAR(Int, gl_fxaa)
|
||||
EXTERN_CVAR(Int, gl_ssao)
|
||||
EXTERN_CVAR(Int, gl_ssao_portals)
|
||||
EXTERN_CVAR(Float, gl_ssao_strength)
|
||||
EXTERN_CVAR(Int, gl_ssao_debug)
|
||||
EXTERN_CVAR(Float, gl_ssao_bias)
|
||||
EXTERN_CVAR(Float, gl_ssao_radius)
|
||||
EXTERN_CVAR(Float, gl_ssao_blur)
|
||||
EXTERN_CVAR(Float, gl_ssao_exponent)
|
||||
EXTERN_CVAR(Float, gl_paltonemap_powtable)
|
||||
EXTERN_CVAR(Bool, gl_paltonemap_reverselookup)
|
||||
EXTERN_CVAR(Float, gl_menu_blur)
|
||||
EXTERN_CVAR(Float, vid_brightness)
|
||||
EXTERN_CVAR(Float, vid_contrast)
|
||||
EXTERN_CVAR(Float, vid_saturation)
|
||||
EXTERN_CVAR(Int, gl_satformula)
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#include "c_cvars.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "v_video.h"
|
||||
#include "hw_cvars.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Texture CVARs
|
||||
//
|
||||
//==========================================================================
|
||||
#if 0 // left as a reminder that this will have to be refactored later.
|
||||
CUSTOM_CVAR(Float,gl_texture_filter_anisotropic,8.0f,CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||
{
|
||||
screen->TextureFilterChanged();
|
||||
}
|
||||
|
||||
CCMD(gl_flush)
|
||||
{
|
||||
//TexMan.FlushAll();
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, gl_texture_filter, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||
{
|
||||
if (self < 0 || self > 6) self=4;
|
||||
screen->TextureFilterChanged();
|
||||
}
|
||||
CVAR(Bool, gl_precache, false, CVAR_ARCHIVE)
|
||||
#endif
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
#include "c_cvars.h"
|
||||
|
||||
EXTERN_CVAR(Bool,gl_enhanced_nightvision)
|
||||
EXTERN_CVAR(Int, screenblocks);
|
||||
EXTERN_CVAR(Bool, gl_texture)
|
||||
EXTERN_CVAR(Int, gl_texture_filter)
|
||||
EXTERN_CVAR(Float, gl_texture_filter_anisotropic)
|
||||
EXTERN_CVAR(Int, gl_texture_format)
|
||||
EXTERN_CVAR(Bool, gl_texture_usehires)
|
||||
EXTERN_CVAR(Bool, gl_usefb)
|
||||
|
||||
EXTERN_CVAR(Int, gl_weaponlight)
|
||||
|
||||
EXTERN_CVAR (Bool, gl_light_sprites);
|
||||
EXTERN_CVAR (Bool, gl_light_particles);
|
||||
EXTERN_CVAR (Bool, gl_light_shadowmap);
|
||||
EXTERN_CVAR (Int, gl_shadowmap_quality);
|
||||
|
||||
EXTERN_CVAR(Int, gl_fogmode)
|
||||
EXTERN_CVAR(Int, gl_lightmode)
|
||||
EXTERN_CVAR(Bool,gl_mirror_envmap)
|
||||
|
||||
EXTERN_CVAR(Bool,gl_mirrors)
|
||||
EXTERN_CVAR(Bool,gl_mirror_envmap)
|
||||
|
||||
EXTERN_CVAR(Float, gl_mask_threshold)
|
||||
EXTERN_CVAR(Float, gl_mask_sprite_threshold)
|
||||
|
||||
EXTERN_CVAR(Int, gl_multisample)
|
||||
|
||||
EXTERN_CVAR(Bool, gl_bloom)
|
||||
EXTERN_CVAR(Float, gl_bloom_amount)
|
||||
EXTERN_CVAR(Int, gl_bloom_kernel_size)
|
||||
EXTERN_CVAR(Int, gl_tonemap)
|
||||
EXTERN_CVAR(Float, gl_exposure)
|
||||
EXTERN_CVAR(Bool, gl_lens)
|
||||
EXTERN_CVAR(Float, gl_lens_k)
|
||||
EXTERN_CVAR(Float, gl_lens_kcube)
|
||||
EXTERN_CVAR(Float, gl_lens_chromatic)
|
||||
EXTERN_CVAR(Int, gl_ssao)
|
||||
EXTERN_CVAR(Int, gl_ssao_portals)
|
||||
EXTERN_CVAR(Float, gl_ssao_strength)
|
||||
EXTERN_CVAR(Int, 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(Bool, gl_debug_breakpoint)
|
||||
|
||||
|
||||
EXTERN_CVAR(Bool, gl_usecolorblending)
|
||||
EXTERN_CVAR(Bool, gl_sprite_blend)
|
||||
EXTERN_CVAR(Int, gl_spriteclip)
|
||||
EXTERN_CVAR(Float, gl_sclipthreshold)
|
||||
EXTERN_CVAR(Float, gl_sclipfactor)
|
||||
EXTERN_CVAR(Int, gl_particles_style)
|
||||
EXTERN_CVAR(Int, gl_billboard_mode)
|
||||
EXTERN_CVAR(Bool, gl_billboard_faces_camera)
|
||||
EXTERN_CVAR(Bool, gl_billboard_particles)
|
||||
EXTERN_CVAR(Int, gl_enhanced_nv_stealth)
|
||||
EXTERN_CVAR(Int, gl_fuzztype)
|
||||
|
||||
EXTERN_CVAR(Int, gl_shadowmap_filter)
|
||||
|
||||
EXTERN_CVAR(Bool, gl_brightfog)
|
||||
EXTERN_CVAR(Bool, gl_lightadditivesurfaces)
|
||||
EXTERN_CVAR(Bool, gl_notexturefill)
|
|
@ -1,302 +0,0 @@
|
|||
/*
|
||||
** hw_shaderpatcher.cpp
|
||||
** Modifies shader source to account for different syntax versions or engine changes.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright(C) 2004-2018 Christoph Oelckers
|
||||
** Copyright(C) 2016-2018 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.
|
||||
**
|
||||
** 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 "hw_shaderpatcher.h"
|
||||
|
||||
|
||||
static bool IsGlslWhitespace(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ' ':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\t':
|
||||
case '\f':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static FString NextGlslToken(const char *chars, long len, long &pos)
|
||||
{
|
||||
// Eat whitespace
|
||||
long tokenStart = pos;
|
||||
while (tokenStart != len && IsGlslWhitespace(chars[tokenStart]))
|
||||
tokenStart++;
|
||||
|
||||
// Find token end
|
||||
long tokenEnd = tokenStart;
|
||||
while (tokenEnd != len && !IsGlslWhitespace(chars[tokenEnd]) && chars[tokenEnd] != ';')
|
||||
tokenEnd++;
|
||||
|
||||
pos = tokenEnd;
|
||||
return FString(chars + tokenStart, tokenEnd - tokenStart);
|
||||
}
|
||||
|
||||
static bool isShaderType(const char *name)
|
||||
{
|
||||
return !strcmp(name, "sampler1D") || !strcmp(name, "sampler2D") || !strcmp(name, "sampler3D") || !strcmp(name, "samplerCube") || !strcmp(name, "sampler2DMS");
|
||||
}
|
||||
|
||||
FString RemoveLegacyUserUniforms(FString code)
|
||||
{
|
||||
// User shaders must declare their uniforms via the GLDEFS file.
|
||||
|
||||
code.Substitute("uniform sampler2D tex;", " ");
|
||||
code.Substitute("uniform float timer;", " ");
|
||||
|
||||
// The following code searches for legacy uniform declarations in the shader itself and replaces them with whitespace.
|
||||
|
||||
long len = (long)code.Len();
|
||||
char *chars = code.LockBuffer();
|
||||
|
||||
long startIndex = 0;
|
||||
while (true)
|
||||
{
|
||||
long matchIndex = code.IndexOf("uniform", startIndex);
|
||||
if (matchIndex == -1)
|
||||
break;
|
||||
|
||||
bool isLegacyUniformName = false;
|
||||
|
||||
bool isKeywordStart = matchIndex == 0 || IsGlslWhitespace(chars[matchIndex - 1]);
|
||||
bool isKeywordEnd = matchIndex + 7 == len || IsGlslWhitespace(chars[matchIndex + 7]);
|
||||
if (isKeywordStart && isKeywordEnd)
|
||||
{
|
||||
long pos = matchIndex + 7;
|
||||
FString type = NextGlslToken(chars, len, pos);
|
||||
FString identifier = NextGlslToken(chars, len, pos);
|
||||
|
||||
isLegacyUniformName = type.Compare("float") == 0 && identifier.Compare("timer") == 0;
|
||||
}
|
||||
|
||||
if (isLegacyUniformName)
|
||||
{
|
||||
long statementEndIndex = code.IndexOf(';', matchIndex + 7);
|
||||
if (statementEndIndex == -1)
|
||||
statementEndIndex = len;
|
||||
for (long i = matchIndex; i <= statementEndIndex; i++)
|
||||
{
|
||||
if (!IsGlslWhitespace(chars[i]))
|
||||
chars[i] = ' ';
|
||||
}
|
||||
startIndex = statementEndIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
startIndex = matchIndex + 7;
|
||||
}
|
||||
}
|
||||
|
||||
// Also remove all occurences of the token 'texture2d'. Some shaders may still use this deprecated function to access a sampler.
|
||||
// Modern GLSL only allows use of 'texture'.
|
||||
while (true)
|
||||
{
|
||||
long matchIndex = code.IndexOf("texture2d", startIndex);
|
||||
if (matchIndex == -1)
|
||||
break;
|
||||
|
||||
// Check if this is a real token.
|
||||
bool isKeywordStart = matchIndex == 0 || !isalnum(chars[matchIndex - 1] & 255);
|
||||
bool isKeywordEnd = matchIndex + 9 == len || !isalnum(chars[matchIndex + 9] & 255);
|
||||
if (isKeywordStart && isKeywordEnd)
|
||||
{
|
||||
chars[matchIndex + 7] = chars[matchIndex + 8] = ' ';
|
||||
}
|
||||
startIndex = matchIndex + 9;
|
||||
}
|
||||
|
||||
code.UnlockBuffer();
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
FString RemoveSamplerBindings(FString code, TArray<std::pair<FString, int>> &samplerstobind)
|
||||
{
|
||||
long len = (long)code.Len();
|
||||
char *chars = code.LockBuffer();
|
||||
|
||||
long startIndex = 0;
|
||||
long startpos, endpos;
|
||||
while (true)
|
||||
{
|
||||
long matchIndex = code.IndexOf("layout(binding", startIndex);
|
||||
if (matchIndex == -1)
|
||||
break;
|
||||
|
||||
bool isSamplerUniformName = false;
|
||||
|
||||
bool isKeywordStart = matchIndex == 0 || IsGlslWhitespace(chars[matchIndex - 1]);
|
||||
bool isKeywordEnd = matchIndex + 14 == len || IsGlslWhitespace(chars[matchIndex + 14]) || chars[matchIndex + 14] == '=';
|
||||
if (isKeywordStart && isKeywordEnd)
|
||||
{
|
||||
long pos = matchIndex + 14;
|
||||
startpos = matchIndex;
|
||||
while (IsGlslWhitespace(chars[pos])) pos++;
|
||||
if (chars[pos] == '=')
|
||||
{
|
||||
char *p;
|
||||
pos++;
|
||||
auto val = strtol(&chars[pos], &p, 0);
|
||||
if (p != &chars[pos])
|
||||
{
|
||||
pos = long(p - chars);
|
||||
while (IsGlslWhitespace(chars[pos])) pos++;
|
||||
if (chars[pos] == ')')
|
||||
{
|
||||
endpos = ++pos;
|
||||
FString uniform = NextGlslToken(chars, len, pos);
|
||||
FString type = NextGlslToken(chars, len, pos);
|
||||
FString identifier = NextGlslToken(chars, len, pos);
|
||||
|
||||
isSamplerUniformName = uniform.Compare("uniform") == 0 && isShaderType(type);
|
||||
if (isSamplerUniformName)
|
||||
{
|
||||
samplerstobind.Push(std::make_pair(identifier, val));
|
||||
for (auto pos = startpos; pos < endpos; pos++)
|
||||
{
|
||||
if (!IsGlslWhitespace(chars[pos]))
|
||||
chars[pos] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isSamplerUniformName)
|
||||
{
|
||||
startIndex = endpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
startIndex = matchIndex + 7;
|
||||
}
|
||||
}
|
||||
|
||||
code.UnlockBuffer();
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
FString RemoveLayoutLocationDecl(FString code, const char *inoutkeyword)
|
||||
{
|
||||
long len = (long)code.Len();
|
||||
char *chars = code.LockBuffer();
|
||||
|
||||
long startIndex = 0;
|
||||
while (true)
|
||||
{
|
||||
long matchIndex = code.IndexOf("layout(location", startIndex);
|
||||
if (matchIndex == -1)
|
||||
break;
|
||||
|
||||
long endIndex = matchIndex;
|
||||
|
||||
// Find end of layout declaration
|
||||
while (chars[endIndex] != ')' && chars[endIndex] != 0)
|
||||
endIndex++;
|
||||
|
||||
if (chars[endIndex] == ')')
|
||||
endIndex++;
|
||||
else if (chars[endIndex] == 0)
|
||||
break;
|
||||
|
||||
// Skip whitespace
|
||||
while (IsGlslWhitespace(chars[endIndex]))
|
||||
endIndex++;
|
||||
|
||||
// keyword following the declaration?
|
||||
bool keywordFound = true;
|
||||
long i;
|
||||
for (i = 0; inoutkeyword[i] != 0; i++)
|
||||
{
|
||||
if (chars[endIndex + i] != inoutkeyword[i])
|
||||
{
|
||||
keywordFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (keywordFound && IsGlslWhitespace(chars[endIndex + i]))
|
||||
{
|
||||
// yes - replace declaration with spaces
|
||||
for (long i = matchIndex; i < endIndex; i++)
|
||||
chars[i] = ' ';
|
||||
}
|
||||
|
||||
startIndex = endIndex;
|
||||
}
|
||||
|
||||
code.UnlockBuffer();
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Note: the MaterialShaderIndex enum in gl_shader.h needs to be updated whenever this array is modified.
|
||||
const FDefaultShader defaultshaders[] =
|
||||
{
|
||||
{"Default", "engine/shaders/pp/func_normal.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Warp 1", "engine/shaders/pp/func_warp1.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Warp 2", "engine/shaders/pp/func_warp2.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Brightmap","engine/shaders/pp/func_brightmap.fp", "engine/shaders/pp/material_normal.fp", "#define BRIGHTMAP\n"},
|
||||
{"Specular", "engine/shaders/pp/func_spec.fp", "engine/shaders/pp/material_specular.fp", "#define SPECULAR\n#define NORMALMAP\n"},
|
||||
{"SpecularBrightmap", "engine/shaders/pp/func_spec.fp", "engine/shaders/pp/material_specular.fp", "#define SPECULAR\n#define NORMALMAP\n#define BRIGHTMAP\n"},
|
||||
{"PBR","engine/shaders/pp/func_pbr.fp", "engine/shaders/pp/material_pbr.fp", "#define PBR\n#define NORMALMAP\n"},
|
||||
{"PBRBrightmap","engine/shaders/pp/func_pbr.fp", "engine/shaders/pp/material_pbr.fp", "#define PBR\n#define NORMALMAP\n#define BRIGHTMAP\n"},
|
||||
{"Paletted", "engine/shaders/pp/func_paletted.fp", "engine/shaders/pp/material_nolight.fp", ""},
|
||||
{"No Texture", "engine/shaders/pp/func_notexture.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Basic Fuzz", "engine/shaders/pp/fuzz_standard.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Smooth Fuzz", "engine/shaders/pp/fuzz_smooth.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Swirly Fuzz", "engine/shaders/pp/fuzz_swirly.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Translucent Fuzz", "engine/shaders/pp/fuzz_smoothtranslucent.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Jagged Fuzz", "engine/shaders/pp/fuzz_jagged.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Noise Fuzz", "engine/shaders/pp/fuzz_noise.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Smooth Noise Fuzz", "engine/shaders/pp/fuzz_smoothnoise.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{"Software Fuzz", "engine/shaders/pp/fuzz_software.fp", "engine/shaders/pp/material_normal.fp", ""},
|
||||
{nullptr,nullptr,nullptr,nullptr}
|
||||
};
|
||||
|
||||
const FEffectShader effectshaders[] =
|
||||
{
|
||||
{ "fogboundary", "engine/shaders/pp/main.vp", "engine/shaders/pp/fogboundary.fp", nullptr, nullptr, "#define NO_ALPHATEST\n" },
|
||||
{ "spheremap", "engine/shaders/pp/main.vp", "engine/shaders/pp/main.fp", "engine/shaders/pp/func_normal.fp", "engine/shaders/pp/material_normal.fp", "#define SPHEREMAP\n#define NO_ALPHATEST\n" },
|
||||
{ "burn", "engine/shaders/pp/main.vp", "engine/shaders/pp/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
{ "stencil", "engine/shaders/pp/main.vp", "engine/shaders/pp/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
#include "zstring.h"
|
||||
#include "utility"
|
||||
|
||||
FString RemoveLegacyUserUniforms(FString code);
|
||||
FString RemoveSamplerBindings(FString code, TArray<std::pair<FString, int>> &samplerstobind); // For GL 3.3 compatibility which cannot declare sampler bindings in the sampler source.
|
||||
FString RemoveLayoutLocationDecl(FString code, const char *inoutkeyword);
|
||||
|
||||
struct FDefaultShader
|
||||
{
|
||||
const char * ShaderName;
|
||||
const char * gettexelfunc;
|
||||
const char * lightfunc;
|
||||
const char * Defines;
|
||||
};
|
||||
|
||||
struct FEffectShader
|
||||
{
|
||||
const char *ShaderName;
|
||||
const char *vp;
|
||||
const char *fp1;
|
||||
const char *fp2;
|
||||
const char *fp3;
|
||||
const char *defines;
|
||||
};
|
||||
|
||||
extern const FDefaultShader defaultshaders[];
|
||||
extern const FEffectShader effectshaders[];
|
Loading…
Add table
Add a link
Reference in a new issue