Merge remote-tracking branch 'gzdoom/master' into ssao

# Conflicts:
#	src/gl/renderer/gl_renderer.cpp
#	src/gl/scene/gl_scene.cpp
#	src/gl/shaders/gl_shader.cpp
#	wadsrc/static/language.enu
#	wadsrc/static/menudef.zz
This commit is contained in:
Magnus Norddahl 2016-10-04 00:01:03 +02:00
commit ecb57d6cd9
80 changed files with 2198 additions and 172 deletions

View file

@ -30,8 +30,27 @@ if(CMAKE_CROSSCOMPILING)
include(${IMPORT_EXECUTABLES})
endif()
# Recursive function to place PK3 archive source files into a hierarchy of source file in the IDE
function( assort_pk3_source_folder FOLDER_NAME PK3_DIR )
# Assort source files into folders in the IDE
file(GLOB PK3_SRCS ${PK3_DIR}/*) # Create list of all files in this folder
foreach(PK3_SRC ${PK3_SRCS})
# If there are subfolders, recurse into them
if(IS_DIRECTORY ${PK3_SRC})
get_filename_component(DIRNAME ${PK3_SRC} NAME)
# Exclude folder from list of source files
list(REMOVE_ITEM PK3_SRCS ${PK3_SRC})
# Recurse deeper into the filesystem folder tree
assort_pk3_source_folder( ${FOLDER_NAME}\\${DIRNAME} ${PK3_SRC} )
endif()
# Assign IDE group for current top-level source files
source_group(${FOLDER_NAME} FILES ${PK3_SRCS})
endforeach()
endfunction()
# Simplify pk3 building, add_pk3(filename srcdirectory)
function( add_pk3 PK3_NAME PK3_DIR )
# message(STATUS "Creating build rule for PK3 ${PK3_NAME} ${PK3_DIR}")
# Generate target name. Just use "pk3" for main pk3 target.
string( REPLACE "." "_" PK3_TARGET ${PK3_NAME} )
if( ${PK3_TARGET} STREQUAL "zdoom_pk3" )
@ -48,14 +67,33 @@ function( add_pk3 PK3_NAME PK3_DIR )
COMMAND zipdir -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR}
DEPENDS zipdir )
endif()
# Grab a list of top-level PK3 folder files, so we can conveniently see them in the IDE
file(GLOB PK3_SRCS ${PK3_DIR}/*)
# Create a list of source files for this PK3, for use in the IDE
# Phase 1: Create a list of all source files for this PK3 archive, except
# for a couple of strife image file names that confuse CMake.
file(GLOB_RECURSE PK3_SRCS ${PK3_DIR}/*)
# Exclude from the source list some gzdoom .png files with brackets in the
# file names here, because they confuse CMake.
# This only affects the list of source files shown in the IDE.
# It does not actually remove the files from the PK3 archive.
# First replace that toxic bracket character with something we can handle
string(REPLACE "[" confusing_bracket PK3_SRCS "${PK3_SRCS}")
string(REPLACE "]" confusing_bracket PK3_SRCS "${PK3_SRCS}")
foreach(PK3_SRC ${PK3_SRCS}) # All source files at all levels
# Exclude those quarantined source file source file names that once had a bracket
if(${PK3_SRC} MATCHES confusing_bracket)
# message(STATUS "Ignoring PK3 file name containing brackets "${PK3_SRC})
list(REMOVE_ITEM PK3_SRCS ${PK3_SRC})
endif()
endforeach()
# Phase 2: Create the PK3 build rule, including the source file list for the IDE
# Touch the zipdir executable here so that the pk3s are forced to
# rebuild each time since their dependecy has "changed."
# rebuild each time since their dependency has "changed."
add_custom_target( ${PK3_TARGET} ALL
COMMAND ${CMAKE_COMMAND} -E touch $<TARGET_FILE:zipdir>
DEPENDS ${ZDOOM_OUTPUT_DIR}/${PK3_NAME}
SOURCES "${PK3_SRCS}")
SOURCES ${PK3_SRCS})
# Phase 3: Assign source files to a nice folder structure in the IDE
assort_pk3_source_folder("Source Files" ${PK3_DIR})
endfunction()
# Macro for building libraries without debugging information

33
docs/licenses/fxaa.txt Normal file
View file

@ -0,0 +1,33 @@
//----------------------------------------------------------------------------------
// File: es3-kepler\FXAA/FXAA3_11.h
// SDK Version: v3.00
// Email: gameworks@nvidia.com
// Site: http://developer.nvidia.com/
//
// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 COPYRIGHT OWNER OR
// CONTRIBUTORS 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.
//
//----------------------------------------------------------------------------------

View file

@ -214,6 +214,19 @@ Note: All <bool> fields default to false unless mentioned otherwise.
damagehazard = <bool>; // Changes damage model to Strife's delayed damage for the given sector. Default = false.
floorterrain = <string>; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.'
ceilingterrain = <string>; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.'
portal_ceil_alpha = <float> // translucency of ceiling portal (default is 0 (not visible))
portal_ceil_blocksound = <bool> // ceiling portal blocks sound.
portal_ceil_disabled = <bool> // ceiling portal disabled.
portal_ceil_nopass = <bool> // ceiling portal blocks movement if true.
portal_ceil_norender = <bool> // ceiling portal not rendered.
portal_ceil_overlaytype = <string> // defines translucency style, can either be "translucent" or "additive". Default is "translucent".
portal_floor_alpha = <float> // translucency of floor portal (default is 0 (not visible))
portal_floor_blocksound = <bool> // floor portal blocks sound.
portal_floor_disabled = <bool> // floor portal disabled.
portal_floor_nopass = <bool> // ceiling portal blocks movement if true.
portal_floor_norender = <bool> // ceiling portal not rendered.
portal_floor_overlaytype = <string> // defines translucency style, can either be "translucent" or "additive". Default is "translucent".
* Note about dropactors

View file

@ -9,6 +9,8 @@ endif()
include( CheckCXXSourceCompiles )
include( CheckFunctionExists )
include( CheckCXXCompilerFlag )
include( CheckIncludeFile )
include( CheckIncludeFiles )
include( CheckLibraryExists )
include( FindPkgConfig )
include( FindOpenGL )
@ -119,7 +121,13 @@ if( WIN32 )
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Include )
if( NOT D3D_INCLUDE_DIR )
message( SEND_ERROR "Could not find DirectX 9 header files" )
# Modern versions of the Windows SDK include d3d9.h. Unfortunately,
# CMake cannot find this file via find_path, so we check for it using
# CHECK_INCLUDE_FILE.
CHECK_INCLUDE_FILE( d3d9.h D3D9_H_FOUND )
if ( NOT D3D9_H_FOUND )
message( SEND_ERROR "Could not find DirectX 9 header files" )
endif()
else()
include_directories( ${D3D_INCLUDE_DIR} )
endif()
@ -128,35 +136,41 @@ if( WIN32 )
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Include )
if( NOT XINPUT_INCLUDE_DIR )
message( WARNING "Could not find xinput.h. XInput will be disabled." )
add_definitions( -DNO_XINPUT )
# Modern versions of the Windows SDK include xinput.h. Unfortunately,
# CMake cannot find this file via find_path, so we check for it using
# CHECK_INCLUDE_FILES. windows.h must be included before xinput.h.
CHECK_INCLUDE_FILES( "windows.h;xinput.h" XINPUT_H_FOUND )
if( NOT XINPUT_H_FOUND )
message( WARNING "Could not find xinput.h. XInput will be disabled." )
add_definitions( -DNO_XINPUT )
endif()
else()
include_directories( ${XINPUT_INCLUDE_DIR} )
endif()
find_library( DX_dxguid_LIBRARY dxguid
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Lib Lib/${XBITS} )
find_library( DX_dinput8_LIBRARY dinput8
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Lib Lib/${XBITS} )
find_library( DX_dxguid_LIBRARY dxguid
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Lib Lib/${XBITS} )
set( DX_LIBS_FOUND YES )
if( NOT DX_dxguid_LIBRARY )
set( DX_LIBS_FOUND NO )
endif()
# Modern versions of the Windows SDK include dinput8.lib. Unfortunately,
# CMake cannot find these libraries via find_library.
if( NOT DX_dinput8_LIBRARY )
set( DX_LIBS_FOUND NO )
# If we got this far, assume dinput8.lib is in the system library path.
set( DX_dinput8_LIBRARY dinput8 )
endif()
if( NOT DX_LIBS_FOUND )
message( FATAL_ERROR "Could not find DirectX 9 libraries" )
# Modern versions of the Windows SDK do NOT include dxguid.lib. Its contents
# were moved to dinput8.lib.
if( NOT DX_dxguid_LIBRARY )
message( STATUS "Could not find dxguid.lib. Build may fail on old Windows SDKs.")
endif()
set( ZDOOM_LIBS
wsock32
winmm
"${DX_dxguid_LIBRARY}"
"${DX_dinput8_LIBRARY}"
ole32
user32
@ -167,6 +181,9 @@ if( WIN32 )
setupapi
oleaut32
DelayImp )
if( DX_dxguid_LIBRARY )
list( APPEND ZDOOM_LIBS "${DX_dxguid_LIBRARY}" )
endif()
else()
if( APPLE )
set( FMOD_SEARCH_PATHS "/Developer/FMOD Programmers API Mac/api" )
@ -1116,6 +1133,7 @@ set( FASTMATH_SOURCES
gl/stereo3d/gl_anaglyph.cpp
gl/stereo3d/gl_quadstereo.cpp
gl/stereo3d/gl_sidebyside3d.cpp
gl/stereo3d/gl_interleaved3d.cpp
gl/dynlights/gl_dynlight.cpp
gl/dynlights/gl_glow.cpp
gl/dynlights/gl_dynlight1.cpp
@ -1124,12 +1142,14 @@ set( FASTMATH_SOURCES
gl/shaders/gl_texshader.cpp
gl/shaders/gl_shaderprogram.cpp
gl/shaders/gl_presentshader.cpp
gl/shaders/gl_present3dRowshader.cpp
gl/shaders/gl_bloomshader.cpp
gl/shaders/gl_ambientshader.cpp
gl/shaders/gl_blurshader.cpp
gl/shaders/gl_colormapshader.cpp
gl/shaders/gl_tonemapshader.cpp
gl/shaders/gl_lensshader.cpp
gl/shaders/gl_fxaashader.cpp
gl/system/gl_interface.cpp
gl/system/gl_framebuffer.cpp
gl/system/gl_debug.cpp

View file

@ -755,6 +755,9 @@ public:
// What species am I?
virtual FName GetSpecies();
// set translation
void SetTranslation(const char *trname);
double GetBobOffset(double ticfrac = 0) const
{
if (!(flags2 & MF2_FLOATBOB))

View file

@ -2439,6 +2439,7 @@ void D_DoomMain (void)
if (!batchrun) Printf ("ParseTeamInfo: Load team definitions.\n");
TeamLibrary.ParseTeamInfo ();
R_ParseTrnslate();
PClassActor::StaticInit ();
// [GRB] Initialize player class list

View file

@ -330,7 +330,11 @@ DObject::~DObject ()
}
}
}
type->DestroySpecials(this);
if (nullptr != type)
{
type->DestroySpecials(this);
}
}
}

View file

@ -60,6 +60,7 @@ void DSectorEffect::Destroy()
}
DSectorEffect::DSectorEffect (sector_t *sector)
: DThinker(STAT_SECTOREFFECT)
{
m_Sector = sector;
}

View file

@ -1207,29 +1207,23 @@ void G_FinishTravel ()
pnum = int(pawn->player - players);
pawn->ChangeStatNum (STAT_PLAYER);
pawndup = pawn->player->mo;
start = NULL;
assert (pawn != pawndup);
if (pawndup == NULL)
{ // Oh no! there was no start for this player!
start = G_PickPlayerStart(pnum, PPS_FORCERANDOM);
if (start != NULL) pawndup = P_SpawnPlayer(start, pnum, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
if (pawndup == NULL)
{
pawn->flags |= MF_NOSECTOR | MF_NOBLOCKMAP;
pawn->Destroy();
continue;
}
}
start = G_PickPlayerStart(pnum, 0);
if (start == NULL)
{
start = G_PickPlayerStart(pnum, 0);
if (start == NULL)
if (pawndup != nullptr)
{
Printf(TEXTCOLOR_RED "No player %d start to travel to!\n", pnum + 1);
// Move to the coordinates this player had when they left the level.
pawn->SetXYZ(pawndup->Pos());
}
else
{
// Could not find a start for this player at all. This really should never happen but if it does, let's better abort.
DThinker::DestroyThinkersInList(STAT_TRAVELLING);
I_Error ("No player %d start to travel to!\n", pnum + 1);
}
}
oldpawn = pawndup;
@ -1266,8 +1260,11 @@ void G_FinishTravel ()
pawn->player->camera = pawn;
pawn->player->viewheight = pawn->ViewHeight;
pawn->flags2 &= ~MF2_BLASTED;
DObject::StaticPointerSubstitution (oldpawn, pawn);
oldpawn->Destroy();
if (oldpawn != nullptr)
{
DObject::StaticPointerSubstitution (oldpawn, pawn);
oldpawn->Destroy();
}
if (pawndup != NULL)
{
pawndup->Destroy();

View file

@ -54,6 +54,12 @@ void AFastProjectile::Tick ()
// Handle movement
if (!Vel.isZero() || (Z() != floorz))
{
// force some lateral movement so that collision detection works as intended.
if ((flags & MF_MISSILE) && Vel.X == 0 && Vel.Y == 0 && !IsZeroDamage())
{
Vel.X = MinVel;
}
frac = Vel / count;
changexy = frac.X != 0 || frac.Y != 0;
int ripcount = count / 8;
@ -124,7 +130,7 @@ void AFastProjectile::Tick ()
P_ExplodeMissile (this, NULL, NULL);
return;
}
if (changexy && ripcount <= 0)
if (!frac.isZero() && ripcount <= 0)
{
ripcount = count >> 3;
Effect();

View file

@ -1021,7 +1021,7 @@ class CommandDrawNumber : public CommandDrawString
usePrefix(false), interpolationSpeed(0), drawValue(0), length(3),
lowValue(-1), lowTranslation(CR_UNTRANSLATED), highValue(-1),
highTranslation(CR_UNTRANSLATED), value(CONSTANT),
inventoryItem(NULL)
inventoryItem(NULL), cvarName(nullptr)
{
}
@ -1166,6 +1166,37 @@ class CommandDrawNumber : public CommandDrawString
if(parenthesized) sc.MustGetToken(')');
}
else if (sc.Compare("intcvar"))
{
bool parenthesized = sc.CheckToken('(');
value = INTCVAR;
if (!parenthesized || !sc.CheckToken(TK_StringConst))
sc.MustGetToken(TK_Identifier);
cvarName = sc.String;
// We have a name, but make sure it exists. If not, send notification so modders
// are aware of the situation.
FBaseCVar *CVar = FindCVar(cvarName, nullptr);
if (CVar != nullptr)
{
ECVarType cvartype = CVar->GetRealType();
if (!(cvartype == CVAR_Bool || cvartype == CVAR_Int))
{
sc.ScriptMessage("CVar '%s' is not an int or bool", cvarName.GetChars());
}
}
else
{
sc.ScriptMessage("CVar '%s' does not exist", cvarName.GetChars());
}
if (parenthesized) sc.MustGetToken(')');
}
}
if(value == INVENTORY)
{
@ -1444,6 +1475,24 @@ class CommandDrawNumber : public CommandDrawString
num++;
}
break;
case INTCVAR:
{
FBaseCVar *CVar = GetCVar(statusBar->CPlayer->mo, cvarName);
if (CVar != nullptr)
{
ECVarType cvartype = CVar->GetRealType();
if (cvartype == CVAR_Bool || cvartype == CVAR_Int)
{
num = CVar->GetGenericRep(CVAR_Int).Int;
break;
}
}
// Fallback in case of bad cvar/type. Unset can remove a cvar at will.
num = 0;
break;
}
default: break;
}
if(interpolationSpeed != 0 && (!hudChanged || level.time == 1))
@ -1522,6 +1571,7 @@ class CommandDrawNumber : public CommandDrawString
ACCURACY,
STAMINA,
KEYS,
INTCVAR,
CONSTANT
};
@ -1544,6 +1594,7 @@ class CommandDrawNumber : public CommandDrawString
PClassActor *inventoryItem;
FString prefixPadding;
FString cvarName;
friend class CommandDrawInventoryBar;
};

View file

@ -442,7 +442,7 @@ VSMatrix::computeNormalMatrix(const FLOATTYPE *aMatrix)
mMat3x3[1] * (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) +
mMat3x3[2] * (mMat3x3[3] * mMat3x3[7] - mMat3x3[4] * mMat3x3[6]);
invDet = 1.0f/det;
invDet = 1.0/det;
mMatrix[0] = (mMat3x3[4] * mMat3x3[8] - mMat3x3[5] * mMat3x3[7]) * invDet;
mMatrix[1] = (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) * invDet;

View file

@ -71,6 +71,7 @@ void FSimpleVertexBuffer::BindVBO()
glEnableVertexAttribArray(VATTR_TEXCOORD);
glEnableVertexAttribArray(VATTR_COLOR);
glDisableVertexAttribArray(VATTR_VERTEX2);
glDisableVertexAttribArray(VATTR_NORMAL);
}
else
{
@ -221,7 +222,7 @@ void FFlatVertexBuffer::OutputResized(int width, int height)
vbo_shadowdata[7].Set((float)width, (float)height, 0, 0, 0);
Map();
memcpy(map, &vbo_shadowdata[4], 4 * sizeof(FFlatVertex));
memcpy(&map[4], &vbo_shadowdata[4], 4 * sizeof(FFlatVertex));
Unmap();
}
@ -236,6 +237,7 @@ void FFlatVertexBuffer::BindVBO()
glEnableVertexAttribArray(VATTR_TEXCOORD);
glDisableVertexAttribArray(VATTR_COLOR);
glDisableVertexAttribArray(VATTR_VERTEX2);
glDisableVertexAttribArray(VATTR_NORMAL);
}
else
{

View file

@ -271,6 +271,7 @@ struct FModelVertex
{
float x, y, z; // world position
float u, v; // texture coordinates
unsigned packedNormal; // normal vector as GL_INT_2_10_10_10_REV.
void Set(float xx, float yy, float zz, float uu, float vv)
{
@ -283,7 +284,13 @@ struct FModelVertex
void SetNormal(float nx, float ny, float nz)
{
// GZDoom currently doesn't use normals. This function is so that the high level code can pretend it does.
/*
int inx = int(nx * 512);
int iny = int(ny * 512);
int inz = int(nz * 512);
packedNormal = 0x40000000 | ((inx & 1023) << 20) | ((iny & 1023) << 10) | (inz & 1023);
*/
packedNormal = 0; // Per-pixel lighting for models isn't implemented yet so leave this at 0 for now.
}
};

