Merge remote-tracking branch 'remotes/origin/qzdoom-merge'

This commit is contained in:
Christoph Oelckers 2017-07-20 18:33:20 +02:00
commit 714ada01aa
40 changed files with 1032 additions and 77 deletions

View file

@ -718,6 +718,7 @@ set ( SWRENDER_SOURCES
swrenderer/viewport/r_viewport.cpp
swrenderer/viewport/r_walldrawer.cpp
swrenderer/line/r_line.cpp
swrenderer/line/r_farclip_line.cpp
swrenderer/line/r_walldraw.cpp
swrenderer/line/r_wallsetup.cpp
swrenderer/line/r_fogboundary.cpp
@ -1006,6 +1007,7 @@ set (PCH_SOURCES
gl/shaders/gl_shader.cpp
gl/shaders/gl_texshader.cpp
gl/shaders/gl_shaderprogram.cpp
gl/shaders/gl_postprocessshader.cpp
gl/shaders/gl_shadowmapshader.cpp
gl/shaders/gl_presentshader.cpp
gl/shaders/gl_present3dRowshader.cpp

View file

@ -1765,6 +1765,8 @@ void G_DoReborn (int playernum, bool freshbot)
}
else
{
bool isUnfriendly = players[playernum].mo && !(players[playernum].mo->flags & MF_FRIENDLY);
// respawn at the start
// first disassociate the corpse
if (players[playernum].mo)
@ -1774,7 +1776,7 @@ void G_DoReborn (int playernum, bool freshbot)
}
// spawn at random spot if in deathmatch
if (deathmatch)
if (deathmatch || isUnfriendly)
{
G_DeathMatchSpawnPlayer (playernum);
return;

View file

@ -380,6 +380,7 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_BOOL(nightmarefast, "nightmarefast")
GAMEINFOKEY_COLOR(dimcolor, "dimcolor")
GAMEINFOKEY_FLOAT(dimamount, "dimamount")
GAMEINFOKEY_FLOAT(bluramount, "bluramount")
GAMEINFOKEY_INT(definventorymaxamount, "definventorymaxamount")
GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")
GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime")

View file

@ -159,6 +159,7 @@ struct gameinfo_t
FString CursorPic;
uint32_t dimcolor;
float dimamount;
float bluramount;
int definventorymaxamount;
int defaultrespawntime;
int defaultdropstyle;

View file

@ -62,6 +62,7 @@
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_fxaashader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/shaders/gl_postprocessshader.h"
#include "gl/renderer/gl_2ddrawer.h"
#include "gl/stereo3d/gl_stereo3d.h"
@ -145,10 +146,12 @@ CUSTOM_CVAR(Bool, gl_paltonemap_reverselookup, true, CVAR_ARCHIVE | CVAR_NOINITC
GLRenderer->ClearTonemapPalette();
}
CVAR(Float, gl_menu_blur, -1.0f, CVAR_ARCHIVE)
EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Float, vid_saturation)
EXTERN_CVAR(Int, gl_satformula)
void FGLRenderer::RenderScreenQuad()
{
@ -161,11 +164,13 @@ void FGLRenderer::PostProcessScene(int fixedcm)
{
mBuffers->BlitSceneToTexture();
UpdateCameraExposure();
mCustomPostProcessShaders->Run("beforebloom");
BloomScene(fixedcm);
TonemapScene();
ColormapScene(fixedcm);
LensDistortScene();
ApplyFXAA();
mCustomPostProcessShaders->Run("scene");
}
//-----------------------------------------------------------------------------
@ -467,6 +472,86 @@ void FGLRenderer::BloomScene(int fixedcm)
FGLDebug::PopGroup();
}
//-----------------------------------------------------------------------------
//
// Blur the scene
//
//-----------------------------------------------------------------------------
void FGLRenderer::BlurScene(float gameinfobluramount)
{
// 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) || !FGLRenderBuffers::IsEnabled())
return;
FGLDebug::PushGroup("BlurScene");
FGLPostProcessState savedState;
savedState.SaveTextureBindings(2);
int sampleCount = 9;
int numLevels = 3; // Must be 4 or less (since FGLRenderBuffers::NumBloomLevels is 4 and we are using its buffers).
assert(numLevels <= FGLRenderBuffers::NumBloomLevels);
const auto &viewport = mScreenViewport; // The area we want to blur. Could also be mSceneViewport if only the scene area is to be blured
const auto &level0 = mBuffers->BloomLevels[0];
// Grab the area we want to bloom:
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBuffers->GetCurrentFB());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, level0.VFramebuffer);
glBlitFramebuffer(viewport.left, viewport.top, viewport.width, viewport.height, 0, 0, level0.Width, level0.Height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
// Blur and downscale:
for (int i = 0; i < numLevels - 1; i++)
{
const auto &level = mBuffers->BloomLevels[i];
const auto &next = mBuffers->BloomLevels[i + 1];
mBlurShader->BlurHorizontal(this, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height);
mBlurShader->BlurVertical(this, blurAmount, sampleCount, level.HTexture, next.VFramebuffer, next.Width, next.Height);
}
// Blur and upscale:
for (int i = numLevels - 1; i > 0; i--)
{
const auto &level = mBuffers->BloomLevels[i];
const auto &next = mBuffers->BloomLevels[i - 1];
mBlurShader->BlurHorizontal(this, blurAmount, sampleCount, level.VTexture, level.HFramebuffer, level.Width, level.Height);
mBlurShader->BlurVertical(this, blurAmount, sampleCount, level.HTexture, level.VFramebuffer, level.Width, level.Height);
// Linear upscale:
glBindFramebuffer(GL_FRAMEBUFFER, next.VFramebuffer);
glViewport(0, 0, next.Width, next.Height);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, level.VTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mBloomCombineShader->Bind();
mBloomCombineShader->BloomTexture.Set(0);
RenderScreenQuad();
}
mBlurShader->BlurHorizontal(this, blurAmount, sampleCount, level0.VTexture, level0.HFramebuffer, level0.Width, level0.Height);
mBlurShader->BlurVertical(this, blurAmount, sampleCount, level0.HTexture, level0.VFramebuffer, level0.Width, level0.Height);
// Copy blur back to scene texture:
glBindFramebuffer(GL_READ_FRAMEBUFFER, level0.VFramebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mBuffers->GetCurrentFB());
glBlitFramebuffer(0, 0, level0.Width, level0.Height, viewport.left, viewport.top, viewport.width, viewport.height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
FGLDebug::PopGroup();
}
//-----------------------------------------------------------------------------
//
// Tonemap scene texture and place the result in the HUD/2D texture
@ -734,6 +819,8 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
m2DDrawer->Draw(); // draw all pending 2D stuff before copying the buffer
m2DDrawer->Clear();
mCustomPostProcessShaders->Run("screen");
FGLDebug::PushGroup("CopyToBackbuffer");
if (FGLRenderBuffers::IsEnabled())
{
@ -777,12 +864,15 @@ void FGLRenderer::DrawPresentTexture(const GL_IRECT &box, bool applyGamma)
mPresentShader->InvGamma.Set(1.0f);
mPresentShader->Contrast.Set(1.0f);
mPresentShader->Brightness.Set(0.0f);
mPresentShader->Saturation.Set(1.0f);
}
else
{
mPresentShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
mPresentShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
mPresentShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
mPresentShader->Saturation.Set(clamp<float>(vid_saturation, -15.0f, 15.f));
mPresentShader->GrayFormula.Set(static_cast<int>(gl_satformula));
}
mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight());
RenderScreenQuad();

