This commit is contained in:
Rachael Alexanderson 2018-04-29 10:21:37 -04:00
commit 9f70db98fd
481 changed files with 6616 additions and 9356 deletions

View file

@ -14,7 +14,7 @@ environment:
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
- GENERATOR: "Visual Studio 14 2015 Win64"
CONFIGURATION: Release
TOOLSET: v140_xp
TOOLSET: v140
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
- GENERATOR: "Visual Studio 15 2017"
CONFIGURATION: Release
@ -22,11 +22,11 @@ environment:
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
- GENERATOR: "Visual Studio 15 2017 Win64"
CONFIGURATION: Release
TOOLSET: v141_xp
TOOLSET: v141
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
- GENERATOR: "Visual Studio 14 2015 Win64"
CONFIGURATION: Debug
TOOLSET: v140
TOOLSET: v140_xp
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
build_script:

View file

@ -11,7 +11,12 @@ git:
matrix:
include:
- os: osx
osx_image: xcode9.2
osx_image: xcode8
env:
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7"
- os: osx
osx_image: xcode9.3
env:
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7"

View file

@ -14,8 +14,19 @@ function(enable_precompiled_headers PRECOMPILED_HEADER SOURCE_VARIABLE_NAME)
get_filename_component(pch_basename ${PRECOMPILED_HEADER} NAME_WE)
set(pch_abs ${CMAKE_CURRENT_SOURCE_DIR}/${PRECOMPILED_HEADER})
set(pch_unity ${CMAKE_CURRENT_BINARY_DIR}/${pch_basename}.cpp)
FILE(WRITE ${pch_unity} "// Precompiled header unity generated by CMake\n")
FILE(APPEND ${pch_unity} "#include <${pch_abs}>\n")
set(pch_content "// Precompiled header unity generated by CMake\n#include <${pch_abs}>\n")
# Read .cpp if exists
if(EXISTS ${pch_unity})
file(READ ${pch_unity} pch_content_prev)
endif()
# Compare existing .cpp content with the actual one
if (pch_content_prev AND pch_content STREQUAL pch_content_prev)
unset(pch_content)
endif()
# Write .cpp if it's out-of-date
if (pch_content)
FILE(WRITE ${pch_unity} "${pch_content}")
endif()
set_source_files_properties(${pch_unity} PROPERTIES COMPILE_FLAGS "/Yc\"${pch_abs}\"")
# Update properties of source files to use the precompiled header.

View file