View file

@ -391,6 +391,16 @@ void ADynamicLight::UpdateLocation()
Prev = target->Pos();
subsector = R_PointInSubsector(Prev);
Sector = subsector->sector;
// Some z-coordinate fudging to prevent the light from getting too close to the floor or ceiling planes. With proper attenuation this would render them invisible.
// A distance of 5 is needed so that the light's effect doesn't become too small.
if (Z() < target->floorz + 5.) SetZ(target->floorz + 5.);
else if (Z() > target->ceilingz - 5.) SetZ(target->ceilingz - 5.);
}
else
{
if (Z() < floorz + 5.) SetZ(floorz + 5.);
else if (Z() > ceilingz - 5.) SetZ(ceilingz - 5.);
}

View file

@ -119,6 +119,7 @@ void FModelVertexBuffer::BindVBO()
glEnableVertexAttribArray(VATTR_VERTEX);
glEnableVertexAttribArray(VATTR_TEXCOORD);
glEnableVertexAttribArray(VATTR_VERTEX2);
glEnableVertexAttribArray(VATTR_NORMAL);
glDisableVertexAttribArray(VATTR_COLOR);
}
else
@ -245,6 +246,7 @@ unsigned int FModelVertexBuffer::SetupFrame(unsigned int frame1, unsigned int fr
glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame1].x);
glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame1].u);
glVertexAttribPointer(VATTR_VERTEX2, 3, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame2].x);
glVertexAttribPointer(VATTR_NORMAL, 4, GL_UNSIGNED_INT_2_10_10_10_REV, false, sizeof(FModelVertex), &VMO[frame2].packedNormal);
}
else
{

View file

@ -248,6 +248,7 @@ void FVoxelModel::AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3
FModelVertex vert;
unsigned int indx[4];
vert.packedNormal = 0; // currently this is not being used for voxels.
vert.u = (((col & 15) * 255 / 16) + 7) / 255.f;
vert.v = (((col / 16) * 255 / 16) + 7) / 255.f;
@ -271,6 +272,7 @@ void FVoxelModel::AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3
vert.y = -z3 + PivotZ;
indx[3] = AddVertex(vert, check);
mIndices.Push(indx[0]);
mIndices.Push(indx[1]);
mIndices.Push(indx[3]);

View file

@ -61,6 +61,7 @@
#include "gl/shaders/gl_tonemapshader.h"
#include "gl/shaders/gl_colormapshader.h"
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_fxaashader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/renderer/gl_2ddrawer.h"
#include "gl/stereo3d/gl_stereo3d.h"
@ -70,24 +71,24 @@
// CVARs
//
//==========================================================================
CVAR(Bool, gl_bloom, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
CUSTOM_CVAR(Float, gl_bloom_amount, 1.4f, 0)
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, 0)
CVAR(Float, gl_exposure_min, 0.35f, 0)
CVAR(Float, gl_exposure_base, 0.35f, 0)
CVAR(Float, gl_exposure_speed, 0.05f, 0)
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|CVAR_GLOBALCONFIG)
CUSTOM_CVAR(Int, gl_tonemap, 0, CVAR_ARCHIVE)
{
if (self < 0 || self > 5)
self = 0;
}
CUSTOM_CVAR(Int, gl_bloom_kernel_size, 7, 0)
CUSTOM_CVAR(Int, gl_bloom_kernel_size, 7, CVAR_ARCHIVE)
{
if (self < 3 || self > 15 || self % 2 == 0)
self = 7;
@ -95,9 +96,17 @@ CUSTOM_CVAR(Int, gl_bloom_kernel_size, 7, 0)
CVAR(Bool, gl_lens, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, gl_lens_k, -0.12f, 0)
CVAR(Float, gl_lens_kcube, 0.1f, 0)
CVAR(Float, gl_lens_chromatic, 1.12f, 0)
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 >= FFXAAShader::Count)
{
self = 0;
}
}
CUSTOM_CVAR(Int, gl_ssao, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
@ -139,6 +148,7 @@ void FGLRenderer::PostProcessScene()
TonemapScene();
ColormapScene();
LensDistortScene();
ApplyFXAA();
}
//-----------------------------------------------------------------------------
@ -599,6 +609,51 @@ void FGLRenderer::LensDistortScene()
FGLDebug::PopGroup();
}
//-----------------------------------------------------------------------------
//
// Apply FXAA and place the result in the HUD/2D texture
//
//-----------------------------------------------------------------------------
void FGLRenderer::ApplyFXAA()
{
if (0 == gl_fxaa)
{
return;
}
FGLDebug::PushGroup("ApplyFXAA");
const GLfloat rpcRes[2] =
{
1.0f / mBuffers->GetWidth(),
1.0f / mBuffers->GetHeight()
};
FGLPostProcessState savedState;
mBuffers->BindNextFB();
mBuffers->BindCurrentTexture(0);
mFXAALumaShader->Bind();
mFXAALumaShader->InputTexture.Set(0);
RenderScreenQuad();
mBuffers->NextTexture();
mBuffers->BindNextFB();
mBuffers->BindCurrentTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mFXAAShader->Bind();
mFXAAShader->InputTexture.Set(0);
mFXAAShader->ReciprocalResolution.Set(rpcRes);
RenderScreenQuad();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
mBuffers->NextTexture();
FGLDebug::PopGroup();
}
//-----------------------------------------------------------------------------
//
// Copies the rendered screen to its final destination

View file

@ -2,6 +2,7 @@
#define __GL_RENDERBUFFERS_H
#include "gl/shaders/gl_shader.h"
#include "gl/renderer/gl_renderer.h"
class FGLBloomTextureLevel
{

View file

@ -57,7 +57,9 @@
#include "gl/shaders/gl_tonemapshader.h"
#include "gl/shaders/gl_colormapshader.h"
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_fxaashader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/shaders/gl_present3dRowshader.h"
#include "gl/stereo3d/gl_stereo3d.h"
#include "gl/textures/gl_texture.h"
#include "gl/textures/gl_translate.h"
@ -104,6 +106,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mTonemapPalette = nullptr;
mBuffers = nullptr;
mPresentShader = nullptr;
mPresent3dRowShader = nullptr;
mBloomExtractShader = nullptr;
mBloomCombineShader = nullptr;
mExposureExtractShader = nullptr;
@ -118,6 +121,8 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mDepthBlurShader = nullptr;
mSSAOShader = nullptr;
mSSAOCombineShader = nullptr;
mFXAAShader = nullptr;
mFXAALumaShader = nullptr;
}
void gl_LoadModels();
@ -140,7 +145,10 @@ void FGLRenderer::Initialize(int width, int height)
mColormapShader = new FColormapShader();
mTonemapPalette = nullptr;
mLensShader = new FLensShader();
mFXAAShader = new FFXAAShader;
mFXAALumaShader = new FFXAALumaShader;
mPresentShader = new FPresentShader();
mPresent3dRowShader = new FPresent3DRowShader();
m2DDrawer = new F2DDrawer;
// needed for the core profile, because someone decided it was a good idea to remove the default VAO.
@ -197,6 +205,7 @@ FGLRenderer::~FGLRenderer()
if (mDepthBlurShader) delete mDepthBlurShader;
if (mSSAOShader) delete mSSAOShader;
if (mSSAOCombineShader) delete mSSAOCombineShader;
if (mPresent3dRowShader) delete mPresent3dRowShader;
if (mBloomExtractShader) delete mBloomExtractShader;
if (mBloomCombineShader) delete mBloomCombineShader;
if (mExposureExtractShader) delete mExposureExtractShader;
@ -207,6 +216,8 @@ FGLRenderer::~FGLRenderer()
if (mTonemapPalette) delete mTonemapPalette;
if (mColormapShader) delete mColormapShader;
if (mLensShader) delete mLensShader;
delete mFXAAShader;
delete mFXAALumaShader;
}
//==========================================================================