View file

@ -43,6 +43,8 @@ public:
void BindNextFB();
void NextTexture();
int GetCurrentFB() const { return mPipelineFB[mCurrentPipelineTexture]; }
void BindOutputFB();
void BlitToEyeTexture(int eye);

View file

@ -62,6 +62,7 @@
#include "gl/shaders/gl_presentshader.h"
#include "gl/shaders/gl_present3dRowshader.h"
#include "gl/shaders/gl_shadowmapshader.h"
#include "gl/shaders/gl_postprocessshader.h"
#include "gl/stereo3d/gl_stereo3d.h"
#include "gl/textures/gl_texture.h"
#include "gl/textures/gl_translate.h"
@ -128,6 +129,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mFXAAShader = nullptr;
mFXAALumaShader = nullptr;
mShadowMapShader = nullptr;
mCustomPostProcessShaders = nullptr;
}
void gl_LoadModels();
@ -157,6 +159,7 @@ void FGLRenderer::Initialize(int width, int height)
mPresent3dColumnShader = new FPresent3DColumnShader();
mPresent3dRowShader = new FPresent3DRowShader();
mShadowMapShader = new FShadowMapShader();
mCustomPostProcessShaders = new FCustomPostProcessShaders();
m2DDrawer = new F2DDrawer;
// needed for the core profile, because someone decided it was a good idea to remove the default VAO.
@ -232,6 +235,7 @@ FGLRenderer::~FGLRenderer()
if (mColormapShader) delete mColormapShader;
if (mLensShader) delete mLensShader;
if (mShadowMapShader) delete mShadowMapShader;
delete mCustomPostProcessShaders;
delete mFXAAShader;
delete mFXAALumaShader;
}

View file