@ -62,21 +62,6 @@ if( WIN32 )
set( DX_dinput8_LIBRARY dinput8 )
else()
find_path( D3D_INCLUDE_DIR d3d9.h
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Include )
if( NOT D3D_INCLUDE_DIR )
# 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()
find_path( XINPUT_INCLUDE_DIR xinput.h
PATHS ENV DXSDK_DIR
PATH_SUFFIXES Include )
@ -652,19 +637,7 @@ add_definitions(-DADLMIDI_DISABLE_MUS_SUPPORT -DADLMIDI_DISABLE_XMI_SUPPORT -DAD
# Project files should be aware of the header files. We can GLOB these since
# there's generally a new cpp for every header so this file will get changed
if( WIN32 )
set( EXTRA_HEADER_DIRS win32/*.h )
elseif( APPLE )
if( OSX_COCOA_BACKEND )
set( EXTRA_HEADER_DIRS posix/*.h posix/cocoa/*.h )
else()
set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
endif()
else()
set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
endif()
file( GLOB HEADER_FILES
${EXTRA_HEADER_DIRS}
fragglescript/*.h
g_shared/*.h
g_statusbar/*.h
@ -678,6 +651,7 @@ file( GLOB HEADER_FILES
posix/*.h
posix/cocoa/*.h
posix/sdl/*.h
win32/*.h
r_data/*.h
r_data/models/*.h
rapidjson/*.h
@ -713,8 +687,12 @@ file( GLOB HEADER_FILES
polyrenderer/math/*.h
polyrenderer/drawers/*.h
polyrenderer/scene/*.h
hwrenderer/data/*.h
hwrenderer/dynlights/*.h
hwrenderer/scene/*.h
hwrenderer/textures/*.h
hwrenderer/utilities/*.h
gl/*.h
gl/api/*.h
gl/data/*.h
gl/dynlights/*.h
gl/models/*.h
@ -817,7 +795,7 @@ set( NOT_COMPILED_SOURCE_FILES
)
# This is disabled for now because I cannot find a way to give the .pch file a different name.
# Visual C++ 2015 seems hell-bent of only allowing one .pch file with the same name as the executable.
# Visual C++ 2015 seems hell-bent on only allowing one .pch file with the same name as the executable.
#enable_precompiled_headers( g_pch2.h FASTMATH_PCH_SOURCES )
# Enable fast math for some sources
@ -831,7 +809,6 @@ set( FASTMATH_SOURCES
sound/sndfile_decoder.cpp
sound/timiditypp/fft4g.cpp
sound/timiditypp/reverb.cpp
gl/utility/gl_clock.cpp
textures/hires/hqnx/init.cpp
textures/hires/hqnx/hq2x.cpp
textures/hires/hqnx/hq3x.cpp
@ -839,26 +816,28 @@ set( FASTMATH_SOURCES
textures/hires/xbr/xbrz.cpp
textures/hires/xbr/xbrz_old.cpp
gl/scene/gl_bsp.cpp
gl/scene/gl_fakeflat.cpp
gl/scene/gl_clipper.cpp
gl/scene/gl_decal.cpp
gl/scene/gl_drawinfo.cpp
gl/scene/gl_flats.cpp
gl/scene/gl_walls.cpp
gl/scene/gl_sprite.cpp
gl/scene/gl_skydome.cpp
gl/scene/gl_renderhacks.cpp
gl/scene/gl_weapon.cpp
gl/scene/gl_scene.cpp
gl/scene/gl_swscene.cpp
gl/scene/gl_sky.cpp
gl/scene/gl_portal.cpp
gl/scene/gl_walls_draw.cpp
gl/scene/gl_vertex.cpp
gl/scene/gl_spritelight.cpp
gl/dynlights/gl_dynlight1.cpp
gl_load/gl_load.c
gl/models/gl_models.cpp
hwrenderer/dynlights/hw_dynlightdata.cpp
hwrenderer/scene/hw_fakeflat.cpp
hwrenderer/scene/hw_decal.cpp
hwrenderer/scene/hw_drawlist.cpp
hwrenderer/scene/hw_clipper.cpp
hwrenderer/scene/hw_flats.cpp
hwrenderer/scene/hw_renderhacks.cpp
hwrenderer/scene/hw_sky.cpp
hwrenderer/scene/hw_sprites.cpp
hwrenderer/scene/hw_spritelight.cpp
hwrenderer/scene/hw_walls.cpp
hwrenderer/scene/hw_walls_vertex.cpp
r_data/models/models.cpp
r_data/matrix.cpp
sound/adlmidi/adldata.cpp
@ -933,7 +912,6 @@ set (PCH_SOURCES
i_time.cpp
info.cpp
keysections.cpp
lumpconfigfile.cpp
m_alloc.cpp
m_argv.cpp
m_bbox.cpp
@ -1045,6 +1023,7 @@ set (PCH_SOURCES
gl/data/gl_vertexbuffer.cpp
gl/dynlights/gl_lightbuffer.cpp
gl/dynlights/gl_shadowmap.cpp
gl/models/gl_models.cpp
gl/renderer/gl_quaddrawer.cpp
gl/renderer/gl_renderer.cpp
gl/renderer/gl_renderstate.cpp
@ -1076,14 +1055,18 @@ set (PCH_SOURCES
gl/system/gl_interface.cpp
gl/system/gl_framebuffer.cpp
gl/system/gl_debug.cpp
gl/system/gl_menu.cpp
gl/system/gl_wipe.cpp
gl/textures/gl_hwtexture.cpp
gl/textures/gl_texture.cpp
gl/textures/gl_material.cpp
gl/textures/gl_samplers.cpp
hwrenderer/data/flatvertices.cpp
hwrenderer/dynlights/hw_aabbtree.cpp
hwrenderer/dynlights/hw_shadowmap.cpp
hwrenderer/scene/hw_skydome.cpp
hwrenderer/textures/hw_material.cpp
hwrenderer/textures/hw_precache.cpp
hwrenderer/utility/hw_clock.cpp
hwrenderer/utility/hw_cvars.cpp
hwrenderer/utility/hw_lighting.cpp
menu/joystickmenu.cpp
menu/loadsavemenu.cpp
@ -1242,8 +1225,6 @@ set (PCH_SOURCES
sound/wildmidi/wildmidi_lib.cpp
sound/wildmidi/wm_error.cpp
events.cpp
GuillotineBinPack.cpp
SkylineBinPack.cpp
)
enable_precompiled_headers( g_pch.h PCH_SOURCES )
@ -1284,9 +1265,6 @@ set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${ZD_F
set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" )
set_source_files_properties( sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" )
set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE )
if ( WIN32 )
set_source_files_properties( win32/fb_d3d9.cpp win32/fb_d3d9_wipe.cpp PROPERTIES COMPILE_FLAGS ${ZD_FASTMATH_FLAG} )
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")

View file

@ -1,643 +0,0 @@
/** @file GuillotineBinPack.cpp
@author Jukka Jylänki
@brief Implements different bin packer algorithms that use the GUILLOTINE data structure.
This work is released to Public Domain, do whatever you want with it.
*/
#include <cassert>
#include <limits.h>
#include "templates.h"
#include "GuillotineBinPack.h"
using namespace std;
GuillotineBinPack::GuillotineBinPack()
:binWidth(0),
binHeight(0)
{
}
GuillotineBinPack::GuillotineBinPack(int width, int height)
{
Init(width, height);
}
void GuillotineBinPack::Init(int width, int height)
{
binWidth = width;
binHeight = height;
#ifdef _DEBUG
disjointRects.Clear();
#endif
// Clear any memory of previously packed rectangles.
usedRectangles.Clear();
// We start with a single big free rectangle that spans the whole bin.
Rect n;
n.x = 0;
n.y = 0;
n.width = width;
n.height = height;
freeRectangles.Clear();
freeRectangles.Push(n);
}
void GuillotineBinPack::Insert(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
{
dst.Clear();
// Remember variables about the best packing choice we have made so far during the iteration process.
int bestFreeRect = 0;
int bestRect = 0;
bool bestFlipped = false;
// Pack rectangles one at a time until we have cleared the rects array of all rectangles.
// rects will get destroyed in the process.
while(rects.Size() > 0)
{
// Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
int bestScore = INT_MAX;
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
{
for(unsigned j = 0; j < rects.Size(); ++j)
{
// If this rectangle is a perfect match, we pick it instantly.
if (rects[j].width == freeRectangles[i].width && rects[j].height == freeRectangles[i].height)
{
bestFreeRect = i;
bestRect = j;
bestFlipped = false;
bestScore = INT_MIN;
i = freeRectangles.Size(); // Force a jump out of the outer loop as well - we got an instant fit.
break;
}
// If flipping this rectangle is a perfect match, pick that then.
else if (rects[j].height == freeRectangles[i].width && rects[j].width == freeRectangles[i].height)
{
bestFreeRect = i;
bestRect = j;
bestFlipped = true;
bestScore = INT_MIN;
i = freeRectangles.Size(); // Force a jump out of the outer loop as well - we got an instant fit.
break;
}
// Try if we can fit the rectangle upright.
else if (rects[j].width <= freeRectangles[i].width && rects[j].height <= freeRectangles[i].height)
{
int score = ScoreByHeuristic(rects[j].width, rects[j].height, freeRectangles[i], rectChoice);
if (score < bestScore)
{
bestFreeRect = i;
bestRect = j;
bestFlipped = false;
bestScore = score;
}
}
// If not, then perhaps flipping sideways will make it fit?
else if (rects[j].height <= freeRectangles[i].width && rects[j].width <= freeRectangles[i].height)
{
int score = ScoreByHeuristic(rects[j].height, rects[j].width, freeRectangles[i], rectChoice);
if (score < bestScore)
{
bestFreeRect = i;
bestRect = j;
bestFlipped = true;
bestScore = score;
}
}
}
}
// If we didn't manage to find any rectangle to pack, abort.
if (bestScore == INT_MAX)
return;
// Otherwise, we're good to go and do the actual packing.
Rect newNode;
newNode.x = freeRectangles[bestFreeRect].x;
newNode.y = freeRectangles[bestFreeRect].y;
newNode.width = rects[bestRect].width;
newNode.height = rects[bestRect].height;
if (bestFlipped)
std::swap(newNode.width, newNode.height);
// Remove the free space we lost in the bin.
SplitFreeRectByHeuristic(freeRectangles[bestFreeRect], newNode, splitMethod);
freeRectangles.Delete(bestFreeRect);
// Remove the rectangle we just packed from the input list.
rects.Delete(bestRect);
// Perform a Rectangle Merge step if desired.
if (merge)
MergeFreeList();
// Remember the new used rectangle.
usedRectangles.Push(newNode);
// Check that we're really producing correct packings here.
#ifdef _DEBUG
assert(disjointRects.Add(newNode) == true);
#endif
}
}
/// @return True if r fits inside freeRect (possibly rotated).
bool Fits(const RectSize &r, const Rect &freeRect)
{
return (r.width <= freeRect.width && r.height <= freeRect.height) ||
(r.height <= freeRect.width && r.width <= freeRect.height);
}
/// @return True if r fits perfectly inside freeRect, i.e. the leftover area is 0.
bool FitsPerfectly(const RectSize &r, const Rect &freeRect)
{
return (r.width == freeRect.width && r.height == freeRect.height) ||
(r.height == freeRect.width && r.width == freeRect.height);
}
/*
// A helper function for GUILLOTINE-MAXFITTING. Counts how many rectangles fit into the given rectangle
// after it has been split.
void CountNumFitting(const Rect &freeRect, int width, int height, const TArray<RectSize> &rects,
int usedRectIndex, bool splitHorizontal, int &score1, int &score2)
{
const int w = freeRect.width - width;
const int h = freeRect.height - height;
Rect bottom;
bottom.x = freeRect.x;
bottom.y = freeRect.y + height;
bottom.height = h;
Rect right;
right.x = freeRect.x + width;
right.y = freeRect.y;
right.width = w;
if (splitHorizontal)
{
bottom.width = freeRect.width;
right.height = height;
}
else // Split vertically
{
bottom.width = width;
right.height = freeRect.height;
}
int fitBottom = 0;
int fitRight = 0;
for(size_t i = 0; i < rects.size(); ++i)
if (i != usedRectIndex)
{
if (FitsPerfectly(rects[i], bottom))
fitBottom |= 0x10000000;
if (FitsPerfectly(rects[i], right))
fitRight |= 0x10000000;
if (Fits(rects[i], bottom))
++fitBottom;
if (Fits(rects[i], right))
++fitRight;
}
score1 = min(fitBottom, fitRight);
score2 = max(fitBottom, fitRight);
}
*/
/*
// Implements GUILLOTINE-MAXFITTING, an experimental heuristic that's really cool but didn't quite work in practice.
void GuillotineBinPack::InsertMaxFitting(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
{
dst.clear();
int bestRect = 0;
bool bestFlipped = false;
bool bestSplitHorizontal = false;
// Pick rectangles one at a time and pack the one that leaves the most choices still open.
while(rects.size() > 0 && freeRectangles.size() > 0)
{
int bestScore1 = -1;
int bestScore2 = -1;
///\todo Different sort predicates.
clb::sort::QuickSort(&freeRectangles[0], freeRectangles.size(), CompareRectShortSide);
Rect &freeRect = freeRectangles[0];
for(size_t j = 0; j < rects.size(); ++j)
{
int score1;
int score2;
if (rects[j].width == freeRect.width && rects[j].height == freeRect.height)
{
bestRect = j;
bestFlipped = false;
bestScore1 = bestScore2 = std::numeric_limits<int>::max();
break;
}
else if (rects[j].width <= freeRect.width && rects[j].height <= freeRect.height)
{
CountNumFitting(freeRect, rects[j].width, rects[j].height, rects, j, false, score1, score2);
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
{
bestRect = j;
bestScore1 = score1;
bestScore2 = score2;
bestFlipped = false;
bestSplitHorizontal = false;
}
CountNumFitting(freeRect, rects[j].width, rects[j].height, rects, j, true, score1, score2);
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
{
bestRect = j;
bestScore1 = score1;
bestScore2 = score2;
bestFlipped = false;
bestSplitHorizontal = true;
}
}
if (rects[j].height == freeRect.width && rects[j].width == freeRect.height)
{
bestRect = j;
bestFlipped = true;
bestScore1 = bestScore2 = std::numeric_limits<int>::max();
break;
}
else if (rects[j].height <= freeRect.width && rects[j].width <= freeRect.height)
{
CountNumFitting(freeRect, rects[j].height, rects[j].width, rects, j, false, score1, score2);
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
{
bestRect = j;
bestScore1 = score1;
bestScore2 = score2;
bestFlipped = true;
bestSplitHorizontal = false;
}
CountNumFitting(freeRect, rects[j].height, rects[j].width, rects, j, true, score1, score2);
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
{
bestRect = j;
bestScore1 = score1;
bestScore2 = score2;
bestFlipped = true;
bestSplitHorizontal = true;
}
}
}
if (bestScore1 >= 0)
{
Rect newNode;
newNode.x = freeRect.x;
newNode.y = freeRect.y;
newNode.width = rects[bestRect].width;
newNode.height = rects[bestRect].height;
if (bestFlipped)
std::swap(newNode.width, newNode.height);
assert(disjointRects.Disjoint(newNode));
SplitFreeRectAlongAxis(freeRect, newNode, bestSplitHorizontal);
rects.erase(rects.begin() + bestRect);
if (merge)
MergeFreeList();
usedRectangles.push_back(newNode);
#ifdef _DEBUG
disjointRects.Add(newNode);
#endif
}
freeRectangles.erase(freeRectangles.begin());
}
}
*/
Rect GuillotineBinPack::Insert(int width, int height, bool merge, FreeRectChoiceHeuristic rectChoice,
GuillotineSplitHeuristic splitMethod)
{
// Find where to put the new rectangle.
int freeNodeIndex = 0;
Rect newRect = FindPositionForNewNode(width, height, rectChoice, &freeNodeIndex);
// Abort if we didn't have enough space in the bin.
if (newRect.height == 0)
return newRect;
// Remove the space that was just consumed by the new rectangle.
SplitFreeRectByHeuristic(freeRectangles[freeNodeIndex], newRect, splitMethod);
freeRectangles.Delete(freeNodeIndex);
// Perform a Rectangle Merge step if desired.
if (merge)
MergeFreeList();
// Remember the new used rectangle.
usedRectangles.Push(newRect);
// Check that we're really producing correct packings here.
#ifdef _DEBUG
assert(disjointRects.Add(newRect) == true);
#endif
return newRect;
}
/// Computes the ratio of used surface area to the total bin area.
float GuillotineBinPack::Occupancy() const
{
///\todo The occupancy rate could be cached/tracked incrementally instead
/// of looping through the list of packed rectangles here.
unsigned long usedSurfaceArea = 0;
for(unsigned i = 0; i < usedRectangles.Size(); ++i)
usedSurfaceArea += usedRectangles[i].width * usedRectangles[i].height;
return (float)usedSurfaceArea / (binWidth * binHeight);
}
/// Returns the heuristic score value for placing a rectangle of size width*height into freeRect. Does not try to rotate.
int GuillotineBinPack::ScoreByHeuristic(int width, int height, const Rect &freeRect, FreeRectChoiceHeuristic rectChoice)
{
switch(rectChoice)
{
case RectBestAreaFit: return ScoreBestAreaFit(width, height, freeRect);
case RectBestShortSideFit: return ScoreBestShortSideFit(width, height, freeRect);
case RectBestLongSideFit: return ScoreBestLongSideFit(width, height, freeRect);
case RectWorstAreaFit: return ScoreWorstAreaFit(width, height, freeRect);
case RectWorstShortSideFit: return ScoreWorstShortSideFit(width, height, freeRect);
case RectWorstLongSideFit: return ScoreWorstLongSideFit(width, height, freeRect);
default: assert(false); return INT_MAX;
}
}
int GuillotineBinPack::ScoreBestAreaFit(int width, int height, const Rect &freeRect)
{
return freeRect.width * freeRect.height - width * height;
}
int GuillotineBinPack::ScoreBestShortSideFit(int width, int height, const Rect &freeRect)
{
int leftoverHoriz = abs(freeRect.width - width);
int leftoverVert = abs(freeRect.height - height);
int leftover = MIN(leftoverHoriz, leftoverVert);
return leftover;
}
int GuillotineBinPack::ScoreBestLongSideFit(int width, int height, const Rect &freeRect)
{
int leftoverHoriz = abs(freeRect.width - width);
int leftoverVert = abs(freeRect.height - height);
int leftover = MAX(leftoverHoriz, leftoverVert);
return leftover;
}
int GuillotineBinPack::ScoreWorstAreaFit(int width, int height, const Rect &freeRect)
{
return -ScoreBestAreaFit(width, height, freeRect);
}
int GuillotineBinPack::ScoreWorstShortSideFit(int width, int height, const Rect &freeRect)
{
return -ScoreBestShortSideFit(width, height, freeRect);
}
int GuillotineBinPack::ScoreWorstLongSideFit(int width, int height, const Rect &freeRect)
{
return -ScoreBestLongSideFit(width, height, freeRect);
}
Rect GuillotineBinPack::FindPositionForNewNode(int width, int height, FreeRectChoiceHeuristic rectChoice, int *nodeIndex)
{
Rect bestNode;
memset(&bestNode, 0, sizeof(Rect));
int bestScore = INT_MAX;
/// Try each free rectangle to find the best one for placement.
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
{
// If this is a perfect fit upright, choose it immediately.
if (width == freeRectangles[i].width && height == freeRectangles[i].height)
{
bestNode.x = freeRectangles[i].x;
bestNode.y = freeRectangles[i].y;
bestNode.width = width;
bestNode.height = height;
bestScore = INT_MIN;
*nodeIndex = i;
#ifdef _DEBUG
assert(disjointRects.Disjoint(bestNode));
#endif
break;
}
// If this is a perfect fit sideways, choose it.
/* else if (height == freeRectangles[i].width && width == freeRectangles[i].height)
{
bestNode.x = freeRectangles[i].x;
bestNode.y = freeRectangles[i].y;
bestNode.width = height;
bestNode.height = width;
bestScore = INT_MIN;
*nodeIndex = i;
assert(disjointRects.Disjoint(bestNode));
break;
}
*/ // Does the rectangle fit upright?
else if (width <= freeRectangles[i].width && height <= freeRectangles[i].height)
{
int score = ScoreByHeuristic(width, height, freeRectangles[i], rectChoice);
if (score < bestScore)
{
bestNode.x = freeRectangles[i].x;
bestNode.y = freeRectangles[i].y;
bestNode.width = width;
bestNode.height = height;
bestScore = score;
*nodeIndex = i;
#ifdef _DEBUG
assert(disjointRects.Disjoint(bestNode));
#endif
}
}
// Does the rectangle fit sideways?
/* else if (height <= freeRectangles[i].width && width <= freeRectangles[i].height)
{
int score = ScoreByHeuristic(height, width, freeRectangles[i], rectChoice);
if (score < bestScore)
{
bestNode.x = freeRectangles[i].x;
bestNode.y = freeRectangles[i].y;
bestNode.width = height;
bestNode.height = width;
bestScore = score;
*nodeIndex = i;
assert(disjointRects.Disjoint(bestNode));
}
}
*/ }
return bestNode;
}
void GuillotineBinPack::SplitFreeRectByHeuristic(const Rect &freeRect, const Rect &placedRect, GuillotineSplitHeuristic method)
{
// Compute the lengths of the leftover area.
const int w = freeRect.width - placedRect.width;
const int h = freeRect.height - placedRect.height;
// Placing placedRect into freeRect results in an L-shaped free area, which must be split into
// two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line.
// We have two choices: horizontal or vertical.
// Use the given heuristic to decide which choice to make.
bool splitHorizontal;
switch(method)
{
case SplitShorterLeftoverAxis:
// Split along the shorter leftover axis.
splitHorizontal = (w <= h);
break;
case SplitLongerLeftoverAxis:
// Split along the longer leftover axis.
splitHorizontal = (w > h);
break;
case SplitMinimizeArea:
// Maximize the larger area == minimize the smaller area.
// Tries to make the single bigger rectangle.
splitHorizontal = (placedRect.width * h > w * placedRect.height);
break;
case SplitMaximizeArea:
// Maximize the smaller area == minimize the larger area.
// Tries to make the rectangles more even-sized.
splitHorizontal = (placedRect.width * h <= w * placedRect.height);
break;
case SplitShorterAxis:
// Split along the shorter total axis.
splitHorizontal = (freeRect.width <= freeRect.height);
break;
case SplitLongerAxis:
// Split along the longer total axis.
splitHorizontal = (freeRect.width > freeRect.height);
break;
default:
splitHorizontal = true;
assert(false);
}
// Perform the actual split.
SplitFreeRectAlongAxis(freeRect, placedRect, splitHorizontal);
}
/// This function will add the two generated rectangles into the freeRectangles array. The caller is expected to
/// remove the original rectangle from the freeRectangles array after that.
void GuillotineBinPack::SplitFreeRectAlongAxis(const Rect &freeRect, const Rect &placedRect, bool splitHorizontal)
{
// Form the two new rectangles.
Rect bottom;
bottom.x = freeRect.x;
bottom.y = freeRect.y + placedRect.height;
bottom.height = freeRect.height - placedRect.height;
Rect right;
right.x = freeRect.x + placedRect.width;
right.y = freeRect.y;
right.width = freeRect.width - placedRect.width;
if (splitHorizontal)
{
bottom.width = freeRect.width;
right.height = placedRect.height;
}
else // Split vertically
{
bottom.width = placedRect.width;
right.height = freeRect.height;
}
// Add the new rectangles into the free rectangle pool if they weren't degenerate.
if (bottom.width > 0 && bottom.height > 0)
freeRectangles.Push(bottom);
if (right.width > 0 && right.height > 0)
freeRectangles.Push(right);
#ifdef _DEBUG
assert(disjointRects.Disjoint(bottom));
assert(disjointRects.Disjoint(right));
#endif
}
void GuillotineBinPack::MergeFreeList()
{
#ifdef _DEBUG
DisjointRectCollection test;
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
assert(test.Add(freeRectangles[i]) == true);
#endif
// Do a Theta(n^2) loop to see if any pair of free rectangles could me merged into one.
// Note that we miss any opportunities to merge three rectangles into one. (should call this function again to detect that)
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
for(unsigned j = i+1; j < freeRectangles.Size(); ++j)
{
if (freeRectangles[i].width == freeRectangles[j].width && freeRectangles[i].x == freeRectangles[j].x)
{
if (freeRectangles[i].y == freeRectangles[j].y + freeRectangles[j].height)
{
freeRectangles[i].y -= freeRectangles[j].height;
freeRectangles[i].height += freeRectangles[j].height;
freeRectangles.Delete(j);
--j;
}
else if (freeRectangles[i].y + freeRectangles[i].height == freeRectangles[j].y)
{
freeRectangles[i].height += freeRectangles[j].height;
freeRectangles.Delete(j);
--j;
}
}
else if (freeRectangles[i].height == freeRectangles[j].height && freeRectangles[i].y == freeRectangles[j].y)
{
if (freeRectangles[i].x == freeRectangles[j].x + freeRectangles[j].width)
{
freeRectangles[i].x -= freeRectangles[j].width;
freeRectangles[i].width += freeRectangles[j].width;
freeRectangles.Delete(j);
--j;
}
else if (freeRectangles[i].x + freeRectangles[i].width == freeRectangles[j].x)
{
freeRectangles[i].width += freeRectangles[j].width;
freeRectangles.Delete(j);
--j;
}
}
}
#ifdef _DEBUG
test.Clear();
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
assert(test.Add(freeRectangles[i]) == true);
#endif
}

View file

@ -1,135 +0,0 @@
/** @file GuillotineBinPack.h
@author Jukka Jylänki
@brief Implements different bin packer algorithms that use the GUILLOTINE data structure.
This work is released to Public Domain, do whatever you want with it.
*/
#pragma once
#include "tarray.h"
#include "Rect.h"
/** GuillotineBinPack implements different variants of bin packer algorithms that use the GUILLOTINE data structure
to keep track of the free space of the bin where rectangles may be placed. */
class GuillotineBinPack
{
public:
/// The initial bin size will be (0,0). Call Init to set the bin size.
GuillotineBinPack();
/// Initializes a new bin of the given size.
GuillotineBinPack(int width, int height);
/// (Re)initializes the packer to an empty bin of width x height units. Call whenever
/// you need to restart with a new bin.
void Init(int width, int height);
/// Specifies the different choice heuristics that can be used when deciding which of the free subrectangles
/// to place the to-be-packed rectangle into.
enum FreeRectChoiceHeuristic
{
RectBestAreaFit, ///< -BAF
RectBestShortSideFit, ///< -BSSF
RectBestLongSideFit, ///< -BLSF
RectWorstAreaFit, ///< -WAF
RectWorstShortSideFit, ///< -WSSF
RectWorstLongSideFit ///< -WLSF
};
/// Specifies the different choice heuristics that can be used when the packer needs to decide whether to
/// subdivide the remaining free space in horizontal or vertical direction.
enum GuillotineSplitHeuristic
{
SplitShorterLeftoverAxis, ///< -SLAS
SplitLongerLeftoverAxis, ///< -LLAS
SplitMinimizeArea, ///< -MINAS, Try to make a single big rectangle at the expense of making the other small.
SplitMaximizeArea, ///< -MAXAS, Try to make both remaining rectangles as even-sized as possible.
SplitShorterAxis, ///< -SAS
SplitLongerAxis ///< -LAS
};
/// Inserts a single rectangle into the bin. The packer might rotate the rectangle, in which case the returned
/// struct will have the width and height values swapped.
/// @param merge If true, performs free Rectangle Merge procedure after packing the new rectangle. This procedure
/// tries to defragment the list of disjoint free rectangles to improve packing performance, but also takes up
/// some extra time.
/// @param rectChoice The free rectangle choice heuristic rule to use.
/// @param splitMethod The free rectangle split heuristic rule to use.
Rect Insert(int width, int height, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
/// Inserts a list of rectangles into the bin.
/// @param rects The list of rectangles to add. This list will be destroyed in the packing process.
/// @param dst The outputted list of rectangles. Note that the indices will not correspond to the input indices.
/// @param merge If true, performs Rectangle Merge operations during the packing process.
/// @param rectChoice The free rectangle choice heuristic rule to use.
/// @param splitMethod The free rectangle split heuristic rule to use.
void Insert(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
// Implements GUILLOTINE-MAXFITTING, an experimental heuristic that's really cool but didn't quite work in practice.
// void InsertMaxFitting(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
// FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
/// Computes the ratio of used/total surface area. 0.00 means no space is yet used, 1.00 means the whole bin is used.
float Occupancy() const;
/// Returns the internal list of disjoint rectangles that track the free area of the bin. You may alter this vector
/// any way desired, as long as the end result still is a list of disjoint rectangles.
TArray<Rect> &GetFreeRectangles() { return freeRectangles; }
/// Returns the list of packed rectangles. You may alter this vector at will, for example, you can move a Rect from
/// this list to the Free Rectangles list to free up space on-the-fly, but notice that this causes fragmentation.
TArray<Rect> &GetUsedRectangles() { return usedRectangles; }
/// Performs a Rectangle Merge operation. This procedure looks for adjacent free rectangles and merges them if they
/// can be represented with a single rectangle. Takes up Theta(|freeRectangles|^2) time.
void MergeFreeList();
#ifdef _DEBUG
void DelDisjoint(const Rect &r) { disjointRects.Del(r); }
#endif
private:
int binWidth;
int binHeight;
/// Stores a list of all the rectangles that we have packed so far. This is used only to compute the Occupancy ratio,
/// so if you want to have the packer consume less memory, this can be removed.
TArray<Rect> usedRectangles;
/// Stores a list of rectangles that represents the free area of the bin. This rectangles in this list are disjoint.
TArray<Rect> freeRectangles;
#ifdef _DEBUG
/// Used to track that the packer produces proper packings.
DisjointRectCollection disjointRects;
#endif
/// Goes through the list of free rectangles and finds the best one to place a rectangle of given size into.
/// Running time is Theta(|freeRectangles|).
/// @param nodeIndex [out] The index of the free rectangle in the freeRectangles array into which the new
/// rect was placed.
/// @return A Rect structure that represents the placement of the new rect into the best free rectangle.
Rect FindPositionForNewNode(int width, int height, FreeRectChoiceHeuristic rectChoice, int *nodeIndex);
static int ScoreByHeuristic(int width, int height, const Rect &freeRect, FreeRectChoiceHeuristic rectChoice);
// The following functions compute (penalty) score values if a rect of the given size was placed into the
// given free rectangle. In these score values, smaller is better.
static int ScoreBestAreaFit(int width, int height, const Rect &freeRect);
static int ScoreBestShortSideFit(int width, int height, const Rect &freeRect);
static int ScoreBestLongSideFit(int width, int height, const Rect &freeRect);
static int ScoreWorstAreaFit(int width, int height, const Rect &freeRect);
static int ScoreWorstShortSideFit(int width, int height, const Rect &freeRect);
static int ScoreWorstLongSideFit(int width, int height, const Rect &freeRect);
/// Splits the given L-shaped free rectangle into two new free rectangles after placedRect has been placed into it.
/// Determines the split axis by using the given heuristic.
void SplitFreeRectByHeuristic(const Rect &freeRect, const Rect &placedRect, GuillotineSplitHeuristic method);
/// Splits the given L-shaped free rectangle into two new free rectangles along the given fixed split axis.
void SplitFreeRectAlongAxis(const Rect &freeRect, const Rect &placedRect, bool splitHorizontal);
};

View file

@ -1,94 +0,0 @@
/** @file Rect.h
@author Jukka Jylänki
This work is released to Public Domain, do whatever you want with it.
*/
#pragma once
#include <vector>
struct RectSize
{
int width;
int height;
};
struct Rect
{
int x;
int y;
int width;
int height;
};
/// Performs a lexicographic compare on (rect short side, rect long side).
/// @return -1 if the smaller side of a is shorter than the smaller side of b, 1 if the other way around.
/// If they are equal, the larger side length is used as a tie-breaker.
/// If the rectangles are of same size, returns 0.
int CompareRectShortSide(const Rect &a, const Rect &b);
/// Performs a lexicographic compare on (x, y, width, height).
int NodeSortCmp(const Rect &a, const Rect &b);
/// Returns true if a is contained in b.
bool IsContainedIn(const Rect &a, const Rect &b);
#ifdef _DEBUG
class DisjointRectCollection
{
public:
TArray<Rect> rects;
bool Add(const Rect &r)
{
// Degenerate rectangles are ignored.
if (r.width == 0 || r.height == 0)
return true;
if (!Disjoint(r))
return false;
rects.Push(r);
return true;
}
bool Del(const Rect &r)
{
for(unsigned i = 0; i < rects.Size(); ++i)
{
if(r.x == rects[i].x && r.y == rects[i].y && r.width == rects[i].width && r.height == rects[i].height)
{
rects.Delete(i);
return true;
}
}
return false;
}
void Clear()
{
rects.Clear();
}
bool Disjoint(const Rect &r) const
{
// Degenerate rectangles are ignored.
if (r.width == 0 || r.height == 0)
return true;
for(unsigned i = 0; i < rects.Size(); ++i)
if (!Disjoint(rects[i], r))
return false;
return true;
}
static bool Disjoint(const Rect &a, const Rect &b)
{
if (a.x + a.width <= b.x ||
b.x + b.width <= a.x ||
a.y + a.height <= b.y ||
b.y + b.height <= a.y)
return true;
return false;
}
};
#endif

View file

@ -1,412 +0,0 @@
/** @file SkylineBinPack.cpp
@author Jukka Jylänki
@brief Implements different bin packer algorithms that use the SKYLINE data structure.
This work is released to Public Domain, do whatever you want with it.
*/
#include <cassert>
#include <limits.h>
#include "templates.h"
#include "SkylineBinPack.h"
using namespace std;
SkylineBinPack::SkylineBinPack()
:binWidth(0),
binHeight(0)
{
}
SkylineBinPack::SkylineBinPack(int width, int height, bool useWasteMap)
{
Init(width, height, useWasteMap);
}
void SkylineBinPack::Init(int width, int height, bool useWasteMap_)
{
binWidth = width;
binHeight = height;
useWasteMap = useWasteMap_;
#ifdef _DEBUG
disjointRects.Clear();
#endif
usedSurfaceArea = 0;
skyLine.Clear();
SkylineNode node;
node.x = 0;
node.y = 0;
node.width = binWidth;
skyLine.Push(node);
if (useWasteMap)
{
wasteMap.Init(width, height);
wasteMap.GetFreeRectangles().Clear();
}
}
void SkylineBinPack::Insert(TArray<RectSize> &rects, TArray<Rect> &dst)
{
dst.Clear();
while(rects.Size() > 0)
{
Rect bestNode;
int bestScore1 = INT_MAX;
int bestScore2 = INT_MAX;
int bestSkylineIndex = -1;
int bestRectIndex = -1;
for(unsigned i = 0; i < rects.Size(); ++i)
{
Rect newNode;
int score1;
int score2;
int index;
newNode = FindPositionForNewNodeMinWaste(rects[i].width, rects[i].height, score2, score1, index);
#ifdef _DEBUG
assert(disjointRects.Disjoint(newNode));
#endif
if (newNode.height != 0)
{
if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2))
{
bestNode = newNode;
bestScore1 = score1;
bestScore2 = score2;
bestSkylineIndex = index;
bestRectIndex = i;
}
}
}
if (bestRectIndex == -1)
return;
// Perform the actual packing.
#ifdef _DEBUG
assert(disjointRects.Disjoint(bestNode));
disjointRects.Add(bestNode);
#endif
AddSkylineLevel(bestSkylineIndex, bestNode);
usedSurfaceArea += rects[bestRectIndex].width * rects[bestRectIndex].height;
rects.Delete(bestRectIndex);
dst.Push(bestNode);
}
}
Rect SkylineBinPack::Insert(int width, int height)
{
// First try to pack this rectangle into the waste map, if it fits.
Rect node = wasteMap.Insert(width, height, true, GuillotineBinPack::RectBestShortSideFit,
GuillotineBinPack::SplitMaximizeArea);
#ifdef _DEBUG
assert(disjointRects.Disjoint(node));
#endif
if (node.height != 0)
{
Rect newNode;
newNode.x = node.x;
newNode.y = node.y;
newNode.width = node.width;
newNode.height = node.height;
usedSurfaceArea += width * height;
#ifdef _DEBUG
assert(disjointRects.Disjoint(newNode));
disjointRects.Add(newNode);
#endif
return newNode;
}
return InsertBottomLeft(width, height);
}
bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y) const
{
int x = skyLine[skylineNodeIndex].x;
if (x + width > binWidth)
return false;
int widthLeft = width;
int i = skylineNodeIndex;
y = skyLine[skylineNodeIndex].y;
while(widthLeft > 0)
{
y = MAX(y, skyLine[i].y);
if (y + height > binHeight)
return false;
widthLeft -= skyLine[i].width;
++i;
assert(i < (int)skyLine.Size() || widthLeft <= 0);
}
return true;
}
int SkylineBinPack::ComputeWastedArea(int skylineNodeIndex, int width, int height, int y) const
{
int wastedArea = 0;
const int rectLeft = skyLine[skylineNodeIndex].x;
const int rectRight = rectLeft + width;
for(; skylineNodeIndex < (int)skyLine.Size() && skyLine[skylineNodeIndex].x < rectRight; ++skylineNodeIndex)
{
if (skyLine[skylineNodeIndex].x >= rectRight || skyLine[skylineNodeIndex].x + skyLine[skylineNodeIndex].width <= rectLeft)
break;
int leftSide = skyLine[skylineNodeIndex].x;
int rightSide = MIN(rectRight, leftSide + skyLine[skylineNodeIndex].width);
assert(y >= skyLine[skylineNodeIndex].y);
wastedArea += (rightSide - leftSide) * (y - skyLine[skylineNodeIndex].y);
}
return wastedArea;
}
bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y, int &wastedArea) const
{
bool fits = RectangleFits(skylineNodeIndex, width, height, y);
if (fits)
wastedArea = ComputeWastedArea(skylineNodeIndex, width, height, y);
return fits;
}
void SkylineBinPack::AddWasteMapArea(int skylineNodeIndex, int width, int height, int y)
{
int wastedArea = 0;
const int rectLeft = skyLine[skylineNodeIndex].x;
const int rectRight = rectLeft + width;
for(; skylineNodeIndex < (int)skyLine.Size() && skyLine[skylineNodeIndex].x < rectRight; ++skylineNodeIndex)
{
if (skyLine[skylineNodeIndex].x >= rectRight || skyLine[skylineNodeIndex].x + skyLine[skylineNodeIndex].width <= rectLeft)
break;
int leftSide = skyLine[skylineNodeIndex].x;
int rightSide = MIN(rectRight, leftSide + skyLine[skylineNodeIndex].width);
assert(y >= skyLine[skylineNodeIndex].y);
Rect waste;
waste.x = leftSide;
waste.y = skyLine[skylineNodeIndex].y;
waste.width = rightSide - leftSide;
waste.height = y - skyLine[skylineNodeIndex].y;
#ifdef _DEBUG
assert(disjointRects.Disjoint(waste));
#endif
wasteMap.GetFreeRectangles().Push(waste);
}
}
void SkylineBinPack::AddWaste(const Rect &waste)
{
wasteMap.GetFreeRectangles().Push(waste);
#ifdef _DEBUG
disjointRects.Del(waste);
wasteMap.DelDisjoint(waste);
#endif
}
void SkylineBinPack::AddSkylineLevel(int skylineNodeIndex, const Rect &rect)
{
// First track all wasted areas and mark them into the waste map if we're using one.
if (useWasteMap)
AddWasteMapArea(skylineNodeIndex, rect.width, rect.height, rect.y);
SkylineNode newNode;
newNode.x = rect.x;
newNode.y = rect.y + rect.height;
newNode.width = rect.width;
skyLine.Insert(skylineNodeIndex, newNode);
assert(newNode.x + newNode.width <= binWidth);
assert(newNode.y <= binHeight);
for(unsigned i = skylineNodeIndex+1; i < skyLine.Size(); ++i)
{
assert(skyLine[i-1].x <= skyLine[i].x);
if (skyLine[i].x < skyLine[i-1].x + skyLine[i-1].width)
{
int shrink = skyLine[i-1].x + skyLine[i-1].width - skyLine[i].x;
skyLine[i].x += shrink;
skyLine[i].width -= shrink;
if (skyLine[i].width <= 0)
{
skyLine.Delete(i);
--i;
}
else
break;
}
else
break;
}
MergeSkylines();
}
void SkylineBinPack::MergeSkylines()
{
for(unsigned i = 0; i < skyLine.Size()-1; ++i)
if (skyLine[i].y == skyLine[i+1].y)
{
skyLine[i].width += skyLine[i+1].width;
skyLine.Delete(i+1);
--i;
}
}
Rect SkylineBinPack::InsertBottomLeft(int width, int height)
{
int bestHeight;
int bestWidth;
int bestIndex;
Rect newNode = FindPositionForNewNodeBottomLeft(width, height, bestHeight, bestWidth, bestIndex);
if (bestIndex != -1)
{
#ifdef _DEBUG
assert(disjointRects.Disjoint(newNode));
#endif
// Perform the actual packing.
AddSkylineLevel(bestIndex, newNode);
usedSurfaceArea += width * height;
#ifdef _DEBUG
disjointRects.Add(newNode);
#endif
}
else
memset(&newNode, 0, sizeof(Rect));
return newNode;
}
Rect SkylineBinPack::FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const
{
bestHeight = INT_MAX;
bestIndex = -1;
// Used to break ties if there are nodes at the same level. Then pick the narrowest one.
bestWidth = INT_MAX;
Rect newNode = { 0, 0, 0, 0 };
for(unsigned i = 0; i < skyLine.Size(); ++i)
{
int y;
if (RectangleFits(i, width, height, y))
{
if (y + height < bestHeight || (y + height == bestHeight && skyLine[i].width < bestWidth))
{
bestHeight = y + height;
bestIndex = i;
bestWidth = skyLine[i].width;
newNode.x = skyLine[i].x;
newNode.y = y;
newNode.width = width;
newNode.height = height;
#ifdef _DEBUG
assert(disjointRects.Disjoint(newNode));
#endif
}
}
/* if (RectangleFits(i, height, width, y))
{
if (y + width < bestHeight || (y + width == bestHeight && skyLine[i].width < bestWidth))
{
bestHeight = y + width;
bestIndex = i;
bestWidth = skyLine[i].width;
newNode.x = skyLine[i].x;
newNode.y = y;
newNode.width = height;
newNode.height = width;
assert(disjointRects.Disjoint(newNode));
}
}
*/ }
return newNode;
}
Rect SkylineBinPack::InsertMinWaste(int width, int height)
{
int bestHeight;
int bestWastedArea;
int bestIndex;
Rect newNode = FindPositionForNewNodeMinWaste(width, height, bestHeight, bestWastedArea, bestIndex);
if (bestIndex != -1)
{
#ifdef _DEBUG
assert(disjointRects.Disjoint(newNode));
#endif
// Perform the actual packing.
AddSkylineLevel(bestIndex, newNode);
usedSurfaceArea += width * height;
#ifdef _DEBUG
disjointRects.Add(newNode);
#endif
}
else
memset(&newNode, 0, sizeof(newNode));
return newNode;
}
Rect SkylineBinPack::FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const
{
bestHeight = INT_MAX;
bestWastedArea = INT_MAX;
bestIndex = -1;
Rect newNode;
memset(&newNode, 0, sizeof(newNode));
for(unsigned i = 0; i < skyLine.Size(); ++i)
{
int y;
int wastedArea;
if (RectangleFits(i, width, height, y, wastedArea))
{
if (wastedArea < bestWastedArea || (wastedArea == bestWastedArea && y + height < bestHeight))
{
bestHeight = y + height;
bestWastedArea = wastedArea;
bestIndex = i;
newNode.x = skyLine[i].x;
newNode.y = y;
newNode.width = width;
newNode.height = height;
#ifdef _DEBUG
assert(disjointRects.Disjoint(newNode));
#endif
}
}
/* if (RectangleFits(i, height, width, y, wastedArea))
{
if (wastedArea < bestWastedArea || (wastedArea == bestWastedArea && y + width < bestHeight))
{
bestHeight = y + width;
bestWastedArea = wastedArea;
bestIndex = i;
newNode.x = skyLine[i].x;
newNode.y = y;
newNode.width = height;
newNode.height = width;
assert(disjointRects.Disjoint(newNode));
}
}*/
}
return newNode;
}
/// Computes the ratio of used surface area.
float SkylineBinPack::Occupancy() const
{
return (float)usedSurfaceArea / (binWidth * binHeight);
}

View file

@ -1,91 +0,0 @@
/** @file SkylineBinPack.h
@author Jukka Jylänki
@brief Implements different bin packer algorithms that use the SKYLINE data structure.
This work is released to Public Domain, do whatever you want with it.
*/
#pragma once
#include "tarray.h"
#include "Rect.h"
#include "GuillotineBinPack.h"
/** Implements bin packing algorithms that use the SKYLINE data structure to store the bin contents. Uses
GuillotineBinPack as the waste map. */
class SkylineBinPack
{
public:
/// Instantiates a bin of size (0,0). Call Init to create a new bin.
SkylineBinPack();
/// Instantiates a bin of the given size.
SkylineBinPack(int binWidth, int binHeight, bool useWasteMap);
/// (Re)initializes the packer to an empty bin of width x height units. Call whenever
/// you need to restart with a new bin.
void Init(int binWidth, int binHeight, bool useWasteMap);
/// Inserts the given list of rectangles in an offline/batch mode, possibly rotated.
/// @param rects The list of rectangles to insert. This vector will be destroyed in the process.
/// @param dst [out] This list will contain the packed rectangles. The indices will not correspond to that of rects.
/// @param method The rectangle placement rule to use when packing.
void Insert(TArray<RectSize> &rects, TArray<Rect> &dst);
/// Inserts a single rectangle into the bin, possibly rotated.
Rect Insert(int width, int height);
/// Adds a rectangle to the waste list. It must have been previously returned by
/// Insert or the results are undefined.
void AddWaste(const Rect &rect);
/// Computes the ratio of used surface area to the total bin area.
float Occupancy() const;
private:
int binWidth;
int binHeight;
#ifdef _DEBUG
DisjointRectCollection disjointRects;
#endif
/// Represents a single level (a horizontal line) of the skyline/horizon/envelope.
struct SkylineNode
{
/// The starting x-coordinate (leftmost).
int x;
/// The y-coordinate of the skyline level line.
int y;
/// The line width. The ending coordinate (inclusive) will be x+width-1.
int width;
};
TArray<SkylineNode> skyLine;
unsigned long usedSurfaceArea;
/// If true, we use the GuillotineBinPack structure to recover wasted areas into a waste map.
bool useWasteMap;
GuillotineBinPack wasteMap;
Rect InsertBottomLeft(int width, int height);
Rect InsertMinWaste(int width, int height);
Rect FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const;
Rect FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const;
bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const;
bool RectangleFits(int skylineNodeIndex, int width, int height, int &y, int &wastedArea) const;
int ComputeWastedArea(int skylineNodeIndex, int width, int height, int y) const;
void AddWasteMapArea(int skylineNodeIndex, int width, int height, int y);
void AddSkylineLevel(int skylineNodeIndex, const Rect &rect);
/// Merges all skyline nodes that are at the same level.
void MergeSkylines();
};

View file

@ -34,7 +34,6 @@
#include "actorptrselect.h"
#include "actor.h"
#include "d_player.h"
#include "p_pspr.h"
#include "p_local.h"
//==========================================================================

View file

@ -30,14 +30,11 @@
#include "doomdef.h"
#include "templates.h"
#include "g_level.h"
#include "doomdef.h"
#include "st_stuff.h"
#include "p_local.h"
#include "p_lnspec.h"
#include "w_wad.h"
#include "a_sharedglobal.h"
#include "statnums.h"
#include "r_data/r_translate.h"
#include "d_event.h"
#include "gi.h"
#include "p_setup.h"
@ -50,19 +47,10 @@
#include "p_blockmap.h"
#include "m_cheat.h"
#include "i_system.h"
#include "c_dispatch.h"
#include "colormatcher.h"
#include "d_netinf.h"
// Needs access to LFB.
#include "v_video.h"
#include "v_palette.h"
#include "v_text.h"
// State.
#include "doomstat.h"
#include "r_state.h"
#include "r_utility.h"
@ -72,7 +60,6 @@
#include "am_map.h"
#include "po_man.h"
#include "a_keys.h"
#include "r_data/colormaps.h"
#include "g_levellocals.h"
#include "actorinlines.h"

View file

@ -40,7 +40,6 @@
#include "c_cvars.h"
#include "c_dispatch.h"
#include "b_bot.h"
#include "m_argv.h"
#include "doomstat.h"
#include "p_local.h"
#include "cmdlib.h"

View file

@ -48,12 +48,6 @@
#include "p_maputl.h"
#include "b_bot.h"
#include "g_game.h"
#include "m_random.h"
#include "r_sky.h"
#include "st_stuff.h"
#include "stats.h"
#include "i_system.h"
#include "s_sound.h"
#include "d_event.h"
#include "d_player.h"
#include "p_spec.h"

View file

@ -81,20 +81,15 @@ Everything that is changed is marked (maybe commented) with "Added by MC"
#include "p_local.h"
#include "b_bot.h"
#include "g_game.h"
#include "m_random.h"
#include "doomstat.h"
#include "cmdlib.h"
#include "sc_man.h"
#include "stats.h"
#include "m_misc.h"
#include "sbar.h"
#include "p_acs.h"
#include "teaminfo.h"
#include "i_system.h"
#include "d_net.h"
#include "d_netinf.h"
#include "d_player.h"
#include "doomerrors.h"
#include "events.h"
#include "vm.h"

View file

@ -44,11 +44,7 @@
#include "p_local.h"
#include "b_bot.h"
#include "g_game.h"
#include "d_protocol.h"
#include "m_random.h"
#include "i_system.h"
#include "p_lnspec.h"
#include "gi.h"
#include "a_keys.h"
#include "d_event.h"
#include "p_enemy.h"
@ -56,7 +52,6 @@
#include "p_spec.h"
#include "p_checkposition.h"
#include "actorinlines.h"
#include "math/cmath.h"
static FRandom pr_botopendoor ("BotOpenDoor");
static FRandom pr_bottrywalk ("BotTryWalk");

View file

@ -47,14 +47,9 @@
#include "p_local.h"
#include "b_bot.h"
#include "g_game.h"
#include "m_random.h"
#include "stats.h"
#include "a_pickups.h"
#include "statnums.h"
#include "d_net.h"
#include "d_event.h"
#include "d_player.h"
#include "vectors.h"
#include "actorinlines.h"
static FRandom pr_botmove ("BotMove");

View file

@ -44,11 +44,7 @@
#include "actor.h"
#include "gstrings.h"
#include "s_sound.h"
#include "m_random.h"
#include "d_player.h"
#include "g_level.h"
#include "doomstat.h"
#include "g_levellocals.h"
// MACROS ------------------------------------------------------------------

View file

@ -34,14 +34,11 @@
#include "doomtype.h"
#include "doomdef.h"
#include "cmdlib.h"
#include "c_dispatch.h"
#include "c_bind.h"
#include "g_level.h"
#include "hu_stuff.h"
#include "gi.h"
#include "configfile.h"
#include "i_system.h"
#include "d_event.h"
#include "w_wad.h"
#include "templates.h"
@ -49,9 +46,6 @@
#include "vm.h"
#include "i_time.h"
#include <math.h>
#include <stdlib.h>
const char *KeyNames[NUM_KEYS] =
{
// This array is dependant on the particular keyboard input

View file

@ -35,7 +35,6 @@
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#ifdef _WIN32
#include <direct.h>
@ -56,11 +55,9 @@
#include "g_game.h"
#include "g_level.h"
#include "w_wad.h"
#include "g_level.h"
#include "gi.h"
#include "r_defs.h"
#include "d_player.h"
#include "templates.h"
#include "p_local.h"
#include "r_sky.h"
#include "p_setup.h"
@ -68,9 +65,7 @@
#include "d_net.h"
#include "v_text.h"
#include "p_lnspec.h"
#include "v_video.h"
#include "r_utility.h"
#include "r_data/r_interpolate.h"
#include "c_functions.h"
#include "g_levellocals.h"

View file

@ -34,10 +34,6 @@
#include "templates.h"
#include "p_setup.h"
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "version.h"
#include "g_game.h"
@ -49,27 +45,22 @@
#include "i_system.h"
#include "i_video.h"
#include "g_input.h"
#include "m_swap.h"
#include "v_palette.h"
#include "v_video.h"
#include "v_text.h"
#include "w_wad.h"
#include "sbar.h"
#include "s_sound.h"
#include "s_sndseq.h"
#include "doomstat.h"
#include "d_gui.h"
#include "v_video.h"
#include "cmdlib.h"
#include "d_net.h"
#include "g_level.h"
#include "d_event.h"
#include "d_player.h"
#include "gstrings.h"
#include "c_consolebuffer.h"
#include "g_levellocals.h"
#include "vm.h"
#include "i_time.h"
FString FStringFormat(VM_ARGS); // extern from thingdef_data.cpp

View file

@ -33,7 +33,6 @@
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "cmdlib.h"
@ -42,18 +41,12 @@
#include "c_dispatch.h"
#include "doomstat.h"
#include "c_cvars.h"
#include "d_player.h"
#include "d_netinf.h"
#include "i_system.h"
#include "v_palette.h"
#include "v_video.h"
#include "colormatcher.h"
#include "menu/menu.h"
#include "vm.h"
#include "v_text.h"
struct FLatchedValue
{

View file

@ -38,7 +38,6 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "templates.h"
#include "doomtype.h"
@ -49,7 +48,6 @@
#include "doomstat.h"
#include "d_player.h"
#include "configfile.h"
#include "m_crc32.h"
#include "v_text.h"
#include "d_net.h"
#include "d_main.h"

View file

@ -35,7 +35,6 @@
// HEADER FILES ------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

View file

@ -39,7 +39,6 @@
*/
#include <stdlib.h>
#include <string.h>
#include "doomtype.h"
#include "colormatcher.h"

View file

@ -41,20 +41,17 @@
#include "compatibility.h"
#include "sc_man.h"
#include "cmdlib.h"
#include "doomdef.h"
#include "doomdata.h"
#include "doomstat.h"
#include "c_dispatch.h"
#include "gi.h"
#include "g_level.h"
#include "p_lnspec.h"
#include "p_tags.h"
#include "r_state.h"
#include "w_wad.h"
#include "textures.h"
#include "g_levellocals.h"
#include "vm.h"
#include "actor.h"
// MACROS ------------------------------------------------------------------
@ -74,28 +71,6 @@ enum
SLOT_BCOMPAT
};
enum
{
CP_END,
CP_CLEARFLAGS,
CP_SETFLAGS,
CP_SETSPECIAL,
CP_CLEARSPECIAL,
CP_SETACTIVATION,
CP_SETSECTOROFFSET,
CP_SETSECTORSPECIAL,
CP_SETWALLYSCALE,
CP_SETWALLTEXTURE,
CP_SETTHINGZ,
CP_SETTAG,
CP_SETTHINGFLAGS,
CP_SETVERTEX,
CP_SETTHINGSKILLS,
CP_SETSECTORTEXTURE,
CP_SETSECTORLIGHT,
CP_SETLINESECTORREF,
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -397,6 +372,22 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingSkills)
return 0;
}
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingXY)
{
PARAM_PROLOGUE;
PARAM_INT(thing);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
if ((unsigned)thing < MapThingsConverted.Size())
{
auto& pos = MapThingsConverted[thing].pos;
pos.X = x;
pos.Y = y;
}
return 0;
}
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingZ)
{
PARAM_PROLOGUE;
@ -459,6 +450,13 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetLineSectorRef)
return 0;
}
DEFINE_ACTION_FUNCTION(DLevelCompatibility, GetDefaultActor)
{
PARAM_PROLOGUE;
PARAM_NAME(actorclass);
ACTION_RETURN_OBJECT(GetDefaultByName(actorclass));
}
//==========================================================================
//