View file

@ -32,7 +32,10 @@ class FBlurShader;
class FTonemapShader;
class FColormapShader;
class FLensShader;
class FFXAALumaShader;
class FFXAAShader;
class FPresentShader;
class FPresent3DRowShader;
class F2DDrawer;
class FHardwareTexture;
@ -111,7 +114,10 @@ public:
FColormapShader *mColormapShader;
FHardwareTexture *mTonemapPalette;
FLensShader *mLensShader;
FFXAALumaShader *mFXAALumaShader;
FFXAAShader *mFXAAShader;
FPresentShader *mPresentShader;
FPresent3DRowShader *mPresent3dRowShader;
FTexture *gllight;
FTexture *glpart2;
@ -188,6 +194,7 @@ public:
void BindTonemapPalette(int texunit);
void ClearTonemapPalette();
void LensDistortScene();
void ApplyFXAA();
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
void DrawPresentTexture(const GL_IRECT &box, bool applyGamma);
void Flush();

View file

@ -142,6 +142,7 @@ bool FRenderState::ApplyShader()
}
glVertexAttrib4fv(VATTR_COLOR, mColor.vec);
glVertexAttrib4fv(VATTR_NORMAL, mNormal.vec);
activeShader->muDesaturation.Set(mDesaturation / 255.f);
activeShader->muFogEnabled.Set(fogset);
@ -270,12 +271,16 @@ bool FRenderState::ApplyShader()
if (mModelMatrixEnabled)
{
mModelMatrix.matrixToGL(activeShader->modelmatrix_index);
VSMatrix norm;
norm.computeNormalMatrix(mModelMatrix);
mNormalModelMatrix.matrixToGL(activeShader->normalmodelmatrix_index);
activeShader->currentModelMatrixState = true;
}
else if (activeShader->currentModelMatrixState)
{
activeShader->currentModelMatrixState = false;
identityMatrix.matrixToGL(activeShader->modelmatrix_index);
identityMatrix.matrixToGL(activeShader->normalmodelmatrix_index);
}
return true;
}

View file

@ -97,6 +97,7 @@ class FRenderState
float mShaderTimer;
FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer;
FStateVec4 mNormal;
FStateVec4 mColor;
FStateVec4 mCameraPos;
FStateVec4 mGlowTop, mGlowBottom;
@ -128,6 +129,8 @@ public:
VSMatrix mViewMatrix;
VSMatrix mModelMatrix;
VSMatrix mTextureMatrix;
VSMatrix mNormalViewMatrix;
VSMatrix mNormalModelMatrix;
FRenderState()
{
@ -189,6 +192,16 @@ public:
void SetClipHeight(float height, float direction);
void SetNormal(FVector3 norm)
{
mNormal.Set(norm.X, norm.Y, norm.Z, 0.f);
}
void SetNormal(float x, float y, float z)
{
mNormal.Set(x, y, z, 0.f);
}
void SetColor(float r, float g, float b, float a = 1.f, int desat = 0)
{
mColor.Set(r, g, b, a);

View file

@ -374,6 +374,7 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG
}
#endif
gl_RenderState.SetNormal(plane.plane.Normal().X, plane.plane.Normal().Z, plane.plane.Normal().Y);
switch (pass)
{
@ -502,6 +503,11 @@ inline void GLFlat::PutFlat(bool fog)
void GLFlat::Process(sector_t * model, int whichplane, bool fog)
{
plane.GetFromSector(model, whichplane);
if (whichplane != int(ceiling))
{
// Flip the normal if the source plane has a different orientation than what we are about to render.
plane.plane.FlipVert();
}
if (!fog)
{
@ -641,7 +647,7 @@ void GLFlat::ProcessSector(sector_t * frontsector)
Colormap.CopyFrom3DLight(light);
}
renderstyle = STYLE_Translucent;
Process(frontsector, false, false);
Process(frontsector, sector_t::floor, false);
}
}
@ -700,7 +706,7 @@ void GLFlat::ProcessSector(sector_t * frontsector)
Colormap.CopyFrom3DLight(light);
}
renderstyle = STYLE_Translucent;
Process(frontsector, true, false);
Process(frontsector, sector_t::ceiling, false);
}
}

View file