@ -42,6 +42,7 @@ class FPresent3DRowShader;
class F2DDrawer;
class FHardwareTexture;
class FShadowMapShader;
class FCustomPostProcessShaders;
inline float DEG2RAD(float deg)
{
@ -126,6 +127,7 @@ public:
FPresent3DColumnShader *mPresent3dColumnShader;
FPresent3DRowShader *mPresent3dRowShader;
FShadowMapShader *mShadowMapShader;
FCustomPostProcessShaders *mCustomPostProcessShaders;
FShadowMap mShadowMap;
@ -182,6 +184,7 @@ public:
void ClearTonemapPalette();
void LensDistortScene();
void ApplyFXAA();
void BlurScene(float gameinfobluramount);
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
void DrawPresentTexture(const GL_IRECT &box, bool applyGamma);
void Flush();

View file

@ -98,7 +98,7 @@ void GLSceneDrawer::DrawPSprite (player_t * player,DPSprite *psp, float sx, floa
// calculate edges of the shape
scalex = (320.0f / (240.0f * r_viewwindow.WidescreenRatio)) * vw / 320;
tx = sx - (160 - r.left);
tx = (psp->Flags & PSPF_MIRROR) ? ((160 - r.width) - (sx + r.left)) : (sx - (160 - r.left));
x1 = tx * scalex + vw/2;
if (x1 > vw) return; // off the right side
x1 += viewwindowx;
@ -108,7 +108,6 @@ void GLSceneDrawer::DrawPSprite (player_t * player,DPSprite *psp, float sx, floa
if (x2 < 0) return; // off the left side
x2 += viewwindowx;
// killough 12/98: fix psprite positioning problem
ftexturemid = 100.f - sy - r.top;
@ -130,7 +129,8 @@ void GLSceneDrawer::DrawPSprite (player_t * player,DPSprite *psp, float sx, floa
y1 = viewwindowy + vh / 2 - (ftexturemid * scale);
y2 = y1 + (r.height * scale) + 1;
if (!(mirror) != !(psp->Flags & PSPF_FLIP))
if (!(mirror) != !(psp->Flags & (PSPF_FLIP)))
{
fU2 = tex->GetSpriteUL();
fV1 = tex->GetSpriteVT();
@ -437,7 +437,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
if (psp->Flags & PSPF_ADDBOB)
{
sx += bobx;
sx += (psp->Flags & PSPF_MIRROR) ? -bobx : bobx;
sy += boby;
}

View file

@ -0,0 +1,194 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2017 Magnus Norddahl
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
#include "gl/system/gl_system.h"
#include "m_swap.h"
#include "v_video.h"
#include "gl/gl_functions.h"
#include "vectors.h"
#include "w_wad.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_debug.h"
#include "gl/system/gl_cvars.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/shaders/gl_postprocessshader.h"
CVAR(Bool, gl_custompost, true, 0)
TArray<PostProcessShader> PostProcessShaders;
FCustomPostProcessShaders::FCustomPostProcessShaders()
{
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
{
mShaders.push_back(std::unique_ptr<PostProcessShaderInstance>(new PostProcessShaderInstance(&PostProcessShaders[i])));
}
}
FCustomPostProcessShaders::~FCustomPostProcessShaders()
{
}
void FCustomPostProcessShaders::Run(FString target)
{
if (!gl_custompost)
return;
for (auto &shader : mShaders)
{
if (shader->Desc->Target == target)
{
shader->Run();
}
}
}
/////////////////////////////////////////////////////////////////////////////
void PostProcessShaderInstance::Run()
{
if (!IsShaderSupported())
return;
CompileShader();
if (!Desc->Enabled)
return;
FGLDebug::PushGroup(Desc->ShaderLumpName.GetChars());
FGLPostProcessState savedState;
GLRenderer->mBuffers->BindNextFB();
GLRenderer->mBuffers->BindCurrentTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mProgram.Bind();
UpdateUniforms();
mInputTexture.Set(0);
GLRenderer->RenderScreenQuad();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLRenderer->mBuffers->NextTexture();
FGLDebug::PopGroup();
}
bool PostProcessShaderInstance::IsShaderSupported()
{
int activeShaderVersion = (int)round(gl.glslversion * 10) * 10;
return activeShaderVersion >= Desc->ShaderVersion;
}
void PostProcessShaderInstance::CompileShader()
{
if (mProgram)
return;
// Get the custom shader
const char *lumpName = Desc->ShaderLumpName.GetChars();
int lump = Wads.CheckNumForFullName(lumpName);
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName);
FString code = Wads.ReadLump(lump).GetString().GetChars();
// Build an uniform block to use be used as input
// (this is technically not an uniform block, but it could be changed into that for Vulkan GLSL support)
FString uniformBlock;
TMap<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
TMap<FString, PostProcessUniformValue>::Pair *pair;
while (it.NextPair(pair))
{
FString type;
FString name = pair->Key;
switch (pair->Value.Type)
{
case PostProcessUniformType::Float: type = "float"; break;
case PostProcessUniformType::Int: type = "int"; break;
case PostProcessUniformType::Vec2: type = "vec2"; break;
case PostProcessUniformType::Vec3: type = "vec3"; break;
default: break;
}
if (!type.IsEmpty())
uniformBlock.AppendFormat("uniform %s %s;\n", type.GetChars(), name.GetChars());
}
// Build the input textures
FString uniformTextures;
uniformTextures += "uniform sampler2D InputTexture;\n";
// Setup pipeline
FString pipelineInOut;
pipelineInOut += "in vec2 TexCoord;\n";
pipelineInOut += "out vec4 FragColor;\n";
FString prolog;
prolog += uniformBlock;
prolog += uniformTextures;
prolog += pipelineInOut;
mProgram.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", Desc->ShaderVersion);
mProgram.Compile(FShaderProgram::Fragment, lumpName, code, prolog.GetChars(), Desc->ShaderVersion);
mProgram.SetFragDataLocation(0, "FragColor");
mProgram.Link(Desc->ShaderLumpName.GetChars());
mProgram.SetAttribLocation(0, "PositionInProjection");
mInputTexture.Init(mProgram, "InputTexture");
}
void PostProcessShaderInstance::UpdateUniforms()
{
TMap<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
TMap<FString, PostProcessUniformValue>::Pair *pair;
while (it.NextPair(pair))
{
int location = glGetUniformLocation(mProgram, pair->Key.GetChars());
if (location != -1)
{
switch (pair->Value.Type)
{
case PostProcessUniformType::Float:
glUniform1f(location, (float)pair->Value.Values[0]);
break;
case PostProcessUniformType::Int:
glUniform1i(location, (int)pair->Value.Values[0]);
break;
case PostProcessUniformType::Vec2:
glUniform2f(location, (float)pair->Value.Values[0], (float)pair->Value.Values[1]);
break;
case PostProcessUniformType::Vec3:
glUniform3f(location, (float)pair->Value.Values[0], (float)pair->Value.Values[1], (float)pair->Value.Values[2]);
break;
default:
break;
}
}
}
}

View file

@ -0,0 +1,67 @@
#pragma once
#include "gl_shaderprogram.h"
class PostProcessShaderInstance;
enum class PostProcessUniformType
{
Undefined,
Int,
Float,
Vec2,
Vec3
};
struct PostProcessUniformValue
{
PostProcessUniformType Type = PostProcessUniformType::Undefined;
double Values[4] = { 0.0, 0.0, 0.0, 0.0 };
};
struct PostProcessShader
{
FString Target;
FString ShaderLumpName;
int ShaderVersion = 0;
FString Name;
bool Enabled = false;
TMap<FString, PostProcessUniformValue> Uniforms;
};
extern TArray<PostProcessShader> PostProcessShaders;
class PostProcessShaderInstance
{
public:
PostProcessShaderInstance(PostProcessShader *desc) : Desc(desc) { }
void Run();
PostProcessShader *Desc;
private:
bool IsShaderSupported();
void CompileShader();
void UpdateUniforms();
FShaderProgram mProgram;
FBufferedUniformSampler mInputTexture;
};
class FCustomPostProcessShaders
{
public:
FCustomPostProcessShaders();
~FCustomPostProcessShaders();
void Run(FString target);
private:
std::vector<std::unique_ptr<PostProcessShaderInstance>> mShaders;
FCustomPostProcessShaders(const FCustomPostProcessShaders &) = delete;
FCustomPostProcessShaders &operator=(const FCustomPostProcessShaders &) = delete;
};

View file

@ -46,6 +46,8 @@ void FPresentShaderBase::Init(const char * vtx_shader_name, const char * program
InvGamma.Init(mShader, "InvGamma");
Contrast.Init(mShader, "Contrast");
Brightness.Init(mShader, "Brightness");
Saturation.Init(mShader, "Saturation");
GrayFormula.Init(mShader, "GrayFormula");
Scale.Init(mShader, "UVScale");
}

View file

@ -12,6 +12,8 @@ public:
FBufferedUniform1f InvGamma;
FBufferedUniform1f Contrast;
FBufferedUniform1f Brightness;
FBufferedUniform1f Saturation;
FBufferedUniform1i GrayFormula;
FBufferedUniform2f Scale;
protected:

View file

@ -36,6 +36,8 @@
#include "v_palette.h"
#include "sc_man.h"
#include "cmdlib.h"
#include "vm.h"
#include "d_player.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_debug.h"
@ -46,6 +48,7 @@
#include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_shader.h"
#include "gl/shaders/gl_shaderprogram.h"
#include "gl/shaders/gl_postprocessshader.h"
#include "gl/textures/gl_material.h"
#include "gl/dynlights/gl_lightbuffer.h"
@ -671,8 +674,72 @@ void gl_DestroyUserShaders()
//==========================================================================
void gl_ParseHardwareShader(FScanner &sc, int deflump)
{
sc.MustGetString();
if (sc.Compare("postprocess"))
{
sc.MustGetString();
PostProcessShader shaderdesc;
shaderdesc.Target = sc.String;
sc.MustGetToken('{');
while (!sc.CheckToken('}'))
{
sc.MustGetString();
if (sc.Compare("shader"))
{
sc.MustGetString();
shaderdesc.ShaderLumpName = sc.String;
sc.MustGetNumber();
shaderdesc.ShaderVersion = sc.Number;
}
else if (sc.Compare("name"))
{
sc.MustGetString();
shaderdesc.Name = sc.String;
}
else if (sc.Compare("uniform"))
{
sc.MustGetString();
FString uniformType = sc.String;
uniformType.ToLower();
sc.MustGetString();
FString uniformName = sc.String;
PostProcessUniformType parsedType = PostProcessUniformType::Undefined;
if (uniformType.Compare("int") == 0)
parsedType = PostProcessUniformType::Int;
else if (uniformType.Compare("float") == 0)
parsedType = PostProcessUniformType::Float;
else if (uniformType.Compare("vec2") == 0)
parsedType = PostProcessUniformType::Vec2;
else if (uniformType.Compare("vec3") == 0)
parsedType = PostProcessUniformType::Vec3;
if (parsedType != PostProcessUniformType::Undefined)
shaderdesc.Uniforms[uniformName].Type = parsedType;
}
else if (sc.Compare("enabled"))
{
shaderdesc.Enabled = true;
}
}
PostProcessShaders.Push(shaderdesc);
}
else
{
int type = FTexture::TEX_Any;
if (sc.Compare("texture")) type = FTexture::TEX_Wall;
else if (sc.Compare("flat")) type = FTexture::TEX_Flat;
else if (sc.Compare("sprite")) type = FTexture::TEX_Sprite;
else sc.UnGet();
bool disable_fullbright = false;
bool thiswad = false;
bool iwad = false;
@ -680,12 +747,6 @@ void gl_ParseHardwareShader(FScanner &sc, int deflump)
FString maplumpname;
float speed = 1.f;
sc.MustGetString();
if (sc.Compare("texture")) type = FTexture::TEX_Wall;
else if (sc.Compare("flat")) type = FTexture::TEX_Flat;
else if (sc.Compare("sprite")) type = FTexture::TEX_Sprite;
else sc.UnGet();
sc.MustGetString();
FTextureID no = TexMan.CheckForTexture(sc.String, type);
FTexture *tex = TexMan[no];
@ -729,4 +790,138 @@ void gl_ParseHardwareShader(FScanner &sc, int deflump)
tex->gl_info.shaderindex = usershaders.Push(maplumpname) + FIRST_USER_SHADER;
}
}
}
static bool IsConsolePlayer(player_t *player)
{
AActor *activator = player ? player->mo : nullptr;
if (activator == nullptr || activator->player == nullptr)
return false;
return int(activator->player - players) == consoleplayer;
}
DEFINE_ACTION_FUNCTION(_Shader, SetEnabled)
{
PARAM_PROLOGUE;
PARAM_POINTER_DEF(player, player_t);
PARAM_STRING(shaderName);
PARAM_BOOL_DEF(value);
if (IsConsolePlayer(player))
{
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
{
PostProcessShader &shader = PostProcessShaders[i];
if (shader.Name == shaderName)
shader.Enabled = value;
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(_Shader, SetUniform1f)
{
PARAM_PROLOGUE;
PARAM_POINTER_DEF(player, player_t);
PARAM_STRING(shaderName);
PARAM_STRING(uniformName);
PARAM_FLOAT_DEF(value);
if (IsConsolePlayer(player))
{
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
{
PostProcessShader &shader = PostProcessShaders[i];
if (shader.Name == shaderName)
{
double *vec4 = shader.Uniforms[uniformName].Values;
vec4[0] = value;
vec4[1] = 0.0;
vec4[2] = 0.0;
vec4[3] = 1.0;
}
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(_Shader, SetUniform2f)
{
PARAM_PROLOGUE;
PARAM_POINTER_DEF(player, player_t);
PARAM_STRING(shaderName);
PARAM_STRING(uniformName);
PARAM_FLOAT_DEF(x);
PARAM_FLOAT_DEF(y);
if (IsConsolePlayer(player))
{
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
{
PostProcessShader &shader = PostProcessShaders[i];
if (shader.Name == shaderName)
{
double *vec4 = shader.Uniforms[uniformName].Values;
vec4[0] = x;
vec4[1] = y;
vec4[2] = 0.0;
vec4[3] = 1.0;
}
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(_Shader, SetUniform3f)
{
PARAM_PROLOGUE;
PARAM_POINTER_DEF(player, player_t);
PARAM_STRING(shaderName);
PARAM_STRING(uniformName);
PARAM_FLOAT_DEF(x);
PARAM_FLOAT_DEF(y);
PARAM_FLOAT_DEF(z);
if (IsConsolePlayer(player))
{
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
{
PostProcessShader &shader = PostProcessShaders[i];
if (shader.Name == shaderName)
{
double *vec4 = shader.Uniforms[uniformName].Values;
vec4[0] = x;
vec4[1] = y;
vec4[2] = z;
vec4[3] = 1.0;
}
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(_Shader, SetUniform1i)
{
PARAM_PROLOGUE;
PARAM_POINTER_DEF(player, player_t);
PARAM_STRING(shaderName);
PARAM_STRING(uniformName);
PARAM_INT_DEF(value);
if (IsConsolePlayer(player))
{
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
{
PostProcessShader &shader = PostProcessShaders[i];
if (shader.Name == shaderName)
{
double *vec4 = shader.Uniforms[uniformName].Values;
vec4[0] = (double)value;
vec4[1] = 0.0;
vec4[2] = 0.0;
vec4[3] = 1.0;
}
}
}
return 0;
}

View file

@ -41,8 +41,10 @@
#include "gl/system/gl_framebuffer.h"
#include "gl/shaders/gl_present3dRowshader.h"
EXTERN_CVAR(Float, vid_saturation)
EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Int, gl_satformula)
EXTERN_CVAR(Bool, fullscreen)
EXTERN_CVAR(Int, win_x) // screen pixel position of left of display window
EXTERN_CVAR(Int, win_y) // screen pixel position of top of display window
@ -100,12 +102,15 @@ static void prepareInterleavedPresent(FPresentStereoShaderBase& shader)
shader.InvGamma.Set(1.0f);
shader.Contrast.Set(1.0f);
shader.Brightness.Set(0.0f);
shader.Saturation.Set(1.0f);
}
else
{
shader.InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
shader.Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
shader.Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
shader.Saturation.Set(clamp<float>(vid_saturation, -15.0f, 15.0f));
shader.GrayFormula.Set(static_cast<int>(gl_satformula));
}
shader.Scale.Set(
GLRenderer->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(),

View file

@ -73,6 +73,22 @@ CUSTOM_CVAR (Float, vid_contrast, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
}
}
CUSTOM_CVAR (Float, vid_saturation, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (screen != NULL)
{
screen->SetGamma(Gamma);
}
}
CUSTOM_CVAR(Int, gl_satformula, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (screen != NULL)
{
screen->SetGamma(Gamma);
}
}
// Do some tinkering with the menus so that certain options only appear
// when they are actually valid.

View file

@ -57,6 +57,7 @@
#include "textures/textures.h"
#include "vm.h"
#include "events.h"
#include "gl/renderer/gl_renderer.h" // for menu blur
//
// Todo: Move these elsewhere
@ -784,6 +785,8 @@ void M_Drawer (void)
if (CurrentMenu != nullptr && menuactive != MENU_Off)
{
if (GLRenderer)
GLRenderer->BlurScene(gameinfo.bluramount);
if (!CurrentMenu->DontDim)
{
screen->Dim(fade);

View file

@ -1889,6 +1889,9 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
if (!(player->mo->flags & MF_SHOOTABLE))
continue; // not shootable (observer or dead)
if (!((actor->flags ^ player->mo->flags) & MF_FRIENDLY))
continue; // same +MF_FRIENDLY, ignore
if (player->cheats & CF_NOTARGET)
continue; // no target
@ -1988,7 +1991,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look)
targ = NULL;
}
if (targ && targ->player && (targ->player->cheats & CF_NOTARGET))
if (targ && targ->player && ((targ->player->cheats & CF_NOTARGET) || !(targ->flags & MF_FRIENDLY)))
{
return 0;
}

View file

@ -79,6 +79,9 @@ CVAR (Bool, cl_showsprees, true, CVAR_ARCHIVE)
CVAR (Bool, cl_showmultikills, true, CVAR_ARCHIVE)
EXTERN_CVAR (Bool, show_obituaries)
CVAR (Float, sv_damagefactormobj, 1.0, CVAR_SERVERINFO|CVAR_NOSAVE)
CVAR (Float, sv_damagefactorfriendly, 1.0, CVAR_SERVERINFO|CVAR_NOSAVE)
CVAR (Float, sv_damagefactorplayer, 1.0, CVAR_SERVERINFO|CVAR_NOSAVE)
FName MeansOfDeath;
@ -1036,7 +1039,17 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
if (player && damage > 1)
{
// Take half damage in trainer mode
damage = int(damage * G_SkillProperty(SKILLP_DamageFactor));
damage = int(damage * G_SkillProperty(SKILLP_DamageFactor) * sv_damagefactorplayer);
}
else if (!player && damage > 1 && !(target->flags & MF_FRIENDLY))
{
// inflict scaled damage to non-players
damage = int(damage * sv_damagefactormobj);
}
else if (!player && damage > 1 && (target->flags & MF_FRIENDLY))
{
// inflict scaled damage to non-player friends
damage = int(damage * sv_damagefactorfriendly);
}
// Special damage types
if (inflictor)
@ -1865,7 +1878,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain
return;
}
// Take half damage in trainer mode
damage = int(damage * G_SkillProperty(SKILLP_DamageFactor));
damage = int(damage * G_SkillProperty(SKILLP_DamageFactor) * sv_damagefactorplayer);
// Handle passive damage modifiers (e.g. PowerProtection)
damage = target->GetModifiedDamage(player->poisontype, damage, true);
// Modify with damage factors

View file

@ -6718,7 +6718,7 @@ bool P_CheckMissileSpawn (AActor* th, double maxdist)
th->tics = 1;
}
DVector3 newpos = th->Pos();
DVector3 newpos = { 0,0,0 };
if (maxdist > 0)
{
@ -6736,6 +6736,9 @@ bool P_CheckMissileSpawn (AActor* th, double maxdist)
newpos += advance;
}
newpos = th->Vec3Offset(newpos);
th->SetXYZ(newpos);
FCheckPosition tm(!!(th->flags2 & MF2_RIP));
// killough 8/12/98: for non-missile objects (e.g. grenades)
@ -7351,7 +7354,7 @@ bool AActor::IsTeammate (AActor *other)
}
else if (!deathmatch && player && other->player)
{
return true;
return (!((flags ^ other->flags) & MF_FRIENDLY));
}
else if (teamplay)
{
@ -7432,6 +7435,9 @@ bool AActor::IsFriend (AActor *other)
other->FriendPlayer == 0 ||
players[FriendPlayer-1].mo->IsTeammate(players[other->FriendPlayer-1].mo);
}
// [SP] If friendly flags match, then they are on the same team.
/*if (!((flags ^ other->flags) & MF_FRIENDLY))
return true;*/
return false;
}

View file

@ -141,6 +141,7 @@ DEFINE_FIELD_BIT(DPSprite, Flags, bAddBob, PSPF_ADDBOB)
DEFINE_FIELD_BIT(DPSprite, Flags, bPowDouble, PSPF_POWDOUBLE)
DEFINE_FIELD_BIT(DPSprite, Flags, bCVarFast, PSPF_CVARFAST)
DEFINE_FIELD_BIT(DPSprite, Flags, bFlip, PSPF_FLIP)
DEFINE_FIELD_BIT(DPSprite, Flags, bMirror, PSPF_MIRROR)
//------------------------------------------------------------------------
//

View file

@ -68,6 +68,7 @@ enum PSPFlags
PSPF_FLIP = 1 << 6,
PSPF_FORCEALPHA = 1 << 7,
PSPF_FORCESTYLE = 1 << 8,
PSPF_MIRROR = 1 << 9,
};
class DPSprite : public DObject

View file

@ -4119,6 +4119,22 @@ void P_SetupLevel (const char *lumpname, int position)
}
}
// [SP] move unfriendly players around
// horribly hacky - yes, this needs rewritten.
for (i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i] && players[i].mo != NULL)
{
if (!(players[i].mo->flags & MF_FRIENDLY))
{
AActor * oldSpawn = players[i].mo;
G_DeathMatchSpawnPlayer (i);
oldSpawn->Destroy();
}
}
}
// Don't count monsters in end-of-level sectors if option is on
if (dmflags2 & DF2_NOCOUNTENDMONST)
{

View file

@ -232,7 +232,7 @@ void RenderPolyPlayerSprites::RenderSprite(DPSprite *pspr, AActor *owner, float
if (pspr->Flags & PSPF_ADDBOB)
{
sx += bobx;
sx += (pspr->Flags & PSPF_MIRROR) ? -bobx : bobx;
sy += boby;
}
@ -248,17 +248,20 @@ void RenderPolyPlayerSprites::RenderSprite(DPSprite *pspr, AActor *owner, float
double pspriteyscale = pspritexscale * yaspectMul;
double pspritexiscale = 1 / pspritexscale;
// calculate edges of the shape
tx = sx - BASEXCENTER;
int tleft = tex->GetScaledLeftOffset();
int twidth = tex->GetScaledWidth();
// calculate edges of the shape
//tx = sx - BASEXCENTER;
tx = (pspr->Flags & PSPF_MIRROR) ? ((BASEXCENTER - twidth) - (sx - tleft)) : ((sx - BASEXCENTER) - tleft);
tx -= tex->GetScaledLeftOffset();
x1 = xs_RoundToInt(viewwindow.centerx + tx * pspritexscale);
// off the right side
if (x1 > viewwidth)
return;
tx += tex->GetScaledWidth();
tx += twidth;
x2 = xs_RoundToInt(viewwindow.centerx + tx * pspritexscale);
// off the left side

View file

@ -0,0 +1,190 @@
//-----------------------------------------------------------------------------
//
// Copyright 2016 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//
#include <stdlib.h>
#include <stddef.h>
#include "templates.h"
#include "i_system.h"
#include "doomdef.h"
#include "doomstat.h"
#include "doomdata.h"
#include "p_lnspec.h"
#include "p_setup.h"
#include "r_sky.h"
#include "v_video.h"
#include "m_swap.h"
#include "w_wad.h"
#include "stats.h"
#include "a_sharedglobal.h"
#include "d_net.h"
#include "g_level.h"
#include "g_levellocals.h"
#include "r_wallsetup.h"
#include "v_palette.h"
#include "r_utility.h"
#include "r_data/colormaps.h"
#include "swrenderer/r_memory.h"
#include "swrenderer/scene/r_opaque_pass.h"
#include "swrenderer/scene/r_3dfloors.h"
#include "swrenderer/scene/r_portal.h"
#include "swrenderer/scene/r_light.h"
#include "swrenderer/scene/r_scene.h"
#include "swrenderer/viewport/r_viewport.h"
#include "swrenderer/line/r_farclip_line.h"
#include "swrenderer/line/r_walldraw.h"
#include "swrenderer/line/r_wallsetup.h"
#include "swrenderer/drawers/r_draw.h"
#include "swrenderer/segments/r_clipsegment.h"
#include "swrenderer/segments/r_drawsegment.h"
#include "swrenderer/plane/r_visibleplane.h"
#include "swrenderer/plane/r_visibleplanelist.h"
#include "swrenderer/viewport/r_skydrawer.h"
#include "swrenderer/r_renderthread.h"
namespace swrenderer
{
FarClipLine::FarClipLine(RenderThread *thread)
{
Thread = thread;
}
void FarClipLine::Render(seg_t *line, subsector_t *subsector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane)
{
mSubsector = subsector;
mFrontSector = mSubsector->sector;
mLineSegment = line;
mFloorPlane = linefloorplane;
mCeilingPlane = lineceilingplane;
DVector2 pt1 = line->v1->fPos() - Thread->Viewport->viewpoint.Pos;
DVector2 pt2 = line->v2->fPos() - Thread->Viewport->viewpoint.Pos;
// Reject lines not facing viewer
if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0)
return;
if (WallC.Init(Thread, pt1, pt2, 32.0 / (1 << 12)))
return;
RenderPortal *renderportal = Thread->Portal.get();
if (WallC.sx1 >= renderportal->WindowRight || WallC.sx2 <= renderportal->WindowLeft)
return;
if (line->linedef == nullptr)
return;
// reject lines that aren't seen from the portal (if any)
// [ZZ] 10.01.2016: lines inside a skybox shouldn't be clipped, although this imposes some limitations on portals in skyboxes.
if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && P_ClipLineToPortal(line->linedef, renderportal->CurrentPortal->dst, Thread->Viewport->viewpoint.Pos))
return;
mFrontCeilingZ1 = mFrontSector->ceilingplane.ZatPoint(line->v1);
mFrontFloorZ1 = mFrontSector->floorplane.ZatPoint(line->v1);
mFrontCeilingZ2 = mFrontSector->ceilingplane.ZatPoint(line->v2);
mFrontFloorZ2 = mFrontSector->floorplane.ZatPoint(line->v2);
mPrepped = false;
Thread->ClipSegments->Clip(WallC.sx1, WallC.sx2, true, this);
}
bool FarClipLine::RenderWallSegment(int x1, int x2)
{
if (!mPrepped)
{
mPrepped = true;
//walltop.Project(Thread->Viewport.get(), mFrontSector->ceilingplane, &WallC, mLineSegment, Thread->Portal->MirrorFlags & RF_XFLIP);
wallbottom.Project(Thread->Viewport.get(), mFrontSector->floorplane, &WallC, mLineSegment, Thread->Portal->MirrorFlags & RF_XFLIP);
memcpy(walltop.ScreenY, wallbottom.ScreenY, sizeof(short) * MAXWIDTH);
}
ClipSegmentTopBottom(x1, x2);
MarkCeilingPlane(x1, x2);
MarkFloorPlane(x1, x2);
return true;
}
void FarClipLine::ClipSegmentTopBottom(int x1, int x2)
{
// clip wall to the floor and ceiling
auto ceilingclip = Thread->OpaquePass->ceilingclip;
auto floorclip = Thread->OpaquePass->floorclip;
for (int x = x1; x < x2; ++x)
{
if (walltop.ScreenY[x] < ceilingclip[x])
{
walltop.ScreenY[x] = ceilingclip[x];
}
if (wallbottom.ScreenY[x] > floorclip[x])
{
wallbottom.ScreenY[x] = floorclip[x];
}
}
}
void FarClipLine::MarkCeilingPlane(int x1, int x2)
{
if (mCeilingPlane)
{
mCeilingPlane = Thread->PlaneList->GetRange(mCeilingPlane, x1, x2);
auto ceilingclip = Thread->OpaquePass->ceilingclip;
auto floorclip = Thread->OpaquePass->floorclip;
Clip3DFloors *clip3d = Thread->Clip3D.get();
for (int x = x1; x < x2; ++x)
{
short top = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKECEILING) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x];
short bottom = MIN(walltop.ScreenY[x], floorclip[x]);
if (top < bottom)
{
mCeilingPlane->top[x] = top;
mCeilingPlane->bottom[x] = bottom;
}
}
}
}
void FarClipLine::MarkFloorPlane(int x1, int x2)
{
if (mFloorPlane)
{
mFloorPlane = Thread->PlaneList->GetRange(mFloorPlane, x1, x2);
auto ceilingclip = Thread->OpaquePass->ceilingclip;
auto floorclip = Thread->OpaquePass->floorclip;
Clip3DFloors *clip3d = Thread->Clip3D.get();
for (int x = x1; x < x2; ++x)
{
short top = MAX(wallbottom.ScreenY[x], ceilingclip[x]);
short bottom = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKEFLOOR) ? clip3d->fakeFloor->floorclip[x] : floorclip[x];
if (top < bottom)
{
assert(bottom <= viewheight);
mFloorPlane->top[x] = top;
mFloorPlane->bottom[x] = bottom;
}
}
}
}
}

View file

@ -0,0 +1,60 @@
//-----------------------------------------------------------------------------
//
// Copyright 2016 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//
#pragma once
#include "r_line.h"
namespace swrenderer
{
class FarClipLine : VisibleSegmentRenderer
{
public:
FarClipLine(RenderThread *thread);
void Render(seg_t *line, subsector_t *subsector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane);
RenderThread *Thread = nullptr;
private:
bool RenderWallSegment(int x1, int x2) override;
void ClipSegmentTopBottom(int x1, int x2);
void MarkCeilingPlane(int x1, int x2);
void MarkFloorPlane(int x1, int x2);
subsector_t *mSubsector;
sector_t *mFrontSector;
seg_t *mLineSegment;
VisiblePlane *mFloorPlane;
VisiblePlane *mCeilingPlane;
double mFrontCeilingZ1;
double mFrontCeilingZ2;
double mFrontFloorZ1;
double mFrontFloorZ2;
FWallCoords WallC;
bool mPrepped;
ProjectedWallLine walltop;
ProjectedWallLine wallbottom;
};
}

View file

@ -9,6 +9,7 @@
#include "drawers/r_thread.cpp"
#include "line/r_fogboundary.cpp"
#include "line/r_line.cpp"
#include "line/r_farclip_line.cpp"
#include "line/r_renderdrawsegment.cpp"
#include "line/r_walldraw.cpp"
#include "line/r_wallsetup.cpp"

View file

@ -47,6 +47,7 @@
#include "swrenderer/things/r_particle.h"
#include "swrenderer/segments/r_clipsegment.h"
#include "swrenderer/line/r_wallsetup.h"
#include "swrenderer/line/r_farclip_line.h"
#include "swrenderer/scene/r_scene.h"
#include "swrenderer/scene/r_light.h"
#include "swrenderer/viewport/r_viewport.h"
@ -72,6 +73,36 @@
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
EXTERN_CVAR(Bool, r_drawvoxels);
namespace
{
double sprite_distance_cull = 1e16;
double line_distance_cull = 1e16;
}
CUSTOM_CVAR(Float, r_sprite_distance_cull, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (r_sprite_distance_cull > 0.0)
{
sprite_distance_cull = r_sprite_distance_cull * r_sprite_distance_cull;
}
else
{
sprite_distance_cull = 1e16;
}
}
CUSTOM_CVAR(Float, r_line_distance_cull, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (r_line_distance_cull > 0.0)
{
line_distance_cull = r_line_distance_cull * r_line_distance_cull;
}
else
{
line_distance_cull = 1e16;
}
}
namespace swrenderer
{
RenderOpaquePass::RenderOpaquePass(RenderThread *thread) : renderline(thread)
@ -730,10 +761,19 @@ namespace swrenderer
count = sub->numlines;
line = sub->firstline;
DVector2 viewpointPos = Thread->Viewport->viewpoint.Pos.XY();
basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
while (count--)
{
if (!outersubsector || line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ))
double dist1 = (line->v1->fPos() - viewpointPos).LengthSquared();
double dist2 = (line->v2->fPos() - viewpointPos).LengthSquared();
if (dist1 > line_distance_cull && dist2 > line_distance_cull)
{
FarClipLine farclip(Thread);
farclip.Render(line, InSubsector, floorplane, ceilingplane);
}
else if (!outersubsector || line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ))
{
// kg3D - fake planes bounding calculation
if (r_3dfloors && line->backsector && frontsector->e && line->backsector->e->XFloor.ffloors.Size())
@ -934,6 +974,10 @@ namespace swrenderer
if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && !!P_PointOnLineSidePrecise(thing->Pos(), renderportal->CurrentPortal->dst))
return false;
double distanceSquared = (thing->Pos() - Thread->Viewport->viewpoint.Pos).LengthSquared();
if (distanceSquared > sprite_distance_cull)
return false;
return true;
}

View file

@ -240,7 +240,7 @@ namespace swrenderer
if (pspr->Flags & PSPF_ADDBOB)
{
sx += bobx;
sx += (pspr->Flags & PSPF_MIRROR) ? -bobx : bobx;
sy += boby;
}
@ -256,17 +256,18 @@ namespace swrenderer
double pspriteyscale = pspritexscale * viewport->YaspectMul;
double pspritexiscale = 1 / pspritexscale;
// calculate edges of the shape
tx = sx - BASEXCENTER;
int tleft = tex->GetScaledLeftOffset();
int twidth = tex->GetScaledWidth();
tx -= tex->GetScaledLeftOffset();
// calculate edges of the shape
tx = (pspr->Flags & PSPF_MIRROR) ? ((BASEXCENTER - twidth) - (sx - tleft)) : ((sx - BASEXCENTER) - tleft);
x1 = xs_RoundToInt(viewport->CenterX + tx * pspritexscale);
// off the right side
if (x1 > viewwidth)
return;
tx += tex->GetScaledWidth();
tx += twidth;
x2 = xs_RoundToInt(viewport->CenterX + tx * pspritexscale);
// off the left side

View file

@ -2658,6 +2658,7 @@ DSPLYMNU_GLOPT = "OpenGL Renderer";
DSPLYMNU_SWOPT = "Software Renderer";
DSPLYMNU_GAMMA = "Gamma correction";
DSPLYMNU_CONTRAST = "Contrast";
DSPLYMNU_SATURATION = "Saturation";
DSPLYMNU_HWGAMMA = "Hardware Gamma";
// OpenGL Options
@ -2708,6 +2709,7 @@ GLPREFMNU_SPRBILLFACECAMERA = "Sprites face camera";
GLPREFMNU_PARTICLESTYLE = "Particle style";
GLPREFMNU_AMBLIGHT = "Ambient light level";
GLPREFMNU_RENDERQUALITY = "Rendering quality";
GLPREFMNU_MENUBLUR = "Menu Blur";
GLPREFMNU_VRMODE = "Stereo 3D VR";
GLPREFMNU_VRQUADSTEREO = "Enable Quad Stereo";
GLPREFMNU_MULTISAMPLE = "Multisample";

View file

@ -38,6 +38,7 @@ gameinfo
weaponslot = 7, "LAZDevice"
dimcolor = "ff d7 00"
dimamount = 0.2
bluramount = 0.0
definventorymaxamount = 25
defaultrespawntime = 12
defaultdropstyle = 1

View file

@ -39,6 +39,7 @@ gameinfo
weaponslot = 7, "BFG9000"
dimcolor = "ff d7 00"
dimamount = 0.2
bluramount = 0.0
definventorymaxamount = 25
defaultrespawntime = 12
defaultdropstyle = 1

View file

@ -38,6 +38,7 @@ gameinfo
weaponslot = 7, "Mace"
dimcolor = "00 00 ff"
dimamount = 0.2
bluramount = 0
definventorymaxamount = 16
defaultrespawntime = 12
defaultdropstyle = 1

View file

@ -37,6 +37,7 @@ gameinfo
weaponslot = 4, "FWeapQuietus", "CWeapWraithverge", "MWeapBloodscourge"
dimcolor = "00 00 ff"
dimamount = 0.2
bluramount = 0.0
definventorymaxamount = 25
defaultrespawntime = 12
defaultdropstyle = 1

View file

@ -27,6 +27,7 @@ gameinfo
intermissioncounter = true
dimcolor = "6f 00 6b"
dimamount = 0.8
bluramount = 0.0
definventorymaxamount = 25
defaultrespawntime = 12
defaultdropstyle = 1

View file

@ -38,6 +38,7 @@ gameinfo
weaponslot = 8, "Sigil"
dimcolor = "ff d7 00"
dimamount = 0.2
bluramount = 0
definventorymaxamount = 25
defaultrespawntime = 16
defaultdropstyle = 2

View file

@ -742,8 +742,9 @@ OptionMenu "VideoOptions" protected
Slider "$DSPLYMNU_GAMMA", "Gamma", 0.75, 3.0, 0.05, 2
Slider "$DSPLYMNU_BRIGHTNESS", "vid_brightness", -0.8,0.8, 0.05,2
Slider "$DSPLYMNU_CONTRAST", "vid_contrast", 0.1, 3.0, 0.1
Slider "$DSPLYMNU_SATURATION", "vid_saturation", -3.0, 3.0, 0.25, 2
Option "$DSPLYMNU_HWGAMMA", "vid_hwgamma", "HWGammaModes"
StaticText " "
Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff"
Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn"
Slider "$DSPLYMNU_BLOODFADE", "blood_fade_scalar", 0.0, 1.0, 0.05, 2
@ -2160,6 +2161,8 @@ OptionMenu "OpenGLOptions" protected
Option "$GLPREFMNU_PARTICLESTYLE", gl_particles_style, "Particles"
Option "$GLPREFMNU_RENDERQUALITY", gl_render_precise, "Precision"
StaticText " "
Slider "$GLPREFMNU_MENUBLUR", gl_menu_blur, 0, 5.0, 0.5, 2
StaticText " "
Option "$GLPREFMNU_VRMODE", vr_mode, "VRMode"
Option "$GLPREFMNU_VRQUADSTEREO", vr_enable_quadbuffered, "OnOff"
StaticText " "

View file

@ -6,10 +6,17 @@ uniform sampler2D InputTexture;
uniform float InvGamma;
uniform float Contrast;
uniform float Brightness;
uniform float Saturation;
uniform int GrayFormula;
vec4 ApplyGamma(vec4 c)
{
vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5;
vec3 valgray;
if (GrayFormula == 0)
valgray = vec3(c.r + c.g + c.b) * (1 - Saturation) / 3 + c.rgb * Saturation;
else
valgray = mix(vec3(dot(c.rgb, vec3(0.3,0.56,0.14))), c.rgb, Saturation);
vec3 val = valgray * Contrast - (Contrast - 1.0) * 0.5;
val += Brightness * 0.5;
val = pow(max(val, vec3(0.0)), vec3(InvGamma));
return vec4(val, c.a);

View file

@ -775,3 +775,11 @@ class Lighting : SectorEffect native
{
}
struct Shader native
{
native clearscope static void SetEnabled(PlayerInfo player, string shaderName, bool enable);
native clearscope static void SetUniform1f(PlayerInfo player, string shaderName, string uniformName, float value);
native clearscope static void SetUniform2f(PlayerInfo player, string shaderName, string uniformName, vector2 value);
native clearscope static void SetUniform3f(PlayerInfo player, string shaderName, string uniformName, vector3 value);
native clearscope static void SetUniform1i(PlayerInfo player, string shaderName, string uniformName, int value);
}

View file

@ -726,6 +726,7 @@ enum EPSpriteFlags
PSPF_FLIP = 1 << 6,
PSPF_FORCEALPHA = 1 << 7,
PSPF_FORCESTYLE = 1 << 8,
PSPF_MIRROR = 1 << 9,
};
// Default psprite layers