View file

@ -26,20 +26,15 @@
#include "doomdef.h"
#include "m_swap.h"
#include "hu_stuff.h"
#include "w_wad.h"
#include "s_sound.h"
#include "doomstat.h"
#include "st_stuff.h"
#include "c_console.h"
#include "c_dispatch.h"
#include "c_cvars.h"
#include "d_player.h"
#include "v_text.h"
#include "v_video.h"
#include "gi.h"
#include "d_gui.h"
#include "g_input.h"
#include "templates.h"
#include "d_net.h"
#include "d_event.h"
#include "sbar.h"

View file

@ -48,30 +48,19 @@
#include "doomstat.h"
#include "info.h"
#include "d_dehacked.h"
#include "s_sound.h"
#include "g_level.h"
#include "cmdlib.h"
#include "gstrings.h"
#include "m_alloc.h"
#include "m_misc.h"
#include "w_wad.h"
#include "d_player.h"
#include "r_state.h"
#include "gi.h"
#include "c_dispatch.h"
#include "decallib.h"
#include "v_palette.h"
#include "a_sharedglobal.h"
#include "vectors.h"
#include "dobject.h"
#include "r_data/r_translate.h"
#include "sc_man.h"
#include "i_system.h"
#include "doomerrors.h"
#include "p_effect.h"
#include "serializer.h"
#include "thingdef.h"
#include "info.h"
#include "v_text.h"
#include "backend/vmbuilder.h"
#include "types.h"