@ -176,12 +176,12 @@ void GLPortal::DrawPortalStencil()
bool GLPortal::Start(bool usestencil, bool doquery)
{
rendered_portals++;
PortalAll.Clock();
// PortalAll.Clock();
if (usestencil)
{
if (!gl_portals)
{
PortalAll.Unclock();
// PortalAll.Unclock();
return false;
}
@ -297,7 +297,7 @@ bool GLPortal::Start(bool usestencil, bool doquery)
GLRenderer->mCurrentPortal = this;
if (PrevPortal != NULL) PrevPortal->PushState();
PortalAll.Unclock();
// PortalAll.Unclock();
return true;
}
@ -1219,7 +1219,7 @@ void GLEEHorizonPortal::DrawContents()
if (sector->GetTexture(sector_t::ceiling) != skyflatnum)
{
GLHorizonInfo horz;
horz.plane.GetFromSector(sector, true);
horz.plane.GetFromSector(sector, sector_t::ceiling);
horz.lightlevel = gl_ClampLight(sector->GetCeilingLight());
horz.colormap = sector->ColorMap;
if (portal->mType == PORTS_PLANE)
@ -1232,7 +1232,7 @@ void GLEEHorizonPortal::DrawContents()
if (sector->GetTexture(sector_t::floor) != skyflatnum)
{
GLHorizonInfo horz;
horz.plane.GetFromSector(sector, false);
horz.plane.GetFromSector(sector, sector_t::floor);
horz.lightlevel = gl_ClampLight(sector->GetFloorLight());
horz.colormap = sector->ColorMap;
if (portal->mType == PORTS_PLANE)

View file

@ -114,6 +114,7 @@ void FSkyVertexBuffer::BindVBO()
glEnableVertexAttribArray(VATTR_TEXCOORD);
glEnableVertexAttribArray(VATTR_COLOR);
glDisableVertexAttribArray(VATTR_VERTEX2);
glDisableVertexAttribArray(VATTR_NORMAL);
}
else
{

View file

@ -406,6 +406,7 @@ void GLSprite::Draw(int pass)
gl_RenderState.Apply();
FVector3 v[4];
gl_RenderState.SetNormal(0, 0, 0);
CalculateVertices(v);
FQuadDrawer qd;

View file

@ -60,6 +60,15 @@ struct GLSeg
float x1,x2;
float y1,y2;
float fracleft, fracright; // fractional offset of the 2 vertices on the linedef
FVector3 Normal() const
{
// we do not use the vector math inlines here because they are not optimized for speed but accuracy in the playsim
float x = y2 - y1;
float y = x1 - x2;
float length = sqrt(x*x + y*y);
return FVector3(x / length, 0, y / length);
}
};
struct texcoord

View file

@ -470,7 +470,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2)
}
else
{
hi.plane.GetFromSector(fs, true);
hi.plane.GetFromSector(fs, sector_t::ceiling);
hi.lightlevel = gl_ClampLight(fs->GetCeilingLight());
hi.colormap = fs->ColorMap;
@ -498,7 +498,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2)
}
else
{
hi.plane.GetFromSector(fs, false);
hi.plane.GetFromSector(fs, sector_t::floor);
hi.lightlevel = gl_ClampLight(fs->GetFloorLight());
hi.colormap = fs->ColorMap;

View file

@ -254,14 +254,13 @@ void GLWall::RenderMirrorSurface()
if (GLRenderer->mirrortexture == NULL) return;
// For the sphere map effect we need a normal of the mirror surface,
Vector v(glseg.y2-glseg.y1, 0 ,-glseg.x2+glseg.x1);
v.Normalize();
FVector3 v = glseg.Normal();
if (!gl.legacyMode)
{
// we use texture coordinates and texture matrix to pass the normal stuff to the shader so that the default vertex buffer format can be used as is.
tcs[LOLFT].u = tcs[LORGT].u = tcs[UPLFT].u = tcs[UPRGT].u = v.X();
tcs[LOLFT].v = tcs[LORGT].v = tcs[UPLFT].v = tcs[UPRGT].v = v.Z();
tcs[LOLFT].u = tcs[LORGT].u = tcs[UPLFT].u = tcs[UPRGT].u = v.X;
tcs[LOLFT].v = tcs[LORGT].v = tcs[UPLFT].v = tcs[UPRGT].v = v.Z;
gl_RenderState.EnableTextureMatrix(true);
gl_RenderState.mTextureMatrix.computeNormalMatrix(gl_RenderState.mViewMatrix);
@ -414,6 +413,7 @@ void GLWall::RenderTranslucentWall()
//==========================================================================
void GLWall::Draw(int pass)
{
gl_RenderState.SetNormal(glseg.Normal());
switch (pass)
{
case GLPASS_LIGHTSONLY:

View file

@ -0,0 +1,99 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2016 Alexey Lysiuk
// 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/
//
//--------------------------------------------------------------------------
//
//
// Fast approXimate Anti-Aliasing (FXAA) post-processing
//
#include "gl/system/gl_system.h"
#include "gl/shaders/gl_fxaashader.h"
EXTERN_CVAR(Int, gl_fxaa)
void FFXAALumaShader::Bind()
{
if (!mShader)
{
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/fxaa.fp", "#define FXAA_LUMA_PASS\n", 330);
mShader.SetFragDataLocation(0, "FragColor");
mShader.Link("shaders/glsl/fxaa");
mShader.SetAttribLocation(0, "PositionInProjection");
InputTexture.Init(mShader, "InputTexture");
}
mShader.Bind();
}
static int GetMaxVersion()
{
return gl.glslversion >= 4.f ? 400 : 330;
}
static FString GetDefines()
{
int quality;
switch (gl_fxaa)
{
default:
case FFXAAShader::Low: quality = 10; break;
case FFXAAShader::Medium: quality = 12; break;
case FFXAAShader::High: quality = 29; break;
case FFXAAShader::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 FFXAAShader::Bind()
{
assert(gl_fxaa > 0 && gl_fxaa < Count);
FShaderProgram &shader = mShaders[gl_fxaa];
if (!shader)
{
const FString defines = GetDefines();
const int maxVersion = GetMaxVersion();
shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
shader.Compile(FShaderProgram::Fragment, "shaders/glsl/fxaa.fp", defines, maxVersion);
shader.SetFragDataLocation(0, "FragColor");
shader.Link("shaders/glsl/fxaa");
shader.SetAttribLocation(0, "PositionInProjection");
InputTexture.Init(shader, "InputTexture");
ReciprocalResolution.Init(shader, "ReciprocalResolution");
}
shader.Bind();
}

View file

@ -0,0 +1,66 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2016 Alexey Lysiuk
// 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/
//
//--------------------------------------------------------------------------
//
//
// Fast approXimate Anti-Aliasing (FXAA) post-processing
//
#ifndef __GL_FXAASHADER_H__
#define __GL_FXAASHADER_H__
#include "gl_shaderprogram.h"
class FFXAALumaShader
{
public:
void Bind();
FBufferedUniform1i InputTexture;
private:
FShaderProgram mShader;
};
class FFXAAShader
{
public:
enum Quality
{
None,
Low,
Medium,
High,
Extreme,
Count
};
void Bind();
FBufferedUniform1i InputTexture;
FBufferedUniform2f ReciprocalResolution;
private:
FShaderProgram mShaders[Count];
};
#endif // __GL_FXAASHADER_H__

View file

@ -0,0 +1,60 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2016 Christopher Bruns
// 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/
//
//--------------------------------------------------------------------------
//
/*
** gl_3dRowshader.cpp
** Copy rendered texture to back buffer, possibly with gamma correction
** while interleaving rows from two independent viewpoint textures,
** representing the left-eye and right-eye views.
**
*/
#include "gl/system/gl_system.h"
#include "files.h"
#include "m_swap.h"
#include "v_video.h"
#include "gl/gl_functions.h"
#include "vectors.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_present3dRowshader.h"
void FPresent3DRowShader::Bind()
{
if (!mShader)
{
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquadscale.vp", "", 330);
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/present_row3d.fp", "", 330);
mShader.SetFragDataLocation(0, "FragColor");
mShader.Link("shaders/glsl/presentRow3d");
mShader.SetAttribLocation(0, "PositionInProjection");
mShader.SetAttribLocation(1, "UV");
LeftEyeTexture.Init(mShader, "LeftEyeTexture");
RightEyeTexture.Init(mShader, "RightEyeTexture");
InvGamma.Init(mShader, "InvGamma");
Contrast.Init(mShader, "Contrast");
Brightness.Init(mShader, "Brightness");
Scale.Init(mShader, "UVScale");
VerticalPixelOffset.Init(mShader, "VerticalPixelOffset");
}
mShader.Bind();
}

View file

@ -0,0 +1,51 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2015 Christopher Bruns
// 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/
//
//--------------------------------------------------------------------------
//
/*
** gl_present3dRowshader.h
** Final composition and present shader for row-interleaved stereoscopic 3D mode
**
*/
#ifndef GL_PRESENT3DROWSHADER_H_
#define GL_PRESENT3DROWSHADER_H_
#include "gl_shaderprogram.h"
class FPresent3DRowShader
{
public:
void Bind();
FBufferedUniformSampler LeftEyeTexture;
FBufferedUniformSampler RightEyeTexture;
FBufferedUniform1f InvGamma;
FBufferedUniform1f Contrast;
FBufferedUniform1f Brightness;
FBufferedUniform2f Scale;
FBufferedUniform1i VerticalPixelOffset;
private:
FShaderProgram mShader;
};
// GL_PRESENT3DROWSHADER_H_
#endif

View file

@ -179,6 +179,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
glBindAttribLocation(hShader, VATTR_TEXCOORD, "aTexCoord");
glBindAttribLocation(hShader, VATTR_COLOR, "aColor");
glBindAttribLocation(hShader, VATTR_VERTEX2, "aVertex2");
glBindAttribLocation(hShader, VATTR_NORMAL, "aNormal");
glBindFragDataLocation(hShader, 0, "FragColor");
glBindFragDataLocation(hShader, 1, "FragData");
@ -244,6 +245,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
texturematrix_index = glGetUniformLocation(hShader, "TextureMatrix");
vertexmatrix_index = glGetUniformLocation(hShader, "uQuadVertices");
texcoordmatrix_index = glGetUniformLocation(hShader, "uQuadTexCoords");
normalviewmatrix_index = glGetUniformLocation(hShader, "NormalViewMatrix");
normalmodelmatrix_index = glGetUniformLocation(hShader, "NormalModelMatrix");
quadmode_index = glGetUniformLocation(hShader, "uQuadMode");
if (!gl.legacyMode && !(gl.flags & RFL_SHADER_STORAGE_BUFFER))
@ -332,14 +335,14 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP
//
//==========================================================================
void FShader::ApplyMatrices(VSMatrix *proj, VSMatrix *view)
void FShader::ApplyMatrices(VSMatrix *proj, VSMatrix *view, VSMatrix *norm)
{
Bind();
glUniformMatrix4fv(projectionmatrix_index, 1, false, proj->get());
glUniformMatrix4fv(viewmatrix_index, 1, false, view->get());
glUniformMatrix4fv(normalviewmatrix_index, 1, false, norm->get());
}
//==========================================================================
//
//
@ -601,23 +604,26 @@ EXTERN_CVAR(Int, gl_fuzztype)
void FShaderCollection::ApplyMatrices(VSMatrix *proj, VSMatrix *view)
{
VSMatrix norm;
norm.computeNormalMatrix(*view);
for (int i = 0; i < 4; i++)
{
mTextureEffects[i]->ApplyMatrices(proj, view);
mTextureEffectsNAT[i]->ApplyMatrices(proj, view);
mTextureEffects[i]->ApplyMatrices(proj, view, &norm);
mTextureEffectsNAT[i]->ApplyMatrices(proj, view, &norm);
}
mTextureEffects[4]->ApplyMatrices(proj, view);
mTextureEffects[4]->ApplyMatrices(proj, view, &norm);
if (gl_fuzztype != 0)
{
mTextureEffects[4 + gl_fuzztype]->ApplyMatrices(proj, view);
mTextureEffects[4 + gl_fuzztype]->ApplyMatrices(proj, view, &norm);
}
for (unsigned i = 12; i < mTextureEffects.Size(); i++)
{
mTextureEffects[i]->ApplyMatrices(proj, view);
mTextureEffects[i]->ApplyMatrices(proj, view, &norm);
}
for (int i = 0; i < MAX_EFFECTS; i++)
{
mEffectShaders[i]->ApplyMatrices(proj, view);
mEffectShaders[i]->ApplyMatrices(proj, view, &norm);
}
}

View file

@ -286,7 +286,9 @@ class FShader
int lights_index;
int projectionmatrix_index;
int viewmatrix_index;
int normalviewmatrix_index;
int modelmatrix_index;
int normalmodelmatrix_index;
int texturematrix_index;
public:
int vertexmatrix_index;
@ -319,7 +321,7 @@ public:
bool Bind();
unsigned int GetHandle() const { return hShader; }
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
void ApplyMatrices(VSMatrix *proj, VSMatrix *view, VSMatrix *norm);
};

View file

@ -0,0 +1,124 @@
/*
** gl_interleaved3d.cpp
** Interleaved image stereoscopic 3D modes for GZDoom
**
**---------------------------------------------------------------------------
** Copyright 2016 Christopher Bruns
** 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 "gl_interleaved3d.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/shaders/gl_present3dRowshader.h"
EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Bool, fullscreen)
EXTERN_CVAR(Int, win_y) // pixel position of top of display window
namespace s3d {
/* static */
const RowInterleaved3D& RowInterleaved3D::getInstance(float ipd)
{
static RowInterleaved3D instance(ipd);
return instance;
}
RowInterleaved3D::RowInterleaved3D(double ipdMeters)
: TopBottom3D(ipdMeters)
{}
void RowInterleaved3D::Present() const
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
// Bind each eye texture, for composition in the shader
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->mBuffers->BindEyeTexture(1, 1);
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glActiveTexture(GL_TEXTURE1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
const GL_IRECT& box = GLRenderer->mOutputLetterbox;
glViewport(box.left, box.top, box.width, box.height);
bool applyGamma = true;
GLRenderer->mPresent3dRowShader->Bind();
GLRenderer->mPresent3dRowShader->LeftEyeTexture.Set(0);
GLRenderer->mPresent3dRowShader->RightEyeTexture.Set(1);
if (!applyGamma || GLRenderer->framebuffer->IsHWGammaActive())
{
GLRenderer->mPresent3dRowShader->InvGamma.Set(1.0f);
GLRenderer->mPresent3dRowShader->Contrast.Set(1.0f);
GLRenderer->mPresent3dRowShader->Brightness.Set(0.0f);
}
else
{
GLRenderer->mPresent3dRowShader->InvGamma.Set(1.0f / clamp<float>(Gamma, 0.1f, 4.f));
GLRenderer->mPresent3dRowShader->Contrast.Set(clamp<float>(vid_contrast, 0.1f, 3.f));
GLRenderer->mPresent3dRowShader->Brightness.Set(clamp<float>(vid_brightness, -0.8f, 0.8f));
}
GLRenderer->mPresent3dRowShader->Scale.Set(
GLRenderer->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(),
GLRenderer->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight());
// Compute absolute offset from top of screen to top of current display window
// because we need screen-relative, not window-relative, scan line parity
int windowVOffset = 0;
#ifdef _WIN32
if (! fullscreen) {
I_SaveWindowedPos(); // update win_y CVAR
windowVOffset = win_y;
}
#endif // _WIN32
GLRenderer->mPresent3dRowShader->VerticalPixelOffset.Set(
windowVOffset // fixme: vary with window location
+ box.height % 2 // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
);
GLRenderer->RenderScreenQuad();
}
} /* namespace s3d */

View file

@ -0,0 +1,60 @@
/*
** gl_interleaved3d.h
** Interleaved stereoscopic 3D modes for GZDoom
**
**---------------------------------------------------------------------------
** Copyright 2016 Christopher Bruns
** 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.
**---------------------------------------------------------------------------
**
**
*/
#ifndef GL_INTERLEAVED3D_H_
#define GL_INTERLEAVED3D_H_
#include "gl_stereo3d.h"
#include "gl_stereo_leftright.h"
#include "gl_sidebyside3d.h"
#include "gl/system/gl_system.h"
#include "gl/renderer/gl_renderstate.h"
class FPresent3DRowShader;
namespace s3d {
class RowInterleaved3D : public TopBottom3D
{
public:
static const RowInterleaved3D& getInstance(float ipd);
RowInterleaved3D(double ipdMeters);
void Present() const override;
};
} /* namespace s3d */
#endif /* GL_INTERLEAVED3D_H_ */

View file

@ -108,4 +108,43 @@ void SideBySideFull::AdjustPlayerSprites() const /* override */
gl_RenderState.ApplyMatrices();
}
/* static */
const TopBottom3D& TopBottom3D::getInstance(float ipd)
{
static TopBottom3D instance(ipd);
return instance;
}
void TopBottom3D::Present() const
{
GLRenderer->mBuffers->BindOutputFB();
GLRenderer->ClearBorders();
// Compute screen regions to use for left and right eye views
int topHeight = GLRenderer->mOutputLetterbox.height / 2;
int bottomHeight = GLRenderer->mOutputLetterbox.height - topHeight;
GL_IRECT topHalfScreen = GLRenderer->mOutputLetterbox;
topHalfScreen.height = topHeight;
topHalfScreen.top = topHeight;
GL_IRECT bottomHalfScreen = GLRenderer->mOutputLetterbox;
bottomHalfScreen.height = bottomHeight;
bottomHalfScreen.top = 0;
GLRenderer->mBuffers->BindEyeTexture(0, 0);
GLRenderer->DrawPresentTexture(topHalfScreen, true);
GLRenderer->mBuffers->BindEyeTexture(1, 0);
GLRenderer->DrawPresentTexture(bottomHalfScreen, true);
}
// AdjustViewports() is called from within FLGRenderer::SetOutputViewport(...)
void TopBottom3D::AdjustViewports() const
{
// Change size of renderbuffer, and align to screen
GLRenderer->mSceneViewport.height /= 2;
GLRenderer->mSceneViewport.top /= 2;
GLRenderer->mScreenViewport.height /= 2;
GLRenderer->mScreenViewport.top /= 2;
}
} /* namespace s3d */

View file

@ -88,6 +88,14 @@ private:
SBSFRightEyePose rightEye;
};
class TopBottom3D : public SideBySideSquished
{
public:
static const TopBottom3D& getInstance(float ipd);
TopBottom3D(double ipdMeters) : SideBySideSquished(ipdMeters) {}
void Present() const override;
virtual void AdjustViewports() const override;
};
} /* namespace s3d */

View file

@ -30,6 +30,7 @@
#include "gl/stereo3d/gl_anaglyph.h"
#include "gl/stereo3d/gl_quadstereo.h"
#include "gl/stereo3d/gl_sidebyside3d.h"
#include "gl/stereo3d/gl_interleaved3d.h"
#include "gl/system/gl_cvars.h"
// Set up 3D-specific console variables:
@ -100,6 +101,12 @@ const Stereo3DMode& Stereo3DMode::getCurrentMode()
setCurrentMode(AmberBlue::getInstance(vr_ipd));
break;
// TODO: 10: HTC Vive/OpenVR
case 11:
setCurrentMode(TopBottom3D::getInstance(vr_ipd));
break;
case 12:
setCurrentMode(RowInterleaved3D::getInstance(vr_ipd));
break;
case 0:
default:
setCurrentMode(MonoView::getInstance());

View file

@ -189,7 +189,9 @@ void OpenGLFrameBuffer::Update()
int clientHeight = GetClientHeight();
if (clientWidth > 0 && clientHeight > 0 && (Width != clientWidth || Height != clientHeight))
{
Resize(clientWidth, clientHeight);
// Do not call Resize here because it's only for software canvases
Pitch = Width = clientWidth;
Height = clientHeight;
V_OutputResized(Width, Height);
GLRenderer->mVBO->OutputResized(Width, Height);
}
@ -209,13 +211,13 @@ void OpenGLFrameBuffer::Swap()
{
Finish.Reset();
Finish.Clock();
glFinish();
if (needsetgamma)
{
//DoSetGamma();
needsetgamma = false;
}
SwapBuffers();
glFinish();
Finish.Unclock();
swapped = true;
FHardwareTexture::UnbindAll();

View file

@ -46,6 +46,11 @@ inline short LittleShort(int x)
return OSSwapLittleToHostInt16((uint16_t)x);
}
inline unsigned short LittleShort(unsigned int x)
{
return OSSwapLittleToHostInt16((uint16_t)x);
}
inline int LittleLong(int x)
{
return OSSwapLittleToHostInt32((uint32_t)x);
@ -56,6 +61,16 @@ inline unsigned int LittleLong(unsigned int x)
return OSSwapLittleToHostInt32(x);
}
inline int LittleLong(long x)
{
return OSSwapLittleToHostInt32((uint32_t)x);
}
inline unsigned int LittleLong(unsigned long x)
{
return OSSwapLittleToHostInt32((uint32_t)x);
}
inline short BigShort(short x)
{
return (short)OSSwapBigToHostInt16((uint16_t)x);

View file

@ -717,7 +717,11 @@ void M_Drawer (void)
if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off)
{
if (DMenu::CurrentMenu->DimAllowed()) screen->Dim(fade);
if (DMenu::CurrentMenu->DimAllowed())
{
screen->Dim(fade);
V_SetBorderNeedRefresh();
}
DMenu::CurrentMenu->Drawer();
}
}