View file

@ -38,11 +38,8 @@
#include "doomstat.h"
#include "i_system.h"
#include "w_wad.h"
#include "w_zip.h"
#include "v_palette.h"
#include "m_argv.h"
#include "m_misc.h"
#include "c_cvars.h"
#include "sc_man.h"
#include "v_video.h"
#include "gameconfigfile.h"
@ -197,6 +194,12 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize,
iwad->StartupType = FStartupInfo::StrifeStartup;
else iwad->StartupType = FStartupInfo::DefaultStartup;
}
else if (sc.Compare("StartupSong"))
{
sc.MustGetStringName("=");
sc.MustGetString();
iwad->Song = sc.String;
}
else
{
sc.ScriptError("Unknown keyword '%s'", sc.String);
@ -769,6 +772,7 @@ const FIWADInfo *FIWadManager::FindIWAD(TArray<FString> &wadfiles, const char *i
DoomStartupInfo.FgColor = iwad_info->FgColor;
}
if (DoomStartupInfo.Type == 0) DoomStartupInfo.Type = iwad_info->StartupType;
if (DoomStartupInfo.Song.IsEmpty()) DoomStartupInfo.Song = iwad_info->Song;
I_SetIWADInfo();
return iwad_info;
}

View file

@ -38,16 +38,13 @@
#ifdef HAVE_FPU_CONTROL
#include <fpu_control.h>
#endif
#include <float.h>
#if defined(__unix__) || defined(__APPLE__)
#include <unistd.h>
#endif
#include <time.h>
#include <math.h>
#include <assert.h>
#include <sys/stat.h>
#include "doomerrors.h"
@ -67,7 +64,6 @@
#include "menu/menu.h"
#include "c_console.h"
#include "c_dispatch.h"
#include "i_system.h"
#include "i_sound.h"
#include "i_video.h"
#include "g_game.h"
@ -81,40 +77,29 @@
#include "d_main.h"
#include "d_dehacked.h"
#include "cmdlib.h"
#include "s_sound.h"
#include "m_swap.h"
#include "v_text.h"
#include "gi.h"
#include "b_bot.h" //Added by MC:
#include "stats.h"
#include "gameconfigfile.h"
#include "sbar.h"
#include "decallib.h"
#include "version.h"
#include "v_text.h"
#include "st_start.h"
#include "templates.h"
#include "teaminfo.h"
#include "hardware.h"
#include "sbarinfo.h"
#include "d_net.h"
#include "g_level.h"
#include "d_event.h"
#include "d_netinf.h"
#include "v_palette.h"
#include "m_cheat.h"
#include "compatibility.h"
#include "m_joy.h"
#include "sc_man.h"
#include "po_man.h"
#include "resourcefiles/resourcefile.h"
#include "r_renderer.h"
#include "p_local.h"
#include "autosegs.h"
#include "fragglescript/t_fs.h"
#include "g_levellocals.h"
#include "events.h"
#include "r_utility.h"
#include "vm.h"
#include "types.h"
#include "r_data/r_vanillatrans.h"

View file

@ -101,6 +101,7 @@ struct FIWADInfo
FString Required; // Requires another IWAD
uint32_t FgColor = 0; // Foreground color for title banner
uint32_t BkColor = 0xc0c0c0; // Background color for title banner
FString Song;
EGameType gametype = GAME_Doom; // which game are we playing?
int StartupType = FStartupInfo::DefaultStartup; // alternate startup type
FString MapInfo; // Base mapinfo to load

View file

@ -30,18 +30,13 @@
#include "version.h"
#include "menu/menu.h"
#include "m_random.h"
#include "i_system.h"
#include "i_video.h"
#include "i_net.h"
#include "g_game.h"
#include "doomdef.h"
#include "doomstat.h"
#include "c_console.h"
#include "d_netinf.h"
#include "d_net.h"
#include "cmdlib.h"
#include "s_sound.h"
#include "m_cheat.h"
#include "p_local.h"
#include "c_dispatch.h"
@ -49,19 +44,15 @@
#include "gi.h"
#include "m_misc.h"
#include "gameconfigfile.h"
#include "d_gui.h"
#include "templates.h"
#include "p_acs.h"
#include "p_trace.h"
#include "a_sharedglobal.h"
#include "st_start.h"
#include "teaminfo.h"
#include "p_conversation.h"
#include "g_level.h"
#include "d_event.h"
#include "m_argv.h"
#include "p_lnspec.h"
#include "v_video.h"
#include "p_spec.h"
#include "hardware.h"
#include "r_utility.h"

View file

@ -35,26 +35,17 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "doomtype.h"
#include "doomdef.h"
#include "doomstat.h"
#include "d_netinf.h"
#include "d_net.h"
#include "d_protocol.h"
#include "d_player.h"
#include "c_dispatch.h"
#include "v_palette.h"
#include "v_video.h"
#include "i_system.h"
#include "r_state.h"
#include "sbar.h"
#include "gi.h"
#include "m_random.h"
#include "teaminfo.h"
#include "r_data/r_translate.h"
#include "templates.h"
#include "cmdlib.h"
#include "serializer.h"
#include "vm.h"

View file

@ -35,7 +35,6 @@
#include "i_system.h"
#include "d_protocol.h"
#include "d_net.h"
#include "doomdef.h"
#include "doomstat.h"
#include "cmdlib.h"
#include "serializer.h"
@ -408,7 +407,6 @@ int SkipTicCmd (uint8_t **stream, int count)
return skip;
}
#include <assert.h>
extern short consistancy[MAXPLAYERS][BACKUPTICS];
void ReadTicCmd (uint8_t **stream, int player, int tic)
{

View file

@ -36,17 +36,13 @@
#include "sc_man.h"
#include "w_wad.h"
#include "v_video.h"
#include "v_palette.h"
#include "cmdlib.h"
#include "m_random.h"
#include "weightedlist.h"
#include "statnums.h"
#include "templates.h"
#include "a_sharedglobal.h"
#include "r_data/r_translate.h"
#include "gi.h"
#include "g_level.h"
#include "colormatcher.h"
#include "b_bot.h"
#include "serializer.h"
#include "g_levellocals.h"

View file

@ -33,19 +33,13 @@
*/
#include <stdlib.h>
#include <string.h>
#include "cmdlib.h"
#include "actor.h"
#include "dobject.h"
#include "doomstat.h" // Ideally, DObjects can be used independant of Doom.
#include "d_player.h" // See p_user.cpp to find out why this doesn't work.
#include "g_game.h" // Needed for bodyque.
#include "c_dispatch.h"
#include "i_system.h"
#include "r_state.h"
#include "stats.h"
#include "a_sharedglobal.h"
#include "dsectoreffect.h"
#include "serializer.h"
#include "vm.h"

View file

@ -63,16 +63,11 @@
#include "g_game.h"
#include "a_sharedglobal.h"
#include "sbar.h"
#include "stats.h"
#include "c_dispatch.h"
#include "s_sndseq.h"
#include "r_data/r_interpolate.h"
#include "doomstat.h"
#include "m_argv.h"
#include "po_man.h"
#include "autosegs.h"
#include "v_video.h"
#include "textures/textures.h"
#include "r_utility.h"
#include "menu/menu.h"
#include "intermission/intermission.h"

View file

@ -35,19 +35,15 @@
// HEADER FILES ------------------------------------------------------------
#include <float.h>
#include <limits>
#include "dobject.h"
#include "i_system.h"
#include "serializer.h"
#include "actor.h"
#include "templates.h"
#include "autosegs.h"
#include "v_text.h"
#include "a_pickups.h"
#include "d_player.h"
#include "doomerrors.h"
#include "fragglescript/t_fs.h"
#include "a_keys.h"
#include "vm.h"

View file

@ -28,10 +28,8 @@
#include "stringtable.h"
#include "doomstat.h"
#include "c_cvars.h"
#include "i_system.h"
#include "g_level.h"
#include "p_local.h"
#include "g_levellocals.h"
int SaveVersion;

View file

@ -283,6 +283,17 @@ enum ESSType
const double M_PI = 3.14159265358979323846; // matches value in gcc v2 math.h
inline float DEG2RAD(float deg)
{
return deg * float(M_PI / 180.0);
}
inline float RAD2DEG(float deg)
{
return deg * float(180. / M_PI);
}
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&array)[N] ))[N];

View file

@ -26,12 +26,10 @@
//-----------------------------------------------------------------------------
#include "dsectoreffect.h"
#include "gi.h"
#include "p_local.h"
#include "g_levellocals.h"
#include "p_3dmidtex.h"
#include "r_data/r_interpolate.h"
#include "statnums.h"
#include "serializer.h"
#include "doomstat.h"
#include "vm.h"

View file

@ -35,9 +35,6 @@
#include "dthinker.h"
#include "stats.h"
#include "p_local.h"
#include "statnums.h"
#include "i_system.h"
#include "doomerrors.h"
#include "serializer.h"
#include "d_player.h"
#include "vm.h"

View file

@ -36,7 +36,6 @@
#include "w_wad.h"
#include "m_argv.h"
#include "zstring.h"
#include "sc_man.h"
#include "g_level.h"
#include "doomdata.h"
@ -46,9 +45,7 @@
#include "p_setup.h"
#include "p_tags.h"
#include "p_terrain.h"
#include "v_palette.h"
#include "p_acs.h"
#include "r_data/colormaps.h"
#include "g_levellocals.h"

View file

@ -35,7 +35,6 @@
#include "r_utility.h"
#include "g_levellocals.h"
#include "gi.h"
#include "v_text.h"
#include "actor.h"
#include "c_dispatch.h"
#include "d_net.h"

View file

@ -23,14 +23,10 @@
//
//-----------------------------------------------------------------------------
#include "i_video.h"
#include "v_video.h"
#include "m_random.h"
#include "doomdef.h"
#include "f_wipe.h"
#include "c_cvars.h"
#include "templates.h"
#include "v_palette.h"
int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density)
{

View file

@ -34,9 +34,7 @@
*/
#include "files.h"
#include "i_system.h"
#include "templates.h"
#include "m_misc.h"

View file

@ -27,7 +27,6 @@
#include <string.h>
#include <stdio.h>
#include "p_local.h"
#include "doomdef.h"
#include "doomstat.h"

View file

@ -37,26 +37,15 @@
#include "templates.h"
#include "p_local.h"
#include "t_script.h"
#include "s_sound.h"
#include "p_lnspec.h"
#include "m_random.h"
#include "c_console.h"
#include "c_dispatch.h"
#include "d_player.h"
#include "w_wad.h"
#include "gi.h"
#include "zstring.h"
#include "i_system.h"
#include "doomstat.h"
#include "g_level.h"
#include "v_palette.h"
#include "v_font.h"
#include "r_data/colormaps.h"
#include "serializer.h"
#include "p_setup.h"
#include "p_spec.h"
#include "r_utility.h"
#include "math/cmath.h"
#include "g_levellocals.h"
#include "actorinlines.h"

View file

@ -25,14 +25,11 @@
#include "w_wad.h"
#include "tarray.h"
#include "g_level.h"
#include "sc_man.h"
#include "s_sound.h"
#include "r_sky.h"
#include "t_script.h"
#include "cmdlib.h"
#include "p_lnspec.h"
#include "gi.h"
#include "g_levellocals.h"
#include "xlat/xlat.h"

View file

@ -33,10 +33,7 @@
/* includes ************************/
#include <stdarg.h>
#include "t_script.h"
#include "s_sound.h"
#include "v_text.h"
#include "c_cvars.h"
#include "i_system.h"
CVAR(Bool, script_debug, false, 0)

View file

@ -41,7 +41,6 @@
/* includes ************************/
#include "t_script.h"
#include "i_system.h"
#include "w_wad.h"
#include "serializer.h"

View file

@ -33,14 +33,10 @@
//
#include "t_script.h"
#include "p_lnspec.h"
#include "a_keys.h"
#include "d_player.h"
#include "p_spec.h"
#include "c_dispatch.h"
#include "i_system.h"
#include "doomerrors.h"
#include "doomstat.h"
#include "serializer.h"
#include "g_levellocals.h"

View file

@ -36,13 +36,8 @@
#include "info.h"
#include "actor.h"
#include "p_lnspec.h"
#include "m_fixed.h"
#include "c_dispatch.h"
#include "templates.h"
#include "cmdlib.h"
#include "g_level.h"
#include "v_text.h"
#include "i_system.h"
const char *SpecialMapthingNames[] = {

View file

@ -26,7 +26,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <time.h>
#include <memory>
#ifdef __APPLE__
#include <CoreServices/CoreServices.h>
@ -43,9 +42,7 @@
#include "m_argv.h"
#include "m_misc.h"
#include "menu/menu.h"
#include "m_random.h"
#include "m_crc32.h"
#include "i_system.h"
#include "p_saveg.h"
#include "p_tick.h"
#include "d_main.h"
@ -54,24 +51,16 @@
#include "st_stuff.h"
#include "am_map.h"
#include "c_console.h"
#include "c_cvars.h"
#include "c_bind.h"
#include "c_dispatch.h"
#include "v_video.h"
#include "w_wad.h"
#include "p_local.h"
#include "s_sound.h"
#include "gstrings.h"
#include "r_sky.h"
#include "g_game.h"
#include "g_level.h"
#include "b_bot.h" //Added by MC:
#include "sbar.h"
#include "m_swap.h"
#include "m_png.h"
#include "gi.h"
#include "a_keys.h"
#include "r_data/r_translate.h"
#include "cmdlib.h"
#include "d_net.h"
#include "d_event.h"
@ -82,18 +71,12 @@
#include "r_utility.h"
#include "a_morph.h"
#include "p_spec.h"
#include "r_data/colormaps.h"
#include "serializer.h"
#include "w_zip.h"
#include "resourcefiles/resourcefile.h"
#include "vm.h"
#include <zlib.h>
#include "g_hub.h"
#include "g_levellocals.h"
#include "events.h"
#include "d_main.h"
static FRandom pr_dmspawn ("DMSpawn");

View file

@ -35,11 +35,8 @@
#include "doomstat.h"
#include "g_hub.h"
#include "tarray.h"
#include "g_level.h"
#include "g_game.h"
#include "gi.h"
#include "files.h"
#include "m_png.h"
#include "gstrings.h"
#include "wi_stuff.h"

View file

@ -37,11 +37,7 @@
#include "gstrings.h"
#include "d_player.h"
#include "c_console.h"
#include "s_sound.h"
#include "sc_man.h"
#include "v_palette.h"
#include "w_wad.h"
#include "doomstat.h"
#include "v_font.h"
#include "vm.h"

View file

@ -36,28 +36,21 @@
#include <assert.h>
#include "info.h"
#include "m_random.h"
#include "p_local.h"
#include "s_sound.h"
#include "gi.h"
#include "p_lnspec.h"
#include "sbar.h"
#include "statnums.h"
#include "c_dispatch.h"
#include "gstrings.h"
#include "templates.h"
#include "a_morph.h"
#include "a_specialspot.h"
#include "g_level.h"
#include "g_game.h"
#include "doomstat.h"
#include "d_player.h"
#include "p_spec.h"
#include "serializer.h"
#include "vm.h"
#include "c_functions.h"
#include "g_levellocals.h"
#include "vm.h"
EXTERN_CVAR(Bool, sv_unlimited_pickup)

View file

@ -38,18 +38,11 @@
#include "a_pickups.h"
#include "gi.h"
#include "d_player.h"
#include "s_sound.h"
#include "i_system.h"
#include "r_state.h"
#include "p_pspr.h"
#include "c_dispatch.h"
#include "m_misc.h"
#include "gameconfigfile.h"
#include "cmdlib.h"
#include "templates.h"
#include "sbar.h"
#include "doomstat.h"
#include "g_level.h"
#include "d_net.h"
#include "serializer.h"
#include "vm.h"

View file

@ -52,7 +52,6 @@
#include "r_sky.h"
#include "c_console.h"
#include "intermission/intermission.h"
#include "gstrings.h"
#include "v_video.h"
#include "st_stuff.h"
#include "hu_stuff.h"
@ -62,31 +61,22 @@
#include "v_text.h"
#include "s_sndseq.h"
#include "b_bot.h"
#include "sc_man.h"
#include "sbar.h"
#include "a_lightning.h"
#include "m_png.h"
#include "m_random.h"
#include "version.h"
#include "statnums.h"
#include "sbarinfo.h"
#include "r_data/r_translate.h"
#include "p_lnspec.h"
#include "r_data/r_interpolate.h"
#include "cmdlib.h"
#include "d_net.h"
#include "d_netinf.h"
#include "v_palette.h"
#include "menu/menu.h"
#include "a_sharedglobal.h"
#include "r_data/colormaps.h"
#include "r_renderer.h"
#include "r_utility.h"
#include "p_spec.h"
#include "serializer.h"
#include "vm.h"
#include "events.h"
#include "dobjgc.h"
#include "i_music.h"
#include "gi.h"
@ -94,11 +84,8 @@
#include "g_hub.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "vm.h"
#include "i_time.h"
#include <string.h>
void STAT_StartNewGame(const char *lev);
void STAT_ChangeLevel(const char *newl);

View file

@ -36,21 +36,17 @@
#include <assert.h>
#include "templates.h"
#include "g_level.h"
#include "sc_man.h"
#include "w_wad.h"
#include "cmdlib.h"
#include "v_video.h"
#include "p_lnspec.h"
#include "p_setup.h"
#include "i_system.h"
#include "gi.h"
#include "gstrings.h"
#include "p_acs.h"
#include "doomstat.h"
#include "d_player.h"
#include "autosegs.h"
#include "version.h"
#include "v_text.h"
#include "g_levellocals.h"
#include "events.h"

View file

@ -24,16 +24,11 @@
#include "actor.h"
#include "p_conversation.h"
#include "p_lnspec.h"
#include "m_random.h"
#include "s_sound.h"
#include "d_player.h"
#include "p_local.h"
#include "p_terrain.h"
#include "p_enemy.h"
#include "statnums.h"
#include "templates.h"
#include "serializer.h"
#include "r_data/r_translate.h"
#include "vm.h"
//----------------------------------------------------------------------------

View file

@ -36,17 +36,12 @@
#include "a_sharedglobal.h"
#include "r_defs.h"
#include "p_local.h"
#include "v_video.h"
#include "p_trace.h"
#include "decallib.h"
#include "statnums.h"
#include "c_dispatch.h"
#include "d_net.h"
#include "colormatcher.h"
#include "v_palette.h"
#include "serializer.h"
#include "doomdata.h"
#include "r_state.h"
#include "g_levellocals.h"
static double DecalWidth, DecalLeft, DecalRight;

View file

@ -55,26 +55,14 @@
**
*/
#include "templates.h"
#include "m_random.h"
#include "p_local.h"
#include "c_dispatch.h"
#include "g_level.h"
#include "thingdef.h"
#include "i_system.h"
#include "templates.h"
#include "doomdata.h"
#include "r_utility.h"
#include "p_local.h"
#include "portal.h"
#include "doomstat.h"
#include "serializer.h"
#include "g_levellocals.h"
#include "a_dynlight.h"
#include "actorinlines.h"
#include "c_cvars.h"
#include "gl/system//gl_interface.h"
#include "vm.h"
CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
@ -179,6 +167,7 @@ void ADynamicLight::BeginPlay()
specialf1 = DAngle(double(SpawnAngle)).Normalized360().Degrees;
visibletoplayer = true;
mShadowmapIndex = 1024;
}
//==========================================================================

View file

@ -6,6 +6,9 @@
EXTERN_CVAR(Bool, gl_lights)
EXTERN_CVAR(Bool, gl_attachedlights)
struct side_t;
struct seg_t;
class ADynamicLight;
class FSerializer;
@ -227,7 +230,9 @@ public:
bool shadowmapped;
int bufferindex;
LightFlags lightflags;
DAngle SpotInnerAngle = 10.0;
DAngle SpotOuterAngle = 25.0;
DAngle SpotInnerAngle;
DAngle SpotOuterAngle;
int mShadowmapIndex;
};