View file

@ -507,6 +507,21 @@ xx(Alphaceiling)
xx(Renderstylefloor)
xx(Renderstyleceiling)
xx(Waterzone)
xx(portal_ceil_alpha)
xx(portal_ceil_blocksound)
xx(portal_ceil_disabled)
xx(portal_ceil_nopass)
xx(portal_ceil_norender)
xx(portal_ceil_overlaytype)
xx(portal_ceil_useglobaltex)
xx(portal_floor_alpha)
xx(portal_floor_blocksound)
xx(portal_floor_disabled)
xx(portal_floor_nopass)
xx(portal_floor_norender)
xx(portal_floor_overlaytype)
xx(portal_floor_useglobaltex)
xx(offsetx_top)
xx(offsety_top)

View file

@ -754,7 +754,7 @@ void ACSStringPool::ReadStrings(FSerializer &file, const char *key)
unsigned bucketnum = h % NUM_BUCKETS;
Pool[ii].Hash = h;
Pool[ii].Next = PoolBuckets[bucketnum];
PoolBuckets[bucketnum] = i;
PoolBuckets[bucketnum] = ii;
}
file.EndObject();
}
@ -4379,10 +4379,11 @@ enum EACSFunctions
ACSF_CheckClass = 200,
ACSF_DamageActor, // [arookas]
ACSF_SetActorFlag,
ACSF_SetTranslation,
// ZDaemon
ACSF_GetTeamScore = 19620, // (int team)
ACSF_SetTeamScore, // (int team, int value)
ACSF_SetTeamScore, // (int team, int value
};
int DLevelScript::SideFromID(int id, int side)
@ -6002,6 +6003,26 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
return count;
}
case ACSF_SetTranslation:
{
int tid = args[0];
const char *trname = FBehavior::StaticLookupString(args[1]);
if (tid == 0)
{
if (activator != nullptr)
activator->SetTranslation(trname);
}
else
{
FActorIterator it(tid);
while ((actor = it.Next()) != nullptr)
{
actor->SetTranslation(trname);
}
}
return 1;
}
default:
break;
}

View file

@ -342,7 +342,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
ceilingheight = sec->FindLowestCeilingPoint(&spot2);
floor->m_FloorDestDist = sec->floorplane.PointToDist(spot, newheight);
if (sec->floorplane.ZatPointDist(spot2, floor->m_FloorDestDist) > ceilingheight)
floor->m_FloorDestDist = sec->floorplane.PointToDist(spot2, floortype == ceilingheight - height);
floor->m_FloorDestDist = sec->floorplane.PointToDist(spot2, ceilingheight - height);
break;
case DFloor::floorRaiseToHighest:

View file

@ -70,6 +70,7 @@
#include "p_spec.h"
#include "p_checkposition.h"
#include "serializer.h"
#include "r_utility.h"
// MACROS ------------------------------------------------------------------
@ -1040,11 +1041,11 @@ bool AActor::IsInsideVisibleAngles() const
if (players[consoleplayer].camera == nullptr)
return true;
DAngle anglestart = VisibleStartAngle.Normalized180();
DAngle angleend = VisibleEndAngle.Normalized180();
DAngle pitchstart = VisibleStartPitch.Normalized180();
DAngle pitchend = VisibleEndPitch.Normalized180();
DAngle anglestart = VisibleStartAngle;
DAngle angleend = VisibleEndAngle;
DAngle pitchstart = VisibleStartPitch;
DAngle pitchend = VisibleEndPitch;
if (anglestart > angleend)
{
DAngle temp = anglestart;
@ -1052,28 +1053,26 @@ bool AActor::IsInsideVisibleAngles() const
angleend = temp;
}
if (pitchstart > angleend)
if (pitchstart > pitchend)
{
DAngle temp = pitchstart;
pitchstart = pitchend;
pitchend = temp;
}
player_t* pPlayer = players[consoleplayer].camera->player;
AActor *mo = players[consoleplayer].camera;
if (pPlayer && pPlayer->mo)
if (mo != nullptr)
{
AActor *mo = pPlayer->mo;
DVector3 diffang = Vec3To(mo);
DVector3 diffang = ViewPos - Pos();
DAngle to = diffang.Angle();
if (!(renderflags & RF_ABSMASKANGLE))
to = deltaangle(Angles.Yaw, to);
// Note that this check is inversed due to only being able to vectorize
// from one way (this actor to the player). It still means to pass
// if the player is within the visible angles.
if ((to <= anglestart || to >= angleend))
if ((to >= anglestart && to <= angleend))
{
to = diffang.Pitch();
if (!(renderflags & RF_ABSMASKPITCH))
@ -1324,6 +1323,9 @@ bool AActor::Massacre ()
if (health > 0)
{
auto f = flags;
auto f2 = flags2;
flags |= MF_SHOOTABLE;
flags2 &= ~(MF2_DORMANT|MF2_INVULNERABLE);
do
@ -1332,6 +1334,12 @@ bool AActor::Massacre ()
P_DamageMobj (this, NULL, NULL, TELEFRAG_DAMAGE, NAME_Massacre);
}
while (health != prevhealth && health > 0); //abort if the actor wasn't hurt.
if (health > 0)
{
// restore flags if this did not kill the monster.
flags = f;
flags2 = f2;
}
return health <= 0;
}
return false;
@ -3518,7 +3526,7 @@ void AActor::Tick ()
sector_t *sec = node->m_sector;
DVector2 scrollv;
if (level.Scrolls.Size() > (sec-sectors))
if (level.Scrolls.Size() > unsigned(sec-sectors))
{
scrollv = level.Scrolls[sec - sectors];
}
@ -6517,6 +6525,23 @@ int AActor::ApplyDamageFactor(FName damagetype, int damage) const
}
void AActor::SetTranslation(const char *trname)
{
if (*trname == 0)
{
// an empty string resets to the default
Translation = GetDefault()->Translation;
return;
}
int tnum = R_FindCustomTranslation(trname);
if (tnum >= 0)
{
Translation = tnum;
}
// silently ignore if the name does not exist, this would create some insane message spam otherwise.
}
//----------------------------------------------------------------------------
//
// DropItem handling

View file

@ -1049,6 +1049,25 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags)
return 0;
}
//---------------------------------------------------------------------------
//
// PROC OverlayID
// Because non-action functions cannot acquire the ID of the overlay...
//---------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, OverlayID)
{
PARAM_ACTION_PROLOGUE;
if (ACTION_CALL_FROM_PSPRITE())
{
ACTION_RETURN_INT(stateinfo->mPSPIndex);
}
ACTION_RETURN_INT(0);
}
//---------------------------------------------------------------------------
//
// PROC A_Lower

View file

@ -642,6 +642,11 @@ static void ReadOnePlayer(FSerializer &arc, bool skipload)
{
CopyPlayer(&players[i], &playerTemp, name);
}
else
{
// we need the player actor, so that G_FinishTravel can destroy it later.
players[i].mo = playerTemp.mo;
}
}
else
{
@ -755,6 +760,13 @@ static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayers
}
}
}
else
{
for (i = 0; i < MAXPLAYERS; ++i)
{
players[i].mo = playertemp[i].mo;
}
}
delete[] tempPlayerUsed;
delete[] playertemp;

View file

@ -259,6 +259,7 @@ DScroller::DScroller (EScroll type, double dx, double dy,
m_Accel = accel;
m_Parts = scrollpos;
m_vdx = m_vdy = 0;
m_LastHeight = 0;
if ((m_Control = control) != -1)
m_LastHeight =
sectors[control].CenterFloor () + sectors[control].CenterCeiling ();
@ -342,6 +343,7 @@ DScroller::DScroller (double dx, double dy, const line_t *l,
m_vdx = m_vdy = 0;
m_Accel = accel;
m_Parts = scrollpos;
m_LastHeight = 0;
if ((m_Control = control) != -1)
m_LastHeight = sectors[control].CenterFloor() + sectors[control].CenterCeiling();
m_Affectee = int(l->sidedef[0] - sides);

View file

@ -1568,6 +1568,60 @@ public:
tagstring = CheckString(key);
break;
case NAME_portal_ceil_alpha:
sec->planes[sector_t::ceiling].alpha = CheckFloat(key);
break;
case NAME_portal_ceil_blocksound:
Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_BLOCKSOUND, key);
break;
case NAME_portal_ceil_disabled:
Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_DISABLED, key);
break;
case NAME_portal_ceil_nopass:
Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_NOPASS, key);
break;
case NAME_portal_ceil_norender:
Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_NORENDER, key);
break;
case NAME_portal_ceil_overlaytype:
if (!stricmp(CheckString(key), "translucent")) sec->planes[sector_t::ceiling].Flags &= ~PLANEF_ADDITIVE;
else if (!stricmp(CheckString(key), "additive")) sec->planes[sector_t::ceiling].Flags |= PLANEF_ADDITIVE;
break;
case NAME_portal_floor_alpha:
sec->planes[sector_t::floor].alpha = CheckFloat(key);
break;
case NAME_portal_floor_blocksound:
Flag(sec->planes[sector_t::floor].Flags, PLANEF_BLOCKSOUND, key);
break;
case NAME_portal_floor_disabled:
Flag(sec->planes[sector_t::floor].Flags, PLANEF_DISABLED, key);
break;
case NAME_portal_floor_nopass:
Flag(sec->planes[sector_t::floor].Flags, PLANEF_NOPASS, key);
break;
case NAME_portal_floor_norender:
Flag(sec->planes[sector_t::floor].Flags, PLANEF_NORENDER, key);
break;
case NAME_portal_floor_overlaytype:
if (!stricmp(CheckString(key), "translucent")) sec->planes[sector_t::floor].Flags &= ~PLANEF_ADDITIVE;
else if (!stricmp(CheckString(key), "additive")) sec->planes[sector_t::floor].Flags |= PLANEF_ADDITIVE;
break;
// These two are used by Eternity for something I do not understand.
//case NAME_portal_ceil_useglobaltex:
//case NAME_portal_floor_useglobaltex:
default:
break;
}

View file

@ -609,26 +609,26 @@ void FRemapTable::AddToTranslation(const char *range)
//
//----------------------------------------------------------------------------
int FRemapTable::StoreTranslation()
int FRemapTable::StoreTranslation(int slot)
{
unsigned int i;
for (i = 0; i < translationtables[TRANSLATION_Decorate].Size(); i++)
for (i = 0; i < translationtables[slot].Size(); i++)
{
if (*this == *translationtables[TRANSLATION_Decorate][i])
if (*this == *translationtables[slot][i])
{
// A duplicate of this translation already exists
return TRANSLATION(TRANSLATION_Decorate, i);
return TRANSLATION(slot, i);
}
}
if (translationtables[TRANSLATION_Decorate].Size() >= MAX_DECORATE_TRANSLATIONS)
if (translationtables[slot].Size() >= MAX_DECORATE_TRANSLATIONS)
{
I_Error("Too many DECORATE translations");
}
FRemapTable *newtrans = new FRemapTable;
*newtrans = *this;
i = translationtables[TRANSLATION_Decorate].Push(newtrans);
return TRANSLATION(TRANSLATION_Decorate, i);
i = translationtables[slot].Push(newtrans);
return TRANSLATION(slot, i);
}
@ -1197,3 +1197,90 @@ void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayer
R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL, NULL);
}
//----------------------------------------------------------------------------
//
//
//
//----------------------------------------------------------------------------
static TMap<FName, int> customTranslationMap;
int R_FindCustomTranslation(const char *name)
{
if (name == nullptr)
{
return -1;
}
// Ice is a special case which will remain in its original slot.
if (!stricmp(name, "Ice"))
{
return TRANSLATION(TRANSLATION_Standard, 7);
}
int *t = customTranslationMap.CheckKey(FName(name, true));
return (t != nullptr)? *t : -1;
}
//----------------------------------------------------------------------------
//
//
//
//----------------------------------------------------------------------------
void R_ParseTrnslate()
{
customTranslationMap.Clear();
translationtables[TRANSLATION_Custom].Clear();
int lump;
int lastlump = 0;
while (-1 != (lump = Wads.FindLump("TRNSLATE", &lastlump)))
{
FScanner sc(lump);
while (sc.GetToken())
{
sc.TokenMustBe(TK_Identifier);
FName newtrans = sc.String;
FRemapTable *base = nullptr;
if (sc.CheckToken(':'))
{
sc.MustGetAnyToken();
if (sc.TokenType == TK_IntConst)
{
int max = 6;
if (sc.Number < 0 || sc.Number > max)
{
sc.ScriptError("Translation must be in the range [0,%d]", max);
}
base = translationtables[TRANSLATION_Standard][sc.Number];
}
else if (sc.TokenType == TK_Identifier)
{
int tnum = R_FindCustomTranslation(sc.String);
if (tnum == -1)
{
sc.ScriptError("Base translation '%s' not found in '%s'", sc.String, newtrans.GetChars());
}
base = translationtables[GetTranslationType(tnum)][GetTranslationIndex(tnum)];
}
else
{
// error out.
sc.TokenMustBe(TK_Identifier);
}
}
sc.MustGetToken('=');
FRemapTable NewTranslation;
if (base != nullptr) NewTranslation = *base;
else NewTranslation.MakeIdentity();
do
{
sc.MustGetToken(TK_StringConst);
NewTranslation.AddToTranslation(sc.String);
} while (sc.CheckToken(','));
int trans = NewTranslation.StoreTranslation(TRANSLATION_Custom);
customTranslationMap[newtrans] = trans;
}
}
}

View file

@ -19,6 +19,7 @@ enum
TRANSLATION_Decorate,
TRANSLATION_Blood,
TRANSLATION_RainPillar,
TRANSLATION_Custom,
NUM_TRANSLATION_TABLES
};
@ -42,7 +43,7 @@ struct FRemapTable
void AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2);
void AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2);
void AddToTranslation(const char * range);
int StoreTranslation();
int StoreTranslation(int slot);
BYTE *Remap; // For the software renderer
PalEntry *Palette; // The ideal palette this maps to
@ -109,6 +110,9 @@ extern TArray<PalEntry> BloodTranslationColors;
int CreateBloodTranslation(PalEntry color);
int R_FindCustomTranslation(const char *name);
void R_ParseTrnslate();
#endif // __R_TRANSLATE_H

View file

@ -321,23 +321,31 @@ protected:
}
bool WriteDouble(double d) {
if (internal::Double(d).IsNanOrInf()) {
if (!(writeFlags & kWriteNanAndInfFlag))
return false;
if (internal::Double(d).IsNan()) {
PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
return true;
}
if (internal::Double(d).Sign()) {
PutReserve(*os_, 9);
PutUnsafe(*os_, '-');
}
else
PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
return true;
bool ret = true;
if (internal::Double(d).IsNanOrInf()) {
if (!(writeFlags & kWriteNanAndInfFlag))
{
// if we abort here, the writer is left in a broken state, unable to recover, so better write a 0 in addition to returning an error.
ret = false;
d = 0;
}
else
{
if (internal::Double(d).IsNan()) {
PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
return true;
}
if (internal::Double(d).Sign()) {
PutReserve(*os_, 9);
PutUnsafe(*os_, '-');
}
else
PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
return true;
}
}
char buffer[25];
@ -345,7 +353,7 @@ protected:
PutReserve(*os_, static_cast<size_t>(end - buffer));
for (char* p = buffer; p != end; ++p)
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
return true;
return ret;
}
bool WriteString(const Ch* str, SizeType length) {

View file

@ -51,6 +51,7 @@
#include "i_system.h"
#include "d_player.h"
#include "serializer.h"
#include "v_text.h"
// MACROS ------------------------------------------------------------------
@ -326,6 +327,99 @@ void S_HashSounds ()
}
}
//==========================================================================
//
// S_CheckIntegrity
//
// Scans the entire sound list and looks for recursive definitions.
//==========================================================================
static bool S_CheckSound(sfxinfo_t *startsfx, sfxinfo_t *sfx, TArray<sfxinfo_t *> &chain)
{
sfxinfo_t *me = sfx;
bool success = true;
unsigned siz = chain.Size();
if (sfx->bPlayerReserve)
{
return true;
}
// There is a bad link in here, but let's report it only for the sound that contains the broken definition.
// Once that sound has been disabled this one will work again.
if (chain.Find(sfx) < chain.Size())
{
return true;
}
chain.Push(sfx);
if (me->bRandomHeader)
{
const FRandomSoundList *list = &S_rnd[me->link];
for (int i = 0; i < list->NumSounds; ++i)
{
auto rsfx = &S_sfx[list->Sounds[i]];
if (rsfx == startsfx)
{
Printf(TEXTCOLOR_RED "recursive sound $random found for %s:\n", startsfx->name.GetChars());
success = false;
for (unsigned i = 1; i<chain.Size(); i++)
{
Printf(TEXTCOLOR_ORANGE " -> %s\n", chain[i]->name.GetChars());
}
}
else
{
success &= S_CheckSound(startsfx, rsfx, chain);
}
}
}
else if (me->link != sfxinfo_t::NO_LINK)
{
me = &S_sfx[me->link];
if (me == startsfx)
{
Printf(TEXTCOLOR_RED "recursive sound $alias found for %s:\n", startsfx->name.GetChars());
success = false;
for (unsigned i = 1; i<chain.Size(); i++)
{
Printf(TEXTCOLOR_ORANGE " -> %s\n", chain[i]->name.GetChars());
}
chain.Resize(siz);
}
else
{
success &= S_CheckSound(startsfx, me, chain);
}
}
chain.Pop();
return success;
}
void S_CheckIntegrity()
{
TArray<sfxinfo_t *> chain;
TArray<bool> broken;
broken.Resize(S_sfx.Size());
memset(&broken[0], 0, sizeof(bool)*S_sfx.Size());
for (unsigned i = 0; i < S_sfx.Size(); i++)
{
auto &sfx = S_sfx[i];
broken[i] = !S_CheckSound(&sfx, &sfx, chain);
}
for (unsigned i = 0; i < S_sfx.Size(); i++)
{
if (broken[i])
{
auto &sfx = S_sfx[i];
Printf(TEXTCOLOR_RED "Sound %s has been disabled\n", sfx.name.GetChars());
sfx.bRandomHeader = false;
sfx.link = 0; // link to the empty sound.
}
}
}
//==========================================================================
//
// S_PickReplacement
@ -334,13 +428,12 @@ void S_HashSounds ()
// is not the head of a random list, then the sound passed is returned.
//==========================================================================
int S_PickReplacement (int refid)
int S_PickReplacement(int refid)
{
if (S_sfx[refid].bRandomHeader)
while (S_sfx[refid].bRandomHeader)
{
const FRandomSoundList *list = &S_rnd[S_sfx[refid].link];
return list->Sounds[pr_randsound() % list->NumSounds];
refid = list->Sounds[pr_randsound() % list->NumSounds];
}
return refid;
}
@ -941,6 +1034,7 @@ void S_ParseSndInfo (bool redefine)
S_ShrinkPlayerSoundLists ();
sfx_empty = Wads.CheckNumForName ("dsempty", ns_sounds);
S_CheckIntegrity();
}
//==========================================================================
@ -961,6 +1055,7 @@ void S_AddLocalSndInfo(int lump)
}
S_ShrinkPlayerSoundLists ();
S_CheckIntegrity();
}
//==========================================================================

View file

@ -522,18 +522,19 @@ void S_CacheSound (sfxinfo_t *sfx)
{
return;
}
else if (sfx->bRandomHeader)
sfxinfo_t *orig = sfx;
while (!sfx->bRandomHeader && sfx->link != sfxinfo_t::NO_LINK)
{
S_CacheRandomSound (sfx);
sfx = &S_sfx[sfx->link];
}
if (sfx->bRandomHeader)
{
S_CacheRandomSound(sfx);
}
else
{
while (sfx->link != sfxinfo_t::NO_LINK)
{
sfx = &S_sfx[sfx->link];
}
S_LoadSound(sfx);
sfx->bUsed = true;
S_LoadSound (sfx);
}
}
}
@ -753,8 +754,8 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector,
if (type == SOURCE_Actor && actor != NULL)
{
vel->X = float(actor->Vel.X * TICRATE);
vel->Y = float(actor->Vel.Y * TICRATE);
vel->Z = float(actor->Vel.Z * TICRATE);
vel->Y = float(actor->Vel.Z * TICRATE);
vel->Z = float(actor->Vel.Y * TICRATE);
}
else
{

View file

@ -215,8 +215,14 @@ struct FWriter
void Double(double k)
{
if (mWriter1) mWriter1->Double(k);
else if (mWriter2) mWriter2->Double(k);
if (mWriter1)
{
mWriter1->Double(k);
}
else if (mWriter2)
{
mWriter2->Double(k);
}
}
};
@ -815,7 +821,6 @@ void FSerializer::WriteObjects()
for (unsigned i = 0; i < w->mDObjects.Size(); i++)
{
auto obj = w->mDObjects[i];
player_t *player;
BeginObject(nullptr);
w->Key("classtype");
@ -1294,7 +1299,7 @@ FSerializer &SerializePointer(FSerializer &arc, const char *key, T *&value, T **
assert(base != nullptr);
if (arc.isReading() || !arc.w->inObject() || defval == nullptr || value != *defval)
{
ptrdiff_t vv = value == nullptr ? -1 : value - base;
int64_t vv = value == nullptr ? -1 : value - base;
Serialize(arc, key, vv, nullptr);
value = vv < 0 ? nullptr : base + vv;
}

View file

@ -211,11 +211,11 @@ bool MUSSong2::CheckDone()
void MUSSong2::Precache()
{
TArray<WORD> work(MusHeader->NumInstruments);
TArray<WORD> work(LittleShort(MusHeader->NumInstruments));
const BYTE *used = (BYTE *)MusHeader + sizeof(MUSHeader) / sizeof(BYTE);
int i, k;
for (i = k = 0; i < MusHeader->NumInstruments; ++i)
for (i = k = 0; i < LittleShort(MusHeader->NumInstruments); ++i)
{
BYTE instr = used[k++];
WORD val;

View file

@ -288,7 +288,7 @@ static void FinishThingdef()
if (func == nullptr)
{
VMFunctionBuilder buildit;
VMFunctionBuilder buildit(true);
assert(tcall->Proto != nullptr);

View file

@ -3322,6 +3322,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslucent)
return 0;
}
//===========================================================================
//
// A_SetRenderStyle
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRenderStyle)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_FLOAT(alpha);
PARAM_INT_OPT(mode) { mode = 0; }
self->Alpha = clamp(alpha, 0., 1.);
self->RenderStyle = ERenderStyle(mode);
return 0;
}
//===========================================================================
//
// A_FadeIn
@ -7396,3 +7412,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetVisibleRotation)
ACTION_RETURN_BOOL(true);
}
//==========================================================================
//
//
//
//==========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslation)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_STRING(trname);
self->SetTranslation(trname);
return 0;
}

View file

@ -3373,7 +3373,7 @@ FxExpression *FxClassMember::Resolve(FCompileContext &ctx)
ExpEmit FxClassMember::Emit(VMFunctionBuilder *build)
{
if (~membervar->Flags & VARF_Native)
if (build->IsActionFunc && ~membervar->Flags & VARF_Native)
{ // Check if this is a user-defined variable.
// As of right now, FxClassMember is only ever used with FxSelf.
// This very user variable was defined in stateowner so if
@ -3948,15 +3948,16 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
//==========================================================================
//
// Assumption: This call is being made to generate code inside an action
// method, so the first three address registers are all set up for such a
// function. (self, stateowner, callingstate)
// Assumption: This call is being generated inside a function whose a0
// register is a self pointer. For action functions, a1 maps to stateowner
// and a2 maps to callingstate. (self, stateowner, callingstate)
//
//==========================================================================
ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
{
assert(build->Registers[REGT_POINTER].GetMostUsed() >= 3);
assert((build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= NAP) ||
(!build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 1));
int count = (ArgList ? ArgList->Size() : 0);
if (count == 1)
@ -3975,8 +3976,18 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
}
if (Function->Flags & VARF_Action)
{
build->Emit(OP_PARAM, 0, REGT_POINTER, 1);
build->Emit(OP_PARAM, 0, REGT_POINTER, 2);
static_assert(NAP == 3, "This code needs to be updated if NAP changes");
if (build->IsActionFunc)
{
build->Emit(OP_PARAM, 0, REGT_POINTER, 1);
build->Emit(OP_PARAM, 0, REGT_POINTER, 2);
}
else
{
int null = build->GetConstantAddress(nullptr, ATAG_GENERIC);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, null);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, null);
}
count += 2;
}
// Emit code to pass explicit parameters
@ -4967,7 +4978,8 @@ static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numpa
ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build)
{
assert(build->Registers[REGT_POINTER].GetMostUsed() >= 3);
assert(build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 3 &&
"FxRuntimeStateIndex is only valid inside action functions");
ExpEmit out(build, REGT_POINTER);
@ -5139,7 +5151,14 @@ int DecoFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, V
ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
{
ExpEmit dest(build, REGT_POINTER);
build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // pass stateowner
if (build->IsActionFunc)
{
build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // pass stateowner
}
else
{
build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self
}
for (unsigned i = 0; i < names.Size(); ++i)
{
build->EmitParamInt(names[i]);

View file

@ -1100,9 +1100,10 @@ DEFINE_PROPERTY(translation, L, Actor)
for(int i = 1; i < PROP_PARM_COUNT; i++)
{
PROP_STRING_PARM(str, i);
if (i== 1 && PROP_PARM_COUNT == 2 && !stricmp(str, "Ice"))
int tnum;
if (i== 1 && PROP_PARM_COUNT == 2 && (tnum = R_FindCustomTranslation(str)) != -1)
{
defaults->Translation = TRANSLATION(TRANSLATION_Standard, 7);
defaults->Translation = tnum;
return;
}
else
@ -1110,7 +1111,7 @@ DEFINE_PROPERTY(translation, L, Actor)
CurrentTranslation.AddToTranslation(str);
}
}
defaults->Translation = CurrentTranslation.StoreTranslation ();
defaults->Translation = CurrentTranslation.StoreTranslation (TRANSLATION_Decorate);
}
}
@ -1437,7 +1438,7 @@ DEFINE_PROPERTY(spriterotation, F, Actor)
DEFINE_PROPERTY(visibleangles, Ff, Actor)
{
PROP_DOUBLE_PARM(visstart, 0);
PROP_DOUBLE_PARM(visend, 0);
PROP_DOUBLE_PARM(visend, 1);
defaults->VisibleStartAngle = visstart;
defaults->VisibleEndAngle = visend;
}
@ -1448,7 +1449,7 @@ DEFINE_PROPERTY(visibleangles, Ff, Actor)
DEFINE_PROPERTY(visiblepitch, Ff, Actor)
{
PROP_DOUBLE_PARM(visstart, 0);
PROP_DOUBLE_PARM(visend, 0);
PROP_DOUBLE_PARM(visend, 1);
defaults->VisibleStartPitch = visstart;
defaults->VisibleEndPitch = visend;
}