View file

@ -33,7 +33,6 @@
*/
#include "a_sharedglobal.h"
#include "g_level.h"
#include "d_player.h"
#include "serializer.h"
#include "g_levellocals.h"

View file

@ -25,7 +25,6 @@
#include "a_lightning.h"
#include "doomstat.h"
#include "p_lnspec.h"
#include "statnums.h"
#include "m_random.h"
#include "templates.h"
#include "s_sound.h"

View file

@ -23,23 +23,18 @@
#include "info.h"
#include "a_pickups.h"
#include "gstrings.h"
#include "p_local.h"
#include "gi.h"
#include "s_sound.h"
#include "m_random.h"
#include "a_sharedglobal.h"
#include "sbar.h"
#include "a_morph.h"
#include "doomstat.h"
#include "g_level.h"
#include "serializer.h"
#include "p_enemy.h"
#include "d_player.h"
#include "r_data/sprites.h"
#include "g_levellocals.h"
#include "vm.h"
#include "vm.h"
static FRandom pr_morphmonst ("MorphMonster");

View file

@ -27,11 +27,7 @@
#include "doomstat.h"
#include "p_local.h"
#include "actor.h"
#include "m_bbox.h"
#include "m_random.h"
#include "s_sound.h"
#include "a_sharedglobal.h"
#include "statnums.h"
#include "serializer.h"
#include "d_player.h"
#include "r_utility.h"

View file

@ -33,10 +33,7 @@
**
*/
#include "a_specialspot.h"
#include "m_random.h"
#include "p_local.h"
#include "statnums.h"
#include "i_system.h"
#include "doomstat.h"
#include "serializer.h"
#include "a_pickups.h"

View file

@ -38,7 +38,6 @@
#include "c_cvars.h"
#include "v_video.h"
#include "cmdlib.h"
#include "doomstat.h"
#include "serializer.h"
#include "vm.h"

View file

@ -40,12 +40,10 @@
#include "doomdef.h"
#include "v_video.h"
#include "gi.h"
#include "c_cvars.h"
#include "w_wad.h"
#include "a_keys.h"
#include "sbar.h"
#include "sc_man.h"
#include "templates.h"
#include "p_local.h"
#include "doomstat.h"
#include "g_level.h"

View file

@ -36,12 +36,9 @@
#include <ctype.h>
#include "doomstat.h"
#include "d_player.h"
#include "g_level.h"
#include "g_game.h"
#include "gi.h"
#include "templates.h"
#include "v_font.h"
#include "m_fixed.h"
#include "gstrings.h"
#include "g_levellocals.h"
#include "vm.h"

View file

@ -36,10 +36,7 @@
#include "r_defs.h"
#include "m_random.h"
#include "d_player.h"
#include "d_event.h"
#include "sbar.h"
#include "sbarinfo.h"
#include "templates.h"
#include "r_utility.h"
#include "actorinlines.h"

View file

@ -38,24 +38,13 @@
#include "v_font.h"
#include "v_video.h"
#include "sbar.h"
#include "r_defs.h"
#include "w_wad.h"
#include "m_random.h"
#include "d_player.h"
#include "st_stuff.h"
#include "m_swap.h"
#include "a_keys.h"
#include "templates.h"
#include "i_system.h"
#include "sbar.h"
#include "sbarinfo.h"
#include "gi.h"
#include "r_data/r_translate.h"
#include "g_level.h"
#include "v_palette.h"
#include "p_acs.h"
#include "gstrings.h"
#include "cmdlib.h"
#include "g_levellocals.h"
#include "vm.h"

View file

@ -41,25 +41,19 @@
#include "c_dispatch.h"
#include "c_console.h"
#include "v_video.h"
#include "m_swap.h"
#include "w_wad.h"
#include "v_text.h"
#include "s_sound.h"
#include "gi.h"
#include "doomstat.h"
#include "g_level.h"
#include "d_net.h"
#include "colormatcher.h"
#include "v_palette.h"
#include "d_player.h"
#include "serializer.h"
#include "gstrings.h"
#include "r_utility.h"
#include "cmdlib.h"
#include "g_levellocals.h"
#include "vm.h"
#include "p_acs.h"
#include "r_data/r_translate.h"
#include "sbarinfo.h"
#include "events.h"
@ -658,7 +652,6 @@ void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer
{
DHUDMessageBase *old = NULL;
DHUDMessageBase **prev;
DObject *container = this;
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
if (old != NULL)
@ -679,14 +672,13 @@ void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer
// it gets drawn back to front.)
while (*prev != NULL && (*prev)->SBarID > id)
{
container = *prev;
prev = &(*prev)->Next;
}
msg->Next = *prev;
msg->SBarID = id;
*prev = msg;
GC::WriteBarrier(container, msg);
GC::WriteBarrier(msg);
}
DEFINE_ACTION_FUNCTION(DBaseStatusBar, AttachMessage)

View file

@ -33,18 +33,15 @@
*/
#include <stdio.h>
#include <time.h>
#ifdef __APPLE__
#include <CoreServices/CoreServices.h>
#endif
#include "doomdef.h"
#include "gameconfigfile.h"
#include "c_cvars.h"
#include "c_dispatch.h"
#include "c_bind.h"
#include "gstrings.h"
#include "m_argv.h"
#include "cmdlib.h"
#include "version.h"
@ -52,7 +49,6 @@
#include "v_font.h"
#include "a_pickups.h"
#include "doomstat.h"
#include "i_system.h"
#include "gi.h"
#include "d_main.h"

View file

@ -35,11 +35,8 @@
#include <stdlib.h>
#include "info.h"
#include "gi.h"
#include "m_fixed.h"
#include "v_palette.h"
#include "sc_man.h"
#include "w_wad.h"
#include "i_system.h"
#include "v_video.h"
#include "g_level.h"
#include "vm.h"

View file

@ -30,21 +30,15 @@
#include "gl/system/gl_system.h"
#include "menu/menu.h"
#include "tarray.h"
#include "doomtype.h"
#include "m_argv.h"
#include "zstring.h"
#include "i_system.h"
#include "v_text.h"
#include "r_utility.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "g_levellocals.h"
#include "gl/dynlights/gl_dynlight.h"
#include "hwrenderer/dynlights/hw_dynlightdata.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_cvars.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_scenedrawer.h"
@ -438,7 +432,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, FVector3 & nearP
if (radius <= 0.f) return false;
if (dist > radius) return false;
if (checkside && gl_lights_checkside && p.PointOnSide(lpos.X, lpos.Z, lpos.Y))
if (checkside && p.PointOnSide(lpos.X, lpos.Z, lpos.Y))
{
return false;
}
@ -489,8 +483,8 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, FVector3 & nearP
bool gl_SetupLightTexture()
{
if (!GLRenderer->glLight.isValid()) return false;
FMaterial * pat = FMaterial::ValidateTexture(GLRenderer->glLight, false, false);
if (!TexMan.glLight.isValid()) return false;
FMaterial * pat = FMaterial::ValidateTexture(TexMan.glLight, false, false);
gl_RenderState.SetMaterial(pat, CLAMP_XY_NOMIP, 0, -1, false);
return true;
}
@ -501,7 +495,7 @@ bool gl_SetupLightTexture()
//
//==========================================================================
static bool gl_CheckFog(FColormap *cm, int lightlevel)
static bool CheckFog(FColormap *cm, int lightlevel)
{
bool frontfog;
@ -555,11 +549,13 @@ bool FDrawInfo::PutWallCompat(GLWall *wall, int passflag)
if (wall->sub->lighthead == nullptr) return false;
}
bool foggy = gl_CheckFog(&wall->Colormap, wall->lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
bool foggy = CheckFog(&wall->Colormap, wall->lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
bool masked = passflag == 2 && wall->gltexture->isMasked();
int list = list_indices[masked][foggy];
dldrawlists[list].AddWall(wall);
auto newwall = dldrawlists[list].NewWall();
*newwall = *wall;
if (!masked) newwall->ProcessDecals(this);
return true;
}
@ -570,20 +566,21 @@ bool FDrawInfo::PutWallCompat(GLWall *wall, int passflag)
//
//==========================================================================
bool GLFlat::PutFlatCompat(bool fog)
bool FDrawInfo::PutFlatCompat(GLFlat *flat, bool fog)
{
// are lights possible?
if (mDrawer->FixedColormap != CM_DEFAULT || !gl_lights || !gltexture || renderstyle != STYLE_Translucent || alpha < 1.f - FLT_EPSILON || sector->lighthead == NULL) return false;
if (FixedColormap != CM_DEFAULT || !gl_lights || !flat->gltexture || flat->renderstyle != STYLE_Translucent || flat->alpha < 1.f - FLT_EPSILON || flat->sector->lighthead == NULL) return false;
static int list_indices[2][2] =
{ { GLLDL_FLATS_PLAIN, GLLDL_FLATS_FOG },{ GLLDL_FLATS_MASKED, GLLDL_FLATS_FOGMASKED } };
bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);
bool foggy = gl_CheckFog(&Colormap, lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
bool masked = flat->gltexture->isMasked() && ((flat->renderflags&SSRF_RENDER3DPLANES) || flat->stack);
bool foggy = CheckFog(&flat->Colormap, flat->lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
int list = list_indices[masked][foggy];
gl_drawinfo->dldrawlists[list].AddFlat(this);
auto newflat = gl_drawinfo->dldrawlists[list].NewFlat();
*newflat = *flat;
return true;
}
@ -594,11 +591,17 @@ bool GLFlat::PutFlatCompat(bool fog)
//
//==========================================================================
void GLWall::RenderFogBoundaryCompat()
void FDrawInfo::RenderFogBoundaryCompat(GLWall *wall)
{
// without shaders some approximation is needed. This won't look as good
// as the shader version but it's an acceptable compromise.
float fogdensity = gl_GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.FogDensity);
auto &Colormap = wall->Colormap;
auto &glseg = wall->glseg;
auto tcs = wall->tcs;
auto ztop = wall->ztop;
auto zbottom = wall->zbottom;
float fogdensity = hw_GetFogDensity(wall->lightlevel, Colormap.FadeColor, Colormap.FogDensity);
float dist1 = Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, glseg.x1, glseg.y1);
float dist2 = Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, glseg.x2, glseg.y2);
@ -618,14 +621,14 @@ void GLWall::RenderFogBoundaryCompat()
glDepthFunc(GL_LEQUAL);
glColor4f(fc[0], fc[1], fc[2], fogd1);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(tcs[LOLFT].u, tcs[LOLFT].v);
glTexCoord2f(tcs[GLWall::LOLFT].u, tcs[GLWall::LOLFT].v);
glVertex3f(glseg.x1, zbottom[0], glseg.y1);
glTexCoord2f(tcs[UPLFT].u, tcs[UPLFT].v);
glTexCoord2f(tcs[GLWall::UPLFT].u, tcs[GLWall::UPLFT].v);
glVertex3f(glseg.x1, ztop[0], glseg.y1);
glColor4f(fc[0], fc[1], fc[2], fogd2);
glTexCoord2f(tcs[UPRGT].u, tcs[UPRGT].v);
glTexCoord2f(tcs[GLWall::UPRGT].u, tcs[GLWall::UPRGT].v);
glVertex3f(glseg.x2, ztop[1], glseg.y2);
glTexCoord2f(tcs[LORGT].u, tcs[LORGT].v);
glTexCoord2f(tcs[GLWall::LORGT].u, tcs[GLWall::LORGT].v);
glVertex3f(glseg.x2, zbottom[1], glseg.y2);
glEnd();
glDepthFunc(GL_LESS);
@ -642,7 +645,7 @@ void GLWall::RenderFogBoundaryCompat()
//
//==========================================================================
void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
void FDrawInfo::DrawSubsectorLights(GLFlat *flat, subsector_t * sub, int pass)
{
Plane p;
FVector3 nearPt, up, right, t1;
@ -663,14 +666,14 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
// we must do the side check here because gl_SetupLight needs the correct plane orientation
// which we don't have for Legacy-style 3D-floors
double planeh = plane.plane.ZatPoint(light);
if (gl_lights_checkside && ((planeh<light->Z() && ceiling) || (planeh>light->Z() && !ceiling)))
double planeh = flat->plane.plane.ZatPoint(light);
if (((planeh<light->Z() && flat->ceiling) || (planeh>light->Z() && !flat->ceiling)))
{
node = node->nextLight;
continue;
}
p.Set(plane.plane.Normal(), plane.plane.fD());
p.Set(flat->plane.plane.Normal(), flat->plane.plane.fD());
if (!gl_SetupLight(sub->sector->PortalGroup, p, light, nearPt, up, right, scale, false, pass != GLPASS_LIGHTTEX))
{
node = node->nextLight;
@ -683,7 +686,7 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
{
vertex_t *vt = sub->firstline[k].v1;
ptr->x = vt->fX();
ptr->z = plane.plane.ZatPoint(vt) + dz;
ptr->z = flat->plane.plane.ZatPoint(vt) + flat->dz;
ptr->y = vt->fY();
t1 = { ptr->x, ptr->z, ptr->y };
FVector3 nearToVert = t1 - nearPt;
@ -703,29 +706,29 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
//
//==========================================================================
void GLFlat::DrawLightsCompat(int pass)
void FDrawInfo::DrawLightsCompat(GLFlat *flat, int pass)
{
gl_RenderState.Apply();
// Draw the subsectors belonging to this sector
for (int i = 0; i<sector->subsectorcount; i++)
for (int i = 0; i<flat->sector->subsectorcount; i++)
{
subsector_t * sub = sector->subsectors[i];
if (gl_drawinfo->ss_renderflags[sub->Index()] & renderflags)
subsector_t * sub = flat->sector->subsectors[i];
if (gl_drawinfo->ss_renderflags[sub->Index()] & flat->renderflags)
{
DrawSubsectorLights(sub, pass);
DrawSubsectorLights(flat, sub, pass);
}
}
// Draw the subsectors assigned to it due to missing textures
if (!(renderflags&SSRF_RENDER3DPLANES))
if (!(flat->renderflags&SSRF_RENDER3DPLANES))
{
gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR) ?
gl_drawinfo->GetOtherFloorPlanes(sector->sectornum) :
gl_drawinfo->GetOtherCeilingPlanes(sector->sectornum);
gl_subsectorrendernode * node = (flat->renderflags&SSRF_RENDERFLOOR) ?
gl_drawinfo->GetOtherFloorPlanes(flat->sector->sectornum) :
gl_drawinfo->GetOtherCeilingPlanes(flat->sector->sectornum);
while (node)
{
DrawSubsectorLights(node->sub, pass);
DrawSubsectorLights(flat, node->sub, pass);
node = node->next;
}
}
@ -737,22 +740,27 @@ void GLFlat::DrawLightsCompat(int pass)
// Sets up the texture coordinates for one light to be rendered
//
//==========================================================================
bool GLWall::PrepareLight(ADynamicLight * light, int pass)
static bool PrepareLight(GLWall *wall, ADynamicLight * light, int pass)
{
auto &glseg = wall->glseg;
auto tcs = wall->tcs;
auto ztop = wall->ztop;
auto zbottom = wall->zbottom;
float vtx[] = { glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2 };
Plane p;
FVector3 nearPt, up, right;
float scale;
auto normal = glseg.Normal();
p.Set(normal, -normal.X * glseg.x1 - normal.Y * glseg.y1);
p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1);
if (!p.ValidNormal())
{
return false;
}
if (!gl_SetupLight(seg->frontsector->PortalGroup, p, light, nearPt, up, right, scale, true, pass != GLPASS_LIGHTTEX))
if (!gl_SetupLight(wall->seg->frontsector->PortalGroup, p, light, nearPt, up, right, scale, true, pass != GLPASS_LIGHTTEX))
{
return false;
}
@ -782,27 +790,27 @@ bool GLWall::PrepareLight(ADynamicLight * light, int pass)
}
void GLWall::RenderLightsCompat(int pass)
void FDrawInfo::RenderLightsCompat(GLWall *wall, int pass)
{
FLightNode * node;
// black fog is diminishing light and should affect lights less than the rest!
if (pass == GLPASS_LIGHTTEX) mDrawer->SetFog((255 + lightlevel) >> 1, 0, NULL, false);
else mDrawer->SetFog(lightlevel, 0, &Colormap, true);
if (pass == GLPASS_LIGHTTEX) mDrawer->SetFog((255 + wall->lightlevel) >> 1, 0, NULL, false);
else mDrawer->SetFog(wall->lightlevel, 0, &wall->Colormap, true);
if (seg->sidedef == NULL)
if (wall->seg->sidedef == NULL)
{
return;
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
else if (!(wall->seg->sidedef->Flags & WALLF_POLYOBJ))
{
// Iterate through all dynamic lights which touch this wall and render them
node = seg->sidedef->lighthead;
node = wall->seg->sidedef->lighthead;
}
else if (sub)
else if (wall->sub)
{
// To avoid constant rechecking for polyobjects use the subsector's lightlist instead
node = sub->lighthead;
node = wall->sub->lighthead;
}
else
{
@ -810,7 +818,7 @@ void GLWall::RenderLightsCompat(int pass)
}
texcoord save[4];
memcpy(save, tcs, sizeof(tcs));
memcpy(save, wall->tcs, sizeof(wall->tcs));
while (node)
{
ADynamicLight * light = node->lightsource;
@ -822,15 +830,15 @@ void GLWall::RenderLightsCompat(int pass)
node = node->nextLight;
continue;
}
if (PrepareLight(light, pass))
if (PrepareLight(wall, light, pass))
{
vertcount = 0;
RenderWall(RWF_TEXTURED);
wall->vertcount = 0;
RenderWall(wall, GLWall::RWF_TEXTURED);
}
node = node->nextLight;
}
memcpy(tcs, save, sizeof(tcs));
vertcount = 0;
memcpy(wall->tcs, save, sizeof(wall->tcs));
wall->vertcount = 0;
}
//==========================================================================
@ -849,8 +857,8 @@ void GLSceneDrawer::RenderMultipassStuff()
gl_RenderState.EnableTexture(false);
gl_RenderState.EnableBrightmap(false);
gl_RenderState.Apply();
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_PLAIN);
// Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show
// This creates a blank surface that only fills the nontransparent parts of the texture
@ -858,18 +866,18 @@ void GLSceneDrawer::RenderMultipassStuff()
gl_RenderState.SetTextureMode(TM_MASK);
gl_RenderState.EnableBrightmap(true);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_PLAIN);
// Part 3: The base of fogged surfaces, including the texture
gl_RenderState.EnableBrightmap(false);
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(gl_drawinfo, GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(gl_drawinfo, GLPASS_PLAIN);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(gl_drawinfo, GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(gl_drawinfo, GLPASS_PLAIN);
// second pass: draw lights
glDepthMask(false);
@ -880,10 +888,10 @@ void GLSceneDrawer::RenderMultipassStuff()
gl_RenderState.BlendFunc(GL_ONE, GL_ONE);
glDepthFunc(GL_EQUAL);
if (level.lightmode == 8) gl_RenderState.SetSoftLightLevel(255);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX);
gl_RenderState.BlendEquation(GL_FUNC_ADD);
}
else gl_lights = false;
@ -895,11 +903,11 @@ void GLSceneDrawer::RenderMultipassStuff()
gl_RenderState.EnableFog(false);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0);
glDepthFunc(GL_LEQUAL);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_TEXONLY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_TEXONLY);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_TEXONLY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_TEXONLY);
gl_RenderState.AlphaFunc(GL_GREATER, gl_mask_threshold);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_TEXONLY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_TEXONLY);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_TEXONLY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_TEXONLY);
// fourth pass: additive lights
gl_RenderState.EnableFog(true);
@ -907,14 +915,14 @@ void GLSceneDrawer::RenderMultipassStuff()
glDepthFunc(GL_EQUAL);
if (gl_SetupLightTexture())
{
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
}
else gl_lights = false;
@ -1001,4 +1009,4 @@ int LegacyDesaturation(F2DDrawer::RenderCommand &cmd)
auto &tbl = DesaturatedTranslationTable[cmd.mTranslation];
tbl.tables[desat] = newremap;
return newremap->GetUniqueIndex();
}
}