View file

@ -556,17 +556,29 @@ struct TVector3
// Resizes this vector to be the specified length (if it is not 0)
TVector3 &MakeResize(double len)
{
double scale = len / Length();
X = vec_t(X * scale);
Y = vec_t(Y * scale);
Z = vec_t(Z * scale);
double vlen = Length();
if (vlen != 0.)
{
double scale = len / vlen;
X = vec_t(X * scale);
Y = vec_t(Y * scale);
Z = vec_t(Z * scale);
}
return *this;
}
TVector3 Resized(double len)
{
double scale = len / Length();
return{ vec_t(X * scale), vec_t(Y * scale), vec_t(Z * scale) };
double vlen = Length();
if (vlen != 0.)
{
double scale = len / vlen;
return{ vec_t(X * scale), vec_t(Y * scale), vec_t(Z * scale) };
}
else
{
return *this;
}
}
// Dot product

View file

@ -27,6 +27,12 @@
// MACROS ------------------------------------------------------------------
// This macro is defined by newer versions of xinput.h. In case we are
// compiling with an older version, define it here.
#ifndef XUSER_MAX_COUNT
#define XUSER_MAX_COUNT 4
#endif
// TYPES -------------------------------------------------------------------
typedef DWORD (WINAPI *XInputGetStateType)(DWORD index, XINPUT_STATE *state);

View file

@ -37,7 +37,9 @@ extern int NewWidth, NewHeight, NewBits, DisplayBits;
// these get used before GLEW is initialized so we have to use separate pointers with different names
PFNWGLCHOOSEPIXELFORMATARBPROC myWglChoosePixelFormatARB; // = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
PFNWGLCREATECONTEXTATTRIBSARBPROC myWglCreateContextAttribsARB;
PFNWGLSWAPINTERVALEXTPROC vsyncfunc;
PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc;
CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
@ -933,10 +935,32 @@ Win32GLFrameBuffer::Win32GLFrameBuffer(void *hMonitor, int width, int height, in
vid_renderer = 0;
return;
}
vsyncfunc = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
HDC hDC = GetDC(Window);
const char *wglext = nullptr;
myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
auto myWglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
if (myWglGetExtensionsStringARB)
{
wglext = myWglGetExtensionsStringARB(hDC);
}
else
{
auto myWglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT");
if (myWglGetExtensionsStringEXT)
{
wglext = myWglGetExtensionsStringEXT();
}
}
SwapInterval = 1;
if (wglext != nullptr)
{
if (strstr(wglext, "WGL_EXT_swap_control_tear"))
{
SwapInterval = -1;
}
}
m_supportsGamma = !!GetDeviceGammaRamp(hDC, (void *)m_origGamma);
ReleaseDC(Window, hDC);
}
@ -1091,7 +1115,7 @@ void Win32GLFrameBuffer::ReleaseResources ()
void Win32GLFrameBuffer::SetVSync (bool vsync)
{
if (vsyncfunc != NULL) vsyncfunc(vsync ? 1 : 0);
if (myWglSwapIntervalExtProc != NULL) myWglSwapIntervalExtProc(vsync ? SwapInterval : 0);
}
void Win32GLFrameBuffer::SwapBuffers()

View file

@ -148,6 +148,7 @@ protected:
int m_Lock;
char m_displayDeviceNameBuffer[CCHDEVICENAME];
char *m_displayDeviceName;
int SwapInterval;
friend class Win32GLVideo;

View file

@ -6,7 +6,7 @@
//
//==========================================================================
VMFunctionBuilder::VMFunctionBuilder()
VMFunctionBuilder::VMFunctionBuilder(bool selfcheck)
{
NumIntConstants = 0;
NumFloatConstants = 0;
@ -14,6 +14,7 @@ VMFunctionBuilder::VMFunctionBuilder()
NumStringConstants = 0;
MaxParam = 0;
ActiveParam = 0;
IsActionFunc = selfcheck;
}
//==========================================================================

View file

@ -23,7 +23,7 @@ public:
friend class VMFunctionBuilder;
};
VMFunctionBuilder();
VMFunctionBuilder(bool checkself = false);
~VMFunctionBuilder();
VMScriptFunction *MakeFunction();
@ -60,6 +60,9 @@ public:
// Track available registers.
RegAvailability Registers[4];
// For use by DECORATE's self/stateowner sanitizer.
bool IsActionFunc;
private:
struct AddrKonst
{

View file

@ -57,6 +57,7 @@ ACTOR Actor native //: Thinker
native float GetSpriteAngle(int ptr = AAPTR_DEFAULT);
native float GetSpriteRotation(int ptr = AAPTR_DEFAULT);
native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT);
action native int OverlayID();
// Action functions
// Meh, MBF redundant functions. Only for DeHackEd support.
@ -218,6 +219,7 @@ ACTOR Actor native //: Thinker
native void A_LogInt(int whattoprint);
native void A_LogFloat(float whattoprint);
native void A_SetTranslucent(float alpha, int style = 0);
native void A_SetRenderStyle(float alpha, int style);
action native A_FadeIn(float reduce = 0.1, int flags = 0);
action native A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true
native void A_FadeTo(float target, float amount = 0.1, int flags = 0);
@ -343,6 +345,7 @@ ACTOR Actor native //: Thinker
action native bool A_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT);
action native bool A_SetSpriteRotation(float angle = 0, int ptr = AAPTR_DEFAULT);
action native bool A_SetVisibleRotation(float anglestart = 0, float angleend = 0, float pitchstart = 0, float pitchend = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetTranslation(string transname);
native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0);
native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0);

View file

@ -689,4 +689,22 @@ enum
VRF_NOANGLE = VRF_NOANGLESTART|VRF_NOANGLEEND,
VRF_NOPITCH = VRF_NOPITCHSTART|VRF_NOPITCHEND,
};
};
enum
{
STYLE_None,
STYLE_Normal,
STYLE_Fuzzy,
STYLE_SoulTrans,
STYLE_OptFuzzy,
STYLE_Stencil,
STYLE_Translucent,
STYLE_Add,
STYLE_Shaded,
STYLE_TranslucentStencil,
STYLE_Shadow,
STYLE_Subtract,
STYLE_AddStencil,
STYLE_AddShaded,
};

View file

@ -151,6 +151,7 @@ $alias switches/exitbutn switches/normbutn // Heretic has no special exit button
plats/pt1_strt pstart
plats/pt1_stop pstop
plats/pt1_mid dormov
plats/pt2_mid stnmov
//
// Door Sounds

View file

@ -0,0 +1,5 @@
:Platform
playuntildone plats/pt1_strt
playrepeat plats/pt2_mid
stopsound plats/pt1_stop
end

View file

@ -2638,6 +2638,7 @@ GLPREFMNU_BLOOM = "Bloom effect";
GLPREFMNU_LENS = "Lens distortion effect";
GLPREFMNU_SSAO = "Ambient occlusion quality";
GLPREFMNU_SSAO_PORTALS = "Portals with AO";
GLPREFMNU_FXAA = "FXAA Quality";
// Option Values
OPTVAL_SMART = "Smart";
@ -2708,8 +2709,14 @@ OPTVAL_LEFTEYE = "Left Eye";
OPTVAL_RIGHTEYE = "Right Eye";
OPTVAL_SBSFULL = "Side-by-side Full";
OPTVAL_SBSNARROW = "Side-by-side Narrow";
OPTVAL_TOPBOTTOM = "Top/Bottom";
OPTVAL_ROWINTERLEAVED = "Row Interleaved";
OPTVAL_QUADBUFFERED = "Quad-buffered";
OPTVAL_UNCHARTED2 = "Uncharted 2";
OPTVAL_HEJLDAWSON = "Hejl Dawson";
OPTVAL_REINHARD = "Reinhard";
OPTVAL_PALETTE = "Palette";
OPTVAL_PALETTE = "Palette";
OPTVAL_LOW = "Low";
OPTVAL_MEDIUM = "Medium";
OPTVAL_HIGH = "High";
OPTVAL_EXTREME = "Extreme";

View file

@ -50,6 +50,15 @@ OptionValue "SSAOModes"
3, "$OPTVAL_HIGH"
}
OptionValue "FXAAQuality"
{
0, "$OPTVAL_OFF"
1, "$OPTVAL_LOW"
2, "$OPTVAL_MEDIUM"
3, "$OPTVAL_HIGH"
4, "$OPTVAL_EXTREME"
}
OptionValue "TextureFormats"
{
0, "$OPTVAL_RGBA8"
@ -177,6 +186,8 @@ OptionValue VRMode
9, "$OPTVAL_AMBERBLUE"
3, "$OPTVAL_SBSFULL"
4, "$OPTVAL_SBSNARROW"
11, "$OPTVAL_TOPBOTTOM"
12, "$OPTVAL_ROWINTERLEAVED"
5, "$OPTVAL_LEFTEYE"
6, "$OPTVAL_RIGHTEYE"
7, "$OPTVAL_QUADBUFFERED"
@ -236,4 +247,5 @@ OptionMenu "GLPrefOptions"
Option "$GLPREFMNU_LENS", gl_lens, "OnOff"
Option "$GLPREFMNU_SSAO", gl_ssao, "SSAOModes"
Slider "$GLPREFMNU_SSAO_PORTALS", gl_ssao_portals, 0.0, 4.0, 1.0, 0
Option "$GLPREFMNU_FXAA", gl_fxaa, "FXAAQuality"
}

View file

@ -0,0 +1,615 @@
//----------------------------------------------------------------------------------
// File: es3-kepler\FXAA/FXAA3_11.h
// SDK Version: v3.00
// Email: gameworks@nvidia.com
// Site: http://developer.nvidia.com/
//
// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 COPYRIGHT OWNER OR
// CONTRIBUTORS 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.
//
//----------------------------------------------------------------------------------
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D InputTexture;
#ifdef FXAA_LUMA_PASS
void main()
{
vec3 tex = texture(InputTexture, TexCoord).rgb;
vec3 luma = vec3(0.299, 0.587, 0.114);
FragColor = vec4(tex, dot(tex, luma));
}
#else // FXAA itself
//============================================================================
// NVIDIA FXAA 3.11 by TIMOTHY LOTTES
//============================================================================
#define FXAA_DISCARD 1
#define FXAA_GREEN_AS_LUMA 0
#define FxaaBool bool
#define FxaaDiscard discard
#define FxaaFloat float
#define FxaaFloat2 vec2
#define FxaaFloat3 vec3
#define FxaaFloat4 vec4
#define FxaaHalf float
#define FxaaHalf2 vec2
#define FxaaHalf3 vec3
#define FxaaHalf4 vec4
#define FxaaInt2 ivec2
#define FxaaSat(x) clamp(x, 0.0, 1.0)
#define FxaaTex sampler2D
#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
#if (FXAA_GATHER4_ALPHA == 1)
#define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
#define FxaaTexGreen4(t, p) textureGather(t, p, 1)
#define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
#endif
#if (FXAA_GREEN_AS_LUMA == 0)
FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }
#else
FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
#endif
#if (FXAA_QUALITY__PRESET == 10)
#define FXAA_QUALITY__PS 3
#define FXAA_QUALITY__P0 1.5
#define FXAA_QUALITY__P1 3.0
#define FXAA_QUALITY__P2 12.0
#elif (FXAA_QUALITY__PRESET == 11)
#define FXAA_QUALITY__PS 4
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 3.0
#define FXAA_QUALITY__P3 12.0
#elif (FXAA_QUALITY__PRESET == 12)
#define FXAA_QUALITY__PS 5
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 4.0
#define FXAA_QUALITY__P4 12.0
#elif (FXAA_QUALITY__PRESET == 13)
#define FXAA_QUALITY__PS 6
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 4.0
#define FXAA_QUALITY__P5 12.0
#elif (FXAA_QUALITY__PRESET == 14)
#define FXAA_QUALITY__PS 7
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 4.0
#define FXAA_QUALITY__P6 12.0
#elif (FXAA_QUALITY__PRESET == 15)
#define FXAA_QUALITY__PS 8
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 4.0
#define FXAA_QUALITY__P7 12.0
#elif (FXAA_QUALITY__PRESET == 20)
#define FXAA_QUALITY__PS 3
#define FXAA_QUALITY__P0 1.5
#define FXAA_QUALITY__P1 2.0
#define FXAA_QUALITY__P2 8.0
#elif (FXAA_QUALITY__PRESET == 21)
#define FXAA_QUALITY__PS 4
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 8.0
#elif (FXAA_QUALITY__PRESET == 22)
#define FXAA_QUALITY__PS 5
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 8.0
#elif (FXAA_QUALITY__PRESET == 23)
#define FXAA_QUALITY__PS 6
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 8.0
#elif (FXAA_QUALITY__PRESET == 24)
#define FXAA_QUALITY__PS 7
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 3.0
#define FXAA_QUALITY__P6 8.0
#elif (FXAA_QUALITY__PRESET == 25)
#define FXAA_QUALITY__PS 8
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 4.0
#define FXAA_QUALITY__P7 8.0
#elif (FXAA_QUALITY__PRESET == 26)
#define FXAA_QUALITY__PS 9
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 4.0
#define FXAA_QUALITY__P8 8.0
#elif (FXAA_QUALITY__PRESET == 27)
#define FXAA_QUALITY__PS 10
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 2.0
#define FXAA_QUALITY__P8 4.0
#define FXAA_QUALITY__P9 8.0
#elif (FXAA_QUALITY__PRESET == 28)
#define FXAA_QUALITY__PS 11
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 2.0
#define FXAA_QUALITY__P8 2.0
#define FXAA_QUALITY__P9 4.0
#define FXAA_QUALITY__P10 8.0
#elif (FXAA_QUALITY__PRESET == 29)
#define FXAA_QUALITY__PS 12
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 2.0
#define FXAA_QUALITY__P8 2.0
#define FXAA_QUALITY__P9 2.0
#define FXAA_QUALITY__P10 4.0
#define FXAA_QUALITY__P11 8.0
#elif (FXAA_QUALITY__PRESET == 39)
#define FXAA_QUALITY__PS 12
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.0
#define FXAA_QUALITY__P2 1.0
#define FXAA_QUALITY__P3 1.0
#define FXAA_QUALITY__P4 1.0
#define FXAA_QUALITY__P5 1.5
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 2.0
#define FXAA_QUALITY__P8 2.0
#define FXAA_QUALITY__P9 2.0
#define FXAA_QUALITY__P10 4.0
#define FXAA_QUALITY__P11 8.0
#endif
FxaaFloat4 FxaaPixelShader(FxaaFloat2 pos, FxaaTex tex, FxaaFloat2 fxaaQualityRcpFrame,
FxaaFloat fxaaQualitySubpix, FxaaFloat fxaaQualityEdgeThreshold, FxaaFloat fxaaQualityEdgeThresholdMin)
{
FxaaFloat2 posM;
posM.x = pos.x;
posM.y = pos.y;
#if (FXAA_GATHER4_ALPHA == 1)
#if (FXAA_DISCARD == 0)
FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
#if (FXAA_GREEN_AS_LUMA == 0)
#define lumaM rgbyM.w
#else
#define lumaM rgbyM.y
#endif
#endif
#if (FXAA_GREEN_AS_LUMA == 0)
FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);
FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));
#else
FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);
FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));
#endif
#if (FXAA_DISCARD == 1)
#define lumaM luma4A.w
#endif
#define lumaE luma4A.z
#define lumaS luma4A.x
#define lumaSE luma4A.y
#define lumaNW luma4B.w
#define lumaN luma4B.z
#define lumaW luma4B.x
#else
FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
#if (FXAA_GREEN_AS_LUMA == 0)
#define lumaM rgbyM.w
#else
#define lumaM rgbyM.y
#endif
FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));
#endif
/*--------------------------------------------------------------------------*/
FxaaFloat maxSM = max(lumaS, lumaM);
FxaaFloat minSM = min(lumaS, lumaM);
FxaaFloat maxESM = max(lumaE, maxSM);
FxaaFloat minESM = min(lumaE, minSM);
FxaaFloat maxWN = max(lumaN, lumaW);
FxaaFloat minWN = min(lumaN, lumaW);
FxaaFloat rangeMax = max(maxWN, maxESM);
FxaaFloat rangeMin = min(minWN, minESM);
FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
FxaaFloat range = rangeMax - rangeMin;
FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
FxaaBool earlyExit = range < rangeMaxClamped;
/*--------------------------------------------------------------------------*/
if(earlyExit)
#if (FXAA_DISCARD == 1)
FxaaDiscard;
#else
return rgbyM;
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_GATHER4_ALPHA == 0)
FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
#else
FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
#endif
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNS = lumaN + lumaS;
FxaaFloat lumaWE = lumaW + lumaE;
FxaaFloat subpixRcpRange = 1.0/range;
FxaaFloat subpixNSWE = lumaNS + lumaWE;
FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;
FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNESE = lumaNE + lumaSE;
FxaaFloat lumaNWNE = lumaNW + lumaNE;
FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNWSW = lumaNW + lumaSW;
FxaaFloat lumaSWSE = lumaSW + lumaSE;
FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;
FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;
/*--------------------------------------------------------------------------*/
FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;
FxaaFloat lengthSign = fxaaQualityRcpFrame.x;
FxaaBool horzSpan = edgeHorz >= edgeVert;
FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
/*--------------------------------------------------------------------------*/
if(!horzSpan) lumaN = lumaW;
if(!horzSpan) lumaS = lumaE;
if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;
/*--------------------------------------------------------------------------*/
FxaaFloat gradientN = lumaN - lumaM;
FxaaFloat gradientS = lumaS - lumaM;
FxaaFloat lumaNN = lumaN + lumaM;
FxaaFloat lumaSS = lumaS + lumaM;
FxaaBool pairN = abs(gradientN) >= abs(gradientS);
FxaaFloat gradient = max(abs(gradientN), abs(gradientS));
if(pairN) lengthSign = -lengthSign;
FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
/*--------------------------------------------------------------------------*/
FxaaFloat2 posB;
posB.x = posM.x;
posB.y = posM.y;
FxaaFloat2 offNP;
offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
if(!horzSpan) posB.x += lengthSign * 0.5;
if( horzSpan) posB.y += lengthSign * 0.5;
/*--------------------------------------------------------------------------*/
FxaaFloat2 posN;
posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;
posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;
FxaaFloat2 posP;
posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;
posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;
FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;
FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
FxaaFloat subpixE = subpixC * subpixC;
FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
/*--------------------------------------------------------------------------*/
if(!pairN) lumaNN = lumaSS;
FxaaFloat gradientScaled = gradient * 1.0/4.0;
FxaaFloat lumaMM = lumaM - lumaNN * 0.5;
FxaaFloat subpixF = subpixD * subpixE;
FxaaBool lumaMLTZero = lumaMM < 0.0;
/*--------------------------------------------------------------------------*/
lumaEndN -= lumaNN * 0.5;
lumaEndP -= lumaNN * 0.5;
FxaaBool doneN = abs(lumaEndN) >= gradientScaled;
FxaaBool doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;
FxaaBool doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;
/*--------------------------------------------------------------------------*/
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 3)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 4)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 5)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 6)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 7)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 8)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 9)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 10)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 11)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 12)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
/*--------------------------------------------------------------------------*/
FxaaFloat dstN = posM.x - posN.x;
FxaaFloat dstP = posP.x - posM.x;
if(!horzSpan) dstN = posM.y - posN.y;
if(!horzSpan) dstP = posP.y - posM.y;
/*--------------------------------------------------------------------------*/
FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
FxaaFloat spanLength = (dstP + dstN);
FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
FxaaFloat spanLengthRcp = 1.0/spanLength;
/*--------------------------------------------------------------------------*/
FxaaBool directionN = dstN < dstP;
FxaaFloat dst = min(dstN, dstP);
FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;
FxaaFloat subpixG = subpixF * subpixF;
FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
FxaaFloat subpixH = subpixG * fxaaQualitySubpix;
/*--------------------------------------------------------------------------*/
FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
#if (FXAA_DISCARD == 1)
return FxaaTexTop(tex, posM);
#else
return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);
#endif
}
uniform vec2 ReciprocalResolution;
void main()
{
FragColor = FxaaPixelShader(TexCoord, InputTexture, ReciprocalResolution, 0.75f, 0.166f, 0.0833f);
}
#endif // FXAA_LUMA_PASS

View file

@ -1,6 +1,8 @@
in vec4 pixelpos;
in vec2 glowdist;
in vec4 vWorldNormal;
in vec4 vEyeNormal;
in vec4 vTexCoord;
in vec4 vColor;
@ -124,6 +126,37 @@ float R_DoomLightingEquation(float light)
return lightscale;
}
//===========================================================================
//
// Standard lambertian diffuse light calculation
//
//===========================================================================
float diffuseContribution(vec3 lightDirection, vec3 normal)
{
return max(dot(normal, lightDirection), 0.0f);
}
//===========================================================================
//
// Calculates the brightness of a dynamic point light
// Todo: Find a better way to define which lighting model to use.
// (Specular mode has been removed for now.)
//
//===========================================================================
float pointLightAttenuation(vec4 lightpos)
{
float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
#if 0
return attenuation;
#else
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
float diffuseAmount = diffuseContribution(lightDirection, normalize(vWorldNormal.xyz));
return attenuation * diffuseAmount;
#endif
}
//===========================================================================
//
// Calculate light
@ -199,7 +232,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
lightcolor.rgb *= pointLightAttenuation(lightpos);
dynlight.rgb += lightcolor.rgb;
}
//
@ -210,7 +243,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
lightcolor.rgb *= pointLightAttenuation(lightpos);
dynlight.rgb -= lightcolor.rgb;
}
}
@ -318,7 +351,7 @@ void main()
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
lightcolor.rgb *= pointLightAttenuation(lightpos);
addlight.rgb += lightcolor.rgb;
}
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);

View file

@ -4,8 +4,12 @@ in vec2 aTexCoord;
in vec4 aColor;
#ifndef SIMPLE // we do not need these for simple shaders
in vec4 aVertex2;
in vec4 aNormal;
out vec4 pixelpos;
out vec2 glowdist;
out vec4 vWorldNormal;
out vec4 vEyeNormal;
#endif
out vec4 vTexCoord;
@ -54,6 +58,9 @@ void main()
gl_ClipDistance[3] = -((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y;
gl_ClipDistance[4] = worldcoord.y + ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z);
}
vWorldNormal = NormalModelMatrix * aNormal;
vEyeNormal = NormalViewMatrix * vWorldNormal;
#endif
#ifdef SPHEREMAP

View file

@ -0,0 +1,35 @@
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D LeftEyeTexture;
uniform sampler2D RightEyeTexture;
uniform float InvGamma;
uniform float Contrast;
uniform float Brightness;
uniform int VerticalPixelOffset; // top-of-window might not be top-of-screen
vec4 ApplyGamma(vec4 c)
{
vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5;
val += Brightness * 0.5;
val = pow(max(val, vec3(0.0)), vec3(InvGamma));
return vec4(val, c.a);
}
void main()
{
int thisVerticalPixel = int(gl_FragCoord.y + 1.0); // Bottom row is typically the right eye, when WindowHeight is even
bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row
+ VerticalPixelOffset // because the window might not be aligned to the screen
) % 2 == 0;
vec4 inputColor;
if (isLeftEye) {
inputColor = texture(LeftEyeTexture, TexCoord);
}
else {
// inputColor = vec4(0, 1, 0, 1);
inputColor = texture(RightEyeTexture, TexCoord);
}
FragColor = ApplyGamma(inputColor);
}

View file

@ -56,5 +56,7 @@ uniform int uQuadMode;
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ModelMatrix;
uniform mat4 NormalViewMatrix;
uniform mat4 NormalModelMatrix;
uniform mat4 TextureMatrix;