View file

@ -30,14 +30,10 @@
#include "gl/system/gl_system.h"
#include "tarray.h"
#include "doomtype.h"
#include "zstring.h"
#include "i_system.h"
#include "r_utility.h"
#include "w_wad.h"
#include "gl/dynlights/gl_dynlight.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/system/gl_interface.h"
#include "gl/renderer/gl_renderstate.h"
class LegacyShader

View file

@ -29,9 +29,6 @@
#include "doomtype.h"
#include "p_local.h"
#include "r_state.h"
#include "m_argv.h"
#include "c_cvars.h"
#include "g_levellocals.h"
#include "gl/system/gl_interface.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/shaders/gl_shader.h"
@ -160,13 +157,9 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
mIndex = mCurIndex = 0;
mNumReserved = NUM_RESERVED;
if (gl.buffermethod == BM_DEFERRED)
{
Map();
memcpy(map, &vbo_shadowdata[0], mNumReserved * sizeof(FFlatVertex));
Unmap();
}
Map();
memcpy(map, &vbo_shadowdata[0], mNumReserved * sizeof(FFlatVertex));
Unmap();
}
FFlatVertexBuffer::~FFlatVertexBuffer()

View file

@ -23,11 +23,15 @@
#ifndef __VERTEXBUFFER_H
#define __VERTEXBUFFER_H
#include <atomic>
#include <thread>
#include <mutex>
#include "tarray.h"
#include "gl/utility/gl_clock.h"
#include "hwrenderer/utility/hw_clock.h"
#include "gl/system/gl_interface.h"
#include "r_data/models/models.h"
#include "hwrenderer/data/flatvertices.h"
#include "hwrenderer/scene/hw_skydome.h"
struct vertex_t;
struct secplane_t;
@ -93,7 +97,8 @@ class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator
{
FFlatVertex *map;
unsigned int mIndex;
unsigned int mCurIndex;
std::atomic<unsigned int> mCurIndex;
std::mutex mBufferMutex;
unsigned int mNumReserved;
@ -125,12 +130,22 @@ public:
{
return &map[mCurIndex];
}
FFlatVertex *Alloc(int num, int *poffset)
template<class T>
FFlatVertex *Alloc(int num, T *poffset)
{
again:
FFlatVertex *p = GetBuffer();
*poffset = mCurIndex;
mCurIndex += num;
if (mCurIndex >= BUFFER_SIZE_TO_USE) mCurIndex = mIndex;
auto index = mCurIndex.fetch_add(num);
*poffset = static_cast<T>(index);
if (index + num >= BUFFER_SIZE_TO_USE)
{
std::lock_guard<std::mutex> lock(mBufferMutex);
if (mCurIndex >= BUFFER_SIZE_TO_USE) // retest condition, in case another thread got here first
mCurIndex = mIndex;
if (index >= BUFFER_SIZE_TO_USE) goto again;
}
return p;
}
@ -182,73 +197,15 @@ public:
};
struct FSkyVertex
class FSkyVertexBuffer : public FVertexBuffer, public FSkyDomeCreator
{
float x, y, z, u, v;
PalEntry color;
void Set(float xx, float zz, float yy, float uu=0, float vv=0, PalEntry col=0xffffffff)
{
x = xx;
z = zz;
y = yy;
u = uu;
v = vv;
color = col;
}
void SetXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0, PalEntry col = 0xffffffff)
{
x = xx;
y = yy;
z = zz;
u = uu;
v = vv;
color = col;
}
};
class FSkyVertexBuffer : public FVertexBuffer
{
public:
static const int SKYHEMI_UPPER = 1;
static const int SKYHEMI_LOWER = 2;
enum
{
SKYMODE_MAINLAYER = 0,
SKYMODE_SECONDLAYER = 1,
SKYMODE_FOGLAYER = 2
};
private:
TArray<FSkyVertex> mVertices;
TArray<unsigned int> mPrimStart;
int mRows, mColumns;
// indices for sky cubemap faces
int mFaceStart[7];
int mSideStart;
void SkyVertex(int r, int c, bool yflip);
void CreateSkyHemisphere(int hemi);
void CreateDome();
void RenderRow(int prim, int row);
public:
FSkyVertexBuffer();
virtual ~FSkyVertexBuffer();
void RenderDome(FMaterial *tex, int mode);
void BindVBO();
int FaceStart(int i)
{
if (i >= 0 && i < 7) return mFaceStart[i];
else return mSideStart;
}
};
class FModelVertexBuffer : public FVertexBuffer, public IModelVertexBuffer

View file

@ -28,9 +28,8 @@
#include "gl/system/gl_system.h"
#include "gl/shaders/gl_shader.h"
#include "gl/dynlights/gl_lightbuffer.h"
#include "gl/dynlights/gl_dynlight.h"
#include "gl/system/gl_interface.h"
#include "gl/utility//gl_clock.h"
#include "hwrenderer/utility/hw_clock.h"
#include "hwrenderer/dynlights/hw_dynlightdata.h"
static const int INITIAL_BUFFER_SIZE = 160000; // This means 80000 lights per frame and 160000*16 bytes == 2.56 MB.

View file

@ -2,7 +2,7 @@
#define __GL_LIGHTBUFFER_H
#include "tarray.h"
struct FDynLightData;
#include "hwrenderer/dynlights/hw_dynlightdata.h"
class FLightBuffer
{
@ -35,5 +35,9 @@ public:
int GetIndex(int i) const { return mIndices[i]; }
};
int gl_SetDynModelLight(AActor *self, int dynlightindex);
extern thread_local FDynLightData lightdata;
#endif

View file

@ -1,6 +1,6 @@
//
//---------------------------------------------------------------------------
// 1D dynamic shadow maps
// 1D dynamic shadow maps (OpenGL dependent part)
// Copyright(C) 2017 Magnus Norddahl
// All rights reserved.
//
@ -23,80 +23,15 @@
#include "gl/system/gl_system.h"
#include "gl/shaders/gl_shader.h"
#include "gl/dynlights/gl_shadowmap.h"
#include "gl/dynlights/gl_dynlight.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_debug.h"
#include "gl/system/gl_cvars.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_postprocessstate.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/shaders/gl_shadowmapshader.h"
#include "r_state.h"
#include "g_levellocals.h"
#include "hwrenderer/dynlights/hw_dynlightdata.h"
#include "stats.h"
/*
The 1D shadow maps are stored in a 1024x1024 texture as float depth values (R32F).
Each line in the texture is assigned to a single light. For example, to grab depth values for light 20
the fragment shader (main.fp) needs to sample from row 20. That is, the V texture coordinate needs
to be 20.5/1024.
mLightToShadowmap is a hash map storing which line each ADynamicLight is assigned to. The public
ShadowMapIndex function allows the main rendering to find the index and upload that along with the
normal light data. From there, the main.fp shader can sample from the shadow map texture, which
is currently always bound to texture unit 16.
The texel row for each light is split into four parts. One for each direction, like a cube texture,
but then only in 2D where this reduces itself to a square. When main.fp samples from the shadow map
it first decides in which direction the fragment is (relative to the light), like cubemap sampling does
for 3D, but once again just for the 2D case.
Texels 0-255 is Y positive, 256-511 is X positive, 512-767 is Y negative and 768-1023 is X negative.
Generating the shadow map itself is done by FShadowMap::Update(). The shadow map texture's FBO is
bound and then a screen quad is drawn to make a fragment shader cover all texels. For each fragment
it shoots a ray and collects the distance to what it hit.
The shadowmap.fp shader knows which light and texel it is processing by mapping gl_FragCoord.y back
to the light index, and it knows which direction to ray trace by looking at gl_FragCoord.x. For
example, if gl_FragCoord.y is 20.5, then it knows its processing light 20, and if gl_FragCoord.x is
127.5, then it knows we are shooting straight ahead for the Y positive direction.
Ray testing is done by uploading two GPU storage buffers - one holding AABB tree nodes, and one with
the line segments at the leaf nodes of the tree. The fragment shader then performs a test same way
as on the CPU, except everything uses indexes as pointers are not allowed in GLSL.
*/
namespace
{
cycle_t UpdateCycles;
int LightsProcessed;
int LightsShadowmapped;
}
ADD_STAT(shadowmap)
{
FString out;
out.Format("upload=%04.2f ms lights=%d shadowmapped=%d", UpdateCycles.TimeMS(), LightsProcessed, LightsShadowmapped);
return out;
}
CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
switch (self)
{
case 128:
case 256:
case 512:
case 1024:
break;
default:
self = 128;
break;
}
}
void FShadowMap::Update()
{
UpdateCycles.Reset();
@ -139,63 +74,10 @@ void FShadowMap::Update()
UpdateCycles.Unclock();
}
bool FShadowMap::ShadowTest(ADynamicLight *light, const DVector3 &pos)
{
if (light->shadowmapped && light->radius > 0.0 && IsEnabled() && mAABBTree)
return mAABBTree->RayTest(light->Pos(), pos) >= 1.0f;
else
return true;
}
bool FShadowMap::IsEnabled() const
{
return gl_light_shadowmap && !!(gl.flags & RFL_SHADER_STORAGE_BUFFER);
}
int FShadowMap::ShadowMapIndex(ADynamicLight *light)
{
if (IsEnabled())
{
auto val = mLightToShadowmap.CheckKey(light);
if (val != nullptr) return *val;
}
return 1024;
}
void FShadowMap::UploadLights()
{
if (mLights.Size() != 1024 * 4) mLights.Resize(1024 * 4);
int lightindex = 0;
mLightToShadowmap.Clear(mLightToShadowmap.CountUsed() * 2); // To do: allow clearing a TMap while building up a reserve
// Todo: this should go through the blockmap in a spiral pattern around the player so that closer lights are preferred.
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
while (auto light = it.Next())
{
LightsProcessed++;
if (light->shadowmapped)
{
LightsShadowmapped++;
mLightToShadowmap[light] = lightindex >> 2;
mLights[lightindex] = light->X();
mLights[lightindex+1] = light->Y();
mLights[lightindex+2] = light->Z();
mLights[lightindex+3] = light->GetRadius();
lightindex += 4;
if (lightindex == 1024*4) // Only 1024 lights for now
break;
}
}
for (; lightindex < 1024 * 4; lightindex++)
{
mLights[lightindex] = 0;
}
CollectLights();
if (mLightList == 0)
glGenBuffers(1, (GLuint*)&mLightList);
@ -208,28 +90,21 @@ void FShadowMap::UploadLights()
void FShadowMap::UploadAABBTree()
{
// Just comparing the level info is not enough. If two MAPINFO-less levels get played after each other,
// they can both refer to the same default level info.
if (level.info != mLastLevel && (level.nodes.Size() != mLastNumNodes || level.segs.Size() != mLastNumSegs))
Clear();
if (!ValidateAABBTree())
{
int oldBinding = 0;
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
if (mAABBTree)
return;
glGenBuffers(1, (GLuint*)&mNodesBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mNodesBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(hwrenderer::AABBTreeNode) * mAABBTree->nodes.Size(), &mAABBTree->nodes[0], GL_STATIC_DRAW);
mAABBTree.reset(new hwrenderer::LevelAABBTree());
glGenBuffers(1, (GLuint*)&mLinesBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mLinesBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(hwrenderer::AABBTreeLine) * mAABBTree->lines.Size(), &mAABBTree->lines[0], GL_STATIC_DRAW);
int oldBinding = 0;
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
glGenBuffers(1, (GLuint*)&mNodesBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mNodesBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(hwrenderer::AABBTreeNode) * mAABBTree->nodes.Size(), &mAABBTree->nodes[0], GL_STATIC_DRAW);
glGenBuffers(1, (GLuint*)&mLinesBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mLinesBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(hwrenderer::AABBTreeLine) * mAABBTree->lines.Size(), &mAABBTree->lines[0], GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
}
}
void FShadowMap::Clear()
@ -251,10 +126,4 @@ void FShadowMap::Clear()
glDeleteBuffers(1, (GLuint*)&mLinesBuffer);
mLinesBuffer = 0;
}
mAABBTree.reset();
mLastLevel = level.info;
mLastNumNodes = level.nodes.Size();
mLastNumSegs = level.segs.Size();
}

View file

@ -1,33 +1,18 @@
#pragma once
#include "hwrenderer/dynlights/hw_aabbtree.h"
#include "tarray.h"
#include <memory>
#include "hwrenderer/dynlights/hw_shadowmap.h"
class ADynamicLight;
struct level_info_t;
class FShadowMap
class FShadowMap : public IShadowMap
{
public:
FShadowMap() { }
~FShadowMap() { Clear(); }
// Release resources
void Clear();
void Clear() override;
// Update shadow map texture
void Update();
// Return the assigned shadow map index for a given light
int ShadowMapIndex(ADynamicLight *light);
// Test if a world position is in shadow relative to the specified light and returns false if it is
bool ShadowTest(ADynamicLight *light, const DVector3 &pos);
// Returns true if gl_light_shadowmap is enabled and supported by the hardware
bool IsEnabled() const;
void Update() override;
private:
// Upload the AABB-tree to the GPU
@ -39,24 +24,7 @@ private:
// OpenGL storage buffer with the list of lights in the shadow map texture
int mLightList = 0;
// Working buffer for creating the list of lights. Stored here to avoid allocating memory each frame
TArray<float> mLights;
// The assigned shadow map index for each light
TMap<ADynamicLight*, int> mLightToShadowmap;
// OpenGL storage buffers for the AABB tree
int mNodesBuffer = 0;
int mLinesBuffer = 0;
// Used to detect when a level change requires the AABB tree to be regenerated
level_info_t *mLastLevel = nullptr;
unsigned mLastNumNodes = 0;
unsigned mLastNumSegs = 0;
// AABB-tree of the level, used for ray tests
std::unique_ptr<hwrenderer::LevelAABBTree> mAABBTree;
FShadowMap(const FShadowMap &) = delete;
FShadowMap &operator=(FShadowMap &) = delete;
};

View file

@ -28,27 +28,20 @@
#include "gl/system/gl_system.h"
#include "w_wad.h"
#include "cmdlib.h"
#include "sc_man.h"
#include "m_crc32.h"
#include "c_console.h"
#include "g_game.h"
#include "doomstat.h"
#include "g_level.h"
#include "r_state.h"
#include "d_player.h"
#include "g_levellocals.h"
#include "r_utility.h"
#include "i_time.h"
//#include "resources/voxels.h"
//#include "gl/gl_intern.h"
#include "hwrenderer/textures/hw_material.h"
#include "gl/system/gl_interface.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_portal.h"
#include "gl/models/gl_models.h"
#include "gl/textures/gl_material.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/shaders/gl_shader.h"

View file

@ -1,30 +0,0 @@
#ifndef __GL_COLORMAP
#define __GL_COLORMAP
#include "doomtype.h"
#include "v_palette.h"
#include "r_data/colormaps.h"
struct lightlist_t;
enum EColorManipulation
{
CM_SPECIAL2D = -3, // the special colormaps get passed as color pair from the 2D drawer so they need a different value here.
CM_PLAIN2D = -2, // regular 2D drawing.
CM_INVALID=-1,
CM_DEFAULT=0, // untranslated
CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap
CM_FIRSTSPECIALCOLORMAPFORCED= 0x08000000, // first special fixed colormap, application forced (for 2D overlays)
CM_FOGLAYER = 0x10000000, // Sprite shaped fog layer
// These are not to be passed to the texture manager
CM_LITE = 0x20000000, // special values to handle these items without excessive hacking
CM_TORCH= 0x20000010, // These are not real color manipulations
};
#define CM_MAXCOLORMAP int(CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size())
#define CM_MAXCOLORMAPFORCED int(CM_FIRSTSPECIALCOLORMAPFORCED + SpecialColormaps.Size())
#endif

View file

@ -27,73 +27,13 @@
#include "gl/system/gl_system.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_cvars.h"
#include "gl/renderer/gl_colormap.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/shaders/gl_shader.h"
#include "gl/scene/gl_portal.h"
#include "c_dispatch.h"
#include "p_local.h"
#include "g_level.h"
#include "r_sky.h"
#include "g_levellocals.h"
// externally settable lighting properties
static float distfogtable[2][256]; // light to fog conversion table for black fog
CVAR(Int, gl_weaponlight, 8, CVAR_ARCHIVE);
CUSTOM_CVAR(Bool, gl_enhanced_nightvision, true, CVAR_ARCHIVE|CVAR_NOINITCALL)
{
// The fixed colormap state needs to be reset because if this happens when
// a shader is set to CM_LITE or CM_TORCH it won't register the change in behavior caused by this CVAR.
if (GLRenderer != nullptr && GLRenderer->mShaderManager != nullptr)
{
GLRenderer->mShaderManager->ResetFixedColormap();
}
}
//==========================================================================
//
// Sets up the fog tables
//
//==========================================================================
CUSTOM_CVAR (Int, gl_distfog, 70, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
for (int i=0;i<256;i++)
{
if (i<164)
{
distfogtable[0][i]= (gl_distfog>>1) + (gl_distfog)*(164-i)/164;
}
else if (i<230)
{
distfogtable[0][i]= (gl_distfog>>1) - (gl_distfog>>1)*(i-164)/(230-164);
}
else distfogtable[0][i]=0;
if (i<128)
{
distfogtable[1][i]= 6.f + (gl_distfog>>1) + (gl_distfog)*(128-i)/48;
}
else if (i<216)
{
distfogtable[1][i]= (216.f-i) / ((216.f-128.f)) * gl_distfog / 10;
}
else distfogtable[1][i]=0;
}
}
CUSTOM_CVAR(Int,gl_fogmode,1,CVAR_ARCHIVE|CVAR_NOINITCALL)
{
if (self>2) self=2;
if (self<0) self=0;
}
@ -149,79 +89,6 @@ void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend
}
//==========================================================================
//
// Get current light level
//
//==========================================================================
int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon)
{
int light;
if (lightlevel == 0) return 0;
if ((level.lightmode & 2) && lightlevel < 192 && !weapon)
{
if (lightlevel > 100)
{
light = xs_CRoundToInt(192.f - (192 - lightlevel)* 1.87f);
if (light + rellight < 20)
{
light = 20 + (light + rellight - 20) / 5;
}
else
{
light += rellight;
}
}
else
{
light = (lightlevel + rellight) / 5;
}
}
else
{
light=lightlevel+rellight;
}
return clamp(light, 0, 255);
}
//==========================================================================
//
// Get current light color
//
//==========================================================================
static PalEntry gl_CalcLightColor(int light, PalEntry pe, int blendfactor)
{
int r,g,b;
if (level.lightmode == 8)
{
return pe;
}
else if (blendfactor == 0)
{
r = pe.r * light / 255;
g = pe.g * light / 255;
b = pe.b * light / 255;
}
else
{
// This is what Legacy does with colored light in 3D volumes. No, it doesn't really make sense...
// It also doesn't translate well to software style lighting.
int mixlight = light * (255 - blendfactor);
r = (mixlight + pe.r * blendfactor) / 255;
g = (mixlight + pe.g * blendfactor) / 255;
b = (mixlight + pe.b * blendfactor) / 255;
}
return PalEntry(255, uint8_t(r), uint8_t(g), uint8_t(b));
}
//==========================================================================
//
// set current light color
@ -236,144 +103,13 @@ void gl_SetColor(int sectorlightlevel, int rellight, bool fullbright, const FCol
}
else
{
int hwlightlevel = gl_CalcLightLevel(sectorlightlevel, rellight, weapon);
PalEntry pe = gl_CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor);
int hwlightlevel = hw_CalcLightLevel(sectorlightlevel, rellight, weapon);
PalEntry pe = hw_CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor);
gl_RenderState.SetColorAlpha(pe, alpha, cm.Desaturation);
gl_RenderState.SetSoftLightLevel(gl_ClampLight(sectorlightlevel + rellight));
gl_RenderState.SetSoftLightLevel(hw_ClampLight(sectorlightlevel + rellight));
}
}
//==========================================================================
//
// calculates the current fog density
//
// Rules for fog:
//
// 1. If bit 4 of gl_lightmode is set always use the level's fog density.
// This is what Legacy's GL render does.
// 2. black fog means no fog and always uses the distfogtable based on the level's fog density setting
// 3. If outside fog is defined and the current fog color is the same as the outside fog
// the engine always uses the outside fog density to make the fog uniform across the level.
// If the outside fog's density is undefined it uses the level's fog density and if that is
// not defined it uses a default of 70.
// 4. If a global fog density is specified it is being used for all fog on the level
// 5. If none of the above apply fog density is based on the light level as for the software renderer.
//
//==========================================================================
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity)
{
float density;
if (level.lightmode & 4)
{
// uses approximations of Legacy's default settings.
density = level.fogdensity ? level.fogdensity : 18;
}
else if (sectorfogdensity != 0)
{
// case 1: Sector has an explicit fog density set.
density = sectorfogdensity;
}
else if ((fogcolor.d & 0xffffff) == 0)
{
// case 2: black fog
if (level.lightmode != 8 && !(level.flags3 & LEVEL3_NOLIGHTFADE))
{
density = distfogtable[level.lightmode != 0][gl_ClampLight(lightlevel)];
}
else
{
density = 0;
}
}
else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff))
{
// case 3. outsidefogdensity has already been set as needed
density = level.outsidefogdensity;
}
else if (level.fogdensity != 0)
{
// case 4: level has fog density set
density = level.fogdensity;
}
else if (lightlevel < 248)
{
// case 5: use light level
density = clamp<int>(255 - lightlevel, 30, 255);
}
else
{
density = 0.f;
}
return density;
}
//==========================================================================
//
// Check if the current linedef is a candidate for a fog boundary
//
// Requirements for a fog boundary:
// - front sector has no fog
// - back sector has fog
// - at least one of both does not have a sky ceiling.
//
//==========================================================================
bool gl_CheckFog(sector_t *frontsector, sector_t *backsector)
{
if (frontsector == backsector) return false; // there can't be a boundary if both sides are in the same sector.
// Check for fog boundaries. This needs a few more checks for the sectors
PalEntry fogcolor = frontsector->Colormap.FadeColor;
if ((fogcolor.d & 0xffffff) == 0)
{
return false;
}
else if (fogcolor.a != 0)
{
}
else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff))
{
}
else if (level.fogdensity!=0 || (level.lightmode & 4))
{
// case 3: level has fog density set
}
else
{
// case 4: use light level
if (frontsector->lightlevel >= 248) return false;
}
fogcolor = backsector->Colormap.FadeColor;
if ((fogcolor.d & 0xffffff) == 0)
{
}
else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff))
{
return false;
}
else if (level.fogdensity!=0 || (level.lightmode & 4))
{
// case 3: level has fog density set
return false;
}
else
{
// case 4: use light level
if (backsector->lightlevel < 248) return false;
}
// in all other cases this might create more problems than it solves.
return ((frontsector->GetTexture(sector_t::ceiling)!=skyflatnum ||
backsector->GetTexture(sector_t::ceiling)!=skyflatnum));
}
//==========================================================================
//
// Lighting stuff
@ -427,7 +163,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c
else if (cmap != NULL && !fullbright)
{
fogcolor = cmap->FadeColor;
fogdensity = gl_GetFogDensity(lightlevel, fogcolor, cmap->FogDensity);
fogdensity = hw_GetFogDensity(lightlevel, fogcolor, cmap->FogDensity);
fogcolor.a=0;
}
else
@ -450,7 +186,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c
{
if (level.lightmode == 2 && fogcolor == 0)
{
float light = gl_CalcLightLevel(lightlevel, rellight, false);
float light = hw_CalcLightLevel(lightlevel, rellight, false);
gl_SetShaderLight(light, lightlevel);
}
else

View file

@ -4,35 +4,15 @@
#include "v_palette.h"
#include "p_3dfloors.h"
#include "r_data/renderstyle.h"
#include "gl/renderer/gl_colormap.h"
inline int gl_ClampLight(int lightlevel)
{
return clamp(lightlevel, 0, 255);
}
#include "hwrenderer/utility/hw_lighting.h"
#include "r_data/colormaps.h"
void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending,
int *tm, int *sb, int *db, int *be);
int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon);
void gl_SetColor(int light, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon=false);
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity);
struct sector_t;
bool gl_CheckFog(sector_t *frontsector, sector_t *backsector);
void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *cm, bool isadditive);
inline bool gl_isBlack(PalEntry color)
{
return color.r + color.g + color.b == 0;
}
inline bool gl_isWhite(PalEntry color)
{
return color.r + color.g + color.b == 3*0xff;
}
#endif

View file

@ -28,23 +28,10 @@
#include "gl/system/gl_system.h"
#include "gi.h"
#include "m_png.h"
#include "m_random.h"
#include "st_stuff.h"
#include "dobject.h"
#include "doomstat.h"
#include "g_level.h"
#include "r_data/r_interpolate.h"
#include "r_utility.h"
#include "d_player.h"
#include "p_effect.h"
#include "sbar.h"
#include "po_man.h"
#include "r_utility.h"
#include "p_local.h"
#include "colormatcher.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_cvars.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "gl/system/gl_debug.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/renderer/gl_renderstate.h"
@ -60,9 +47,9 @@
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_fxaashader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/shaders/gl_postprocessshader.h"
#include "gl/shaders/gl_postprocessshaderinstance.h"
#include "gl/stereo3d/gl_stereo3d.h"
#include "gl/textures/gl_hwtexture.h"
#include "r_videoscale.h"
//==========================================================================
@ -614,7 +601,8 @@ void FGLRenderer::CreateTonemapPalette()
{
for (int b = 0; b < 64; b++)
{
PalEntry color = GPalette.BaseColors[(uint8_t)PTM_BestColor((uint32_t *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4), 0, 256)];
PalEntry color = GPalette.BaseColors[(uint8_t)PTM_BestColor((uint32_t *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4),
gl_paltonemap_reverselookup, gl_paltonemap_powtable, 0, 256)];
int index = ((r * 64 + g) * 64 + b) * 4;
lut[index] = color.b;
lut[index + 1] = color.g;
@ -927,41 +915,3 @@ void FGLRenderer::ClearBorders()
glDisable(GL_SCISSOR_TEST);
}
// [SP] Re-implemented BestColor for more precision rather than speed. This function is only ever called once until the game palette is changed.
int FGLRenderer::PTM_BestColor (const uint32_t *pal_in, int r, int g, int b, int first, int num)
{
const PalEntry *pal = (const PalEntry *)pal_in;
static double powtable[256];
static bool firstTime = true;
static float trackpowtable = 0.;
double fbestdist = DBL_MAX, fdist;
int bestcolor = 0;
if (firstTime || trackpowtable != gl_paltonemap_powtable)
{
trackpowtable = gl_paltonemap_powtable;
firstTime = false;
for (int x = 0; x < 256; x++) powtable[x] = pow((double)x/255, (double)gl_paltonemap_powtable);
}
for (int color = first; color < num; color++)
{
double x = powtable[abs(r-pal[color].r)];
double y = powtable[abs(g-pal[color].g)];
double z = powtable[abs(b-pal[color].b)];
fdist = x + y + z;
if (color == first || ((gl_paltonemap_reverselookup)?(fdist <= fbestdist):(fdist < fbestdist)))
{
if (fdist == 0 && !gl_paltonemap_reverselookup)
return color;
fbestdist = fdist;
bestcolor = color;
}
}
return bestcolor;
}

View file

@ -29,9 +29,6 @@
#include "gl/system/gl_system.h"
#include "gl/system/gl_interface.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_shader.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_postprocessstate.h"
//-----------------------------------------------------------------------------

View file

@ -23,9 +23,7 @@
#include "gl/system/gl_system.h"
#include "gl/shaders/gl_shader.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_quaddrawer.h"
#include "r_data/matrix.h"
/*
** For handling of dynamically created quads when no persistently mapped

View file

@ -26,18 +26,12 @@
*/
#include "gl/system/gl_system.h"
#include "m_swap.h"
#include "v_video.h"
#include "vectors.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_cvars.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "gl/system/gl_debug.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "w_wad.h"
#include "i_system.h"
#include "doomerrors.h"
#include <random>
CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);

View file

@ -27,13 +27,9 @@
#include "gl/system/gl_system.h"
#include "files.h"
#include "m_swap.h"
#include "v_video.h"
#include "r_data/r_translate.h"
#include "m_png.h"
#include "m_crc32.h"
#include "w_wad.h"
#include "vectors.h"
#include "doomstat.h"
#include "i_time.h"
#include "p_effect.h"
@ -42,7 +38,7 @@
#include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_cvars.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "gl/system/gl_debug.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_lightdata.h"
@ -52,8 +48,6 @@
#include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_scenedrawer.h"
#include "gl/scene/gl_swscene.h"
#include "gl/scene/gl_portal.h"
#include "gl/shaders/gl_shader.h"
#include "gl/shaders/gl_ambientshader.h"
#include "gl/shaders/gl_bloomshader.h"
#include "gl/shaders/gl_blurshader.h"
@ -64,13 +58,9 @@
#include "gl/shaders/gl_presentshader.h"
#include "gl/shaders/gl_present3dRowshader.h"
#include "gl/shaders/gl_shadowmapshader.h"
#include "gl/shaders/gl_postprocessshader.h"
#include "gl/shaders/gl_postprocessshaderinstance.h"
#include "gl/stereo3d/gl_stereo3d.h"
#include "gl/textures/gl_material.h"
#include "gl/textures/gl_samplers.h"
#include "gl/utility/gl_clock.h"
#include "gl/models/gl_models.h"
#include "gl/dynlights/gl_lightbuffer.h"
#include "r_videoscale.h"
@ -105,7 +95,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mViewVector = FVector2(0,0);
mVBO = nullptr;
mSkyVBO = nullptr;
gl_spriteindex = 0;
mShaderManager = nullptr;
mLights = nullptr;
mTonemapPalette = nullptr;
@ -168,8 +157,6 @@ void FGLRenderer::Initialize(int width, int height)
legacyShaders = new LegacyShaderContainer;
}
GetSpecialTextures();
// needed for the core profile, because someone decided it was a good idea to remove the default VAO.
if (!gl.legacyMode)
{
@ -240,16 +227,6 @@ FGLRenderer::~FGLRenderer()
delete mFXAALumaShader;
}
void FGLRenderer::GetSpecialTextures()
{
if (gl.legacyMode) glLight = TexMan.CheckForTexture("glstuff/gllight.png", ETextureType::MiscPatch);
glPart2 = TexMan.CheckForTexture("glstuff/glpart2.png", ETextureType::MiscPatch);
glPart = TexMan.CheckForTexture("glstuff/glpart.png", ETextureType::MiscPatch);
mirrorTexture = TexMan.CheckForTexture("glstuff/mirror.png", ETextureType::MiscPatch);
}
//==========================================================================
//
// Calculates the viewport values needed for 2D and 3D operations

View file

@ -9,6 +9,10 @@
#include "gl/dynlights/gl_shadowmap.h"
#include <functional>
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
struct particle_t;
class FCanvasTexture;
class FFlatVertexBuffer;
@ -47,27 +51,6 @@ class FCustomPostProcessShaders;
class GLSceneDrawer;
class SWSceneDrawer;
inline float DEG2RAD(float deg)
{
return deg * float(M_PI / 180.0);
}
inline float RAD2DEG(float deg)
{
return deg * float(180. / M_PI);
}
enum SectorRenderFlags
{
// This is used to avoid creating too many drawinfos
SSRF_RENDERFLOOR = 1,
SSRF_RENDERCEILING = 2,
SSRF_RENDER3DPLANES = 4,
SSRF_RENDERALL = 7,
SSRF_PROCESSED = 8,
SSRF_SEEN = 16,
};
struct GL_IRECT
{
int left,top;
@ -126,7 +109,6 @@ public:
AActor *mViewActor;
FShaderManager *mShaderManager;
FSamplerManager *mSamplerManager;
int gl_spriteindex;
unsigned int mFBID;
unsigned int mVAOID;
int mOldFBID;
@ -157,13 +139,6 @@ public:
FShadowMap mShadowMap;
FTextureID glLight;
FTextureID glPart2;
FTextureID glPart;
FTextureID mirrorTexture;
float mSky1Pos, mSky2Pos;
FRotator mAngles;
FVector2 mViewVector;
@ -213,7 +188,6 @@ public:
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
void DrawPresentTexture(const GL_IRECT &box, bool applyGamma);
void Flush();
void GetSpecialTextures();
void Draw2D(F2DDrawer *data);
void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV);
void WriteSavePic(player_t *player, FileWriter *file, int width, int height);
@ -228,24 +202,11 @@ public:
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
int PTM_BestColor (const uint32_t *pal_in, int r, int g, int b, int first, int num);
static float GetZNear() { return 5.f; }
static float GetZFar() { return 65536.f; }
};
enum area_t
{
area_normal,
area_below,
area_above,
area_default
};
// Global functions. Make them members of GLRenderer later?
bool gl_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector);
sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
#include "hwrenderer/scene/hw_fakeflat.h"
struct TexFilter_s
{
@ -257,4 +218,4 @@ struct TexFilter_s
extern FGLRenderer *GLRenderer;
#endif
#endif

View file

@ -27,17 +27,15 @@
#include "templates.h"
#include "doomstat.h"
#include "r_data/colormaps.h"
#include "gl/system/gl_system.h"
#include "gl/system/gl_interface.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/system/gl_cvars.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "gl/shaders/gl_shader.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_colormap.h"
#include "gl/dynlights//gl_lightbuffer.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "g_levellocals.h"
void gl_SetTextureMode(int type);
@ -69,7 +67,6 @@ void FRenderState::Reset()
currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true;
mFogColor.d = -1;
mTextureMode = -1;
mLightIndex = -1;
mDesaturation = 0;
mSrcBlend = GL_SRC_ALPHA;
mDstBlend = GL_ONE_MINUS_SRC_ALPHA;
@ -176,7 +173,7 @@ bool FRenderState::ApplyShader()
activeShader->muClipHeightDirection.Set(mClipHeightDirection);
activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.);
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
activeShader->muLightIndex.Set(-1);
activeShader->muClipSplit.Set(mClipSplit);
activeShader->muViewHeight.Set(viewheight);
activeShader->muSpecularMaterial.Set(mGlossiness, mSpecularLevel);

View file

@ -26,7 +26,8 @@
#include <string.h>
#include "gl/system/gl_interface.h"
#include "r_data/matrix.h"
#include "gl/textures/gl_material.h"
#include "hwrenderer/scene//hw_drawstructs.h"
#include "hwrenderer/textures/hw_material.h"
#include "c_cvars.h"
#include "r_defs.h"
#include "r_data/r_translate.h"
@ -34,6 +35,7 @@
class FVertexBuffer;
class FShader;
struct GLSectorPlane;
extern TArray<VSMatrix> gl_MatrixStack;
EXTERN_CVAR(Bool, gl_direct_state_change)
@ -82,7 +84,6 @@ class FRenderState
bool mBrightmapEnabled;
bool mColorMask[4];
bool currentColorMask[4];
int mLightIndex;
int mSpecialEffect;
int mTextureMode;
int mDesaturation;
@ -327,11 +328,6 @@ public:
}
}
void SetLightIndex(int n)
{
mLightIndex = n;
}
void EnableBrightmap(bool on)
{
mBrightmapEnabled = on;
@ -536,6 +532,15 @@ public:
// Backwards compatibility crap follows
void ApplyFixedFunction();
void DrawColormapOverlay();
void SetPlaneTextureRotation(GLSectorPlane *plane, FMaterial *texture)
{
if (hw_SetPlaneTextureRotation(plane, texture, mTextureMatrix))
{
EnableTextureMatrix(true);
}
}
};
extern FRenderState gl_RenderState;

View file

@ -29,18 +29,12 @@
#include "p_local.h"
#include "a_sharedglobal.h"
#include "g_levellocals.h"
#include "r_sky.h"
#include "p_effect.h"
#include "po_man.h"
#include "doomdata.h"
#include "g_levellocals.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/scene/gl_scenedrawer.h"
#include "gl/scene/gl_portal.h"
#include "gl/scene/gl_wall.h"
#include "gl/utility/gl_clock.h"
EXTERN_CVAR(Bool, gl_render_segs)
@ -91,7 +85,7 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
if (portalclip)
{
int clipres = GLRenderer->mClipPortal->ClipSeg(seg);
if (clipres == GLPortal::PClip_InFront) return;
if (clipres == PClip_InFront) return;
}
angle_t startAngle = clipper.GetClipAngle(seg->v2);
@ -146,11 +140,11 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
else
{
// clipping checks are only needed when the backsector is not the same as the front sector
CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
in_area = hw_CheckViewArea(in_area, seg->v1, seg->v2, seg->frontsector, seg->backsector);
backsector = gl_FakeFlat(seg->backsector, &bs, in_area, true);
backsector = hw_FakeFlat(seg->backsector, &bs, in_area, true);
if (gl_CheckClip(seg->sidedef, currentsector, backsector))
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
{
clipper.SafeAddClipRange(startAngle, endAngle);
}
@ -172,9 +166,9 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
{
SetupWall.Clock();
GLWall wall(this);
GLWall wall;
wall.sub = currentsubsector;
wall.Process(seg, currentsector, backsector);
wall.Process(gl_drawinfo, seg, currentsector, backsector);
rendered_lines++;
SetupWall.Unclock();
@ -369,9 +363,12 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
continue;
}
}
GLSprite sprite(this);
sprite.Process(thing, sector, false);
// If this thing is in a map section that's not in view it can't possibly be visible
if (CurrentMapSections[thing->subsector->mapsection])
{
GLSprite sprite;
sprite.Process(gl_drawinfo, thing, sector, in_area, false);
}
}
for (msecnode_t *node = sec->sectorportal_thinglist; node; node = node->m_snext)
@ -388,8 +385,8 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
}
}
GLSprite sprite(this);
sprite.Process(thing, sector, true);
GLSprite sprite;
sprite.Process(gl_drawinfo, thing, sector, gl_drawinfo->mDrawer->in_area, true);
}
SetupSprite.Unclock();
}
@ -434,12 +431,12 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
}
if (clipper.IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet.
fakesector=gl_FakeFlat(sector, &fake, in_area, false);
fakesector=hw_FakeFlat(sector, &fake, in_area, false);
if (GLRenderer->mClipPortal)
{
int clipres = GLRenderer->mClipPortal->ClipSubsector(sub);
if (clipres == GLPortal::PClip_InFront)
if (clipres == PClip_InFront)
{
line_t *line = GLRenderer->mClipPortal->ClipLine();
// The subsector is out of range, but we still have to check lines that lie directly on the boundary and may expose their upper or lower parts.
@ -461,8 +458,14 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
for (i = ParticlesInSubsec[sub->Index()]; i != NO_PARTICLE; i = Particles[i].snext)
{
GLSprite sprite(this);
sprite.ProcessParticle(&Particles[i], fakesector);
if (GLRenderer->mClipPortal)
{
int clipres = GLRenderer->mClipPortal->ClipPoint(Particles[i].Pos);
if (clipres == PClip_InFront) continue;
}
GLSprite sprite;
sprite.ProcessParticle(gl_drawinfo, &Particles[i], fakesector);
}
SetupSprite.Unclock();
}
@ -501,7 +504,7 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
sector = sub->render_sector;
// the planes of this subsector are faked to belong to another sector
// This means we need the heightsec parts and light info of the render sector, not the actual one.
fakesector = gl_FakeFlat(sector, &fake, in_area, false);
fakesector = hw_FakeFlat(sector, &fake, in_area, false);
}
uint8_t &srf = gl_drawinfo->sectorrenderflags[sub->render_sector->sectornum];
@ -510,8 +513,8 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
srf |= SSRF_PROCESSED;
SetupFlat.Clock();
GLFlat flat(this);
flat.ProcessSector(fakesector);
GLFlat flat;
flat.ProcessSector(gl_drawinfo, fakesector);
SetupFlat.Unclock();
}
// mark subsector as processed - but mark for rendering only if it has an actual area.

View file

@ -1,398 +0,0 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2003-2016 Christoph Oelckers
// 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_decal.cpp
** OpenGL decal rendering code
**
*/
#include "doomdata.h"
#include "gl/system/gl_system.h"
#include "a_sharedglobal.h"
#include "r_utility.h"
#include "g_levellocals.h"
#include "gl/system/gl_cvars.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_scenedrawer.h"
#include "gl/shaders/gl_shader.h"
#include "gl/textures/gl_material.h"
#include "gl/utility/gl_clock.h"
#include "gl/renderer/gl_quaddrawer.h"
struct DecalVertex
{
float x,y,z;
float u,v;
};
//==========================================================================
//
//
//
//==========================================================================
void GLWall::DrawDecal(DBaseDecal *decal)
{
line_t * line=seg->linedef;
side_t * side=seg->sidedef;
int i;
float zpos;
int light;
int rel;
float a;
bool flipx, flipy;
DecalVertex dv[4];
FTextureID decalTile;
if (decal->RenderFlags & RF_INVISIBLE) return;
if (type==RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures.
//if (decal->sprite != 0xffff)
{
decalTile = decal->PicNum;
flipx = !!(decal->RenderFlags & RF_XFLIP);
flipy = !!(decal->RenderFlags & RF_YFLIP);
}
/*
else
{
decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0];
flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1;
}
*/
FTexture *texture = TexMan[decalTile];
if (texture == NULL) return;
FMaterial *tex;
tex = FMaterial::ValidateTexture(texture, true);
// the sectors are only used for their texture origin coordinates
// so we don't need the fake sectors for deep water etc.
// As this is a completely split wall fragment no further splits are
// necessary for the decal.
sector_t *frontsector;
// for 3d-floor segments use the model sector as reference
if ((decal->RenderFlags&RF_CLIPMASK)==RF_CLIPMID) frontsector=decal->Sector;
else frontsector=seg->frontsector;
switch (decal->RenderFlags & RF_RELMASK)
{
default:
// No valid decal can have this type. If one is encountered anyway
// it is in some way invalid so skip it.
return;
//zpos = decal->z;
//break;
case RF_RELUPPER:
if (type!=RENDERWALL_TOP) return;
if (line->flags & ML_DONTPEGTOP)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
else
{
zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling);
}
break;
case RF_RELLOWER:
if (type!=RENDERWALL_BOTTOM) return;
if (line->flags & ML_DONTPEGBOTTOM)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
else
{
zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor);
}
break;
case RF_RELMID:
if (type==RENDERWALL_TOP || type==RENDERWALL_BOTTOM) return;
if (line->flags & ML_DONTPEGBOTTOM)
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor);
}
else
{
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
}
if (decal->RenderFlags & RF_FULLBRIGHT)
{
light = 255;
rel = 0;
}
else
{
light = lightlevel;
rel = rellight + getExtraLight();
}
FColormap p = Colormap;
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)
{
p.Decolorize();
}
a = decal->Alpha;
// now clip the decal to the actual polygon
float decalwidth = tex->TextureWidth() * decal->ScaleX;
float decalheight= tex->TextureHeight() * decal->ScaleY;
float decallefto = tex->GetLeftOffset() * decal->ScaleX;
float decaltopo = tex->GetTopOffset() * decal->ScaleY;
float leftedge = glseg.fracleft * side->TexelLength;
float linelength = glseg.fracright * side->TexelLength - leftedge;
// texel index of the decal's left edge
float decalpixpos = (float)side->TexelLength * decal->LeftDistance - (flipx? decalwidth-decallefto : decallefto) - leftedge;
float left,right;
float lefttex,righttex;
// decal is off the left edge
if (decalpixpos < 0)
{
left = 0;
lefttex = -decalpixpos;
}
else
{
left = decalpixpos;
lefttex = 0;
}
// decal is off the right edge
if (decalpixpos + decalwidth > linelength)
{
right = linelength;
righttex = right - decalpixpos;
}
else
{
right = decalpixpos + decalwidth;
righttex = decalwidth;
}
if (right<=left) return; // nothing to draw
// one texture unit on the wall as vector
float vx=(glseg.x2-glseg.x1)/linelength;
float vy=(glseg.y2-glseg.y1)/linelength;
dv[1].x=dv[0].x=glseg.x1+vx*left;
dv[1].y=dv[0].y=glseg.y1+vy*left;
dv[3].x=dv[2].x=glseg.x1+vx*right;
dv[3].y=dv[2].y=glseg.y1+vy*right;
zpos+= (flipy? decalheight-decaltopo : decaltopo);
dv[1].z=dv[2].z = zpos;
dv[0].z=dv[3].z = dv[1].z - decalheight;
dv[1].v=dv[2].v = tex->GetVT();
dv[1].u=dv[0].u = tex->GetU(lefttex / decal->ScaleX);
dv[3].u=dv[2].u = tex->GetU(righttex / decal->ScaleX);
dv[0].v=dv[3].v = tex->GetVB();
// now clip to the top plane
float vzt=(ztop[1]-ztop[0])/linelength;
float topleft=this->ztop[0]+vzt*left;
float topright=this->ztop[0]+vzt*right;
// completely below the wall
if (topleft<dv[0].z && topright<dv[3].z)
return;
if (topleft<dv[1].z || topright<dv[2].z)
{
// decal has to be clipped at the top
// let texture clamping handle all extreme cases
dv[1].v=(dv[1].z-topleft)/(dv[1].z-dv[0].z)*dv[0].v;
dv[2].v=(dv[2].z-topright)/(dv[2].z-dv[3].z)*dv[3].v;
dv[1].z=topleft;
dv[2].z=topright;
}
// now clip to the bottom plane
float vzb=(zbottom[1]-zbottom[0])/linelength;
float bottomleft=this->zbottom[0]+vzb*left;
float bottomright=this->zbottom[0]+vzb*right;
// completely above the wall
if (bottomleft>dv[1].z && bottomright>dv[2].z)
return;
if (bottomleft>dv[0].z || bottomright>dv[3].z)
{
// decal has to be clipped at the bottom
// let texture clamping handle all extreme cases
dv[0].v=(dv[1].z-bottomleft)/(dv[1].z-dv[0].z)*(dv[0].v-dv[1].v) + dv[1].v;
dv[3].v=(dv[2].z-bottomright)/(dv[2].z-dv[3].z)*(dv[3].v-dv[2].v) + dv[2].v;
dv[0].z=bottomleft;
dv[3].z=bottomright;
}
if (flipx)
{
float ur = tex->GetUR();
for(i=0;i<4;i++) dv[i].u=ur-dv[i].u;
}
if (flipy)
{
float vb = tex->GetVB();
for(i=0;i<4;i++) dv[i].v=vb-dv[i].v;
}
// calculate dynamic light effect.
if (gl_lights && GLRenderer->mLightCount && !mDrawer->FixedColormap && gl_light_sprites)
{
// Note: This should be replaced with proper shader based lighting.
double x, y;
decal->GetXY(seg->sidedef, x, y);
gl_SetDynSpriteLight(nullptr, x, y, zpos - decalheight * 0.5f, sub);
}
// alpha color only has an effect when using an alpha texture.
if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha)
{
gl_RenderState.SetObjectColor(decal->AlphaColor|0xff000000);
}
gl_SetRenderStyle(decal->RenderStyle, false, false);
gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha));
// If srcalpha is one it looks better with a higher alpha threshold
if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
else gl_RenderState.AlphaFunc(GL_GREATER, 0.f);
mDrawer->SetColor(light, rel, p, a);
// for additively drawn decals we must temporarily set the fog color to black.
PalEntry fc = gl_RenderState.GetFogColor();
if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One)
{
gl_RenderState.SetFog(0,-1);
}
gl_RenderState.SetNormal(glseg.Normal());
FQuadDrawer qd;
for (i = 0; i < 4; i++)
{
qd.Set(i, dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v);
}
if (lightlist == NULL)
{
gl_RenderState.Apply();
qd.Render(GL_TRIANGLE_FAN);
}
else
{
for (unsigned k = 0; k < lightlist->Size(); k++)
{
secplane_t &lowplane = k == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[k + 1].plane;
float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y);
float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y);
if (low1 < dv[1].z || low2 < dv[2].z)
{
int thisll = (*lightlist)[k].caster != NULL ? gl_ClampLight(*(*lightlist)[k].p_lightlevel) : lightlevel;
FColormap thiscm;
thiscm.FadeColor = Colormap.FadeColor;
thiscm.CopyFrom3DLight(&(*lightlist)[k]);
mDrawer->SetColor(thisll, rel, thiscm, a);
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize();
mDrawer->SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add);
gl_RenderState.SetSplitPlanes((*lightlist)[k].plane, lowplane);
gl_RenderState.Apply();
qd.Render(GL_TRIANGLE_FAN);
}
if (low1 <= dv[0].z && low2 <= dv[3].z) break;
}
}
rendered_decals++;
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.SetObjectColor(0xffffffff);
gl_RenderState.SetFog(fc,-1);
gl_RenderState.SetDynLight(0,0,0);
}
//==========================================================================
//
//
//
//==========================================================================
void GLWall::DoDrawDecals()
{
if (seg->sidedef && seg->sidedef->AttachedDecals)
{
if (lightlist != NULL)
{
gl_RenderState.EnableSplit(true);
}
else
{
mDrawer->SetFog(lightlevel, rellight + getExtraLight(), &Colormap, false);
}
DBaseDecal *decal = seg->sidedef->AttachedDecals;
while (decal)
{
DrawDecal(decal);
decal = decal->WallNext;
}
if (lightlist != NULL)
{
gl_RenderState.EnableSplit(false);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,13 @@
#ifndef __GL_DRAWINFO_H
#define __GL_DRAWINFO_H
#include "gl/scene/gl_wall.h"
#include "hwrenderer/scene/hw_drawlist.h"
enum GLDrawItemType
{
GLDIT_WALL,
GLDIT_FLAT,
GLDIT_SPRITE,
};
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
class GLSceneDrawer;
enum DrawListType
{
@ -18,10 +17,10 @@ enum DrawListType
GLDL_MASKEDFLATS,
GLDL_MASKEDWALLSOFS,
GLDL_MODELS,
GLDL_TRANSLUCENT,
GLDL_TRANSLUCENTBORDER,
GLDL_TYPES,
};
@ -31,16 +30,16 @@ enum DLDrawListType
// These are organized so that the various multipass rendering modes have to be set as few times as possible
GLLDL_WALLS_PLAIN, // dynamic lights on normal walls
GLLDL_WALLS_MASKED, // dynamic lights on masked midtextures
GLLDL_FLATS_PLAIN, // dynamic lights on normal flats
GLLDL_FLATS_MASKED, // dynamic lights on masked flats
GLLDL_WALLS_FOG, // lights on fogged walls
GLLDL_WALLS_FOGMASKED, // lights on fogged masked midtextures
GLLDL_FLATS_FOG, // lights on fogged walls
GLLDL_FLATS_FOGMASKED, // lights on fogged masked midtextures
GLLDL_TYPES,
};
@ -52,7 +51,7 @@ enum Drawpasses
GLPASS_PLAIN, // Main pass without dynamic lights
GLPASS_DECALS, // Draws a decal
GLPASS_TRANSLUCENT, // Draws translucent objects
// these are only used with texture based dynamic lights
GLPASS_BASE, // untextured base for dynamic lights
GLPASS_BASE_MASKED, // same but with active texture
@ -60,226 +59,86 @@ enum Drawpasses
GLPASS_TEXONLY, // finishing texture pass
GLPASS_LIGHTTEX_ADDITIVE, // lighttexture pass (additive)
GLPASS_LIGHTTEX_FOGGY, // lighttexture pass on foggy surfaces (forces all lights to be additive)
};
//==========================================================================
//
// Intermediate struct to link one draw item into a draw list
//
// unfortunately this struct must not contain pointers because
// the arrays may be reallocated!
//
//==========================================================================
struct GLDrawItem
{
GLDrawItemType rendertype;
int index;
GLDrawItem(GLDrawItemType _rendertype,int _index) : rendertype(_rendertype),index(_index) {}
};
struct SortNode
{
int itemindex;
SortNode * parent;
SortNode * next; // unsorted successor
SortNode * left; // left side of this node
SortNode * equal; // equal to this node
SortNode * right; // right side of this node
void UnlinkFromChain();
void Link(SortNode * hook);
void AddToEqual(SortNode * newnode);
void AddToLeft (SortNode * newnode);
void AddToRight(SortNode * newnode);
};
//==========================================================================
//
// One draw list. This contains all info for one type of rendering data
//
//==========================================================================
struct GLDrawList
{
//private:
TArray<GLWall> walls;
TArray<GLFlat> flats;
TArray<GLSprite> sprites;
TArray<GLDrawItem> drawitems;
int SortNodeStart;
SortNode * sorted;
public:
GLDrawList()
{
next=NULL;
SortNodeStart=-1;
sorted=NULL;
}
~GLDrawList()
{
Reset();
}
unsigned int Size()
{
return drawitems.Size();
}
void AddWall(GLWall * wall);
void AddFlat(GLFlat * flat);
void AddSprite(GLSprite * sprite);
void Reset();
void SortWalls();
void SortFlats();
void MakeSortList();
SortNode * FindSortPlane(SortNode * head);
SortNode * FindSortWall(SortNode * head);
void SortPlaneIntoPlane(SortNode * head,SortNode * sort);
void SortWallIntoPlane(SortNode * head,SortNode * sort);
void SortSpriteIntoPlane(SortNode * head,SortNode * sort);
void SortWallIntoWall(SortNode * head,SortNode * sort);
void SortSpriteIntoWall(SortNode * head,SortNode * sort);
int CompareSprites(SortNode * a,SortNode * b);
SortNode * SortSpriteList(SortNode * head);
SortNode * DoSort(SortNode * head);
void DoDraw(int pass, int index, bool trans);
void DoDrawSorted(SortNode * node);
void DrawSorted();
void Draw(int pass, bool trans = false);
void DrawWalls(int pass);
void DrawFlats(int pass);
void DrawDecals();
GLDrawList * next;
} ;
//==========================================================================
//
// these are used to link faked planes due to missing textures to a sector
//
//==========================================================================
struct gl_subsectorrendernode
{
gl_subsectorrendernode * next;
subsector_t * sub;
};
struct FDrawInfo
struct FDrawInfo : public HWDrawInfo
{
struct wallseg
{
float x1, y1, z1, x2, y2, z2;
};
bool temporary;
struct MissingTextureInfo
{
seg_t * seg;
subsector_t * sub;
float Planez;
float Planezfront;
};
struct MissingSegInfo
{
seg_t * seg;
int MTI_Index; // tells us which MissingTextureInfo represents this seg.
};
struct SubsectorHackInfo
{
subsector_t * sub;
uint8_t flags;
};
GLSceneDrawer *mDrawer;
TArray<uint8_t> sectorrenderflags;
TArray<uint8_t> ss_renderflags;
TArray<uint8_t> no_renderflags;
TArray<MissingTextureInfo> MissingUpperTextures;
TArray<MissingTextureInfo> MissingLowerTextures;
TArray<MissingSegInfo> MissingUpperSegs;
TArray<MissingSegInfo> MissingLowerSegs;
TArray<SubsectorHackInfo> SubsectorHacks;
TArray<gl_subsectorrendernode*> otherfloorplanes;
TArray<gl_subsectorrendernode*> otherceilingplanes;
TArray<sector_t *> CeilingStacks;
TArray<sector_t *> FloorStacks;
TArray<subsector_t *> HandledSubsectors;
FDrawInfo * next;
GLDrawList drawlists[GLDL_TYPES];
GLDrawList *dldrawlists = NULL; // only gets allocated when needed.
HWDrawList drawlists[GLDL_TYPES];
TArray<GLDecal *> decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
HWDrawList *dldrawlists = NULL; // only gets allocated when needed.
FDrawInfo();
~FDrawInfo();
void ClearBuffers();
void AddWall(GLWall *wall) override;
void AddMirrorSurface(GLWall *w) override;
GLDecal *AddDecal(bool onmirror) override;
void AddPortal(GLWall *w, int portaltype) override;
void AddFlat(GLFlat *flat, bool fog) override;
void AddSprite(GLSprite *sprite, bool translucent) override;
void AddWall(GLWall *wall);
bool PutWallCompat(GLWall *wall, int passflag); // Legacy GL only.
std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) override;
bool DoOneSectorUpper(subsector_t * subsec, float planez);
bool DoOneSectorLower(subsector_t * subsec, float planez);
bool DoFakeBridge(subsector_t * subsec, float planez);
bool DoFakeCeilingBridge(subsector_t * subsec, float planez);
// Legacy GL only.
bool PutWallCompat(GLWall *wall, int passflag);
bool PutFlatCompat(GLFlat *flat, bool fog);
void RenderFogBoundaryCompat(GLWall *wall);
void RenderLightsCompat(GLWall *wall, int pass);
void DrawSubsectorLights(GLFlat *flat, subsector_t * sub, int pass);
void DrawLightsCompat(GLFlat *flat, int pass);
bool CheckAnchorFloor(subsector_t * sub);
bool CollectSubsectorsFloor(subsector_t * sub, sector_t * anchor);
bool CheckAnchorCeiling(subsector_t * sub);
bool CollectSubsectorsCeiling(subsector_t * sub, sector_t * anchor);
void CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor);
void CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor);
void AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight);
void AddLowerMissingTexture(side_t * side, subsector_t *sub, float backheight);
void HandleMissingTextures();
void DrawUnhandledMissingTextures();
void AddHackedSubsector(subsector_t * sub);
void HandleHackedSubsectors();
void AddFloorStack(sector_t * sec);
void AddCeilingStack(sector_t * sec);
void ProcessSectorStacks();
void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node);
void AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node);
void DrawDecal(GLDecal *gldecal);
void DrawDecals();
void DrawDecalsForMirror(GLWall *wall);
void StartScene();
void SetupFloodStencil(wallseg * ws);
void ClearFloodStencil(wallseg * ws);
void DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling);
void FloodUpperGap(seg_t * seg);
void FloodLowerGap(seg_t * seg);
void FloodUpperGap(seg_t * seg) override;
void FloodLowerGap(seg_t * seg) override;
// Wall drawer
void RenderWall(GLWall *wall, int textured);
void RenderFogBoundary(GLWall *wall);
void RenderMirrorSurface(GLWall *wall);
void RenderTranslucentWall(GLWall *wall);
void RenderTexturedWall(GLWall *wall, int rflags);
void DrawWall(GLWall *wall, int pass) override;
// Flat drawer
void DrawFlat(GLFlat *flat, int pass, bool trans) override; // trans only has meaning for GLPASS_LIGHTSONLY
void DrawSkyboxSector(GLFlat *flat, int pass, bool processlights);
void DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool istrans);
void ProcessLights(GLFlat *flat, bool istrans);
void DrawSubsector(GLFlat *flat, subsector_t * sub);
void SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli);
// Sprite drawer
void DrawSprite(GLSprite *sprite, int pass);
void DoDrawSorted(HWDrawList *dl, SortNode * head);
void DrawSorted(int listindex);
// These two may be moved to the API independent part of the renderer later.
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs) override;
void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) override;
int ClipPoint(const DVector3 &pos) override;
static void StartDrawInfo(GLSceneDrawer *drawer);
static void EndDrawInfo();
gl_subsectorrendernode * GetOtherFloorPlanes(unsigned int sector)
{
if (sector<otherfloorplanes.Size()) return otherfloorplanes[sector];
else return NULL;
}
gl_subsectorrendernode * GetOtherCeilingPlanes(unsigned int sector)
{
if (sector<otherceilingplanes.Size()) return otherceilingplanes[sector];
@ -290,9 +149,9 @@ struct FDrawInfo
class FDrawInfoList
{
TDeletingArray<FDrawInfo *> mList;
public:
FDrawInfo *GetNew();
void Release(FDrawInfo *);
};
@ -300,7 +159,6 @@ public:
extern FDrawInfo * gl_drawinfo;
void gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture);
void gl_SetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending);
#endif
#endif

Some files were not shown because too many files have changed in this diff Show more