diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b0a593bb16d760950c71623f49e7349abd1df8ad..7a3f0564d3dc269239dcccae7e0e1af7200ae9e7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -418,6 +418,7 @@ endif() if(${SRB2_CONFIG_HWRENDER}) add_definitions(-DHWRENDER) set(SRB2_HWRENDER_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c @@ -433,6 +434,7 @@ if(${SRB2_CONFIG_HWRENDER}) ) set (SRB2_HWRENDER_HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h diff --git a/src/Makefile b/src/Makefile index fdf9c78b774b513ee5650654c32913e468d77d83..e00c84bc9ff63277e33a23b6fbab392c6c94a384 100644 --- a/src/Makefile +++ b/src/Makefile @@ -222,12 +222,10 @@ endif ifdef NOHW OPTS+=-DNOHW else - #Hurdler: not really supported and not tested recently - #OPTS+=-DUSE_PALETTED_TEXTURE OPTS+=-DHWRENDER OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \ - $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o + $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o endif ifdef NOHS diff --git a/src/console.c b/src/console.c index 0f1ccbd33b02269e167ecfe9816b2164e77b09ca..a172aa412418341a073bdcbcf58283816610de6f 100644 --- a/src/console.c +++ b/src/console.c @@ -1649,10 +1649,7 @@ void CON_Drawer(void) return; if (needpatchrecache) - { - W_FlushCachedPatches(); HU_LoadGraphics(); - } if (con_recalc) { diff --git a/src/d_main.c b/src/d_main.c index 902074947a8b25d12f355ecaecc34b18ad7295d2..6057e65a770056ae74ff92dd9e05a83fa5decb37 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -416,6 +416,7 @@ static void D_Display(void) if (!automapactive && !dedicated && cv_renderview.value) { + rs_rendercalltime = I_GetTimeMicros(); if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) { topleft = screens[0] + viewwindowy*vid.width + viewwindowx; @@ -462,6 +463,7 @@ static void D_Display(void) if (postimgtype2) V_DoPostProcessor(1, postimgtype2, postimgparam2); } + rs_rendercalltime = I_GetTimeMicros() - rs_rendercalltime; } if (lastdraw) @@ -596,23 +598,97 @@ static void D_Display(void) snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent); V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s); } + + if (cv_renderstats.value) + { + char s[50]; + int frametime = I_GetTimeMicros() - rs_prevframetime; + int divisor = 1; + rs_prevframetime = I_GetTimeMicros(); + + if (rs_rendercalltime > 10000) divisor = 1000; + + snprintf(s, sizeof s - 1, "ft %d", frametime / divisor); + V_DrawThinString(30, 10, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "rtot %d", rs_rendercalltime / divisor); + V_DrawThinString(30, 20, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "bsp %d", rs_bsptime / divisor); + V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "nbsp %d", rs_numbspcalls); + V_DrawThinString(80, 10, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "nspr %d", rs_numsprites); + V_DrawThinString(80, 20, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "nnod %d", rs_numdrawnodes); + V_DrawThinString(80, 30, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "npob %d", rs_numpolyobjects); + V_DrawThinString(80, 40, V_MONOSPACE | V_BLUEMAP, s); + if (rendermode == render_opengl) // OpenGL specific stats + { + snprintf(s, sizeof s - 1, "nsrt %d", rs_hw_nodesorttime / divisor); + V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "ndrw %d", rs_hw_nodedrawtime / divisor); + V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "ssrt %d", rs_hw_spritesorttime / divisor); + V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "sdrw %d", rs_hw_spritedrawtime / divisor); + V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor); + V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s); + if (cv_grbatching.value) + { + snprintf(s, sizeof s - 1, "bsrt %d", rs_hw_batchsorttime / divisor); + V_DrawThinString(80, 55, V_MONOSPACE | V_REDMAP, s); + snprintf(s, sizeof s - 1, "bdrw %d", rs_hw_batchdrawtime / divisor); + V_DrawThinString(80, 65, V_MONOSPACE | V_REDMAP, s); + + snprintf(s, sizeof s - 1, "npol %d", rs_hw_numpolys); + V_DrawThinString(130, 10, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "ndc %d", rs_hw_numcalls); + V_DrawThinString(130, 20, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "nshd %d", rs_hw_numshaders); + V_DrawThinString(130, 30, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "nvrt %d", rs_hw_numverts); + V_DrawThinString(130, 40, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "ntex %d", rs_hw_numtextures); + V_DrawThinString(185, 10, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "npf %d", rs_hw_numpolyflags); + V_DrawThinString(185, 20, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "ncol %d", rs_hw_numcolors); + V_DrawThinString(185, 30, V_MONOSPACE | V_PURPLEMAP, s); + } + } + else // software specific stats + { + snprintf(s, sizeof s - 1, "prtl %d", rs_sw_portaltime / divisor); + V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "plns %d", rs_sw_planetime / divisor); + V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "mskd %d", rs_sw_maskedtime / divisor); + V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor); + V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s); + } + } + rs_swaptime = I_GetTimeMicros(); I_FinishUpdate(); // page flip or blit buffer + rs_swaptime = I_GetTimeMicros() - rs_swaptime; } needpatchflush = false; needpatchrecache = false; } -// Lactozilla: Check the renderer's state +// Check the renderer's state // after a possible renderer switch. void D_CheckRendererState(void) { // flush all patches from memory - // (also frees memory tagged with PU_CACHE) - // (which are not necessarily patches but I don't care) if (needpatchflush) + { Z_FlushCachedPatches(); + needpatchflush = false; + } // some patches have been freed, // so cache them again @@ -668,7 +744,7 @@ void D_SRB2Loop(void) */ /* Smells like a hack... Don't fade Sonic's ass into the title screen. */ if (gamestate != GS_TITLESCREEN) - V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE)); + V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_PATCH)); for (;;) { diff --git a/src/dehacked.c b/src/dehacked.c index dba759894ab2e857e14dd3d1d34fc508ba7136e4..88aaeac5473a0a3328cc432946316774f93af6fe 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9364,8 +9364,6 @@ static const char *const MENUTYPES_LIST[] = { "OP_COLOR", "OP_OPENGL", "OP_OPENGL_LIGHTING", - "OP_OPENGL_FOG", - "OP_OPENGL_COLOR", "OP_SOUND", diff --git a/src/doomdef.h b/src/doomdef.h index 1cb491a10ab65fe032afd9af873b6b3088f2c722..64bf217d34fea0e30935a3bd55cfc21b4aa23f35 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -638,17 +638,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +/// OpenGL shaders +#define GL_SHADERS + /// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink. /// \note Required for proper collision with moving sloped surfaces that have sector specials on them. #define SECTORSPECIALSAFTERTHINK -/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up -/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down) -/// on the bright side it fixes some weird issues with translucent walls -/// \note SRB2CB port. -/// SRB2CB itself ported this from PrBoom+ -#define NEWCLIP - /// Cache patches in Lua in a way that renderer switching will work flawlessly. //#define LUA_PATCH_SAFETY diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index 5c0f7eb99ed6ab0d41fc93bcfd87fc89ab8d044b..4a657ed19db3cb0166c10c3d9f38bd28a54b139f 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -16,6 +16,11 @@ tic_t I_GetTime(void) return 0; } +int I_GetTimeMicros(void) +{ + return 0; +} + void I_Sleep(void){} void I_GetEvent(void){} diff --git a/src/hardware/hw3dsdrv.h b/src/hardware/hw3dsdrv.h index 8811d4546df376aa72a2524ad184a66e16db706c..9b8670705989d1e63e8fbc5b99244bc0f78c92ba 100644 --- a/src/hardware/hw3dsdrv.h +++ b/src/hardware/hw3dsdrv.h @@ -1,20 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3dsdrv.h /// \brief 3D sound import/export prototypes for low-level hardware interface #ifndef __HW_3DS_DRV_H__ diff --git a/src/hardware/hw3sound.c b/src/hardware/hw3sound.c index 7858640c018ac1c15609e7b0387c182efaf868cb..81f1d8e68fadf94e69c97e02daa65e3ecccf36ab 100644 --- a/src/hardware/hw3sound.c +++ b/src/hardware/hw3sound.c @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3sound.c /// \brief Hardware 3D sound general code #include "../doomdef.h" diff --git a/src/hardware/hw3sound.h b/src/hardware/hw3sound.h index a8a475b69d75c08fee44d1c825d31529e6feabe1..1796dd6963ac46d69949f90a410098c07adadc68 100644 --- a/src/hardware/hw3sound.h +++ b/src/hardware/hw3sound.h @@ -1,20 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3sound.h /// \brief High-level functions of hardware 3D sound #ifndef __HW3_SOUND_H__ diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c new file mode 100644 index 0000000000000000000000000000000000000000..67cda03058309ba15f48231b179e4bb83ec7eb10 --- /dev/null +++ b/src/hardware/hw_batching.c @@ -0,0 +1,454 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.c +/// \brief Draw call batching and related things. + +#ifdef HWRENDER +#include "hw_glob.h" +#include "hw_batching.h" +#include "../i_system.h" + +// The texture for the next polygon given to HWR_ProcessPolygon. +// Set with HWR_SetCurrentTexture. +GLMipmap_t *current_texture = NULL; + +boolean currently_batching = false; + +FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu +UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion +// NOTE have this alloced as 3x finalVertexArray size +int finalVertexArrayAllocSize = 65536; +//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed +//int colorArrayAllocSize = 65536; +// not gonna use this for now, just sort by color and change state when it changes +// later maybe when using vertex attributes if it's needed + +PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed +int polygonArraySize = 0; +UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray +int polygonArrayAllocSize = 65536; + +FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon +int unsortedVertexArraySize = 0; +int unsortedVertexArrayAllocSize = 65536; + +// Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend. +// Call HWR_RenderBatches to render all the collected geometry. +void HWR_StartBatching(void) +{ + if (currently_batching) + I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches"); + + // init arrays if that has not been done yet + if (!finalVertexArray) + { + finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + } + + currently_batching = true; +} + +// This replaces the direct calls to pfnSetTexture in cases where batching is available. +// The texture selection is saved for the next HWR_ProcessPolygon call. +// Doing this was easier than getting a texture pointer to HWR_ProcessPolygon. +void HWR_SetCurrentTexture(GLMipmap_t *texture) +{ + if (currently_batching) + { + current_texture = texture; + } + else + { + HWD.pfnSetTexture(texture); + } +} + +// If batching is enabled, this function collects the polygon data and the chosen texture +// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to +// render the polygon immediately. +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +{ + if (currently_batching) + { + if (!pSurf) + I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to + if (polygonArraySize == polygonArrayAllocSize) + { + PolygonArrayEntry* new_array; + // ran out of space, make new array double the size + polygonArrayAllocSize *= 2; + new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); + free(polygonArray); + polygonArray = new_array; + // also need to redo the index array, dont need to copy it though + free(polygonIndexArray); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + } + + while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) + { + FOutVector* new_array; + // need more space for vertices in unsortedVertexArray + unsortedVertexArrayAllocSize *= 2; + new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); + free(unsortedVertexArray); + unsortedVertexArray = new_array; + } + + // add the polygon data to the arrays + + polygonArray[polygonArraySize].surf = *pSurf; + polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; + polygonArray[polygonArraySize].numVerts = iNumPts; + polygonArray[polygonArraySize].polyFlags = PolyFlags; + polygonArray[polygonArraySize].texture = current_texture; + polygonArray[polygonArraySize].shader = shader; + polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; + polygonArraySize++; + + memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); + unsortedVertexArraySize += iNumPts; + } + else + { + if (shader) + HWD.pfnSetShader(shader); + HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); + } +} + +static int comparePolygons(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + + int shader1 = poly1->shader; + int shader2 = poly2->shader; + // make skywalls and horizon lines first in order + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + shader1 = -1; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + shader2 = -1; + diff = shader1 - shader2; + if (diff != 0) return diff; + + // skywalls and horizon lines must retain their order for horizon lines to work + if (shader1 == -1 && shader2 == -1) + return index1 - index2; + + diff64 = poly1->texture - poly2->texture; + if (diff64 != 0) return diff64; + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level; + if (diff != 0) return diff; + diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start; + if (diff != 0) return diff; + diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end; + return diff; +} + +static int comparePolygonsNoShaders(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + + GLMipmap_t *texture1 = poly1->texture; + GLMipmap_t *texture2 = poly2->texture; + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + texture1 = NULL; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + texture2 = NULL; + diff64 = texture1 - texture2; + if (diff64 != 0) return diff64; + + // skywalls and horizon lines must retain their order for horizon lines to work + if (texture1 == NULL && texture2 == NULL) + return index1 - index2; + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + return 0; +} + +// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses +// the rendering backend to draw them. +void HWR_RenderBatches(void) +{ + int finalVertexWritePos = 0;// position in finalVertexArray + int finalIndexWritePos = 0;// position in finalVertexIndexArray + + int polygonReadPos = 0;// position in polygonIndexArray + + int currentShader; + int nextShader = 0; + GLMipmap_t *currentTexture; + GLMipmap_t *nextTexture = NULL; + FBITFIELD currentPolyFlags = 0; + FBITFIELD nextPolyFlags = 0; + FSurfaceInfo currentSurfaceInfo; + FSurfaceInfo nextSurfaceInfo; + + int i; + + if (!currently_batching) + I_Error("HWR_RenderBatches called without starting batching"); + + nextSurfaceInfo.LightInfo.fade_end = 0; + nextSurfaceInfo.LightInfo.fade_start = 0; + nextSurfaceInfo.LightInfo.light_level = 0; + + currently_batching = false;// no longer collecting batches + if (!polygonArraySize) + { + rs_hw_numpolys = rs_hw_numcalls = rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 0; + return;// nothing to draw + } + // init stats vars + rs_hw_numpolys = polygonArraySize; + rs_hw_numcalls = rs_hw_numverts = 0; + rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 1; + // init polygonIndexArray + for (i = 0; i < polygonArraySize; i++) + { + polygonIndexArray[i] = i; + } + + // sort polygons + rs_hw_batchsorttime = I_GetTimeMicros(); + if (cv_grshaders.value) // TODO also have the shader availability check here when its done + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); + else + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); + rs_hw_batchsorttime = I_GetTimeMicros() - rs_hw_batchsorttime; + // sort order + // 1. shader + // 2. texture + // 3. polyflags + // 4. colors + light level + // not sure about what order of the last 2 should be, or if it even matters + + rs_hw_batchdrawtime = I_GetTimeMicros(); + + currentShader = polygonArray[polygonIndexArray[0]].shader; + currentTexture = polygonArray[polygonIndexArray[0]].texture; + currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags; + currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf; + // For now, will sort and track the colors. Vertex attributes could be used instead of uniforms + // and a color array could replace the color calls. + + // set state for first batch + + if (cv_grshaders.value) // TODO also have the shader availability check here when its done + { + HWD.pfnSetShader(currentShader); + } + + if (currentPolyFlags & PF_NoTexture) + currentTexture = NULL; + else + HWD.pfnSetTexture(currentTexture); + + while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) + { + int firstIndex; + int lastIndex; + + boolean stopFlag = false; + boolean changeState = false; + boolean changeShader = false; + boolean changeTexture = false; + boolean changePolyFlags = false; + boolean changeSurfaceInfo = false; + + // steps: + // write vertices + // check for changes or end, otherwise go back to writing + // changes will affect the next vars and the change bools + // end could set flag for stopping + // execute draw call + // could check ending flag here + // change states according to next vars and change bools, updating the current vars and reseting the bools + // reset write pos + // repeat loop + + int index = polygonIndexArray[polygonReadPos++]; + int numVerts = polygonArray[index].numVerts; + // before writing, check if there is enough room + // using 'while' instead of 'if' here makes sure that there will *always* be enough room. + // probably never will this loop run more than once though + while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) + { + FOutVector* new_array; + unsigned int* new_index_array; + finalVertexArrayAllocSize *= 2; + new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); + free(finalVertexArray); + finalVertexArray = new_array; + // also increase size of index array, 3x of vertex array since + // going from fans to triangles increases vertex count to 3x + new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); + free(finalVertexIndexArray); + finalVertexIndexArray = new_index_array; + } + // write the vertices of the polygon + memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], + numVerts * sizeof(FOutVector)); + // write the indexes, pointing to the fan vertexes but in triangles format + firstIndex = finalVertexWritePos; + lastIndex = finalVertexWritePos + numVerts; + finalVertexWritePos += 2; + while (finalVertexWritePos < lastIndex) + { + finalVertexIndexArray[finalIndexWritePos++] = firstIndex; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; + } + + if (polygonReadPos >= polygonArraySize) + { + stopFlag = true; + } + else + { + // check if a state change is required, set the change bools and next vars + int nextIndex = polygonIndexArray[polygonReadPos]; + nextShader = polygonArray[nextIndex].shader; + nextTexture = polygonArray[nextIndex].texture; + nextPolyFlags = polygonArray[nextIndex].polyFlags; + nextSurfaceInfo = polygonArray[nextIndex].surf; + if (nextPolyFlags & PF_NoTexture) + nextTexture = 0; + if (currentShader != nextShader) + { + changeState = true; + changeShader = true; + } + if (currentTexture != nextTexture) + { + changeState = true; + changeTexture = true; + } + if (currentPolyFlags != nextPolyFlags) + { + changeState = true; + changePolyFlags = true; + } + if (cv_grshaders.value) // TODO also have the shader availability check here when its done + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || + currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || + currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) + { + changeState = true; + changeSurfaceInfo = true; + } + } + } + + if (changeState || stopFlag) + { + // execute draw call + HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); + // update stats + rs_hw_numcalls++; + rs_hw_numverts += finalIndexWritePos; + // reset write positions + finalVertexWritePos = 0; + finalIndexWritePos = 0; + } + else continue; + + // if we're here then either its time to stop or time to change state + if (stopFlag) break; + + // change state according to change bools and next vars, update current vars and reset bools + if (changeShader) + { + HWD.pfnSetShader(nextShader); + currentShader = nextShader; + changeShader = false; + + rs_hw_numshaders++; + } + if (changeTexture) + { + // texture should be already ready for use from calls to SetTexture during batch collection + HWD.pfnSetTexture(nextTexture); + currentTexture = nextTexture; + changeTexture = false; + + rs_hw_numtextures++; + } + if (changePolyFlags) + { + currentPolyFlags = nextPolyFlags; + changePolyFlags = false; + + rs_hw_numpolyflags++; + } + if (changeSurfaceInfo) + { + currentSurfaceInfo = nextSurfaceInfo; + changeSurfaceInfo = false; + + rs_hw_numcolors++; + } + // and that should be it? + } + // reset the arrays (set sizes to 0) + polygonArraySize = 0; + unsortedVertexArraySize = 0; + + rs_hw_batchdrawtime = I_GetTimeMicros() - rs_hw_batchdrawtime; +} + + +#endif // HWRENDER diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h new file mode 100644 index 0000000000000000000000000000000000000000..7c108a4bd2a18e2cee24487afe8c79b4b856c28b --- /dev/null +++ b/src/hardware/hw_batching.h @@ -0,0 +1,37 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.h +/// \brief Draw call batching and related things. + +#ifndef __HWR_BATCHING_H__ +#define __HWR_BATCHING_H__ + +#include "hw_defs.h" +#include "hw_data.h" +#include "hw_drv.h" + +typedef struct +{ + FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused + unsigned int vertsIndex;// location of verts in unsortedVertexArray + FUINT numVerts; + FBITFIELD polyFlags; + GLMipmap_t *texture; + int shader; + // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls + boolean horizonSpecial; +} PolygonArrayEntry; + +void HWR_StartBatching(void); +void HWR_SetCurrentTexture(GLMipmap_t *texture); +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial); +void HWR_RenderBatches(void); + +#endif diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index ebb74f653ad0b5157f86a497e3d12df2696f3f4f..6987e9d01c6adaab73016fa8becd403b2d9a3dd7 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_bsp.c /// \brief convert SRB2 map #include "../doomdef.h" diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 059556f15ba19ea2cdb0e5ab15b1468ccb92858e..ab9a50dd5d884ba39ee9acf7c5f850d9589d1f67 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -1,20 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_cache.c /// \brief load and convert graphics to the hardware format #include "../doomdef.h" @@ -22,6 +15,7 @@ #ifdef HWRENDER #include "hw_glob.h" #include "hw_drv.h" +#include "hw_batching.h" #include "../doomstat.h" //gamemode #include "../i_video.h" //rendermode @@ -33,9 +27,6 @@ #include "../r_patch.h" #include "../p_setup.h" -// Values set after a call to HWR_ResizeBlock() -static INT32 blocksize, blockwidth, blockheight; - INT32 patchformat = GR_TEXFMT_AP_88; // use alpha for holes INT32 textureformat = GR_TEXFMT_P_8; // use chromakey for hole @@ -308,13 +299,13 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, if (pwidth <= 0 || pheight <= 0) return; - ncols = (pwidth * pblockwidth) / pwidth; + ncols = pwidth; // source advance xfrac = 0; - xfracstep = (pwidth << FRACBITS) / pblockwidth; - yfracstep = (pheight << FRACBITS) / pblockheight; - scale_y = (pblockheight << FRACBITS) / pheight; + xfracstep = FRACUNIT; + yfracstep = FRACUNIT; + scale_y = FRACUNIT; bpp = format2bpp[mipmap->grInfo.format]; @@ -322,7 +313,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); // NOTE: should this actually be pblockwidth*bpp? - blockmodulo = blockwidth*bpp; + blockmodulo = pblockwidth*bpp; // Draw each column to the block cache for (; ncols--; block += bpp, xfrac += xfracstep) @@ -415,7 +406,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); // NOTE: should this actually be pblockwidth*bpp? - blockmodulo = blockwidth*bpp; + blockmodulo = pblockwidth*bpp; // Draw each column to the block cache for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep) @@ -433,142 +424,12 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, } } - -// resize the patch to be 3dfx compliant -// set : blocksize = blockwidth * blockheight (no bpp used) -// blockwidth -// blockheight -//note : 8bit (1 byte per pixel) palettized format -static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, - GrTexInfo *grInfo) -{ -#ifdef GLIDE_API_COMPATIBILITY - // Build the full textures from patches. - static const GrLOD_t gr_lods[9] = - { - GR_LOD_LOG2_256, - GR_LOD_LOG2_128, - GR_LOD_LOG2_64, - GR_LOD_LOG2_32, - GR_LOD_LOG2_16, - GR_LOD_LOG2_8, - GR_LOD_LOG2_4, - GR_LOD_LOG2_2, - GR_LOD_LOG2_1 - }; - - typedef struct - { - GrAspectRatio_t aspect; - float max_s; - float max_t; - } booring_aspect_t; - - static const booring_aspect_t gr_aspects[8] = - { - {GR_ASPECT_LOG2_1x1, 255, 255}, - {GR_ASPECT_LOG2_2x1, 255, 127}, - {GR_ASPECT_LOG2_4x1, 255, 63}, - {GR_ASPECT_LOG2_8x1, 255, 31}, - - {GR_ASPECT_LOG2_1x1, 255, 255}, - {GR_ASPECT_LOG2_1x2, 127, 255}, - {GR_ASPECT_LOG2_1x4, 63, 255}, - {GR_ASPECT_LOG2_1x8, 31, 255} - }; - - INT32 j,k; - INT32 max,min; -#else - (void)grInfo; -#endif - - // find a power of 2 width/height - if (cv_grrounddown.value) - { - blockwidth = 256; - while (originalwidth < blockwidth) - blockwidth >>= 1; - if (blockwidth < 1) - I_Error("3D GenerateTexture : too small"); - - blockheight = 256; - while (originalheight < blockheight) - blockheight >>= 1; - if (blockheight < 1) - I_Error("3D GenerateTexture : too small"); - } - else - { -#ifdef GLIDE_API_COMPATIBILITY - //size up to nearest power of 2 - blockwidth = 1; - while (blockwidth < originalwidth) - blockwidth <<= 1; - // scale down the original graphics to fit in 256 - if (blockwidth > 2048) - blockwidth = 2048; - //I_Error("3D GenerateTexture : too big"); - - //size up to nearest power of 2 - blockheight = 1; - while (blockheight < originalheight) - blockheight <<= 1; - // scale down the original graphics to fit in 256 - if (blockheight > 2048) - blockheight = 2048; - //I_Error("3D GenerateTexture : too big"); -#else - blockwidth = originalwidth; - blockheight = originalheight; -#endif - } - - // do the boring LOD stuff.. blech! -#ifdef GLIDE_API_COMPATIBILITY - if (blockwidth >= blockheight) - { - max = blockwidth; - min = blockheight; - } - else - { - max = blockheight; - min = blockwidth; - } - - for (k = 2048, j = 0; k > max; j++) - k>>=1; - grInfo->smallLodLog2 = gr_lods[j]; - grInfo->largeLodLog2 = gr_lods[j]; - - for (k = max, j = 0; k > min && j < 4; j++) - k>>=1; - // aspect ratio too small for 3Dfx (eg: 8x128 is 1x16 : use 1x8) - if (j == 4) - { - j = 3; - //CONS_Debug(DBG_RENDER, "HWR_ResizeBlock : bad aspect ratio %dx%d\n", blockwidth,blockheight); - if (blockwidth < blockheight) - blockwidth = max>>3; - else - blockheight = max>>3; - } - if (blockwidth < blockheight) - j += 4; - grInfo->aspectRatioLog2 = gr_aspects[j].aspect; -#endif - - blocksize = blockwidth * blockheight; - - //CONS_Debug(DBG_RENDER, "Width is %d, Height is %d\n", blockwidth, blockheight); -} - static UINT8 *MakeBlock(GLMipmap_t *grMipmap) { UINT8 *block; INT32 bpp, i; UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX); + INT32 blocksize = (grMipmap->width * grMipmap->height); bpp = format2bpp[grMipmap->grInfo.format]; block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data)); @@ -599,6 +460,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) texpatch_t *patch; patch_t *realpatch; UINT8 *pdata; + INT32 blockwidth, blockheight, blocksize; INT32 i; boolean skyspecial = false; //poor hack for Legacy large skies.. @@ -619,11 +481,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) else grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY; - HWR_ResizeBlock (texture->width, texture->height, &grtex->mipmap.grInfo); - grtex->mipmap.width = (UINT16)blockwidth; - grtex->mipmap.height = (UINT16)blockheight; + grtex->mipmap.width = (UINT16)texture->width; + grtex->mipmap.height = (UINT16)texture->height; grtex->mipmap.grInfo.format = textureformat; + blockwidth = texture->width; + blockheight = texture->height; + blocksize = (blockwidth * blockheight); block = MakeBlock(&grtex->mipmap); if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading) @@ -692,8 +556,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // patch may be NULL if grMipmap has been initialised already and makebitmap is false void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) { - INT32 newwidth, newheight; - #ifndef NO_PNG_LUMPS // lump is a png so convert it size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum); @@ -712,51 +574,32 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm grPatch->leftoffset = SHORT(patch->leftoffset); grPatch->topoffset = SHORT(patch->topoffset); - // find the good 3dfx size (boring spec) - HWR_ResizeBlock (SHORT(patch->width), SHORT(patch->height), &grMipmap->grInfo); - grMipmap->width = (UINT16)blockwidth; - grMipmap->height = (UINT16)blockheight; + grMipmap->width = grMipmap->height = 1; + while (grMipmap->width < grPatch->width) grMipmap->width <<= 1; + while (grMipmap->height < grPatch->height) grMipmap->height <<= 1; // no wrap around, no chroma key grMipmap->flags = 0; // setup the texture info grMipmap->grInfo.format = patchformat; - } - else - { - blockwidth = grMipmap->width; - blockheight = grMipmap->height; - blocksize = blockwidth * blockheight; + + //grPatch->max_s = grPatch->max_t = 1.0f; + grPatch->max_s = (float)grPatch->width / (float)grMipmap->width; + grPatch->max_t = (float)grPatch->height / (float)grMipmap->height; } Z_Free(grMipmap->grInfo.data); grMipmap->grInfo.data = NULL; - // if rounddown, rounddown patches as well as textures - if (cv_grrounddown.value) - { - newwidth = blockwidth; - newheight = blockheight; - } - else - { - // no rounddown, do not size up patches, so they don't look 'scaled' - newwidth = min(grPatch->width, blockwidth); - newheight = min(grPatch->height, blockheight); - } - if (makebitmap) { MakeBlock(grMipmap); HWR_DrawPatchInCache(grMipmap, - newwidth, newheight, + grMipmap->width, grMipmap->height, grPatch->width, grPatch->height, patch); } - - grPatch->max_s = (float)newwidth / (float)blockwidth; - grPatch->max_t = (float)newheight / (float)blockheight; } @@ -896,8 +739,11 @@ GLTexture_t *HWR_GetTexture(INT32 tex) if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) HWR_GenerateTexture(tex, grtex); - // Tell the hardware driver to bind the current texture to the flat's mipmap - HWD.pfnSetTexture(&grtex->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtex->mipmap.downloaded) + HWD.pfnSetTexture(&grtex->mipmap); + + HWR_SetCurrentTexture(&grtex->mipmap); // The system-memory data can be purged now. Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -910,11 +756,6 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) size_t size, pflatsize; // setup the texture info -#ifdef GLIDE_API_COMPATIBILITY - grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; @@ -957,15 +798,7 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) { UINT8 *flat; - if (needpatchflush) - W_FlushCachedPatches(); - // setup the texture info -#ifdef GLIDE_API_COMPATIBILITY - grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; @@ -985,14 +818,15 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) if (flatlumpnum == LUMPERROR) return; - if (needpatchflush) - W_FlushCachedPatches(); - grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFlat(grmip, flatlumpnum); - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -1026,14 +860,17 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum); - // Tell the hardware driver to bind the current texture to the flat's mipmap - HWD.pfnSetTexture(&grtex->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtex->mipmap.downloaded) + HWD.pfnSetTexture(&grtex->mipmap); + + HWR_SetCurrentTexture(&grtex->mipmap); // The system-memory data can be purged now. Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); } else // set no texture - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); } // @@ -1055,7 +892,11 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) Z_Free(patch); } - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -1066,9 +907,6 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) // -----------------+ void HWR_GetPatch(GLPatch_t *gpatch) { - if (needpatchflush) - W_FlushCachedPatches(); - // is it in hardware cache if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data) { @@ -1085,7 +923,11 @@ void HWR_GetPatch(GLPatch_t *gpatch) Z_Free(ptr); } - HWD.pfnSetTexture(gpatch->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!gpatch->mipmap->downloaded) + HWD.pfnSetTexture(gpatch->mipmap); + + HWR_SetCurrentTexture(gpatch->mipmap); // The system-memory patch data can be purged now. Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -1099,9 +941,6 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap) { GLMipmap_t *grmip, *newmip; - if (needpatchflush) - W_FlushCachedPatches(); - if (colormap == colormaps || colormap == NULL) { // Load the default (green) color in doom cache (temporary?) AND hardware cache @@ -1225,19 +1064,12 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig // -----------------+ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) { - GLPatch_t *grpatch; - - if (needpatchflush) - W_FlushCachedPatches(); - - grpatch = HWR_GetCachedGLPatch(lumpnum); - + GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum); if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data) { pic_t *pic; UINT8 *block; size_t len; - INT32 newwidth, newheight; pic = W_CacheLumpNum(lumpnum, PU_CACHE); grpatch->width = SHORT(pic->width); @@ -1247,10 +1079,8 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) grpatch->leftoffset = 0; grpatch->topoffset = 0; - // find the good 3dfx size (boring spec) - HWR_ResizeBlock (grpatch->width, grpatch->height, &grpatch->mipmap->grInfo); - grpatch->mipmap->width = (UINT16)blockwidth; - grpatch->mipmap->height = (UINT16)blockheight; + grpatch->mipmap->width = (UINT16)grpatch->width; + grpatch->mipmap->height = (UINT16)grpatch->height; if (pic->mode == PALETTE) grpatch->mipmap->grInfo.format = textureformat; // can be set by driver @@ -1262,30 +1092,16 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) // allocate block block = MakeBlock(grpatch->mipmap); - // if rounddown, rounddown patches as well as textures - if (cv_grrounddown.value) - { - newwidth = blockwidth; - newheight = blockheight; - } - else - { - // no rounddown, do not size up patches, so they don't look 'scaled' - newwidth = min(SHORT(pic->width),blockwidth); - newheight = min(SHORT(pic->height),blockheight); - } - - - if (grpatch->width == blockwidth && - grpatch->height == blockheight && + if (grpatch->width == SHORT(pic->width) && + grpatch->height == SHORT(pic->height) && format2bpp[grpatch->mipmap->grInfo.format] == format2bpp[picmode2GR[pic->mode]]) { // no conversion needed M_Memcpy(grpatch->mipmap->grInfo.data, pic->data,len); } else - HWR_DrawPicInCache(block, newwidth, newheight, - blockwidth*format2bpp[grpatch->mipmap->grInfo.format], + HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height), + SHORT(pic->width)*format2bpp[grpatch->mipmap->grInfo.format], pic, format2bpp[grpatch->mipmap->grInfo.format]); @@ -1293,8 +1109,7 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); grpatch->mipmap->flags = 0; - grpatch->max_s = (float)newwidth / (float)blockwidth; - grpatch->max_t = (float)newheight / (float)blockheight; + grpatch->max_s = grpatch->max_t = 1.0f; } HWD.pfnSetTexture(grpatch->mipmap); //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.grInfo.data, grpatch->mipmap.downloaded); @@ -1330,7 +1145,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 { INT32 i,j; fixed_t posx, posy, stepx, stepy; - UINT8 *block = mipmap->grInfo.data; // places the data directly into here, it already has the space allocated from HWR_ResizeBlock + UINT8 *block = mipmap->grInfo.data; // places the data directly into here UINT8 *flat; UINT8 *dest, *src, texel; RGBA_t col; @@ -1345,7 +1160,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 for (j = 0; j < pblockheight; j++) { posx = 0; - dest = &block[j*blockwidth]; // 1bpp + dest = &block[j*(mipmap->width)]; // 1bpp src = &flat[(posy>>FRACBITS)*SHORT(fmwidth)]; for (i = 0; i < pblockwidth;i++) { @@ -1399,14 +1214,12 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) } // Thankfully, this will still work for this scenario - HWR_ResizeBlock(fmwidth, fmheight, &grMipmap->grInfo); - - grMipmap->width = blockwidth; - grMipmap->height = blockheight; + grMipmap->width = fmwidth; + grMipmap->height = fmheight; MakeBlock(grMipmap); - HWR_DrawFadeMaskInCache(grMipmap, blockwidth, blockheight, fademasklumpnum, fmwidth, fmheight); + HWR_DrawFadeMaskInCache(grMipmap, fmwidth, fmheight, fademasklumpnum, fmwidth, fmheight); // I DO need to convert this because it isn't power of 2 and we need the alpha } @@ -1414,13 +1227,7 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum) { - GLMipmap_t *grmip; - - if (needpatchflush) - W_FlushCachedPatches(); - - grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; - + GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFadeMask(grmip, fademasklumpnum); diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index a63527083125824fc5cbc521c040db5fa615670a..86e0c58d25a72956dd9b10d6950baf10fd731ae1 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -78,8 +78,8 @@ #include "r_opengl/r_opengl.h" #ifdef HAVE_SPHEREFRUSTRUM -static GLfloat viewMatrix[16]; -static GLfloat projMatrix[16]; +static GLdouble viewMatrix[16]; +static GLdouble projMatrix[16]; float frustum[6][4]; #endif @@ -320,12 +320,12 @@ void gld_clipper_Clear(void) #define RMUL (1.6f/1.333333f) -angle_t gld_FrustumAngle(void) +angle_t gld_FrustumAngle(angle_t tiltangle) { double floatangle; angle_t a1; - float tilt = (float)fabs(((double)(int)aimingangle) / ANG1); + float tilt = (float)fabs(((double)(int)tiltangle) / ANG1); // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function @@ -339,7 +339,7 @@ angle_t gld_FrustumAngle(void) } // If the pitch is larger than this you can look all around at a FOV of 90 - if (abs((signed)aimingangle) > 46 * ANG1) + if (abs((signed)tiltangle) > 46 * ANG1) return 0xffffffff; // ok, this is a gross hack that barely works... @@ -352,7 +352,7 @@ angle_t gld_FrustumAngle(void) } // SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either -// compiler complains about (p)glGetDoublev anyway, in case anyone wants this +// compiler complains about (p)glGetFloatv anyway, in case anyone wants this // only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks // btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h #ifdef HAVE_SPHEREFRUSTRUM @@ -381,7 +381,7 @@ void gld_FrustrumSetup(void) float t; float clip[16]; - pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix); + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix); clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12); diff --git a/src/hardware/hw_clip.h b/src/hardware/hw_clip.h index 3ba26e5e56f3dc053adc068078dc11859e8a86df..27a2ed1efa2de4b9f6d54278a5052fb03c4a1d46 100644 --- a/src/hardware/hw_clip.h +++ b/src/hardware/hw_clip.h @@ -17,7 +17,7 @@ boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle); void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle); void gld_clipper_Clear(void); -angle_t gld_FrustumAngle(void); +angle_t gld_FrustumAngle(angle_t tiltangle); #ifdef HAVE_SPHEREFRUSTRUM void gld_FrustrumSetup(void); boolean gld_SphereInFrustum(float x, float y, float z, float radius); diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index ef57426a4b66b484d3285a2a39f92dd7be14a474..686d522a0d96cb284c057a5fc826d16d9023a54b 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -1,21 +1,14 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief defines structures and exports for the standard 3D driver DLL used by Doom Legacy +/// \file hw_data.h +/// \brief defines structures and exports for the hardware interface used by Sonic Robo Blast 2 #ifndef _HWR_DATA_ #define _HWR_DATA_ diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 95882b03eb93bb57fc429a12c648fdd8f5167c7b..715c45ef3ea5d28da8d4b241fa38fdd960a2d3a4 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -1,24 +1,19 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_defs.h /// \brief 3D hardware renderer definitions #ifndef _HWR_DEFS_ #define _HWR_DEFS_ #include "../doomtype.h" +#include "../r_defs.h" #define ZCLIP_PLANE 4.0f // Used for the actual game drawing #define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures @@ -82,16 +77,18 @@ typedef struct // Simple 3D vector typedef struct FVector { - FLOAT x,y,z; + FLOAT x,y,z; } FVector; -// 3D model vector (coords + texture coords) -typedef struct -{ - //FVector Point; - FLOAT x,y,z; - FLOAT s,t,w; // texture coordinates -} v3d_t, wallVert3D; +// ====================== +// wallVert3D +// ---------------------- +// :crab: IS GONE! :crab: +// ====================== + +// ----------- +// structures +// ----------- //Hurdler: Transform (coords + angles) //BP: transform order : scale(rotation_x(rotation_y(translation(v)))) @@ -123,15 +120,16 @@ typedef struct #ifdef USE_FTRANSFORM_MIRROR boolean mirror; // SRB2Kart: Encore Mode #endif + boolean shearing; // 14042019 + float viewaiming; // 17052019 } FTransform; // Transformed vector, as passed to HWR API typedef struct { FLOAT x,y,z; - FUINT argb; // flat-shaded color - FLOAT sow; // s texture ordinate (s over w) - FLOAT tow; // t texture ordinate (t over w) + FLOAT s; // s texture ordinate (s over w) + FLOAT t; // t texture ordinate (t over w) } FOutVector; @@ -162,10 +160,10 @@ enum EPolyFlags PF_Invisible = 0x00000400, // Disable write to color buffer PF_Decal = 0x00000800, // Enable polygon offset PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB) - // When set, pass the color constant into the FSurfaceInfo -> FlatColor + // When set, pass the color constant into the FSurfaceInfo -> PolyColor PF_NoTexture = 0x00002000, // Use the small white texture PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona - PF_Unused = 0x00008000, // Unused + PF_Ripple = 0x00008000, // Water shader effect PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y PF_ForceWrapX = 0x00020000, // Force repeat texture on X PF_ForceWrapY = 0x00040000, // Force repeat texture on Y @@ -178,7 +176,6 @@ enum EPolyFlags enum ESurfFlags { SF_DYNLIGHT = 0x00000001, - }; enum ETextureFlags @@ -190,38 +187,36 @@ enum ETextureFlags TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0 }; -#ifdef TODO -struct FTextureInfo +typedef struct GLMipmap_s FTextureInfo; + +// jimita 14032019 +struct FLightInfo { - FUINT Width; // Pixels - FUINT Height; // Pixels - FUBYTE *TextureData; // Image data - FUINT Format; // FORMAT_RGB, ALPHA ... - FBITFIELD Flags; // Flags to tell driver about texture (see ETextureFlags) - void DriverExtra; // (OpenGL texture object nr, ...) - // chromakey enabled,... - - struct FTextureInfo *Next; // Manage list of downloaded textures. + FUINT light_level; + FUINT fade_start; + FUINT fade_end; }; -#else -typedef struct GLMipmap_s FTextureInfo; -#endif +typedef struct FLightInfo FLightInfo; // Description of a renderable surface struct FSurfaceInfo { - FUINT PolyFlags; // Surface flags -- UNUSED YET -- - RGBA_t FlatColor; // Flat-shaded color used with PF_Modulated mode + FUINT PolyFlags; + RGBA_t PolyColor; + RGBA_t TintColor; + RGBA_t FadeColor; + FLightInfo LightInfo; // jimita 14032019 }; typedef struct FSurfaceInfo FSurfaceInfo; +#define GL_DEFAULTMIX 0x00000000 +#define GL_DEFAULTFOG 0xFF000000 + //Hurdler: added for backward compatibility enum hwdsetspecialstate { HWD_SET_MODEL_LIGHTING = 1, - HWD_SET_FOG_MODE, - HWD_SET_FOG_COLOR, - HWD_SET_FOG_DENSITY, + HWD_SET_SHADERS, HWD_SET_TEXTUREFILTERMODE, HWD_SET_TEXTUREANISOTROPICMODE, HWD_NUMSTATE @@ -229,6 +224,15 @@ enum hwdsetspecialstate typedef enum hwdsetspecialstate hwdspecialstate_t; +// Lactozilla: Shader info +// Generally set at the start of the frame. +enum hwdshaderinfo +{ + HWD_SHADERINFO_LEVELTIME = 1, +}; + +typedef enum hwdshaderinfo hwdshaderinfo_t; + enum hwdfiltermode { HWD_SET_TEXTUREFILTER_POINTSAMPLED, diff --git a/src/hardware/hw_dll.h b/src/hardware/hw_dll.h index 3fa5852d88d844060f6a3601e148d1a540461493..d22c8c3126bd05b4e5d15302962a1357638354bc 100644 --- a/src/hardware/hw_dll.h +++ b/src/hardware/hw_dll.h @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- +// Copyright (C) 2005 by Sonic Team Junior. // -// Copyright (C) 2005 by SRB2 Jr. Team. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_dll.h /// \brief Win32 DLL and Shared Objects API definitions #ifndef __HWR_DLL_H__ @@ -54,8 +47,6 @@ #endif #endif -typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR; - // ========================================================================== // MATHS // ========================================================================== @@ -63,7 +54,7 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR; // Constants #define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360 -void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/; +void GL_DBG_Printf(const char *format, ...) /*FUNCPRINTF*/; #ifdef _WINDOWS BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index d0133176589e9a03f6681fc393e9d3cf0c19526a..5d58d4b203d149325ce9314493c97d97ffba3f67 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_draw.c /// \brief miscellaneous drawing (mainly 2d) #ifdef __GNUC__ @@ -23,6 +17,7 @@ #include "../doomdef.h" #ifdef HWRENDER +#include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" @@ -43,9 +38,6 @@ #define O_BINARY 0 #endif -float gr_patch_scalex; -float gr_patch_scaley; - #if defined(_MSC_VER) #pragma pack(1) #endif @@ -65,9 +57,6 @@ typedef struct #if defined(_MSC_VER) #pragma pack() #endif -typedef UINT8 GLRGB[3]; - -#define BLENDMODE PF_Translucent static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255}; static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; @@ -121,12 +110,12 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = gpatch->max_s; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = gpatch->max_t; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -356,19 +345,19 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t if (option & V_FLIP) { - v[0].sow = v[3].sow = gpatch->max_s; - v[2].sow = v[1].sow = 0.0f; + v[0].s = v[3].s = gpatch->max_s; + v[2].s = v[1].s = 0.0f; } else { - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = gpatch->max_s; } - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = gpatch->max_t; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -379,11 +368,11 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t if (alphalevel) { FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency]; - else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; + Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; + if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; + else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -514,19 +503,19 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; + v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; if (sx + w > SHORT(gpatch->width)) - v[2].sow = v[1].sow = gpatch->max_s; + v[2].s = v[1].s = gpatch->max_s; else - v[2].sow = v[1].sow = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; + v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; - v[0].tow = v[1].tow = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; + v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; if (sy + h > SHORT(gpatch->height)) - v[2].tow = v[3].tow = gpatch->max_t; + v[2].t = v[3].t = gpatch->max_t; else - v[2].tow = v[3].tow = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; + v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -537,11 +526,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal if (alphalevel) { FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency]; - else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; + Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; + if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; + else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -569,10 +558,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0; - v[2].sow = v[1].sow = patch->max_s; - v[0].tow = v[1].tow = 0; - v[2].tow = v[3].tow = patch->max_t; + v[0].s = v[3].s = 0; + v[2].s = v[1].s = patch->max_s; + v[0].t = v[1].t = 0; + v[2].t = v[3].t = patch->max_t; //Hurdler: Boris, the same comment as above... but maybe for pics @@ -581,7 +570,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) // But then, the question is: why not 0 instead of PF_Masked ? // or maybe PF_Environment ??? (like what I said above) // BP: PF_Environment don't change anything ! and 0 is undifined - HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); + HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip); } // ========================================================================== @@ -644,10 +633,10 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; // flat is 64x64 lod and texture offsets are [0.0, 1.0] - v[0].sow = v[3].sow = (float)((x & flatflag)/dflatsize); - v[2].sow = v[1].sow = (float)(v[0].sow + w/dflatsize); - v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize); - v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize); + v[0].s = v[3].s = (float)((x & flatflag)/dflatsize); + v[2].s = v[1].s = (float)(v[0].s + w/dflatsize); + v[0].t = v[1].t = (float)((y & flatflag)/dflatsize); + v[2].t = v[3].t = (float)(v[0].t + h/dflatsize); HWR_LiterallyGetFlat(flatlumpnum); @@ -679,20 +668,20 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) v[2].y = v[3].y = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 0.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; if (color & 0xFF00) // Do COLORMAP fade. { - Surf.FlatColor.rgba = UINT2RGBA(0x01010160); - Surf.FlatColor.s.alpha = (strength*8); + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); } else // Do TRANSMAP** fade. { - Surf.FlatColor.rgba = V_GetColor(color).rgba; - Surf.FlatColor.s.alpha = softwaretranstogl[strength]; + Surf.PolyColor.rgba = V_GetColor(color).rgba; + Surf.PolyColor.s.alpha = softwaretranstogl[strength]; } HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -850,24 +839,22 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac v[0].y = v[1].y = fy; v[2].y = v[3].y = fy - fh; - //Hurdler: do we still use this argb color? if not, we should remove it - v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 1.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = 1.0f; if (actualcolor & 0xFF00) // Do COLORMAP fade. { - Surf.FlatColor.rgba = UINT2RGBA(0x01010160); - Surf.FlatColor.s.alpha = (strength*8); + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); } else // Do TRANSMAP** fade. { - Surf.FlatColor.rgba = V_GetColor(actualcolor).rgba; - Surf.FlatColor.s.alpha = softwaretranstogl[strength]; + Surf.PolyColor.rgba = V_GetColor(actualcolor).rgba; + Surf.PolyColor.s.alpha = softwaretranstogl[strength]; } HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -888,13 +875,13 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) v[2].y = v[3].y = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 0.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; - Surf.FlatColor.rgba = UINT2RGBA(color); - Surf.FlatColor.s.alpha = 0x80; + Surf.PolyColor.rgba = UINT2RGBA(color); + Surf.PolyColor.s.alpha = 0x80; HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -914,13 +901,13 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight) v[2].y = v[3].y = -1.0f+((height<<1)/(float)vid.height); v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 0.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; - Surf.FlatColor.rgba = UINT2RGBA(color); - Surf.FlatColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software + Surf.PolyColor.rgba = UINT2RGBA(color); + Surf.PolyColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -1232,17 +1219,15 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 v[0].y = v[1].y = fy; v[2].y = v[3].y = fy - fh; - //Hurdler: do we still use this argb color? if not, we should remove it - v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 1.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = 1.0f; - Surf.FlatColor.rgba = UINT2RGBA(actualcolor); - Surf.FlatColor.s.alpha = 0x80; + Surf.PolyColor.rgba = UINT2RGBA(actualcolor); + Surf.PolyColor.s.alpha = 0x80; HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -1412,16 +1397,14 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) v[0].y = v[1].y = fy; v[2].y = v[3].y = fy - fh; - //Hurdler: do we still use this argb color? if not, we should remove it - v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 1.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = 1.0f; - Surf.FlatColor = V_GetColor(color); + Surf.PolyColor = V_GetColor(color); HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_NoTexture|PF_NoDepthTest); diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 3314fb01587a8be020b345810d49805e13d981ec..50ac6cbec16fb0220fe8aec64da62a3c564dd103 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,20 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_drv.h /// \brief imports/exports for the 3D hardware low-level interface API #ifndef __HWR_DRV_H__ @@ -32,7 +25,7 @@ // STANDARD DLL EXPORTS // ========================================================================== -EXPORT boolean HWRAPI(Init) (I_Error_t ErrorFunction); +EXPORT boolean HWRAPI(Init) (void); #ifndef HAVE_SDL EXPORT void HWRAPI(Shutdown) (void); #endif @@ -43,10 +36,12 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal); EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray); EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -55,14 +50,11 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); -EXPORT INT32 HWRAPI(GetRenderVersion) (void); -#define SCREENVERTS 10 -EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); EXPORT void HWRAPI(FlushScreenTextures) (void); EXPORT void HWRAPI(StartScreenWipe) (void); EXPORT void HWRAPI(EndScreenWipe) (void); @@ -71,6 +63,20 @@ EXPORT void HWRAPI(DrawIntermissionBG) (void); EXPORT void HWRAPI(MakeScreenTexture) (void); EXPORT void HWRAPI(MakeScreenFinalTexture) (void); EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); + +#define SCREENVERTS 10 +EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); + +// jimita +EXPORT void HWRAPI(LoadShaders) (void); +EXPORT void HWRAPI(KillShaders) (void); +EXPORT void HWRAPI(SetShader) (int shader); +EXPORT void HWRAPI(UnSetShader) (void); + +EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); +EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment); +EXPORT void HWRAPI(InitCustomShaders) (void); + // ========================================================================== // HWR DRIVER OBJECT, FOR CLIENT PROGRAM // ========================================================================== @@ -84,10 +90,12 @@ struct hwdriver_s FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; + DrawIndexedTriangles pfnDrawIndexedTriangles; RenderSkyDome pfnRenderSkyDome; SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; + UpdateTexture pfnUpdateTexture; ReadRect pfnReadRect; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; @@ -96,7 +104,6 @@ struct hwdriver_s CreateModelVBOs pfnCreateModelVBOs; SetTransform pfnSetTransform; GetTextureUsed pfnGetTextureUsed; - GetRenderVersion pfnGetRenderVersion; #ifdef _WINDOWS GetModeList pfnGetModeList; #endif @@ -112,13 +119,19 @@ struct hwdriver_s MakeScreenTexture pfnMakeScreenTexture; MakeScreenFinalTexture pfnMakeScreenFinalTexture; DrawScreenFinalTexture pfnDrawScreenFinalTexture; + + LoadShaders pfnLoadShaders; + KillShaders pfnKillShaders; + SetShader pfnSetShader; + UnSetShader pfnUnSetShader; + + SetShaderInfo pfnSetShaderInfo; + LoadCustomShader pfnLoadCustomShader; + InitCustomShaders pfnInitCustomShaders; }; extern struct hwdriver_s hwdriver; -//Hurdler: 16/10/99: added for OpenGL gamma correction -//extern RGBA_t gamma_correction; - #define HWD hwdriver #endif //not defined _CREATE_DLL_ diff --git a/src/hardware/hw_glide.h b/src/hardware/hw_glide.h index bf91229efa1ccde01f73436079cc009a12aa62ac..d0eeebaeb7399fa5f4c97f13bd12bf1a59cce7eb 100644 --- a/src/hardware/hw_glide.h +++ b/src/hardware/hw_glide.h @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_glide.h /// \brief Declaration needed by Glide renderer /// !!! To be replaced by our own def in the future !!! @@ -25,26 +18,6 @@ typedef unsigned long FxU32; typedef long FxI32; -typedef FxI32 GrAspectRatio_t; -#define GR_ASPECT_LOG2_8x1 3 /* 8W x 1H */ -#define GR_ASPECT_LOG2_4x1 2 /* 4W x 1H */ -#define GR_ASPECT_LOG2_2x1 1 /* 2W x 1H */ -#define GR_ASPECT_LOG2_1x1 0 /* 1W x 1H */ -#define GR_ASPECT_LOG2_1x2 -1 /* 1W x 2H */ -#define GR_ASPECT_LOG2_1x4 -2 /* 1W x 4H */ -#define GR_ASPECT_LOG2_1x8 -3 /* 1W x 8H */ - -typedef FxI32 GrLOD_t; -#define GR_LOD_LOG2_256 0x8 -#define GR_LOD_LOG2_128 0x7 -#define GR_LOD_LOG2_64 0x6 -#define GR_LOD_LOG2_32 0x5 -#define GR_LOD_LOG2_16 0x4 -#define GR_LOD_LOG2_8 0x3 -#define GR_LOD_LOG2_4 0x2 -#define GR_LOD_LOG2_2 0x1 -#define GR_LOD_LOG2_1 0x0 - typedef FxI32 GrTextureFormat_t; #define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */ #define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */ @@ -59,11 +32,6 @@ typedef FxI32 GrTextureFormat_t; typedef struct { -#ifdef GLIDE_API_COMPATIBILITY - GrLOD_t smallLodLog2; - GrLOD_t largeLodLog2; - GrAspectRatio_t aspectRatioLog2; -#endif GrTextureFormat_t format; void *data; } GrTexInfo; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index a2bf79817ac15f1b85740dfbe20bd121cd2e880d..861c2f382f05d6f869ad6859f6cd561673fb0695 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,20 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_glob.h /// \brief globals (shared data & code) for hw_ modules #ifndef _HWR_GLOB_H_ @@ -118,11 +111,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- -extern float gr_patch_scalex; -extern float gr_patch_scaley; - -extern consvar_t cv_grrounddown; // on/off - extern INT32 patchformat; extern INT32 textureformat; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 3d1316a2f199508e866dc983265ff0da9de27f99..b2139d5ee946f9508b296675f06f2579289a1527 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_light.c /// \brief Corona/Dynamic/Static lighting add on by Hurdler /// !!! Under construction !!! @@ -879,19 +873,19 @@ void HWR_WallLighting(FOutVector *wlVerts) #endif for (i = 0; i < 4; i++) { - wlVerts[i].sow = (float)(0.5f + d[i]*s); - wlVerts[i].tow = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f); + wlVerts[i].s = (float)(0.5f + d[i]*s); + wlVerts[i].t = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f); } HWR_SetLight(); - Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); + Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); #ifdef DL_HIGH_QUALITY - Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); + Surf.PolyColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha); #endif // next state is null so fade out with alpha if (dynlights->mo[j]->state->nextstate == S_NULL) - Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); + Surf.PolyColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha); HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS); @@ -948,19 +942,19 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts) #endif for (i = 0; i < nrClipVerts; i++) { - clVerts[i].sow = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s; - clVerts[i].tow = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f; + clVerts[i].s = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s; + clVerts[i].t = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f; } HWR_SetLight(); - Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); + Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); #ifdef DL_HIGH_QUALITY - Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); + Surf.PolyColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha); #endif // next state is null so fade out with alpha if ((dynlights->mo[j]->state->nextstate == S_NULL)) - Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); + Surf.PolyColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha); HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS); @@ -1027,11 +1021,11 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr) // more realistique corona ! if (cz >= 255*8+250) return; - Surf.FlatColor.rgba = p_lspr->corona_color; + Surf.PolyColor.rgba = p_lspr->corona_color; if (cz > 250.0f) - Surf.FlatColor.s.alpha = 0xff-((int)cz-250)/8; + Surf.PolyColor.s.alpha = 0xff-((int)cz-250)/8; else - Surf.FlatColor.s.alpha = 0xff; + Surf.PolyColor.s.alpha = 0xff; // do not be hide by sprite of the light itself ! cz = cz - 2.0f; @@ -1043,19 +1037,19 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr) // car comme l'offset est minime sa ce voit pas ! light[0].x = cx-size; light[0].z = cz; light[0].y = cy-size*1.33f+p_lspr->light_yoffset; - light[0].sow = 0.0f; light[0].tow = 0.0f; + light[0].s = 0.0f; light[0].t = 0.0f; light[1].x = cx+size; light[1].z = cz; light[1].y = cy-size*1.33f+p_lspr->light_yoffset; - light[1].sow = 1.0f; light[1].tow = 0.0f; + light[1].s = 1.0f; light[1].t = 0.0f; light[2].x = cx+size; light[2].z = cz; light[2].y = cy+size*1.33f+p_lspr->light_yoffset; - light[2].sow = 1.0f; light[2].tow = 1.0f; + light[2].s = 1.0f; light[2].t = 1.0f; light[3].x = cx-size; light[3].z = cz; light[3].y = cy+size*1.33f+p_lspr->light_yoffset; - light[3].sow = 0.0f; light[3].tow = 1.0f; + light[3].s = 0.0f; light[3].t = 1.0f; HWR_GetPic(coronalumpnum); /// \todo use different coronas @@ -1101,11 +1095,11 @@ void HWR_DrawCoronas(void) // more realistique corona ! if (cz >= 255*8+250) continue; - Surf.FlatColor.rgba = p_lspr->corona_color; + Surf.PolyColor.rgba = p_lspr->corona_color; if (cz > 250.0f) - Surf.FlatColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8)); + Surf.PolyColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8)); else - Surf.FlatColor.s.alpha = 0xff; + Surf.PolyColor.s.alpha = 0xff; switch (p_lspr->type) { @@ -1113,7 +1107,7 @@ void HWR_DrawCoronas(void) size = p_lspr->corona_radius * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ? break; case ROCKET_SPR: - Surf.FlatColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff); + Surf.PolyColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff); // don't need a break case CORONA_SPR: size = p_lspr->corona_radius * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ? @@ -1133,19 +1127,19 @@ void HWR_DrawCoronas(void) light[0].x = cx-size; light[0].z = cz; light[0].y = cy-size*1.33f; - light[0].sow = 0.0f; light[0].tow = 0.0f; + light[0].s = 0.0f; light[0].t = 0.0f; light[1].x = cx+size; light[1].z = cz; light[1].y = cy-size*1.33f; - light[1].sow = 1.0f; light[1].tow = 0.0f; + light[1].s = 1.0f; light[1].t = 0.0f; light[2].x = cx+size; light[2].z = cz; light[2].y = cy+size*1.33f; - light[2].sow = 1.0f; light[2].tow = 1.0f; + light[2].s = 1.0f; light[2].t = 1.0f; light[3].x = cx-size; light[3].z = cz; light[3].y = cy+size*1.33f; - light[3].sow = 0.0f; light[3].tow = 1.0f; + light[3].s = 0.0f; light[3].t = 1.0f; HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona); } @@ -1254,11 +1248,6 @@ static void HWR_SetLight(void) lightmappatch.height = 128; lightmappatch.mipmap->width = 128; lightmappatch.mipmap->height = 128; -#ifdef GLIDE_API_COMPATIBILITY - lightmappatch.mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_128; - lightmappatch.mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_128; - lightmappatch.mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif lightmappatch.mipmap->flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw ! } HWD.pfnSetTexture(lightmappatch.mipmap); diff --git a/src/hardware/hw_light.h b/src/hardware/hw_light.h index 2733cc698e9f4cf9d8f5e5a715dbcad9ab8a8875..3b12f9c8715e5de6acfca21b3e7953b1030af88a 100644 --- a/src/hardware/hw_light.h +++ b/src/hardware/hw_light.h @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_light.h /// \brief Dynamic lighting & coronas add on by Hurdler #ifndef _HW_LIGHTS_ diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index df51198143f86cc9749cd1f53ae82beabf60e198..3163b701aff4cb49b361a6e3e71216b59e72111a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_main.c /// \brief hardware renderer, using the standard HardWareRender driver DLL for SRB2 #include <math.h> @@ -24,6 +18,7 @@ #include "hw_glob.h" #include "hw_light.h" #include "hw_drv.h" +#include "hw_batching.h" #include "../i_video.h" // for rendermode == render_glide #include "../v_video.h" @@ -51,7 +46,6 @@ #define R_FAKEFLOORS #define HWPRECIP -#define SORTING //#define POLYSKY // ========================================================================== @@ -70,175 +64,12 @@ static void HWR_ProjectSprite(mobj_t *thing); static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif -#ifdef SORTING -void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); -#else -static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, fixed_t fixedheight, - INT32 lightlevel, INT32 alpha, sector_t *FOFSector); -static void HWR_Render3DWater(void); -static void HWR_RenderTransparentWalls(void); -#endif -static void HWR_FoggingOn(void); -static UINT32 atohex(const char *s); boolean drawsky = true; -/* - * lookuptable for lightvalues - * calculated as follow: - * floatlight = (1.0-exp((light^3)*gamma)) / (1.0-exp(1.0*gamma)); - * gamma=-0,2;-2,0;-4,0;-6,0;-8,0 - * light = 0,0 .. 1,0 - */ -static const float lighttable[5][256] = -{ - { - 0.00000f,0.00000f,0.00000f,0.00000f,0.00000f,0.00001f,0.00001f,0.00002f,0.00003f,0.00004f, - 0.00006f,0.00008f,0.00010f,0.00013f,0.00017f,0.00020f,0.00025f,0.00030f,0.00035f,0.00041f, - 0.00048f,0.00056f,0.00064f,0.00073f,0.00083f,0.00094f,0.00106f,0.00119f,0.00132f,0.00147f, - 0.00163f,0.00180f,0.00198f,0.00217f,0.00237f,0.00259f,0.00281f,0.00305f,0.00331f,0.00358f, - 0.00386f,0.00416f,0.00447f,0.00479f,0.00514f,0.00550f,0.00587f,0.00626f,0.00667f,0.00710f, - 0.00754f,0.00800f,0.00848f,0.00898f,0.00950f,0.01003f,0.01059f,0.01117f,0.01177f,0.01239f, - 0.01303f,0.01369f,0.01437f,0.01508f,0.01581f,0.01656f,0.01734f,0.01814f,0.01896f,0.01981f, - 0.02069f,0.02159f,0.02251f,0.02346f,0.02444f,0.02544f,0.02647f,0.02753f,0.02862f,0.02973f, - 0.03088f,0.03205f,0.03325f,0.03448f,0.03575f,0.03704f,0.03836f,0.03971f,0.04110f,0.04252f, - 0.04396f,0.04545f,0.04696f,0.04851f,0.05009f,0.05171f,0.05336f,0.05504f,0.05676f,0.05852f, - 0.06031f,0.06214f,0.06400f,0.06590f,0.06784f,0.06981f,0.07183f,0.07388f,0.07597f,0.07810f, - 0.08027f,0.08248f,0.08473f,0.08702f,0.08935f,0.09172f,0.09414f,0.09659f,0.09909f,0.10163f, - 0.10421f,0.10684f,0.10951f,0.11223f,0.11499f,0.11779f,0.12064f,0.12354f,0.12648f,0.12946f, - 0.13250f,0.13558f,0.13871f,0.14188f,0.14511f,0.14838f,0.15170f,0.15507f,0.15850f,0.16197f, - 0.16549f,0.16906f,0.17268f,0.17635f,0.18008f,0.18386f,0.18769f,0.19157f,0.19551f,0.19950f, - 0.20354f,0.20764f,0.21179f,0.21600f,0.22026f,0.22458f,0.22896f,0.23339f,0.23788f,0.24242f, - 0.24702f,0.25168f,0.25640f,0.26118f,0.26602f,0.27091f,0.27587f,0.28089f,0.28596f,0.29110f, - 0.29630f,0.30156f,0.30688f,0.31226f,0.31771f,0.32322f,0.32879f,0.33443f,0.34013f,0.34589f, - 0.35172f,0.35761f,0.36357f,0.36960f,0.37569f,0.38185f,0.38808f,0.39437f,0.40073f,0.40716f, - 0.41366f,0.42022f,0.42686f,0.43356f,0.44034f,0.44718f,0.45410f,0.46108f,0.46814f,0.47527f, - 0.48247f,0.48974f,0.49709f,0.50451f,0.51200f,0.51957f,0.52721f,0.53492f,0.54271f,0.55058f, - 0.55852f,0.56654f,0.57463f,0.58280f,0.59105f,0.59937f,0.60777f,0.61625f,0.62481f,0.63345f, - 0.64217f,0.65096f,0.65984f,0.66880f,0.67783f,0.68695f,0.69615f,0.70544f,0.71480f,0.72425f, - 0.73378f,0.74339f,0.75308f,0.76286f,0.77273f,0.78268f,0.79271f,0.80283f,0.81304f,0.82333f, - 0.83371f,0.84417f,0.85472f,0.86536f,0.87609f,0.88691f,0.89781f,0.90880f,0.91989f,0.93106f, - 0.94232f,0.95368f,0.96512f,0.97665f,0.98828f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00003f,0.00005f,0.00007f,0.00010f, - 0.00014f,0.00019f,0.00024f,0.00031f,0.00038f,0.00047f,0.00057f,0.00069f,0.00081f,0.00096f, - 0.00112f,0.00129f,0.00148f,0.00170f,0.00193f,0.00218f,0.00245f,0.00274f,0.00306f,0.00340f, - 0.00376f,0.00415f,0.00456f,0.00500f,0.00547f,0.00597f,0.00649f,0.00704f,0.00763f,0.00825f, - 0.00889f,0.00957f,0.01029f,0.01104f,0.01182f,0.01264f,0.01350f,0.01439f,0.01532f,0.01630f, - 0.01731f,0.01836f,0.01945f,0.02058f,0.02176f,0.02298f,0.02424f,0.02555f,0.02690f,0.02830f, - 0.02974f,0.03123f,0.03277f,0.03436f,0.03600f,0.03768f,0.03942f,0.04120f,0.04304f,0.04493f, - 0.04687f,0.04886f,0.05091f,0.05301f,0.05517f,0.05738f,0.05964f,0.06196f,0.06434f,0.06677f, - 0.06926f,0.07181f,0.07441f,0.07707f,0.07979f,0.08257f,0.08541f,0.08831f,0.09126f,0.09428f, - 0.09735f,0.10048f,0.10368f,0.10693f,0.11025f,0.11362f,0.11706f,0.12056f,0.12411f,0.12773f, - 0.13141f,0.13515f,0.13895f,0.14281f,0.14673f,0.15072f,0.15476f,0.15886f,0.16303f,0.16725f, - 0.17153f,0.17587f,0.18028f,0.18474f,0.18926f,0.19383f,0.19847f,0.20316f,0.20791f,0.21272f, - 0.21759f,0.22251f,0.22748f,0.23251f,0.23760f,0.24274f,0.24793f,0.25318f,0.25848f,0.26383f, - 0.26923f,0.27468f,0.28018f,0.28573f,0.29133f,0.29697f,0.30266f,0.30840f,0.31418f,0.32001f, - 0.32588f,0.33179f,0.33774f,0.34374f,0.34977f,0.35585f,0.36196f,0.36810f,0.37428f,0.38050f, - 0.38675f,0.39304f,0.39935f,0.40570f,0.41207f,0.41847f,0.42490f,0.43136f,0.43784f,0.44434f, - 0.45087f,0.45741f,0.46398f,0.47057f,0.47717f,0.48379f,0.49042f,0.49707f,0.50373f,0.51041f, - 0.51709f,0.52378f,0.53048f,0.53718f,0.54389f,0.55061f,0.55732f,0.56404f,0.57075f,0.57747f, - 0.58418f,0.59089f,0.59759f,0.60429f,0.61097f,0.61765f,0.62432f,0.63098f,0.63762f,0.64425f, - 0.65086f,0.65746f,0.66404f,0.67060f,0.67714f,0.68365f,0.69015f,0.69662f,0.70307f,0.70948f, - 0.71588f,0.72224f,0.72857f,0.73488f,0.74115f,0.74739f,0.75359f,0.75976f,0.76589f,0.77199f, - 0.77805f,0.78407f,0.79005f,0.79599f,0.80189f,0.80774f,0.81355f,0.81932f,0.82504f,0.83072f, - 0.83635f,0.84194f,0.84747f,0.85296f,0.85840f,0.86378f,0.86912f,0.87441f,0.87964f,0.88482f, - 0.88995f,0.89503f,0.90005f,0.90502f,0.90993f,0.91479f,0.91959f,0.92434f,0.92903f,0.93366f, - 0.93824f,0.94276f,0.94723f,0.95163f,0.95598f,0.96027f,0.96451f,0.96868f,0.97280f,0.97686f, - 0.98086f,0.98481f,0.98869f,0.99252f,0.99629f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00003f,0.00005f,0.00008f,0.00013f,0.00018f, - 0.00025f,0.00033f,0.00042f,0.00054f,0.00067f,0.00083f,0.00101f,0.00121f,0.00143f,0.00168f, - 0.00196f,0.00227f,0.00261f,0.00299f,0.00339f,0.00383f,0.00431f,0.00483f,0.00538f,0.00598f, - 0.00661f,0.00729f,0.00802f,0.00879f,0.00961f,0.01048f,0.01140f,0.01237f,0.01340f,0.01447f, - 0.01561f,0.01680f,0.01804f,0.01935f,0.02072f,0.02215f,0.02364f,0.02520f,0.02682f,0.02850f, - 0.03026f,0.03208f,0.03397f,0.03594f,0.03797f,0.04007f,0.04225f,0.04451f,0.04684f,0.04924f, - 0.05172f,0.05428f,0.05691f,0.05963f,0.06242f,0.06530f,0.06825f,0.07129f,0.07441f,0.07761f, - 0.08089f,0.08426f,0.08771f,0.09125f,0.09487f,0.09857f,0.10236f,0.10623f,0.11019f,0.11423f, - 0.11836f,0.12257f,0.12687f,0.13125f,0.13571f,0.14027f,0.14490f,0.14962f,0.15442f,0.15931f, - 0.16427f,0.16932f,0.17445f,0.17966f,0.18496f,0.19033f,0.19578f,0.20130f,0.20691f,0.21259f, - 0.21834f,0.22417f,0.23007f,0.23605f,0.24209f,0.24820f,0.25438f,0.26063f,0.26694f,0.27332f, - 0.27976f,0.28626f,0.29282f,0.29944f,0.30611f,0.31284f,0.31962f,0.32646f,0.33334f,0.34027f, - 0.34724f,0.35426f,0.36132f,0.36842f,0.37556f,0.38273f,0.38994f,0.39718f,0.40445f,0.41174f, - 0.41907f,0.42641f,0.43378f,0.44116f,0.44856f,0.45598f,0.46340f,0.47084f,0.47828f,0.48573f, - 0.49319f,0.50064f,0.50809f,0.51554f,0.52298f,0.53042f,0.53784f,0.54525f,0.55265f,0.56002f, - 0.56738f,0.57472f,0.58203f,0.58932f,0.59658f,0.60381f,0.61101f,0.61817f,0.62529f,0.63238f, - 0.63943f,0.64643f,0.65339f,0.66031f,0.66717f,0.67399f,0.68075f,0.68746f,0.69412f,0.70072f, - 0.70726f,0.71375f,0.72017f,0.72653f,0.73282f,0.73905f,0.74522f,0.75131f,0.75734f,0.76330f, - 0.76918f,0.77500f,0.78074f,0.78640f,0.79199f,0.79751f,0.80295f,0.80831f,0.81359f,0.81880f, - 0.82393f,0.82898f,0.83394f,0.83883f,0.84364f,0.84836f,0.85301f,0.85758f,0.86206f,0.86646f, - 0.87078f,0.87502f,0.87918f,0.88326f,0.88726f,0.89118f,0.89501f,0.89877f,0.90245f,0.90605f, - 0.90957f,0.91301f,0.91638f,0.91966f,0.92288f,0.92601f,0.92908f,0.93206f,0.93498f,0.93782f, - 0.94059f,0.94329f,0.94592f,0.94848f,0.95097f,0.95339f,0.95575f,0.95804f,0.96027f,0.96244f, - 0.96454f,0.96658f,0.96856f,0.97049f,0.97235f,0.97416f,0.97591f,0.97760f,0.97924f,0.98083f, - 0.98237f,0.98386f,0.98530f,0.98669f,0.98803f,0.98933f,0.99058f,0.99179f,0.99295f,0.99408f, - 0.99516f,0.99620f,0.99721f,0.99817f,0.99910f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00005f,0.00008f,0.00012f,0.00019f,0.00026f, - 0.00036f,0.00048f,0.00063f,0.00080f,0.00099f,0.00122f,0.00148f,0.00178f,0.00211f,0.00249f, - 0.00290f,0.00335f,0.00386f,0.00440f,0.00500f,0.00565f,0.00636f,0.00711f,0.00793f,0.00881f, - 0.00975f,0.01075f,0.01182f,0.01295f,0.01416f,0.01543f,0.01678f,0.01821f,0.01971f,0.02129f, - 0.02295f,0.02469f,0.02652f,0.02843f,0.03043f,0.03252f,0.03469f,0.03696f,0.03933f,0.04178f, - 0.04433f,0.04698f,0.04973f,0.05258f,0.05552f,0.05857f,0.06172f,0.06498f,0.06834f,0.07180f, - 0.07537f,0.07905f,0.08283f,0.08672f,0.09072f,0.09483f,0.09905f,0.10337f,0.10781f,0.11236f, - 0.11701f,0.12178f,0.12665f,0.13163f,0.13673f,0.14193f,0.14724f,0.15265f,0.15817f,0.16380f, - 0.16954f,0.17538f,0.18132f,0.18737f,0.19351f,0.19976f,0.20610f,0.21255f,0.21908f,0.22572f, - 0.23244f,0.23926f,0.24616f,0.25316f,0.26023f,0.26739f,0.27464f,0.28196f,0.28935f,0.29683f, - 0.30437f,0.31198f,0.31966f,0.32740f,0.33521f,0.34307f,0.35099f,0.35896f,0.36699f,0.37506f, - 0.38317f,0.39133f,0.39952f,0.40775f,0.41601f,0.42429f,0.43261f,0.44094f,0.44929f,0.45766f, - 0.46604f,0.47443f,0.48283f,0.49122f,0.49962f,0.50801f,0.51639f,0.52476f,0.53312f,0.54146f, - 0.54978f,0.55807f,0.56633f,0.57457f,0.58277f,0.59093f,0.59905f,0.60713f,0.61516f,0.62314f, - 0.63107f,0.63895f,0.64676f,0.65452f,0.66221f,0.66984f,0.67739f,0.68488f,0.69229f,0.69963f, - 0.70689f,0.71407f,0.72117f,0.72818f,0.73511f,0.74195f,0.74870f,0.75536f,0.76192f,0.76839f, - 0.77477f,0.78105f,0.78723f,0.79331f,0.79930f,0.80518f,0.81096f,0.81664f,0.82221f,0.82768f, - 0.83305f,0.83832f,0.84347f,0.84853f,0.85348f,0.85832f,0.86306f,0.86770f,0.87223f,0.87666f, - 0.88098f,0.88521f,0.88933f,0.89334f,0.89726f,0.90108f,0.90480f,0.90842f,0.91194f,0.91537f, - 0.91870f,0.92193f,0.92508f,0.92813f,0.93109f,0.93396f,0.93675f,0.93945f,0.94206f,0.94459f, - 0.94704f,0.94941f,0.95169f,0.95391f,0.95604f,0.95810f,0.96009f,0.96201f,0.96386f,0.96564f, - 0.96735f,0.96900f,0.97059f,0.97212f,0.97358f,0.97499f,0.97634f,0.97764f,0.97888f,0.98007f, - 0.98122f,0.98231f,0.98336f,0.98436f,0.98531f,0.98623f,0.98710f,0.98793f,0.98873f,0.98949f, - 0.99021f,0.99090f,0.99155f,0.99218f,0.99277f,0.99333f,0.99387f,0.99437f,0.99486f,0.99531f, - 0.99575f,0.99616f,0.99654f,0.99691f,0.99726f,0.99759f,0.99790f,0.99819f,0.99847f,0.99873f, - 0.99897f,0.99920f,0.99942f,0.99963f,0.99982f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00003f,0.00006f,0.00010f,0.00017f,0.00025f,0.00035f, - 0.00048f,0.00064f,0.00083f,0.00106f,0.00132f,0.00163f,0.00197f,0.00237f,0.00281f,0.00330f, - 0.00385f,0.00446f,0.00513f,0.00585f,0.00665f,0.00751f,0.00845f,0.00945f,0.01054f,0.01170f, - 0.01295f,0.01428f,0.01569f,0.01719f,0.01879f,0.02048f,0.02227f,0.02415f,0.02614f,0.02822f, - 0.03042f,0.03272f,0.03513f,0.03765f,0.04028f,0.04303f,0.04589f,0.04887f,0.05198f,0.05520f, - 0.05855f,0.06202f,0.06561f,0.06933f,0.07318f,0.07716f,0.08127f,0.08550f,0.08987f,0.09437f, - 0.09900f,0.10376f,0.10866f,0.11369f,0.11884f,0.12414f,0.12956f,0.13512f,0.14080f,0.14662f, - 0.15257f,0.15865f,0.16485f,0.17118f,0.17764f,0.18423f,0.19093f,0.19776f,0.20471f,0.21177f, - 0.21895f,0.22625f,0.23365f,0.24117f,0.24879f,0.25652f,0.26435f,0.27228f,0.28030f,0.28842f, - 0.29662f,0.30492f,0.31329f,0.32175f,0.33028f,0.33889f,0.34756f,0.35630f,0.36510f,0.37396f, - 0.38287f,0.39183f,0.40084f,0.40989f,0.41897f,0.42809f,0.43723f,0.44640f,0.45559f,0.46479f, - 0.47401f,0.48323f,0.49245f,0.50167f,0.51088f,0.52008f,0.52927f,0.53843f,0.54757f,0.55668f, - 0.56575f,0.57479f,0.58379f,0.59274f,0.60164f,0.61048f,0.61927f,0.62799f,0.63665f,0.64524f, - 0.65376f,0.66220f,0.67056f,0.67883f,0.68702f,0.69511f,0.70312f,0.71103f,0.71884f,0.72655f, - 0.73415f,0.74165f,0.74904f,0.75632f,0.76348f,0.77053f,0.77747f,0.78428f,0.79098f,0.79756f, - 0.80401f,0.81035f,0.81655f,0.82264f,0.82859f,0.83443f,0.84013f,0.84571f,0.85117f,0.85649f, - 0.86169f,0.86677f,0.87172f,0.87654f,0.88124f,0.88581f,0.89026f,0.89459f,0.89880f,0.90289f, - 0.90686f,0.91071f,0.91445f,0.91807f,0.92157f,0.92497f,0.92826f,0.93143f,0.93450f,0.93747f, - 0.94034f,0.94310f,0.94577f,0.94833f,0.95081f,0.95319f,0.95548f,0.95768f,0.95980f,0.96183f, - 0.96378f,0.96565f,0.96744f,0.96916f,0.97081f,0.97238f,0.97388f,0.97532f,0.97669f,0.97801f, - 0.97926f,0.98045f,0.98158f,0.98266f,0.98369f,0.98467f,0.98560f,0.98648f,0.98732f,0.98811f, - 0.98886f,0.98958f,0.99025f,0.99089f,0.99149f,0.99206f,0.99260f,0.99311f,0.99359f,0.99404f, - 0.99446f,0.99486f,0.99523f,0.99559f,0.99592f,0.99623f,0.99652f,0.99679f,0.99705f,0.99729f, - 0.99751f,0.99772f,0.99792f,0.99810f,0.99827f,0.99843f,0.99857f,0.99871f,0.99884f,0.99896f, - 0.99907f,0.99917f,0.99926f,0.99935f,0.99943f,0.99951f,0.99958f,0.99964f,0.99970f,0.99975f, - 0.99980f,0.99985f,0.99989f,0.99993f,0.99997f,1.00000f - } -}; - -#define gld_CalcLightLevel(lightlevel) (lighttable[1][max(min((lightlevel),255),0)]) - // ========================================================================== // VIEW GLOBALS // ========================================================================== @@ -311,151 +142,195 @@ static float gr_viewsin, gr_viewcos; static float gr_viewludsin, gr_viewludcos; // look up down kik test static float gr_fovlud; +static angle_t gr_aimingangle; +static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox); + +// Render stats +int rs_hw_nodesorttime = 0; +int rs_hw_nodedrawtime = 0; +int rs_hw_spritesorttime = 0; +int rs_hw_spritedrawtime = 0; + +// Render stats for batching +int rs_hw_numpolys = 0; +int rs_hw_numverts = 0; +int rs_hw_numcalls = 0; +int rs_hw_numshaders = 0; +int rs_hw_numtextures = 0; +int rs_hw_numpolyflags = 0; +int rs_hw_numcolors = 0; +int rs_hw_batchsorttime = 0; +int rs_hw_batchdrawtime = 0; + + // ========================================================================== -// LIGHT stuffs +// Lighting // ========================================================================== -static UINT8 lightleveltonumlut[256]; - -// added to SRB2's sector lightlevel to make things a bit brighter (sprites/walls/planes) -FUNCMATH UINT8 LightLevelToLum(INT32 l) +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap) { - return (UINT8)(255*gld_CalcLightLevel(l)); -} + RGBA_t poly_color, tint_color, fade_color; -static inline void InitLumLut(void) -{ - INT32 i, k = 0; - for (i = 0; i < 256; i++) + poly_color.rgba = 0xFFFFFFFF; + tint_color.rgba = (colormap != NULL) ? (UINT32)colormap->rgba : GL_DEFAULTMIX; + fade_color.rgba = (colormap != NULL) ? (UINT32)colormap->fadergba : GL_DEFAULTFOG; + + // Crappy backup coloring if you can't do shaders + if (!cv_grshaders.value) { - if (i > 128) - k += 2; - else - k = 1; - lightleveltonumlut[i] = (UINT8)(k); - } -} + // be careful, this may get negative for high lightlevel values. + float tint_alpha, fade_alpha; + float red, green, blue; -//#define FOGFACTOR 300 //was 600 >> Covered by cv_grfogdensity -#define NORMALFOG 0x00000000 -#define FADEFOG 0x19000000 -#define CALCFOGDENSITY(x) ((float)((5220.0f*(1.0f/((x)/41.0f+1.0f)))-(5220.0f*(1.0f/(255.0f/41.0f+1.0f))))) // Approximate fog calculation based off of software walls -#define CALCFOGDENSITYFLOOR(x) ((float)((40227.0f*(1.0f/((x)/11.0f+1.0f)))-(40227.0f*(1.0f/(255.0f/11.0f+1.0f))))) // Approximate fog calculation based off of software floors -#define CALCLIGHT(x,y) ((float)(x)*((y)/255.0f)) -UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane) -{ - RGBA_t realcolor, fogcolor, surfcolor; - INT32 alpha, fogalpha; + red = (float)poly_color.s.red; + green = (float)poly_color.s.green; + blue = (float)poly_color.s.blue; - (void)fogblockpoly; + // 48 is just an arbritrary value that looked relatively okay. + tint_alpha = (float)(sqrt(tint_color.s.alpha) * 48) / 255.0f; - // Don't go out of bounds - if (light < 0) - light = 0; - else if (light > 255) - light = 255; + // 8 is roughly the brightness of the "close" color in Software, and 16 the brightness of the "far" color. + // 8 is too bright for dark levels, and 16 is too dark for bright levels. + // 12 is the compromise value. It doesn't look especially good anywhere, but it's the most balanced. + // (Also, as far as I can tell, fade_color's alpha is actually not used in Software, so we only use light level.) + fade_alpha = (float)(sqrt(255-light_level) * 12) / 255.0f; - realcolor.rgba = color; - fogcolor.rgba = fadecolor; + // Clamp the alpha values + tint_alpha = min(max(tint_alpha, 0.0f), 1.0f); + fade_alpha = min(max(fade_alpha, 0.0f), 1.0f); - alpha = (realcolor.s.alpha*255)/25; - fogalpha = (fogcolor.s.alpha*255)/25; + red = (tint_color.s.red * tint_alpha) + (red * (1.0f - tint_alpha)); + green = (tint_color.s.green * tint_alpha) + (green * (1.0f - tint_alpha)); + blue = (tint_color.s.blue * tint_alpha) + (blue * (1.0f - tint_alpha)); - if (cv_grfog.value && cv_grsoftwarefog.value) // Only do this when fog is on, software fog mode is on, and the poly is not from a fog block - { - // Modulate the colors by alpha. - realcolor.s.red = (UINT8)(CALCLIGHT(alpha,realcolor.s.red)); - realcolor.s.green = (UINT8)(CALCLIGHT(alpha,realcolor.s.green)); - realcolor.s.blue = (UINT8)(CALCLIGHT(alpha,realcolor.s.blue)); + red = (fade_color.s.red * fade_alpha) + (red * (1.0f - fade_alpha)); + green = (fade_color.s.green * fade_alpha) + (green * (1.0f - fade_alpha)); + blue = (fade_color.s.blue * fade_alpha) + (blue * (1.0f - fade_alpha)); + + poly_color.s.red = (UINT8)red; + poly_color.s.green = (UINT8)green; + poly_color.s.blue = (UINT8)blue; + } - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.red,255)); - surfcolor.s.green = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.green,255)); - surfcolor.s.blue = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.blue,255)); - surfcolor.s.alpha = 0xFF; + Surface->PolyColor.rgba = poly_color.rgba; + Surface->TintColor.rgba = tint_color.rgba; + Surface->FadeColor.rgba = fade_color.rgba; + Surface->LightInfo.light_level = light_level; + Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0; + Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31; +} - // Modulate the colors by alpha. - fogcolor.s.red = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.red)); - fogcolor.s.green = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.green)); - fogcolor.s.blue = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.blue)); +UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work +{ + RGBA_t realcolor, surfcolor; + INT32 alpha; + + realcolor.rgba = (colormap != NULL) ? colormap->rgba : GL_DEFAULTMIX; + + if (cv_grshaders.value) + { + surfcolor.s.alpha = (255 - light); } else { - // Modulate the colors by alpha. - realcolor.s.red = (UINT8)(CALCLIGHT(alpha,realcolor.s.red)); - realcolor.s.green = (UINT8)(CALCLIGHT(alpha,realcolor.s.green)); - realcolor.s.blue = (UINT8)(CALCLIGHT(alpha,realcolor.s.blue)); + light = light - (255 - light); - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.red,light)); - surfcolor.s.green = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.green,light)); - surfcolor.s.blue = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.blue,light)); + // Don't go out of bounds + if (light < 0) + light = 0; + else if (light > 255) + light = 255; - // Modulate the colors by alpha. - fogcolor.s.red = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.red)); - fogcolor.s.green = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.green)); - fogcolor.s.blue = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.blue)); + alpha = (realcolor.s.alpha*255)/25; - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = surfcolor.s.red+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.red,(255-light)))); - surfcolor.s.green = surfcolor.s.green+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.green,(255-light)))); - surfcolor.s.blue = surfcolor.s.blue+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.blue,(255-light)))); - surfcolor.s.alpha = 0xFF; + // at 255 brightness, alpha is between 0 and 127, at 0 brightness alpha will always be 255 + surfcolor.s.alpha = (alpha*light) / (2*256) + 255-light; } - if(cv_grfog.value) + return surfcolor.s.alpha; +} + +static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y) +{ + INT16 finallight = lightnum; + + if (cv_grfakecontrast.value != 0) { - if (cv_grsoftwarefog.value) + const UINT8 contrast = 8; + fixed_t extralight = 0; + + if (cv_grfakecontrast.value == 2) // Smooth setting { - fogcolor.s.red = (UINT8)((CALCLIGHT(fogcolor.s.red,(255-light)))+(CALCLIGHT(realcolor.s.red,light))); - fogcolor.s.green = (UINT8)((CALCLIGHT(fogcolor.s.green,(255-light)))+(CALCLIGHT(realcolor.s.green,light))); - fogcolor.s.blue = (UINT8)((CALCLIGHT(fogcolor.s.blue,(255-light)))+(CALCLIGHT(realcolor.s.blue,light))); - - // Set the fog options. - if (cv_grsoftwarefog.value == 1 && plane) // With floors, software draws them way darker for their distance - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(CALCFOGDENSITYFLOOR(light))); - else // everything else is drawn like walls - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(CALCFOGDENSITY(light))); + extralight = (-(contrast<<FRACBITS) + + FixedDiv(AngleFixed(R_PointToAngle2(0, 0, + abs(v1x - v2x), + abs(v1y - v2y))), 90<<FRACBITS) + * (contrast * 2)) >> FRACBITS; } else { - fogcolor.s.red = (UINT8)((CALCLIGHT(fogcolor.s.red,(255-light)))+(CALCLIGHT(realcolor.s.red,light))); - fogcolor.s.green = (UINT8)((CALCLIGHT(fogcolor.s.green,(255-light)))+(CALCLIGHT(realcolor.s.green,light))); - fogcolor.s.blue = (UINT8)((CALCLIGHT(fogcolor.s.blue,(255-light)))+(CALCLIGHT(realcolor.s.blue,light))); + if (v1y == v2y) + extralight = -contrast; + else if (v1x == v2x) + extralight = contrast; + } - fogalpha = (UINT8)((CALCLIGHT(fogalpha,(255-light)))+(CALCLIGHT(alpha,light))); + if (extralight != 0) + { + finallight += extralight; - // Set the fog options. - light = (UINT8)(CALCLIGHT(light,(255-fogalpha))); - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(cv_grfogdensity.value-(cv_grfogdensity.value*(float)light/255.0f))); + if (finallight < 0) + finallight = 0; + if (finallight > 255) + finallight = 255; } - - HWD.pfnSetSpecialState(HWD_SET_FOG_COLOR, (fogcolor.s.red*0x10000)+(fogcolor.s.green*0x100)+fogcolor.s.blue); - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 1); } - return surfcolor.rgba; -} + return (FUINT)finallight; +} -static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this can work +static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta) { - RGBA_t realcolor, surfcolor; - INT32 alpha; + INT16 finallight = lightnum; - // Don't go out of bounds - if (light < 0) - light = 0; - else if (light > 255) - light = 255; + if (cv_grfakecontrast.value != 0 && cv_grslopecontrast.value != 0) + { + const UINT8 contrast = 8; + fixed_t extralight = 0; - realcolor.rgba = color; + if (cv_grfakecontrast.value == 2) // Smooth setting + { + fixed_t dirmul = abs(FixedDiv(AngleFixed(dir) - (180<<FRACBITS), 180<<FRACBITS)); - alpha = (realcolor.s.alpha*255)/25; + extralight = -(contrast<<FRACBITS) + (dirmul * (contrast * 2)); - // at 255 brightness, alpha is between 0 and 127, at 0 brightness alpha will always be 255 - surfcolor.s.alpha = (alpha*light)/(2*256)+255-light; + extralight = FixedMul(extralight, delta*4) >> FRACBITS; + } + else + { + dir = ((dir + ANGLE_45) / ANGLE_90) * ANGLE_90; - return surfcolor.s.alpha; + if (dir == ANGLE_180) + extralight = -contrast; + else if (dir == 0) + extralight = contrast; + + if (delta >= FRACUNIT/2) + extralight *= 2; + } + + if (extralight != 0) + { + finallight += extralight; + + if (finallight < 0) + finallight = 0; + if (finallight > 255) + finallight = 255; + } + } + + return (FUINT)finallight; } // ========================================================================== @@ -467,8 +342,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c // -----------------+ // HWR_RenderPlane : Render a floor or ceiling convex polygon // -----------------+ -static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) +static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -489,6 +363,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + int shader; + // no convex poly were generated for this subsector if (!xsub->planepoly) return; @@ -521,13 +397,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool if (nrPlaneVerts < 3) //not even a triangle ? return; - // This check is so inconsistent between functions, it hurts. - if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size - { - CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, INT16_MAX); - return; - } - // Allocate plane-vertex buffer if we need to if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts) { @@ -578,7 +447,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool } } else // set no texture - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); // reference point for flat texture coord for each vertex around the polygon flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth); @@ -616,9 +485,18 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool } } + if (angle) // Only needs to be done if there's an altered angle { - angle = InvAngle(angle)>>ANGLETOFINESHIFT; + + angle = (InvAngle(angle)+ANGLE_180)>>ANGLETOFINESHIFT; + + // This needs to be done so that it scrolls in a different direction after rotation like software + /*tempxsow = FLOAT_TO_FIXED(scrollx); + tempytow = FLOAT_TO_FIXED(scrolly); + scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); + scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));*/ + // This needs to be done so everything aligns after rotation // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does tempxsow = FLOAT_TO_FIXED(flatxref); @@ -631,24 +509,24 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool /* Hurdler: add scrolling texture on floor/ceiling */\ if (texflat)\ {\ - vert->sow = (float)((vx) / fflatwidth) + scrollx;\ - vert->tow = -(float)((vy) / fflatheight) + scrolly;\ + vert->s = (float)((vx) / fflatwidth) + scrollx;\ + vert->t = -(float)((vy) / fflatheight) + scrolly;\ }\ else\ {\ - vert->sow = (float)(((vx) / fflatwidth) - flatxref + scrollx);\ - vert->tow = (float)(flatyref - ((vy) / fflatheight) + scrolly);\ + vert->s = (float)(((vx) / fflatwidth) - flatxref + scrollx);\ + vert->t = (float)(flatyref - ((vy) / fflatheight) + scrolly);\ }\ \ /* Need to rotate before translate */\ if (angle) /* Only needs to be done if there's an altered angle */\ {\ - tempxsow = FLOAT_TO_FIXED(vert->sow);\ - tempytow = FLOAT_TO_FIXED(vert->tow);\ + tempxsow = FLOAT_TO_FIXED(vert->s);\ + tempytow = FLOAT_TO_FIXED(vert->t);\ if (texflat)\ tempytow = -tempytow;\ - vert->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ - vert->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ + vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ + vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ }\ \ vert->x = (vx);\ @@ -665,39 +543,27 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++) SETUP3DVERT(v3d, pv->x, pv->y); - // only useful for flat coloured triangles - //Surf.FlatColor = 0xff804020; + if (slope) + lightlevel = HWR_CalcSlopeLight(lightlevel, R_PointToAngle2(0, 0, slope->normal.x, slope->normal.y), abs(slope->zdelta)); - // use different light tables - // for horizontal / vertical / diagonal - // note: try to get the same visual feel as the original - Surf.FlatColor.s.red = Surf.FlatColor.s.green = - Surf.FlatColor.s.blue = LightLevelToLum(lightlevel); // Don't take from the frontsector, or the game will crash + HWR_Lighting(&Surf, lightlevel, planecolormap); - if (planecolormap) + if (PolyFlags & (PF_Translucent|PF_Fog)) { - if (fogplane) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, true, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true); + Surf.PolyColor.s.alpha = (UINT8)alpha; + PolyFlags |= PF_Modulated; } else - { - if (fogplane) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, true, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); - } + PolyFlags |= PF_Masked|PF_Modulated; - if (PolyFlags & (PF_Translucent|PF_Fog)) - { - Surf.FlatColor.s.alpha = (UINT8)alpha; - PolyFlags |= PF_Modulated|PF_Clip; - } + if (PolyFlags & PF_Fog) + shader = 6; // fog shader + else if (PolyFlags & PF_Ripple) + shader = 5; // water shader else - PolyFlags |= PF_Masked|PF_Modulated|PF_Clip; + shader = 1; // floor shader - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); if (subsector) { @@ -766,7 +632,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool horizonpts[4].y = gr_viewz; // Draw - HWD.pfnDrawPolygon(&Surf, horizonpts, 6, PolyFlags); + HWR_ProcessPolygon(&Surf, horizonpts, 6, PolyFlags, shader, true); } } } @@ -811,8 +677,8 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) v3d = planeVerts; for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) { - v3d->sow = 0.0f; - v3d->tow = 0.0f; + v3d->s = 0.0f; + v3d->t = 0.0f; v3d->x = pv->x; v3d->y = height; v3d->z = pv->y; @@ -835,13 +701,10 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) #ifdef WALLSPLATS static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) { - FOutVector trVerts[4], *wv; - wallVert3D wallVerts[4]; - wallVert3D *pwallVerts; + FOutVector wallVerts[4]; wallsplat_t *splat; GLPatch_t *gpatch; fixed_t i; - FSurfaceInfo pSurf2; // seg bbox fixed_t segbbox[4]; @@ -879,141 +742,64 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) wallVerts[3].s = wallVerts[3].t = wallVerts[2].s = wallVerts[0].t = 0.0f; wallVerts[1].s = wallVerts[1].t = wallVerts[2].t = wallVerts[0].s = 1.0f; - // transform - wv = trVerts; - pwallVerts = wallVerts; - for (i = 0; i < 4; i++,wv++,pwallVerts++) - { - wv->x = pwallVerts->x; - wv->z = pwallVerts->z; - wv->y = pwallVerts->y; - - // Kalaron: TOW and SOW needed to be switched - wv->sow = pwallVerts->t; - wv->tow = pwallVerts->s; - } - M_Memcpy(&pSurf2,pSurf,sizeof (FSurfaceInfo)); switch (splat->flags & SPLATDRAWMODE_MASK) { case SPLATDRAWMODE_OPAQUE : - pSurf2.FlatColor.s.alpha = 0xff; + pSurf.PolyColor.s.alpha = 0xff; i = PF_Translucent; break; case SPLATDRAWMODE_TRANS : - pSurf2.FlatColor.s.alpha = 128; + pSurf.PolyColor.s.alpha = 128; i = PF_Translucent; break; case SPLATDRAWMODE_SHADE : - pSurf2.FlatColor.s.alpha = 0xff; + pSurf.PolyColor.s.alpha = 0xff; i = PF_Substractive; break; } - HWD.pfnDrawPolygon(&pSurf2, trVerts, 4, i|PF_Modulated|PF_Clip|PF_Decal); + HWD.pfnSetShader(2); // wall shader + HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal); } } #endif -// ========================================================================== -// WALL GENERATION FROM SUBSECTOR SEGS -// ========================================================================== - - FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) { switch (transtablenum) { - case tr_trans10 : pSurf->FlatColor.s.alpha = 0xe6;return PF_Translucent; - case tr_trans20 : pSurf->FlatColor.s.alpha = 0xcc;return PF_Translucent; - case tr_trans30 : pSurf->FlatColor.s.alpha = 0xb3;return PF_Translucent; - case tr_trans40 : pSurf->FlatColor.s.alpha = 0x99;return PF_Translucent; - case tr_trans50 : pSurf->FlatColor.s.alpha = 0x80;return PF_Translucent; - case tr_trans60 : pSurf->FlatColor.s.alpha = 0x66;return PF_Translucent; - case tr_trans70 : pSurf->FlatColor.s.alpha = 0x4c;return PF_Translucent; - case tr_trans80 : pSurf->FlatColor.s.alpha = 0x33;return PF_Translucent; - case tr_trans90 : pSurf->FlatColor.s.alpha = 0x19;return PF_Translucent; + case tr_trans10 : pSurf->PolyColor.s.alpha = 0xe6;return PF_Translucent; + case tr_trans20 : pSurf->PolyColor.s.alpha = 0xcc;return PF_Translucent; + case tr_trans30 : pSurf->PolyColor.s.alpha = 0xb3;return PF_Translucent; + case tr_trans40 : pSurf->PolyColor.s.alpha = 0x99;return PF_Translucent; + case tr_trans50 : pSurf->PolyColor.s.alpha = 0x80;return PF_Translucent; + case tr_trans60 : pSurf->PolyColor.s.alpha = 0x66;return PF_Translucent; + case tr_trans70 : pSurf->PolyColor.s.alpha = 0x4c;return PF_Translucent; + case tr_trans80 : pSurf->PolyColor.s.alpha = 0x33;return PF_Translucent; + case tr_trans90 : pSurf->PolyColor.s.alpha = 0x19;return PF_Translucent; } return PF_Translucent; } -// v1,v2 : the start & end vertices along the original wall segment, that may have been -// clipped so that only a visible portion of the wall seg is drawn. -// floorheight, ceilingheight : depend on wall upper/lower/middle, comes from the sectors. +static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); -static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo * pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); +// ========================================================================== +// Wall generation from subsector segs +// ========================================================================== -// -----------------+ -// HWR_ProjectWall : -// -----------------+ -/* - wallVerts order is : - 3--2 - | /| - |/ | - 0--1 -*/ -static void HWR_ProjectWall(wallVert3D * wallVerts, - FSurfaceInfo * pSurf, - FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) +// +// HWR_ProjectWall +// +static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { - FOutVector trVerts[4]; - FOutVector *wv; + HWR_Lighting(pSurf, lightlevel, wallcolormap); - // transform - wv = trVerts; - // it sounds really stupid to do this conversion with the new T&L code - // we should directly put the right information in the right structure - // wallVerts3D seems ok, doesn't need FOutVector - // also remove the light copy - - // More messy to unwrap, but it's also quicker, uses less memory. - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - - if (wallcolormap) - { - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, false, false); - } - else - { - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); - } - - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blendmode|PF_Modulated|PF_Occlude|PF_Clip); + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, 2, false); // wall shader #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) HWR_DrawSegsSplats(pSurf); #endif -#ifdef ALAM_LIGHTING - //Hurdler: TDOD: do static lighting using gr_curline->lm - HWR_WallLighting(trVerts); - - //Hurdler: for better dynamic light in dark area, we should draw the light first - // and then the wall all that with the right blending func - //HWD.pfnDrawPolygon(pSurf, trVerts, 4, PF_Additive|PF_Modulated|PF_Occlude|PF_Clip); -#endif } // ========================================================================== @@ -1055,38 +841,10 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) } #endif -static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y) -{ - INT16 finallight = lightnum; - - if (cv_grfakecontrast.value != 0) - { - const UINT8 contrast = 8; - fixed_t extralight = 0; - - if (v1y == v2y) - extralight = -contrast; - else if (v1x == v2x) - extralight = contrast; - - if (extralight != 0) - { - finallight += extralight; - - if (finallight < 0) - finallight = 0; - if (finallight > 255) - finallight = 255; - } - } - - return (FUINT)finallight; -} - // // HWR_SplitWall // -static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor) +static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor) { /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts @@ -1111,7 +869,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, INT32 solid, i; lightlist_t * list = sector->lightlist; - const UINT8 alpha = Surf->FlatColor.s.alpha; + const UINT8 alpha = Surf->PolyColor.s.alpha; FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; @@ -1129,10 +887,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, for (i = 0; i < sector->numlights; i++) { - if (endtop < endrealbot && top < realbot) + if (endtop < endrealbot && top < realbot) return; - // There's a compiler warning here if this comment isn't here because of indentation if (!(list[i].flags & FF_NOSHADE)) { if (pfloor && (pfloor->flags & FF_FOG)) @@ -1210,7 +967,8 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (endbot < endrealbot) endbot = endrealbot; - Surf->FlatColor.s.alpha = alpha; + + Surf->PolyColor.s.alpha = alpha; wallVerts[3].t = pegt + ((realtop - top) * pegmul); wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul); @@ -1239,7 +997,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (endtop <= endrealbot && top <= realbot) return; - Surf->FlatColor.s.alpha = alpha; + Surf->PolyColor.s.alpha = alpha; wallVerts[3].t = pegt + ((realtop - top) * pegmul); wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul); @@ -1262,35 +1020,31 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, // HWR_DrawSkyWall // Draw walls into the depth buffer so that anything behind is culled properly -static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf) +static void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) { - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); // no texture wallVerts[3].t = wallVerts[2].t = 0; wallVerts[0].t = wallVerts[1].t = 0; wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = 0; // this no longer sets top/bottom coords, this should be done before caling the function - HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL); + HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_NoTexture, 255, NULL); // PF_Invisible so it's not drawn into the colour buffer // PF_NoTexture for no texture // PF_Occlude is set in HWR_ProjectWall to draw into the depth buffer } // -// HWR_StoreWallRange +// HWR_ProcessSeg // A portion or all of a wall segment will be drawn, from startfrac to endfrac, // where 0 is the start of the segment, 1 the end of the segment // Anything between means the wall segment has been clipped with solidsegs, // reducing wall overdraw to a minimum // -#ifdef NEWCLIP static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom -#else -static void HWR_StoreWallRange(double startfrac, double endfrac) -#endif { - wallVert3D wallVerts[4]; + FOutVector wallVerts[4]; v2d_t vs, ve; // start, end vertices of 2d line (view from above) fixed_t worldtop, worldbottom; @@ -1309,11 +1063,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) extracolormap_t *colormap; FSurfaceInfo Surf; -#ifndef NEWCLIP - if (startfrac > endfrac) - return; -#endif - gr_sidedef = gr_curline->sidedef; gr_linedef = gr_curline->linedef; @@ -1345,35 +1094,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) wallVerts[0].z = wallVerts[3].z = vs.y; wallVerts[2].x = wallVerts[1].x = ve.x; wallVerts[2].z = wallVerts[1].z = ve.y; - wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f; + // x offset the texture { - // x offset the texture fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset; - -#ifndef NEWCLIP - // clip texture s start/end coords with solidsegs - if (startfrac > 0.0f && startfrac < 1.0f) - cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac); - else -#endif - cliplow = (float)texturehpeg; - -#ifndef NEWCLIP - if (endfrac > 0.0f && endfrac < 1.0f) - cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac); - else -#endif - cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); + cliplow = (float)texturehpeg; + cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); } lightnum = HWR_CalcWallLight(gr_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = gr_frontsector->extra_colormap; if (gr_frontsector) - { - Surf.FlatColor.s.alpha = 255; - } + Surf.PolyColor.s.alpha = 255; if (gr_backsector) { @@ -1762,7 +1495,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { if (gr_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn { - Surf.FlatColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode + Surf.PolyColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode blendmode = PF_Masked; } else @@ -1782,16 +1515,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); - - // If there is a colormap change, remove it. -/* if (!(Surf.FlatColor.s.red + Surf.FlatColor.s.green + Surf.FlatColor.s.blue == Surf.FlatColor.s.red/3) - { - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.rgba = 0xffffffff; - }*/ } -#if 1 // Sky culling // No longer so much a mess as before! if (!gr_curline->polyseg) // Don't do it for polyobjects @@ -1818,13 +1543,12 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } } } -#endif } else { // Single sided line... Deal only with the middletexture (if one exists) gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture); - if (gr_midtexture && gr_linedef->special != HORIZONSPECIAL) // Ignore horizon line for OGL + if (gr_midtexture && gr_linedef->special != 41) // (Ignore horizon line for OGL) { { fixed_t texturevpeg; @@ -1898,7 +1622,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) //Hurdler: 3d-floors test -#ifdef R_FAKEFLOORS if (gr_frontsector && gr_backsector && gr_frontsector->tag != gr_backsector->tag && (gr_backsector->ffloors || gr_frontsector->ffloors)) { ffloor_t * rover; @@ -2016,15 +1739,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = rover->master->frontsector->extra_colormap; - if (rover->master->frontsector->extra_colormap) - { - - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba); - } - else - { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); - } + Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); if (gr_frontsector->numlights) HWR_SplitWall(gr_frontsector, wallVerts, 0, &Surf, rover->flags, rover); @@ -2038,7 +1753,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; - Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } if (gr_frontsector->numlights) @@ -2124,14 +1839,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = rover->master->frontsector->extra_colormap; - if (rover->master->frontsector->extra_colormap) - { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba); - } - else - { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); - } + Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); if (gr_backsector->numlights) HWR_SplitWall(gr_backsector, wallVerts, 0, &Surf, rover->flags, rover); @@ -2145,7 +1853,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; - Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } if (gr_backsector->numlights) @@ -2161,7 +1869,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } } } -#endif //Hurdler: end of 3d-floors test } @@ -2976,7 +2683,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; - fixed_t tempxsow, tempytow; + fixed_t tempxs, tempyt; size_t nrPlaneVerts; static FOutVector *planeVerts = NULL; @@ -3045,7 +2752,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, } } else // set no texture - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); // reference point for flat texture coord for each vertex around the polygon flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth); @@ -3088,17 +2795,17 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, if (angle) // Only needs to be done if there's an altered angle { // This needs to be done so that it scrolls in a different direction after rotation like software - tempxsow = FLOAT_TO_FIXED(scrollx); - tempytow = FLOAT_TO_FIXED(scrolly); - scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + tempxs = FLOAT_TO_FIXED(scrollx); + tempyt = FLOAT_TO_FIXED(scrolly); + scrollx = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + scrolly = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle)))); // This needs to be done so everything aligns after rotation // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does - tempxsow = FLOAT_TO_FIXED(flatxref); - tempytow = FLOAT_TO_FIXED(flatyref); - flatxref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + tempxs = FLOAT_TO_FIXED(flatxref); + tempyt = FLOAT_TO_FIXED(flatyref); + flatxref = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + flatyref = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle)))); } for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) @@ -3107,24 +2814,24 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, // Means the flat is offset based on the original vertex locations if (texflat) { - v3d->sow = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; - v3d->tow = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; + v3d->s = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; + v3d->t = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; } else { - v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); - v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); + v3d->s = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); + v3d->t = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { - tempxsow = FLOAT_TO_FIXED(v3d->sow); - tempytow = FLOAT_TO_FIXED(v3d->tow); + tempxs = FLOAT_TO_FIXED(v3d->s); + tempyt = FLOAT_TO_FIXED(v3d->t); if (texflat) - tempytow = -tempytow; - v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); + tempyt = -tempyt; + v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + v3d->t = (FIXED_TO_FLOAT(-FixedMul(tempxs, FINESINE(angle)) - FixedMul(tempyt, FINECOSINE(angle)))); } v3d->x = FIXED_TO_FLOAT(polysector->vertices[i]->x); @@ -3133,20 +2840,17 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, } - if (planecolormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); + HWR_Lighting(&Surf, lightlevel, planecolormap); if (blendmode & PF_Translucent) { - Surf.FlatColor.s.alpha = (UINT8)alpha; + Surf.PolyColor.s.alpha = (UINT8)alpha; blendmode |= PF_Modulated|PF_Occlude|PF_Clip; } else blendmode |= PF_Masked|PF_Modulated|PF_Clip; - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, 1, false); // floor shader } static void HWR_AddPolyObjectPlanes(void) @@ -3180,7 +2884,7 @@ static void HWR_AddPolyObjectPlanes(void) memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->floorpic], po_ptrs[i], false, polyobjsector->floorheight, - (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { @@ -3203,7 +2907,7 @@ static void HWR_AddPolyObjectPlanes(void) memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->ceilingpic], po_ptrs[i], true, polyobjsector->ceilingheight, - (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { @@ -3351,7 +3055,7 @@ static void HWR_Subsector(size_t num) // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, &levelflats[gr_frontsector->floorpic], NULL, 255, false, floorcolormap); + PF_Occlude, floorlightlevel, &levelflats[gr_frontsector->floorpic], NULL, 255, floorcolormap); } } else @@ -3373,7 +3077,7 @@ static void HWR_Subsector(size_t num) // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, &levelflats[gr_frontsector->ceilingpic], NULL, 255, false, ceilingcolormap); + PF_Occlude, ceilinglightlevel, &levelflats[gr_frontsector->ceilingpic], NULL, 255, ceilingcolormap); } } else @@ -3419,13 +3123,9 @@ static void HWR_Subsector(size_t num) UINT8 alpha; light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); - if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); - else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - - HWR_AddTransparentFloor(NULL, + HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, @@ -3436,28 +3136,21 @@ static void HWR_Subsector(size_t num) else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) // SoM: Flags are more efficient { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); -#ifndef SORTING - HWR_Add3DWater(&levelflats[*rover->bottompic], - &extrasubsectors[num], - *rover->bottomheight, - *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1, rover->master->frontsector); -#else + HWR_AddTransparentFloor(&levelflats[*rover->bottompic], &extrasubsectors[num], false, *rover->bottomheight, *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, + rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, false, *gr_frontsector->lightlist[light].extra_colormap); -#endif } else { HWR_GetLevelFlat(&levelflats[*rover->bottompic]); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], - rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); + HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], + rover->master->frontsector, 255, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -3475,13 +3168,9 @@ static void HWR_Subsector(size_t num) UINT8 alpha; light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); - if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); - else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - - HWR_AddTransparentFloor(NULL, + HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, @@ -3492,29 +3181,21 @@ static void HWR_Subsector(size_t num) else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); -#ifndef SORTING - HWR_Add3DWater(&levelflats[*rover->toppic], - &extrasubsectors[num], - *rover->topheight, - *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1, rover->master->frontsector); -#else + HWR_AddTransparentFloor(&levelflats[*rover->toppic], &extrasubsectors[num], true, *rover->topheight, *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, + rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, false, *gr_frontsector->lightlist[light].extra_colormap); -#endif - } else { HWR_GetLevelFlat(&levelflats[*rover->toppic]); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], - rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); + HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], + rover->master->frontsector, 255, *gr_frontsector->lightlist[light].extra_colormap); } } } @@ -3536,6 +3217,9 @@ static void HWR_Subsector(size_t num) po = (polyobj_t *)(po->link.next); } + // for render stats + rs_numpolyobjects += numpolys; + // Sort polyobjects R_SortPolyObjects(sub); @@ -3641,6 +3325,8 @@ static void HWR_RenderBSPNode(INT32 bspnum) // Decide which side the view point is on INT32 side; + + rs_numbspcalls++; // Found a subsector? if (bspnum & NF_SUBSECTOR) @@ -3853,13 +3539,12 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v return false; } -static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale) +static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) { GLPatch_t *gpatch; FOutVector shadowVerts[4]; FSurfaceInfo sSurf; float fscale; float fx; float fy; float offset; - UINT8 lightlevel = 255; extracolormap_t *colormap = NULL; UINT8 i; SINT8 flip = P_MobjFlip(thing); @@ -3903,10 +3588,18 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale else offset = (float)(SHORT(gpatch->height)/2); - shadowVerts[0].x = shadowVerts[3].x = fx - offset; - shadowVerts[2].x = shadowVerts[1].x = fx + offset; - shadowVerts[0].z = shadowVerts[1].z = fy - offset; - shadowVerts[3].z = shadowVerts[2].z = fy + offset; + shadowVerts[2].x = shadowVerts[3].x = fx + offset; + shadowVerts[1].x = shadowVerts[0].x = fx - offset; + shadowVerts[1].z = shadowVerts[2].z = fy - offset; + shadowVerts[0].z = shadowVerts[3].z = fy + offset; + + for (i = 0; i < 4; i++) + { + float oldx = shadowVerts[i].x; + float oldy = shadowVerts[i].z; + shadowVerts[i].x = fx + ((oldx - fx) * gr_viewcos) - ((oldy - fy) * gr_viewsin); + shadowVerts[i].z = fy + ((oldx - fx) * gr_viewsin) + ((oldy - fy) * gr_viewcos); + } if (groundslope) { @@ -3922,57 +3615,29 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale shadowVerts[i].y = FIXED_TO_FLOAT(groundz) + flip * 0.05f; } - if (spr->flip) - { - shadowVerts[0].sow = shadowVerts[3].sow = gpatch->max_s; - shadowVerts[2].sow = shadowVerts[1].sow = 0; - } - else - { - shadowVerts[0].sow = shadowVerts[3].sow = 0; - shadowVerts[2].sow = shadowVerts[1].sow = gpatch->max_s; - } + shadowVerts[0].s = shadowVerts[3].s = 0; + shadowVerts[2].s = shadowVerts[1].s = gpatch->max_s; - // flip the texture coords (look familiar?) - if (spr->vflip) - { - shadowVerts[3].tow = shadowVerts[2].tow = gpatch->max_t; - shadowVerts[0].tow = shadowVerts[1].tow = 0; - } - else - { - shadowVerts[3].tow = shadowVerts[2].tow = 0; - shadowVerts[0].tow = shadowVerts[1].tow = gpatch->max_t; - } + shadowVerts[3].t = shadowVerts[2].t = 0; + shadowVerts[0].t = shadowVerts[1].t = gpatch->max_t; if (thing->subsector->sector->numlights) { light = R_GetPlaneLight(thing->subsector->sector, groundz, false); // Always use the light at the top instead of whatever I was doing before - if (*thing->subsector->sector->lightlist[light].lightlevel > 255) - lightlevel = 255; - else - lightlevel = *thing->subsector->sector->lightlist[light].lightlevel; - if (*thing->subsector->sector->lightlist[light].extra_colormap) colormap = *thing->subsector->sector->lightlist[light].extra_colormap; } else { - lightlevel = thing->subsector->sector->lightlevel; - if (thing->subsector->sector->extra_colormap) colormap = thing->subsector->sector->extra_colormap; } - if (colormap) - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); - - sSurf.FlatColor.s.alpha = alpha; + HWR_Lighting(&sSurf, 0, colormap); + sSurf.PolyColor.s.alpha = alpha; - HWD.pfnDrawPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, 3, false); // sprite shader } // This is expecting a pointer to an array containing 4 wallVerts for a sprite @@ -4024,7 +3689,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) INT32 i; float realtop, realbot, top, bot; - float towtop, towbot, towmult; + float ttop, tbot, tmult; float bheight; float realheight, heightmult; const sector_t *sector = spr->mobj->subsector->sector; @@ -4065,25 +3730,25 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (spr->flip) { - baseWallVerts[0].sow = baseWallVerts[3].sow = gpatch->max_s; - baseWallVerts[2].sow = baseWallVerts[1].sow = 0; + baseWallVerts[0].s = baseWallVerts[3].s = gpatch->max_s; + baseWallVerts[2].s = baseWallVerts[1].s = 0; } else { - baseWallVerts[0].sow = baseWallVerts[3].sow = 0; - baseWallVerts[2].sow = baseWallVerts[1].sow = gpatch->max_s; + baseWallVerts[0].s = baseWallVerts[3].s = 0; + baseWallVerts[2].s = baseWallVerts[1].s = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - baseWallVerts[3].tow = baseWallVerts[2].tow = gpatch->max_t; - baseWallVerts[0].tow = baseWallVerts[1].tow = 0; + baseWallVerts[3].t = baseWallVerts[2].t = gpatch->max_t; + baseWallVerts[0].t = baseWallVerts[1].t = 0; } else { - baseWallVerts[3].tow = baseWallVerts[2].tow = 0; - baseWallVerts[0].tow = baseWallVerts[1].tow = gpatch->max_t; + baseWallVerts[3].t = baseWallVerts[2].t = 0; + baseWallVerts[0].t = baseWallVerts[1].t = gpatch->max_t; } // if it has a dispoffset, push it a little towards the camera @@ -4101,9 +3766,9 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) realtop = top = baseWallVerts[3].y; realbot = bot = baseWallVerts[0].y; - towtop = baseWallVerts[3].tow; - towbot = baseWallVerts[0].tow; - towmult = (towbot - towtop) / (top - bot); + ttop = baseWallVerts[3].t; + tbot = baseWallVerts[0].t; + tmult = (tbot - ttop) / (top - bot); endrealtop = endtop = baseWallVerts[2].y; endrealbot = endbot = baseWallVerts[1].y; @@ -4115,12 +3780,12 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (!cv_translucency.value) // translucency disabled { - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } else if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4131,11 +3796,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) // work properly under glide nor with fogcolor to ffffff :( // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - alpha = Surf.FlatColor.s.alpha; + alpha = Surf.PolyColor.s.alpha; // Start with the lightlevel and colormap from the top of the sprite lightlevel = *list[sector->numlights - 1].lightlevel; @@ -4197,10 +3862,10 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (endbot < endrealbot) endbot = endrealbot; - wallVerts[3].tow = towtop + ((realtop - top) * towmult); - wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult); - wallVerts[0].tow = towtop + ((realtop - bot) * towmult); - wallVerts[1].tow = towtop + ((endrealtop - endbot) * towmult); + wallVerts[3].t = ttop + ((realtop - top) * tmult); + wallVerts[2].t = ttop + ((endrealtop - endtop) * tmult); + wallVerts[0].t = ttop + ((realtop - bot) * tmult); + wallVerts[1].t = ttop + ((endrealtop - endbot) * tmult); wallVerts[3].y = top; wallVerts[2].y = endtop; @@ -4231,14 +3896,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; } - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); - Surf.FlatColor.s.alpha = alpha; + Surf.PolyColor.s.alpha = alpha; - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader top = bot; endtop = endbot; @@ -4250,24 +3912,21 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) return; // If we're ever down here, somehow the above loop hasn't draw all the light levels of sprite - wallVerts[3].tow = towtop + ((realtop - top) * towmult); - wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult); - wallVerts[0].tow = towtop + ((realtop - bot) * towmult); - wallVerts[1].tow = towtop + ((endrealtop - endbot) * towmult); + wallVerts[3].t = ttop + ((realtop - top) * tmult); + wallVerts[2].t = ttop + ((endrealtop - endtop) * tmult); + wallVerts[0].t = ttop + ((realtop - bot) * tmult); + wallVerts[1].t = ttop + ((endrealtop - endbot) * tmult); wallVerts[3].y = top; wallVerts[2].y = endtop; wallVerts[0].y = bot; wallVerts[1].y = endbot; - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); - Surf.FlatColor.s.alpha = alpha; + Surf.PolyColor.s.alpha = alpha; - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader } // -----------------+ @@ -4337,21 +3996,21 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (spr->flip) { - wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s; - wallVerts[2].sow = wallVerts[1].sow = 0; + wallVerts[0].s = wallVerts[3].s = gpatch->max_s; + wallVerts[2].s = wallVerts[1].s = 0; }else{ - wallVerts[0].sow = wallVerts[3].sow = 0; - wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + wallVerts[0].s = wallVerts[3].s = 0; + wallVerts[2].s = wallVerts[1].s = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t; - wallVerts[0].tow = wallVerts[1].tow = 0; + wallVerts[3].t = wallVerts[2].t = gpatch->max_t; + wallVerts[0].t = wallVerts[1].t = 0; }else{ - wallVerts[3].tow = wallVerts[2].tow = 0; - wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + wallVerts[3].t = wallVerts[2].t = 0; + wallVerts[0].t = wallVerts[1].t = gpatch->max_t; } // cache the patch in the graphics card memory @@ -4385,22 +4044,19 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); } { FBITFIELD blend = 0; if (!cv_translucency.value) // translucency disabled { - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } else if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4411,11 +4067,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // work properly under glide nor with fogcolor to ffffff :( // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader } } @@ -4456,11 +4112,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) // Let dispoffset work first since this adjust each vertex HWR_RotateSpritePolyToAim(spr, wallVerts, true); - wallVerts[0].sow = wallVerts[3].sow = 0; - wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + wallVerts[0].s = wallVerts[3].s = 0; + wallVerts[2].s = wallVerts[1].s = gpatch->max_s; - wallVerts[3].tow = wallVerts[2].tow = 0; - wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + wallVerts[3].t = wallVerts[2].t = 0; + wallVerts[0].t = wallVerts[1].t = gpatch->max_t; // cache the patch in the graphics card memory //12/12/99: Hurdler: same comment as above (for md2) @@ -4494,15 +4150,12 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) colormap = sector->extra_colormap; } - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); } if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4513,11 +4166,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) // work properly under glide nor with fogcolor to ffffff :( // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader } #endif @@ -4620,14 +4273,11 @@ static void HWR_SortVisSprites(void) // middle texture. This is used for sorting with sprites. typedef struct { - wallVert3D wallVerts[4]; + FOutVector wallVerts[4]; FSurfaceInfo Surf; INT32 texnum; FBITFIELD blend; INT32 drawcount; -#ifndef SORTING - fixed_t fixedheight; -#endif boolean fogwall; INT32 lightlevel; extracolormap_t *wallcolormap; // Doing the lighting in HWR_RenderWall now for correct fog after sorting @@ -4636,7 +4286,7 @@ typedef struct static wallinfo_t *wallinfo = NULL; static size_t numwalls = 0; // a list of transparent walls to be drawn -static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); +void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); #define MAX_TRANSPARENTWALL 256 @@ -4675,9 +4325,6 @@ typedef struct static size_t numpolyplanes = 0; // a list of transparent poyobject floors to be drawn static polyplaneinfo_t *polyplaneinfo = NULL; -#ifndef SORTING -size_t numfloors = 0; -#else //Hurdler: 3D water sutffs typedef struct gr_drawnode_s { @@ -4695,8 +4342,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, - fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -4727,8 +4373,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane -void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, - fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) +void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { static size_t allocedpolyplanes = 0; @@ -4777,6 +4422,8 @@ static void HWR_CreateDrawNodes(void) // If true, swap the draw order. boolean shift = false; + + rs_hw_nodesorttime = I_GetTimeMicros(); for (i = 0; i < numplanes; i++, p++) { @@ -4795,6 +4442,8 @@ static void HWR_CreateDrawNodes(void) sortnode[p].wall = &wallinfo[i]; sortindex[p] = p; } + + rs_numdrawnodes = p; // p is the number of stuff to sort @@ -4897,8 +4546,14 @@ static void HWR_CreateDrawNodes(void) } //i++ } // loop++ - HWD.pfnSetTransform(&atransform); + rs_hw_nodesorttime = I_GetTimeMicros() - rs_hw_nodesorttime; + + rs_hw_nodedrawtime = I_GetTimeMicros(); + // Okay! Let's draw it all! Woo! + HWD.pfnSetTransform(&atransform); + HWD.pfnSetShader(0); + for (i = 0; i < p; i++) { if (sortnode[sortindex[i]].plane) @@ -4909,7 +4564,7 @@ static void HWR_CreateDrawNodes(void) if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat); HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); + sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->planecolormap); } else if (sortnode[sortindex[i]].polyplane) { @@ -4929,6 +4584,8 @@ static void HWR_CreateDrawNodes(void) sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap); } } + + rs_hw_nodedrawtime = I_GetTimeMicros() - rs_hw_nodedrawtime; numwalls = 0; numplanes = 0; @@ -4939,18 +4596,17 @@ static void HWR_CreateDrawNodes(void) Z_Free(sortindex); } -#endif - // -------------------------------------------------------------------------- // Draw all vissprites // -------------------------------------------------------------------------- -#ifdef SORTING + // added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other static void HWR_DrawSprites(void) { if (gr_visspritecount > 0) { gr_vissprite_t *spr; + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value); // draw all vissprites back to front for (spr = gr_vsprsortedhead.next; @@ -4965,7 +4621,7 @@ static void HWR_DrawSprites(void) { if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value) { - HWR_DrawDropShadow(spr->mobj, spr, spr->mobj->shadowscale); + HWR_DrawDropShadow(spr->mobj, spr->mobj->shadowscale); } if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) @@ -4990,9 +4646,10 @@ static void HWR_DrawSprites(void) } } } + + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, 0); } } -#endif // -------------------------------------------------------------------------- // HWR_AddSprites @@ -5486,7 +5143,7 @@ static void HWR_DrawSkyBackground(player_t *player) //04/01/2000: Hurdler: added for T&L // It should replace all other gr_viewxxx when finished - dometransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + HWR_SetTransformAiming(&dometransform, player, false); dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); if (*type == postimg_flip) @@ -5547,8 +5204,8 @@ static void HWR_DrawSkyBackground(player_t *player) dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); - v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left - v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f) + v[0].s = v[3].s = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left + v[2].s = v[1].s = v[0].s + (1.0f/dimensionmultiply); // right (or left + 1.0f) // use +angle and -1.0f above instead if you wanted old backwards behavior // Y @@ -5566,13 +5223,13 @@ static void HWR_DrawSkyBackground(player_t *player) if (atransform.flip) { // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously - v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top - v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) + v[3].t = v[2].t = -(0.5f-(0.5f/dimensionmultiply)); // top + v[0].t = v[1].t = v[3].t - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) } else { - v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom - v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) + v[0].t = v[1].t = -(0.5f-(0.5f/dimensionmultiply)); // bottom + v[3].t = v[2].t = v[0].t - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) } angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; @@ -5580,16 +5237,18 @@ static void HWR_DrawSkyBackground(player_t *player) if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa { angle = InvAngle(angle); - v[3].tow = v[2].tow += ((float) angle / angleturn); - v[0].tow = v[1].tow += ((float) angle / angleturn); + v[3].t = v[2].t += ((float) angle / angleturn); + v[0].t = v[1].t += ((float) angle / angleturn); } else { - v[3].tow = v[2].tow -= ((float) angle / angleturn); - v[0].tow = v[1].tow -= ((float) angle / angleturn); + v[3].t = v[2].t -= ((float) angle / angleturn); + v[0].t = v[1].t -= ((float) angle / angleturn); } + HWD.pfnSetShader(7); // sky shader HWD.pfnDrawPolygon(NULL, v, 4, 0); + HWD.pfnSetShader(0); } } @@ -5653,6 +5312,28 @@ void HWR_SetViewSize(void) HWD.pfnFlushScreenTextures(); } +// Set view aiming, for the sky dome, the skybox, +// and the normal view, all with a single function. +static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox) +{ + // 1 = always on + // 2 = chasecam only + if (cv_grshearing.value == 1 || (cv_grshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))) + { + fixed_t fixedaiming = AIMINGTODY(aimingangle); + trans->viewaiming = FIXED_TO_FLOAT(fixedaiming); + trans->shearing = true; + gr_aimingangle = 0; + } + else + { + trans->shearing = false; + gr_aimingangle = aimingangle; + } + + trans->anglex = (float)(gr_aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); +} + // ========================================================================== // Same as rendering the player view, but from the skybox object // ========================================================================== @@ -5705,16 +5386,16 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) gr_viewsin = FIXED_TO_FLOAT(viewsin); gr_viewcos = FIXED_TO_FLOAT(viewcos); - gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(aimingangle>>ANGLETOFINESHIFT)); - gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(aimingangle>>ANGLETOFINESHIFT)); - //04/01/2000: Hurdler: added for T&L // It should replace all other gr_viewxxx when finished memset(&atransform, 0x00, sizeof(FTransform)); - atransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + HWR_SetTransformAiming(&atransform, player, true); atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gr_aimingangle>>ANGLETOFINESHIFT)); + gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(gr_aimingangle>>ANGLETOFINESHIFT)); + if (*type == postimg_flip) atransform.flip = true; else @@ -5726,6 +5407,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) atransform.scalex = 1; atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; + atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails if (player->viewrollangle != 0) @@ -5741,14 +5423,6 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) //------------------------------------------------------------------------ HWR_ClearView(); -if (0) -{ // I don't think this is ever used. - if (cv_grfog.value) - HWR_FoggingOn(); // First of all, turn it on, set the default user settings too - else - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); // Turn it off -} - if (drawsky) HWR_DrawSkyBackground(player); @@ -5757,13 +5431,12 @@ if (0) HWR_ClearSprites(); -#ifdef SORTING drawcount = 0; -#endif + #ifdef NEWCLIP if (rendermode == render_opengl) { - angle_t a1 = gld_FrustumAngle(); + angle_t a1 = gld_FrustumAngle(gr_aimingangle); gld_clipper_Clear(); gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); #ifdef HAVE_SPHEREFRUSTRUM @@ -5778,8 +5451,15 @@ if (0) // Actually it only works on Walls and Planes HWD.pfnSetTransform(&atransform); + // Reset the shader state. + HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); + HWD.pfnSetShader(0); + validcount++; + if (cv_grbatching.value) + HWR_StartBatching(); + HWR_RenderBSPNode((INT32)numnodes-1); #ifndef NEWCLIP @@ -5790,14 +5470,14 @@ if (0) viewangle = localaiming2; // Handle stuff when you are looking farther up or down. - if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) + if ((gr_aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); HWR_RenderBSPNode((INT32)numnodes-1); //left dup_viewangle += ANGLE_90; - if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) + if (((INT32)gr_aimingangle > ANGLE_45 || (INT32)gr_aimingangle<-ANGLE_45)) { HWR_ClearClipSegs(); HWR_RenderBSPNode((INT32)numnodes-1); //back @@ -5811,6 +5491,9 @@ if (0) } #endif + if (cv_grbatching.value) + HWR_RenderBatches(); + // Check for new console commands. NetUpdate(); @@ -5821,39 +5504,21 @@ if (0) #endif // Draw MD2 and sprites -#ifdef SORTING HWR_SortVisSprites(); -#endif - -#ifdef SORTING HWR_DrawSprites(); -#endif + #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? HWR_DrawCoronas(); #endif -#ifdef SORTING if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything { HWR_CreateDrawNodes(); } -#else - if (numfloors || numwalls) - { - HWD.pfnSetTransform(&atransform); - if (numfloors) - HWR_Render3DWater(); - if (numwalls) - HWR_RenderTransparentWalls(); - } -#endif HWD.pfnSetTransform(NULL); - - // put it off for menus etc - if (cv_grfog.value) - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); + HWD.pfnUnSetShader(); // Check for new console commands. NetUpdate(); @@ -5885,6 +5550,9 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) ClearColor.blue = 0.0f; ClearColor.alpha = 1.0f; + if (cv_grshaders.value) + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime. + if (viewnumber == 0) // Only do it if it's the first screen being rendered HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. @@ -5931,16 +5599,16 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) gr_viewsin = FIXED_TO_FLOAT(viewsin); gr_viewcos = FIXED_TO_FLOAT(viewcos); - gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(aimingangle>>ANGLETOFINESHIFT)); - gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(aimingangle>>ANGLETOFINESHIFT)); - //04/01/2000: Hurdler: added for T&L // It should replace all other gr_viewxxx when finished memset(&atransform, 0x00, sizeof(FTransform)); - atransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + HWR_SetTransformAiming(&atransform, player, false); atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gr_aimingangle>>ANGLETOFINESHIFT)); + gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(gr_aimingangle>>ANGLETOFINESHIFT)); + if (*type == postimg_flip) atransform.flip = true; else @@ -5952,6 +5620,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) atransform.scalex = 1; atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; + atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails if (player->viewrollangle != 0) @@ -5967,14 +5636,6 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) //------------------------------------------------------------------------ HWR_ClearView(); // Clears the depth buffer and resets the view I believe -if (0) -{ // I don't think this is ever used. - if (cv_grfog.value) - HWR_FoggingOn(); // First of all, turn it on, set the default user settings too - else - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); // Turn it off -} - if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox HWR_DrawSkyBackground(player); @@ -5983,13 +5644,12 @@ if (0) HWR_ClearSprites(); -#ifdef SORTING drawcount = 0; -#endif + #ifdef NEWCLIP if (rendermode == render_opengl) { - angle_t a1 = gld_FrustumAngle(); + angle_t a1 = gld_FrustumAngle(gr_aimingangle); gld_clipper_Clear(); gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); #ifdef HAVE_SPHEREFRUSTRUM @@ -6004,8 +5664,19 @@ if (0) // Actually it only works on Walls and Planes HWD.pfnSetTransform(&atransform); + // Reset the shader state. + HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); + HWD.pfnSetShader(0); + + rs_numbspcalls = 0; + rs_numpolyobjects = 0; + rs_bsptime = I_GetTimeMicros(); + validcount++; + if (cv_grbatching.value) + HWR_StartBatching(); + HWR_RenderBSPNode((INT32)numnodes-1); #ifndef NEWCLIP @@ -6016,14 +5687,14 @@ if (0) viewangle = localaiming2; // Handle stuff when you are looking farther up or down. - if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) + if ((gr_aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); HWR_RenderBSPNode((INT32)numnodes-1); //left dup_viewangle += ANGLE_90; - if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) + if (((INT32)gr_aimingangle > ANGLE_45 || (INT32)gr_aimingangle<-ANGLE_45)) { HWR_ClearClipSegs(); HWR_RenderBSPNode((INT32)numnodes-1); //back @@ -6037,6 +5708,11 @@ if (0) } #endif + rs_bsptime = I_GetTimeMicros() - rs_bsptime; + + if (cv_grbatching.value) + HWR_RenderBatches(); + // Check for new console commands. NetUpdate(); @@ -6047,39 +5723,29 @@ if (0) #endif // Draw MD2 and sprites -#ifdef SORTING + rs_numsprites = gr_visspritecount; + rs_hw_spritesorttime = I_GetTimeMicros(); HWR_SortVisSprites(); -#endif - -#ifdef SORTING + rs_hw_spritesorttime = I_GetTimeMicros() - rs_hw_spritesorttime; + rs_hw_spritedrawtime = I_GetTimeMicros(); HWR_DrawSprites(); -#endif + rs_hw_spritedrawtime = I_GetTimeMicros() - rs_hw_spritedrawtime; + #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? HWR_DrawCoronas(); #endif -#ifdef SORTING + rs_numdrawnodes = 0; + rs_hw_nodesorttime = 0; + rs_hw_nodedrawtime = 0; if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything { HWR_CreateDrawNodes(); } -#else - if (numfloors || numpolyplanes || numwalls) - { - HWD.pfnSetTransform(&atransform); - if (numfloors) - HWR_Render3DWater(); - if (numwalls) - HWR_RenderTransparentWalls(); - } -#endif HWD.pfnSetTransform(NULL); - - // put it off for menus etc - if (cv_grfog.value) - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); + HWD.pfnUnSetShader(); HWR_DoPostProcessor(player); @@ -6091,60 +5757,16 @@ if (0) HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE); } -// ========================================================================== -// FOG -// ========================================================================== - -/// \author faB - -static UINT32 atohex(const char *s) -{ - INT32 iCol; - const char *sCol; - char cCol; - INT32 i; - - if (strlen(s)<6) - return 0; - - iCol = 0; - sCol = s; - for (i = 0; i < 6; i++, sCol++) - { - iCol <<= 4; - cCol = *sCol; - if (cCol >= '0' && cCol <= '9') - iCol |= cCol - '0'; - else - { - if (cCol >= 'F') - cCol -= 'a' - 'A'; - if (cCol >= 'A' && cCol <= 'F') - iCol = iCol | (cCol - 'A' + 10); - } - } - //CONS_Debug(DBG_RENDER, "col %x\n", iCol); - return iCol; -} - -static void HWR_FoggingOn(void) -{ - HWD.pfnSetSpecialState(HWD_SET_FOG_COLOR, atohex(cv_grfogcolor.string)); - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 1); -} - // ========================================================================== // 3D ENGINE COMMANDS // ========================================================================== -static CV_PossibleValue_t grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}}; static CV_PossibleValue_t grmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}}; +static CV_PossibleValue_t grfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}}; +static CV_PossibleValue_t grshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}}; -static void CV_grmodellighting_OnChange(void); static void CV_grfiltermode_OnChange(void); static void CV_granisotropic_OnChange(void); -static void CV_grfogdensity_OnChange(void); static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, @@ -6154,10 +5776,8 @@ static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA {0, NULL}}; CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}}; +consvar_t cv_grshaders = {"gr_shaders", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grsoftwarefog = {"gr_softwarefog", "Off", CV_SAVE, grsoftwarefog_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef ALAM_LIGHTING consvar_t cv_grdynamiclighting = {"gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -6168,15 +5788,13 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0, NULL, 0, consvar_t cv_grmodels = {"gr_models", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grmodelinterpolation = {"gr_modelinterpolation", "Sometimes", CV_SAVE, grmodelinterpolation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grmodellighting = {"gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_grmodellighting_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grmodellighting = {"gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grshearing = {"gr_shearing", "Off", CV_SAVE, grshearing_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfakecontrast = {"gr_fakecontrast", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned, - CV_grfogdensity_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grfakecontrast = {"gr_fakecontrast", "Smooth", CV_SAVE, grfakecontrast_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grslopecontrast = {"gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest", CV_SAVE|CV_CALL, grfiltermode_cons_t, CV_grfiltermode_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -6186,17 +5804,7 @@ consvar_t cv_granisotropicmode = {"gr_anisotropicmode", "1", CV_CALL, granisotro consvar_t cv_grcorrecttricks = {"gr_correcttricks", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static void CV_grmodellighting_OnChange(void) -{ - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value); -} - -static void CV_grfogdensity_OnChange(void) -{ - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); -} +consvar_t cv_grbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static void CV_grfiltermode_OnChange(void) { @@ -6215,11 +5823,6 @@ void HWR_AddCommands(void) { CV_RegisterVar(&cv_fovchange); - CV_RegisterVar(&cv_grfogdensity); - CV_RegisterVar(&cv_grfogcolor); - CV_RegisterVar(&cv_grfog); - CV_RegisterVar(&cv_grsoftwarefog); - #ifdef ALAM_LIGHTING CV_RegisterVar(&cv_grstaticlighting); CV_RegisterVar(&cv_grdynamiclighting); @@ -6234,11 +5837,15 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grskydome); CV_RegisterVar(&cv_grspritebillboarding); CV_RegisterVar(&cv_grfakecontrast); + CV_RegisterVar(&cv_grshearing); + CV_RegisterVar(&cv_grshaders); CV_RegisterVar(&cv_grfiltermode); - CV_RegisterVar(&cv_grrounddown); CV_RegisterVar(&cv_grcorrecttricks); CV_RegisterVar(&cv_grsolvetjoin); + + CV_RegisterVar(&cv_renderstats); + CV_RegisterVar(&cv_grbatching); #ifndef NEWCLIP CV_RegisterVar(&cv_grclipwalls); @@ -6263,17 +5870,12 @@ void HWR_Startup(void) { static boolean startupdone = false; - // setup GLPatch_t scaling - gr_patch_scalex = (float)(1.0f / vid.width); - gr_patch_scaley = (float)(1.0f / vid.height); - - // initalze light lut translation - InitLumLut(); - // do this once if (!startupdone) { + INT32 i; CONS_Printf("HWR_Startup()...\n"); + HWR_InitPolyPool(); HWR_AddSessionCommands(); HWR_InitTextureCache(); @@ -6281,6 +5883,11 @@ void HWR_Startup(void) #ifdef ALAM_LIGHTING HWR_InitLight(); #endif + + // read every custom shader + for (i = 0; i < numwadfiles; i++) + HWR_ReadShaders(i, (wadfiles[i]->type == RET_PK3)); + HWR_LoadShaders(); } if (rendermode == render_opengl) @@ -6295,8 +5902,6 @@ void HWR_Startup(void) void HWR_Switch(void) { // Set special states from CVARs - HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value); - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value); HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); } @@ -6336,106 +5941,7 @@ void transform(float *cx, float *cy, float *cz) *cx *= gr_fovlud; } - -//Hurdler: 3D Water stuff -#ifndef SORTING - -#define MAX_3DWATER 512 - -static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, - fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector) -{ - static size_t allocedplanes = 0; - - // Force realloc if buffer has been freed - if (!planeinfo) - allocedplanes = 0; - - if (allocedplanes < numfloors + 1) - { - allocedplanes += MAX_3DWATER; - Z_Realloc(planeinfo, allocedplanes * sizeof (*planeinfo), PU_LEVEL, &planeinfo); - } - planeinfo[numfloors].fixedheight = fixedheight; - planeinfo[numfloors].lightlevel = lightlevel; - planeinfo[numfloors].levelflat = levelflat; - planeinfo[numfloors].xsub = xsub; - planeinfo[numfloors].alpha = alpha; - planeinfo[numfloors].FOFSector = FOFSector; - numfloors++; -} - -#define DIST_PLANE(i) ABS(planeinfo[(i)].fixedheight-dup_viewz) - -static void HWR_QuickSortPlane(INT32 start, INT32 finish) -{ - INT32 left = start; - INT32 right = finish; - INT32 starterval = (INT32)((right+left)/2); //pick a starter - - planeinfo_t temp; - - //'sort of sort' the two halves of the data list about starterval - while (right > left); - { - while (DIST_PLANE(left) < DIST_PLANE(starterval)) left++; //attempt to find a bigger value on the left - while (DIST_PLANE(right) > DIST_PLANE(starterval)) right--; //attempt to find a smaller value on the right - - if (left < right) //if we haven't gone too far - { - //switch them - M_Memcpy(&temp, &planeinfo[left], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[left], &planeinfo[right], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[right], &temp, sizeof (planeinfo_t)); - //move the bounds - left++; - right--; - } - } - - if (start < right) HWR_QuickSortPlane(start, right); - if (left < finish) HWR_QuickSortPlane(left, finish); -} - -static void HWR_Render3DWater(void) -{ - size_t i; - - //bubble sort 3D Water for correct alpha blending - { - boolean permut = true; - while (permut) - { - size_t j; - for (j = 0, permut= false; j < numfloors-1; j++) - { - if (ABS(planeinfo[j].fixedheight-dup_viewz) < ABS(planeinfo[j+1].fixedheight-dup_viewz)) - { - planeinfo_t temp; - M_Memcpy(&temp, &planeinfo[j+1], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[j+1], &planeinfo[j], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[j], &temp, sizeof (planeinfo_t)); - permut = true; - } - } - } - } -#if 0 //thanks epat, but it's goes looping forever on CTF map Silver Cascade Zone - HWR_QuickSortPlane(0, numplanes-1); -#endif - - gr_frontsector = NULL; //Hurdler: gr_fronsector is no longer valid - for (i = 0; i < numfloors; i++) - { - HWR_GetLevelFlat(planeinfo[i].levelflat); - HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].levelflat, - planeinfo[i].FOFSector, planeinfo[i].alpha, planeinfo[i].fogplane, planeinfo[i].planecolormap); - } - numfloors = 0; -} -#endif - -static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) +void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { static size_t allocedwalls = 0; @@ -6453,103 +5959,43 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, I M_Memcpy(&wallinfo[numwalls].Surf, pSurf, sizeof (FSurfaceInfo)); wallinfo[numwalls].texnum = texnum; wallinfo[numwalls].blend = blend; -#ifdef SORTING wallinfo[numwalls].drawcount = drawcount++; -#endif wallinfo[numwalls].fogwall = fogwall; wallinfo[numwalls].lightlevel = lightlevel; wallinfo[numwalls].wallcolormap = wallcolormap; numwalls++; } -#ifndef SORTING -static void HWR_RenderTransparentWalls(void) +void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { - size_t i; + FBITFIELD blendmode = blend; + UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha - /*{ // sorting is disbale for now, do it! - INT32 permut = 1; - while (permut) - { - INT32 j; - for (j = 0, permut = 0; j < numwalls-1; j++) - { - if (ABS(wallinfo[j].fixedheight-dup_viewz) < ABS(wallinfo[j+1].fixedheight-dup_viewz)) - { - wallinfo_t temp; - M_Memcpy(&temp, &wallinfo[j+1], sizeof (wallinfo_t)); - M_Memcpy(&wallinfo[j+1], &wallinfo[j], sizeof (wallinfo_t)); - M_Memcpy(&wallinfo[j], &temp, sizeof (wallinfo_t)); - permut = 1; - } - } - } - }*/ + int shader; - for (i = 0; i < numwalls; i++) - { - HWR_GetTexture(wallinfo[i].texnum); - HWR_RenderWall(wallinfo[i].wallVerts, &wallinfo[i].Surf, wallinfo[i].blend, wallinfo[i].wall->fogwall, wallinfo[i].wall->lightlevel, wallinfo[i].wall->wallcolormap); - } - numwalls = 0; -} -#endif + // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting + HWR_Lighting(pSurf, lightlevel, wallcolormap); -static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) -{ - FOutVector trVerts[4]; - UINT8 i; - FOutVector *wv; - UINT8 alpha; + pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting - // transform - wv = trVerts; - // it sounds really stupid to do this conversion with the new T&L code - // we should directly put the right information in the right structure - // wallVerts3D seems ok, doesn't need FOutVector - // also remove the light copy - for (i = 0; i < 4; i++, wv++, wallVerts++) - { - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - } + shader = 2; // wall shader - alpha = pSurf->FlatColor.s.alpha; // retain the alpha + if (blend & PF_Environment) + blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects - // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting - if (wallcolormap) - { - if (fogwall) - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, true, false); - else - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, false, false); - } - else + if (fogwall) { - if (fogwall) - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, true, false); - else - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + blendmode |= PF_Fog; + shader = 6; // fog shader } - pSurf->FlatColor.s.alpha = alpha; // put the alpha back after lighting + blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency - if (blend & PF_Environment) - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip|PF_Occlude); // PF_Occlude must be used for solid objects - else - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip); // No PF_Occlude means overlapping (incorrect) transparency + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false); #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) HWR_DrawSegsSplats(pSurf); - -#ifdef ALAM_LIGHTING - //Hurdler: TODO: do static lighting using gr_curline->lm - HWR_WallLighting(trVerts); -#endif #endif } @@ -6562,6 +6008,8 @@ void HWR_DoPostProcessor(player_t *player) { postimg_t *type; + HWD.pfnUnSetShader(); + if (splitscreen && player == &players[secondarydisplayplayer]) type = &postimgtype2; else @@ -6581,13 +6029,13 @@ void HWR_DoPostProcessor(player_t *player) // This won't change if the flash palettes are changed unfortunately, but it works for its purpose if (player->flashpal == PAL_NUKE) { - Surf.FlatColor.s.red = 0xff; - Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0x7F; // The nuke palette is kind of pink-ish + Surf.PolyColor.s.red = 0xff; + Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0x7F; // The nuke palette is kind of pink-ish } else - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; + Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = 0xc0; // match software mode + Surf.PolyColor.s.alpha = 0xc0; // match software mode HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip); } @@ -6634,7 +6082,8 @@ void HWR_DoPostProcessor(player_t *player) } } HWD.pfnPostImgRedraw(v); - disStart += 1; + if (!(paused || P_AutoPause())) + disStart += 1; // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) @@ -6721,4 +6170,161 @@ void HWR_DrawScreenFinalTexture(int width, int height) HWD.pfnDrawScreenFinalTexture(width, height); } +// jimita 18032019 +typedef struct +{ + char type[16]; + INT32 id; +} shaderxlat_t; + +static inline UINT16 HWR_CheckShader(UINT16 wadnum) +{ + UINT16 i; + lumpinfo_t *lump_p; + + lump_p = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name, "SHADERS", 7) == 0) + return i; + + return INT16_MAX; +} + +void HWR_LoadShaders(void) +{ + HWD.pfnInitCustomShaders(); +} + +void HWR_ReadShaders(UINT16 wadnum, boolean PK3) +{ + UINT16 lump; + char *shaderdef, *line; + char *stoken; + char *value; + size_t size; + int linenum = 1; + int shadertype = 0; + int i; + + #define SHADER_TYPES 7 + shaderxlat_t shaderxlat[SHADER_TYPES] = + { + {"Flat", 1}, + {"WallTexture", 2}, + {"Sprite", 3}, + {"Model", 4}, + {"WaterRipple", 5}, + {"Fog", 6}, + {"Sky", 7}, + }; + + lump = HWR_CheckShader(wadnum); + if (lump == INT16_MAX) + return; + + shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + line = Z_Malloc(size+1, PU_STATIC, NULL); + M_Memcpy(line, shaderdef, size); + line[size] = '\0'; + + stoken = strtok(line, "\r\n "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); + goto skip_field; + } + + if (!stricmp(stoken, "GLSL")) + { + value = strtok(NULL, "\r\n "); + if (!value) + { + CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_lump; + } + + if (!stricmp(value, "VERTEX")) + shadertype = 1; + else if (!stricmp(value, "FRAGMENT")) + shadertype = 2; + +skip_lump: + stoken = strtok(NULL, "\r\n "); + linenum++; + } + else + { + value = strtok(NULL, "\r\n= "); + if (!value) + { + CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_field; + } + + if (!shadertype) + { + CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + Z_Free(line); + return; + } + + for (i = 0; i < SHADER_TYPES; i++) + { + if (!stricmp(shaderxlat[i].type, stoken)) + { + size_t shader_size; + char *shader_source; + char *shader_lumpname; + UINT16 shader_lumpnum; + + if (PK3) + { + shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL); + strcpy(shader_lumpname, "Shaders/sh_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0); + } + else + { + shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL); + strcpy(shader_lumpname, "SH_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0); + } + + if (shader_lumpnum == INT16_MAX) + { + CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); + Z_Free(shader_lumpname); + continue; + } + + shader_size = W_LumpLengthPwad(wadnum, shader_lumpnum); + shader_source = Z_Malloc(shader_size, PU_STATIC, NULL); + W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source); + + HWD.pfnLoadCustomShader(shaderxlat[i].id, shader_source, shader_size, (shadertype == 2)); + + Z_Free(shader_source); + Z_Free(shader_lumpname); + } + } + +skip_field: + stoken = strtok(NULL, "\r\n= "); + linenum++; + } + } + + Z_Free(line); + return; +} + #endif // HWRENDER diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ec53621946bd45aa1f892b83c149d0e898e3b3d7..4aadc2c3977ca46c4b0434088b3327701192eab1 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -1,20 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_main.h /// \brief 3D render mode functions #ifndef __HWR_MAIN_H__ @@ -73,8 +66,11 @@ void HWR_MakeScreenFinalTexture(void); void HWR_DrawScreenFinalTexture(int width, int height); // This stuff is put here so MD2's can use them -UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); -FUNCMATH UINT8 LightLevelToLum(INT32 l); +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); +UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work + +void HWR_ReadShaders(UINT16 wadnum, boolean PK3); +void HWR_LoadShaders(void); extern CV_PossibleValue_t granisotropicmode_cons_t[]; @@ -84,21 +80,23 @@ extern consvar_t cv_grstaticlighting; extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronasize; #endif + +extern consvar_t cv_grshaders; extern consvar_t cv_grmodels; extern consvar_t cv_grmodelinterpolation; extern consvar_t cv_grmodellighting; -extern consvar_t cv_grfog; -extern consvar_t cv_grfogcolor; -extern consvar_t cv_grfogdensity; -extern consvar_t cv_grsoftwarefog; extern consvar_t cv_grfiltermode; extern consvar_t cv_granisotropicmode; extern consvar_t cv_grcorrecttricks; extern consvar_t cv_fovchange; extern consvar_t cv_grsolvetjoin; +extern consvar_t cv_grshearing; extern consvar_t cv_grspritebillboarding; extern consvar_t cv_grskydome; extern consvar_t cv_grfakecontrast; +extern consvar_t cv_grslopecontrast; + +extern consvar_t cv_grbatching; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy; @@ -108,4 +106,22 @@ extern float gr_viewwindowx, gr_basewindowcentery; extern fixed_t *hwbbox; extern FTransform atransform; + +// Render stats +extern int rs_hw_nodesorttime; +extern int rs_hw_nodedrawtime; +extern int rs_hw_spritesorttime; +extern int rs_hw_spritedrawtime; + +// Render stats for batching +extern int rs_hw_numpolys; +extern int rs_hw_numverts; +extern int rs_hw_numcalls; +extern int rs_hw_numshaders; +extern int rs_hw_numtextures; +extern int rs_hw_numpolyflags; +extern int rs_hw_numcolors; +extern int rs_hw_batchsorttime; +extern int rs_hw_batchdrawtime; + #endif diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index e4ea26d861a8189c0668fcb487b907ad995ecc0f..76c7f89b4b61526447d0aa421467d2ccd7c0ed81 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,23 +1,16 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief MD2 Handling +/// \file hw_md2.c +/// \brief 3D Model Handling /// Inspired from md2.c by Mete Ciragan (mete@swissquake.ch) - #ifdef __GNUC__ #include <unistd.h> #endif @@ -400,13 +393,6 @@ static void md2_loadTexture(md2_t *model) V_CubeApply(&image->s.red, &image->s.green, &image->s.blue); image++; } - -#ifdef GLIDE_API_COMPATIBILITY - // not correct! - grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif } HWD.pfnSetTexture(grpatch->mipmap); } @@ -455,13 +441,6 @@ static void md2_loadBlendTexture(md2_t *model) grpatch->height = (INT16)h; grpatch->mipmap->width = (UINT16)w; grpatch->mipmap->height = (UINT16)h; - -#ifdef GLIDE_API_COMPATIBILITY - // not correct! - grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif } HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary @@ -949,11 +928,19 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, blendcolor = V_GetColor(translation[firsti]); + if (secondi >= translen) + mul = 0; + if (mul > 0) // If it's 0, then we only need the first color. { - if (secondi >= translen) // blend to black +#if 0 + if (secondi >= translen) + { + // blend to black nextcolor = V_GetColor(31); + } else +#endif nextcolor = V_GetColor(translation[secondi]); // Find difference between points @@ -1188,15 +1175,14 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t boolean HWR_DrawModel(gr_vissprite_t *spr) { - FSurfaceInfo Surf; + md2_t *md2; char filename[64]; INT32 frame = 0; INT32 nextFrame = -1; UINT8 spr2 = 0; FTransform p; - md2_t *md2; - UINT8 color[4]; + FSurfaceInfo Surf; if (!cv_grmodels.value) return false; @@ -1235,13 +1221,10 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) colormap = sector->extra_colormap; } - if (colormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&Surf, lightlevel, colormap); } else - Surf.FlatColor.rgba = 0xFFFFFFFF; + Surf.PolyColor.rgba = 0xFFFFFFFF; // Look at HWR_ProjectSprite for more { @@ -1263,11 +1246,11 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) //durs = tics; if (spr->mobj->flags2 & MF2_SHADOW) - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; else if (spr->mobj->frame & FF_TRANSMASK) HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; // dont forget to enabled the depth test because we can't do this like // before: polygons models are not sorted @@ -1512,11 +1495,6 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) } #endif - color[0] = Surf.FlatColor.s.red; - color[1] = Surf.FlatColor.s.green; - color[2] = Surf.FlatColor.s.blue; - color[3] = Surf.FlatColor.s.alpha; - // SRB2CBTODO: MD2 scaling support finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); @@ -1525,7 +1503,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) p.mirror = atransform.mirror; // from Kart #endif - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); + HWD.pfnSetShader(4); // model shader + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, &Surf); } return true; diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 3bbe300534c5af1b12a5b4a9772f7802a57bb271..faa91caeee42a2ab47321442663584829685c5db 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -1,21 +1,14 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief MD2 Handling +/// \file hw_md2.h +/// \brief 3D Model Handling /// Inspired from md2.h by Mete Ciragan (mete@swissquake.ch) #ifndef _HW_MD2_H_ diff --git a/src/hardware/hws_data.h b/src/hardware/hws_data.h index b890d976b0ec0831dbad6bab765f3befe9ba5dd9..a8607ac67718675468ef22c9515a1a18775991d4 100644 --- a/src/hardware/hws_data.h +++ b/src/hardware/hws_data.h @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- +// Copyright (C) 2005 by Sonic Team Junior. // -// Copyright (C) 2005 by SRB2 Jr. Team. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hws_data.h /// \brief 3D sound definitions #ifndef __HWS_DATA_H__ diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index e4a71734be199bc7180e6be48f8c0dcd9aaa6fd8..c9bf601442a5531b35d0ac629730aa83978d17a6 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -206,7 +206,7 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth if (iLastPFD) { - DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n"); + GL_DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n"); } // set the pixel format only if different than the current @@ -215,17 +215,17 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth else iLastPFD = iPFD; - DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n", + GL_DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n", WantColorBits, WantStencilBits, WantDepthBits); nPixelFormat = ChoosePixelFormat(hDC, &pfd); if (nPixelFormat == 0) - DBG_Printf("ChoosePixelFormat() FAILED\n"); + GL_DBG_Printf("ChoosePixelFormat() FAILED\n"); if (SetPixelFormat(hDC, nPixelFormat, &pfd) == 0) { - DBG_Printf("SetPixelFormat() FAILED\n"); + GL_DBG_Printf("SetPixelFormat() FAILED\n"); return 0; } @@ -243,7 +243,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN); UNREFERENCED_PARAMETER(pcurrentmode); - DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n", + GL_DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n", lvid->width, lvid->height, lvid->bpp*8, WantFullScreen ? "fullscreen" : "windowed"); @@ -301,7 +301,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) hDC = GetDC(hWnd); if (!hDC) { - DBG_Printf("GetDC() FAILED\n"); + GL_DBG_Printf("GetDC() FAILED\n"); return 0; } @@ -321,12 +321,12 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) hGLRC = pwglCreateContext(hDC); if (!hGLRC) { - DBG_Printf("pwglCreateContext() FAILED\n"); + GL_DBG_Printf("pwglCreateContext() FAILED\n"); return 0; } if (!pwglMakeCurrent(hDC, hGLRC)) { - DBG_Printf("wglMakeCurrent() FAILED\n"); + GL_DBG_Printf("wglMakeCurrent() FAILED\n"); return 0; } } @@ -337,15 +337,15 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) //BP: why don't we make it earlier ? //Hurdler: we cannot do that before intialising gl context renderer = (LPCSTR)pglGetString(GL_RENDERER); - DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR)); - DBG_Printf("Renderer : %s\n", renderer); - DBG_Printf("Version : %s\n", pglGetString(GL_VERSION)); - DBG_Printf("Extensions : %s\n", gl_extensions); + GL_DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR)); + GL_DBG_Printf("Renderer : %s\n", renderer); + GL_DBG_Printf("Version : %s\n", pglGetString(GL_VERSION)); + GL_DBG_Printf("Extensions : %s\n", gl_extensions); // BP: disable advenced feature that don't work on somes hardware // Hurdler: Now works on G400 with bios 1.6 and certified drivers 6.04 if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD; - DBG_Printf("oglflags : 0x%X\n", oglflags); + GL_DBG_Printf("oglflags : 0x%X\n", oglflags); #ifdef USE_WGL_SWAP if (isExtAvailable("WGL_EXT_swap_control",gl_extensions)) @@ -386,7 +386,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) // -----------------+ static void UnSetRes(void) { - DBG_Printf("UnSetRes()\n"); + GL_DBG_Printf("UnSetRes()\n"); pwglMakeCurrent(hDC, NULL); pwglDeleteContext(hGLRC); @@ -437,7 +437,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) video_modes[iMode].misc = 0; video_modes[iMode].name = malloc(12 * sizeof (CHAR)); sprintf(video_modes[iMode].name, "%dx%d", (INT32)Tmp.dmPelsWidth, (INT32)Tmp.dmPelsHeight); - DBG_Printf ("Mode: %s\n", video_modes[iMode].name); + GL_DBG_Printf ("Mode: %s\n", video_modes[iMode].name); video_modes[iMode].width = Tmp.dmPelsWidth; video_modes[iMode].height = Tmp.dmPelsHeight; video_modes[iMode].bytesperpixel = Tmp.dmBitsPerPel/8; @@ -474,7 +474,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) HDC bpphdc; INT32 iBitsPerPel; - DBG_Printf ("HWRAPI GetModeList()\n"); + GL_DBG_Printf ("HWRAPI GetModeList()\n"); bpphdc = GetDC(NULL); // on obtient le bpp actuel iBitsPerPel = GetDeviceCaps(bpphdc, BITSPIXEL); @@ -490,7 +490,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) video_modes[i].misc = 0; video_modes[i].name = malloc(12 * sizeof (CHAR)); sprintf(video_modes[i].name, "%dx%d", res[i][0], res[i][1]); - DBG_Printf ("Mode: %s\n", video_modes[i].name); + GL_DBG_Printf ("Mode: %s\n", video_modes[i].name); video_modes[i].width = res[i][0]; video_modes[i].height = res[i][1]; video_modes[i].bytesperpixel = iBitsPerPel/8; @@ -511,9 +511,9 @@ EXPORT void HWRAPI(Shutdown) (void) #ifdef DEBUG_TO_FILE long nb_centiemes; - DBG_Printf ("HWRAPI Shutdown()\n"); + GL_DBG_Printf ("HWRAPI Shutdown()\n"); nb_centiemes = ((clock()-my_clock)*100)/CLOCKS_PER_SEC; - DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n", + GL_DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n", nb_frames, nb_centiemes/100.0f, (100*nb_frames)/(double)nb_centiemes); #endif @@ -530,7 +530,7 @@ EXPORT void HWRAPI(Shutdown) (void) } FreeLibrary(GLU32); FreeLibrary(OGL32); - DBG_Printf ("HWRAPI Shutdown(DONE)\n"); + GL_DBG_Printf ("HWRAPI Shutdown(DONE)\n"); } // -----------------+ @@ -543,7 +543,7 @@ EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl) #else UNREFERENCED_PARAMETER(waitvbl); #endif - // DBG_Printf ("FinishUpdate()\n"); + // GL_DBG_Printf ("FinishUpdate()\n"); #ifdef DEBUG_TO_FILE if ((++nb_frames)==2) // on ne commence pas � la premi�re frame my_clock = clock(); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 73f6a40441b9d4706c06e2265e46842009747b6e..6fe9f7a36627fb9c5cae862e5124b059e59e0cd3 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1,20 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file r_opengl.c /// \brief OpenGL API for Sonic Robo Blast 2 #if defined (_WIN32) @@ -64,10 +56,6 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; static GLuint tex_downloaded = 0; static GLfloat fov = 90.0f; -#if 0 -static GLuint pal_col = 0; -static FRGBAFloat const_pal_col; -#endif static FBITFIELD CurrentPolyFlags; static FTextureInfo *gr_cachetail = NULL; @@ -83,14 +71,16 @@ static GLboolean MipMap = GL_FALSE; static GLint min_filter = GL_LINEAR; static GLint mag_filter = GL_LINEAR; static GLint anisotropic_filter = 0; -static boolean model_lighting = true; +static boolean model_lighting = false; +const GLubyte *gl_version = NULL; +const GLubyte *gl_renderer = NULL; const GLubyte *gl_extensions = NULL; //Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-) -static GLfloat modelMatrix[16]; -static GLfloat projMatrix[16]; -static GLint viewport[4]; +static GLfloat modelMatrix[16]; +static GLfloat projMatrix[16]; +static GLint viewport[4]; // Sryder: NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing // flush all of the stored textures, leaving them unavailable at times such as between levels @@ -100,9 +90,10 @@ static GLuint screentexture = 0; static GLuint startScreenWipe = 0; static GLuint endScreenWipe = 0; static GLuint finalScreenTexture = 0; -#if 0 -GLuint screentexture = FIRST_TEX_AVAIL; -#endif + +// Lactozilla: Set shader programs and uniforms +static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { @@ -140,31 +131,82 @@ static const GLfloat byte2float[256] = { 0.972549f, 0.976471f, 0.980392f, 0.984314f, 0.988235f, 0.992157f, 0.996078f, 1.000000f }; -float byteasfloat(UINT8 fbyte) +// -----------------+ +// GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined, +// : else do nothing +// Returns : +// -----------------+ + +#ifdef DEBUG_TO_FILE +FILE *gllogstream; +#endif + +FUNCPRINTF void GL_DBG_Printf(const char *format, ...) { - return (float)(byte2float[fbyte]*2.0f); -} +#ifdef DEBUG_TO_FILE + char str[4096] = ""; + va_list arglist; + + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); -static I_Error_t I_Error_GL = NULL; + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + + fwrite(str, strlen(str), 1, gllogstream); +#else + (void)format; +#endif +} // -----------------+ -// DBG_Printf : Output error messages to debug log if DEBUG_TO_FILE is defined, -// : else do nothing +// GL_MSG_Warning : Raises a warning. +// : // Returns : // -----------------+ -FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) + +static void GL_MSG_Warning(const char *format, ...) { + char str[4096] = ""; + va_list arglist; + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + +#ifdef HAVE_SDL + CONS_Alert(CONS_WARNING, "%s", str); +#endif #ifdef DEBUG_TO_FILE - char str[4096] = ""; + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + fwrite(str, strlen(str), 1, gllogstream); +#endif +} + +// -----------------+ +// GL_MSG_Error : Raises an error. +// : +// Returns : +// -----------------+ + +static void GL_MSG_Error(const char *format, ...) +{ + char str[4096] = ""; va_list arglist; - va_start (arglist, lpFmt); - vsnprintf (str, 4096, lpFmt, arglist); - va_end (arglist); - if (gllogstream) - fwrite(str, strlen(str), 1, gllogstream); -#else - (void)lpFmt; + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + +#ifdef HAVE_SDL + CONS_Alert(CONS_ERROR, "%s", str); +#endif +#ifdef DEBUG_TO_FILE + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + fwrite(str, strlen(str), 1, gllogstream); #endif } @@ -219,6 +261,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglLightfv glLightfv #define pglLightModelfv glLightModelfv #define pglMaterialfv glMaterialfv +#define pglMateriali glMateriali /* Raster functions */ #define pglPixelStorei glPixelStorei @@ -228,10 +271,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglTexEnvi glTexEnvi #define pglTexParameteri glTexParameteri #define pglTexImage2D glTexImage2D - -/* Fog */ -#define pglFogf glFogf -#define pglFogfv glFogfv +#define pglTexSubImage2D glTexSubImage2D /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -248,7 +288,6 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) /* Miscellaneous */ typedef void (APIENTRY * PFNglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); static PFNglClearColor pglClearColor; -//glClear typedef void (APIENTRY * PFNglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); static PFNglColorMask pglColorMask; typedef void (APIENTRY * PFNglAlphaFunc) (GLenum func, GLclampf ref); @@ -267,8 +306,6 @@ typedef void (APIENTRY * PFNglDisable) (GLenum cap); static PFNglDisable pglDisable; typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params); static PFNglGetFloatv pglGetFloatv; -//glGetIntegerv -//glGetString /* Depth Buffer */ typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth); @@ -329,6 +366,8 @@ typedef void (APIENTRY * PFNglLightModelfv) (GLenum pname, GLfloat *params); static PFNglLightModelfv pglLightModelfv; typedef void (APIENTRY * PFNglMaterialfv) (GLint face, GLenum pname, GLfloat *params); static PFNglMaterialfv pglMaterialfv; +typedef void (APIENTRY * PFNglMateriali) (GLint face, GLenum pname, GLint param); +static PFNglMateriali pglMateriali; /* Raster functions */ typedef void (APIENTRY * PFNglPixelStorei) (GLenum pname, GLint param); @@ -343,12 +382,8 @@ typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint static PFNglTexParameteri pglTexParameteri; typedef void (APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); static PFNglTexImage2D pglTexImage2D; - -/* Fog */ -typedef void (APIENTRY * PFNglFogf) (GLenum pname, GLfloat param); -static PFNglFogf pglFogf; -typedef void (APIENTRY * PFNglFogfv) (GLenum pname, const GLfloat *params); -static PFNglFogfv pglFogfv; +typedef void (APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static PFNglTexSubImage2D pglTexSubImage2D; /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -424,7 +459,7 @@ boolean SetupGLfunc(void) func = GetGLFunc(#proc); \ if (!func) \ { \ - DBG_Printf("failed to get OpenGL function: %s", #proc); \ + GL_MSG_Warning("failed to get OpenGL function: %s", #proc); \ } \ GETOPENGLFUNC(pglClearColor, glClearColor) @@ -442,22 +477,23 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv) GETOPENGLFUNC(pglGetString, glGetString) - GETOPENGLFUNC(pglClearDepth , glClearDepth) - GETOPENGLFUNC(pglDepthFunc , glDepthFunc) - GETOPENGLFUNC(pglDepthMask , glDepthMask) - GETOPENGLFUNC(pglDepthRange , glDepthRange) - - GETOPENGLFUNC(pglMatrixMode , glMatrixMode) - GETOPENGLFUNC(pglViewport , glViewport) - GETOPENGLFUNC(pglPushMatrix , glPushMatrix) - GETOPENGLFUNC(pglPopMatrix , glPopMatrix) - GETOPENGLFUNC(pglLoadIdentity , glLoadIdentity) - GETOPENGLFUNC(pglMultMatrixf , glMultMatrixf) - GETOPENGLFUNC(pglRotatef , glRotatef) - GETOPENGLFUNC(pglScalef , glScalef) - GETOPENGLFUNC(pglTranslatef , glTranslatef) + GETOPENGLFUNC(pglClearDepth, glClearDepth) + GETOPENGLFUNC(pglDepthFunc, glDepthFunc) + GETOPENGLFUNC(pglDepthMask, glDepthMask) + GETOPENGLFUNC(pglDepthRange, glDepthRange) + + GETOPENGLFUNC(pglMatrixMode, glMatrixMode) + GETOPENGLFUNC(pglViewport, glViewport) + GETOPENGLFUNC(pglPushMatrix, glPushMatrix) + GETOPENGLFUNC(pglPopMatrix, glPopMatrix) + GETOPENGLFUNC(pglLoadIdentity, glLoadIdentity) + GETOPENGLFUNC(pglMultMatrixf, glMultMatrixf) + GETOPENGLFUNC(pglRotatef, glRotatef) + GETOPENGLFUNC(pglScalef, glScalef) + GETOPENGLFUNC(pglTranslatef, glTranslatef) GETOPENGLFUNC(pglColor4ubv, glColor4ubv) + GETOPENGLFUNC(pglVertexPointer, glVertexPointer) GETOPENGLFUNC(pglNormalPointer, glNormalPointer) GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) @@ -467,39 +503,329 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglEnableClientState, glEnableClientState) GETOPENGLFUNC(pglDisableClientState, glDisableClientState) - GETOPENGLFUNC(pglShadeModel , glShadeModel) + GETOPENGLFUNC(pglShadeModel, glShadeModel) GETOPENGLFUNC(pglLightfv, glLightfv) - GETOPENGLFUNC(pglLightModelfv , glLightModelfv) - GETOPENGLFUNC(pglMaterialfv , glMaterialfv) - - GETOPENGLFUNC(pglPixelStorei , glPixelStorei) - GETOPENGLFUNC(pglReadPixels , glReadPixels) + GETOPENGLFUNC(pglLightModelfv, glLightModelfv) + GETOPENGLFUNC(pglMaterialfv, glMaterialfv) + GETOPENGLFUNC(pglMateriali, glMateriali) - GETOPENGLFUNC(pglTexEnvi , glTexEnvi) - GETOPENGLFUNC(pglTexParameteri , glTexParameteri) - GETOPENGLFUNC(pglTexImage2D , glTexImage2D) + GETOPENGLFUNC(pglPixelStorei, glPixelStorei) + GETOPENGLFUNC(pglReadPixels, glReadPixels) - GETOPENGLFUNC(pglFogf , glFogf) - GETOPENGLFUNC(pglFogfv , glFogfv) + GETOPENGLFUNC(pglTexEnvi, glTexEnvi) + GETOPENGLFUNC(pglTexParameteri, glTexParameteri) + GETOPENGLFUNC(pglTexImage2D, glTexImage2D) + GETOPENGLFUNC(pglTexSubImage2D, glTexSubImage2D) - GETOPENGLFUNC(pglGenTextures , glGenTextures) - GETOPENGLFUNC(pglDeleteTextures , glDeleteTextures) - GETOPENGLFUNC(pglBindTexture , glBindTexture) + GETOPENGLFUNC(pglGenTextures, glGenTextures) + GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures) + GETOPENGLFUNC(pglBindTexture, glBindTexture) - GETOPENGLFUNC(pglCopyTexImage2D , glCopyTexImage2D) - GETOPENGLFUNC(pglCopyTexSubImage2D , glCopyTexSubImage2D) + GETOPENGLFUNC(pglCopyTexImage2D, glCopyTexImage2D) + GETOPENGLFUNC(pglCopyTexSubImage2D, glCopyTexSubImage2D) #undef GETOPENGLFUNC - pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); - #endif return true; } -// This has to be done after the context is created so the version number can be obtained -// This is stupid -- even some of the oldest usable OpenGL hardware today supports 1.3-level featureset. -boolean SetupGLFunc13(void) +static boolean gl_allowshaders = false; +static boolean gl_shadersenabled = false; + +#ifdef GL_SHADERS +typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum); +typedef void (APIENTRY *PFNglShaderSource) (GLuint, GLsizei, const GLchar**, GLint*); +typedef void (APIENTRY *PFNglCompileShader) (GLuint); +typedef void (APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*); +typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*); +typedef void (APIENTRY *PFNglDeleteShader) (GLuint); +typedef GLuint (APIENTRY *PFNglCreateProgram) (void); +typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint); +typedef void (APIENTRY *PFNglLinkProgram) (GLuint); +typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*); +typedef void (APIENTRY *PFNglUseProgram) (GLuint); +typedef void (APIENTRY *PFNglUniform1i) (GLint, GLint); +typedef void (APIENTRY *PFNglUniform1f) (GLint, GLfloat); +typedef void (APIENTRY *PFNglUniform2f) (GLint, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform3f) (GLint, GLfloat, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform4f) (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform1fv) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY *PFNglUniform2fv) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY *PFNglUniform3fv) (GLint, GLsizei, const GLfloat*); +typedef GLint (APIENTRY *PFNglGetUniformLocation) (GLuint, const GLchar*); + +static PFNglCreateShader pglCreateShader; +static PFNglShaderSource pglShaderSource; +static PFNglCompileShader pglCompileShader; +static PFNglGetShaderiv pglGetShaderiv; +static PFNglGetShaderInfoLog pglGetShaderInfoLog; +static PFNglDeleteShader pglDeleteShader; +static PFNglCreateProgram pglCreateProgram; +static PFNglAttachShader pglAttachShader; +static PFNglLinkProgram pglLinkProgram; +static PFNglGetProgramiv pglGetProgramiv; +static PFNglUseProgram pglUseProgram; +static PFNglUniform1i pglUniform1i; +static PFNglUniform1f pglUniform1f; +static PFNglUniform2f pglUniform2f; +static PFNglUniform3f pglUniform3f; +static PFNglUniform4f pglUniform4f; +static PFNglUniform1fv pglUniform1fv; +static PFNglUniform2fv pglUniform2fv; +static PFNglUniform3fv pglUniform3fv; +static PFNglGetUniformLocation pglGetUniformLocation; + +#define MAXSHADERS 16 +#define MAXSHADERPROGRAMS 16 + +// 18032019 +static char *gl_customvertexshaders[MAXSHADERS]; +static char *gl_customfragmentshaders[MAXSHADERS]; +static GLuint gl_currentshaderprogram = 0; +static boolean gl_shaderprogramchanged = true; + +// 13062019 +typedef enum +{ + // lighting + gluniform_poly_color, + gluniform_tint_color, + gluniform_fade_color, + gluniform_lighting, + gluniform_fade_start, + gluniform_fade_end, + + // misc. (custom shaders) + gluniform_leveltime, + + gluniform_max, +} gluniform_t; + +typedef struct gl_shaderprogram_s +{ + GLuint program; + boolean custom; + GLint uniforms[gluniform_max+1]; +} gl_shaderprogram_t; +static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; + +// Shader info +static INT32 shader_leveltime = 0; + +// ======================== +// Fragment shader macros +// ======================== + +// +// GLSL Software fragment shader +// + +#define GLSL_DOOM_COLORMAP \ + "float R_DoomColormap(float light, float z)\n" \ + "{\n" \ + "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ + "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ + "float startmap = (15.0 - lightnum) * 4.0;\n" \ + "float scale = 160.0 / (lightz + 1.0);\n" \ + "return startmap - scale * 0.5;\n" \ + "}\n" + +#define GLSL_DOOM_LIGHT_EQUATION \ + "float R_DoomLightingEquation(float light)\n" \ + "{\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ + "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ + "}\n" + +#define GLSL_SOFTWARE_TINT_EQUATION \ + "if (tint_color.a > 0.0) {\n" \ + "float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \ + "float strength = sqrt(9.0 * tint_color.a);\n" \ + "final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \ + "final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \ + "final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \ + "}\n" + +#define GLSL_SOFTWARE_FADE_EQUATION \ + "float darkness = R_DoomLightingEquation(lighting);\n" \ + "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ + "float fs = fade_start / 31.0;\n" \ + "float fe = fade_end / 31.0;\n" \ + "float fd = fe - fs;\n" \ + "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ + "}\n" \ + "final_color = mix(final_color, fade_color, darkness);\n" + +#define GLSL_SOFTWARE_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Water surface shader +// +// Mostly guesstimated, rather than the rest being built off Software science. +// Still needs to distort things underneath/around the water... +// + +#define GLSL_WATER_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + "uniform float leveltime;\n" \ + "const float freq = 0.025;\n" \ + "const float amp = 0.025;\n" \ + "const float speed = 2.0;\n" \ + "const float pi = 3.14159;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ + "float a = -pi * (z * freq) + (leveltime * speed);\n" \ + "float sdistort = sin(a) * amp;\n" \ + "float cdistort = cos(a) * amp;\n" \ + "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Fog block shader +// +// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha +// + +#define GLSL_FOG_FRAGMENT_SHADER \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 base_color = gl_Color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// GLSL generic fragment shader +// + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +static const char *fragment_shaders[] = { + // Default fragment shader + GLSL_DEFAULT_FRAGMENT_SHADER, + + // Floor fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Wall fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Sprite fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Model fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Water fragment shader + GLSL_WATER_FRAGMENT_SHADER, + + // Fog fragment shader + GLSL_FOG_FRAGMENT_SHADER, + + // Sky fragment shader + "uniform sampler2D tex;\n" + "void main(void) {\n" + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" + "}\0", + + NULL, +}; + +// ====================== +// Vertex shader macros +// ====================== + +// +// GLSL generic vertex shader +// + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +static const char *vertex_shaders[] = { + // Default vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Floor vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Wall vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Sprite vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Model vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Water vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Fog vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Sky vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + NULL, +}; + +#endif // GL_SHADERS + +void SetupGLFunc4(void) { pglActiveTexture = GetGLFunc("glActiveTexture"); pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); @@ -512,7 +838,253 @@ boolean SetupGLFunc13(void) pglBufferData = GetGLFunc("glBufferData"); pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); - return true; +#ifdef GL_SHADERS + pglCreateShader = GetGLFunc("glCreateShader"); + pglShaderSource = GetGLFunc("glShaderSource"); + pglCompileShader = GetGLFunc("glCompileShader"); + pglGetShaderiv = GetGLFunc("glGetShaderiv"); + pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog"); + pglDeleteShader = GetGLFunc("glDeleteShader"); + pglCreateProgram = GetGLFunc("glCreateProgram"); + pglAttachShader = GetGLFunc("glAttachShader"); + pglLinkProgram = GetGLFunc("glLinkProgram"); + pglGetProgramiv = GetGLFunc("glGetProgramiv"); + pglUseProgram = GetGLFunc("glUseProgram"); + pglUniform1i = GetGLFunc("glUniform1i"); + pglUniform1f = GetGLFunc("glUniform1f"); + pglUniform2f = GetGLFunc("glUniform2f"); + pglUniform3f = GetGLFunc("glUniform3f"); + pglUniform4f = GetGLFunc("glUniform4f"); + pglUniform1fv = GetGLFunc("glUniform1fv"); + pglUniform2fv = GetGLFunc("glUniform2fv"); + pglUniform3fv = GetGLFunc("glUniform3fv"); + pglGetUniformLocation = GetGLFunc("glGetUniformLocation"); +#endif + + // GLU + pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); +} + +// jimita +EXPORT void HWRAPI(LoadShaders) (void) +{ +#ifdef GL_SHADERS + GLuint gl_vertShader, gl_fragShader; + GLint i, result; + + gl_customvertexshaders[0] = NULL; + gl_customfragmentshaders[0] = NULL; + + for (i = 0; vertex_shaders[i] && fragment_shaders[i]; i++) + { + gl_shaderprogram_t *shader; + const GLchar* vert_shader = vertex_shaders[i]; + const GLchar* frag_shader = fragment_shaders[i]; + boolean custom = ((gl_customvertexshaders[i] || gl_customfragmentshaders[i]) && (i > 0)); + + // 18032019 + if (gl_customvertexshaders[i]) + vert_shader = gl_customvertexshaders[i]; + if (gl_customfragmentshaders[i]) + frag_shader = gl_customfragmentshaders[i]; + + if (i >= MAXSHADERS) + break; + if (i >= MAXSHADERPROGRAMS) + break; + + shader = &gl_shaderprograms[i]; + shader->program = 0; + shader->custom = custom; + + // + // Load and compile vertex shader + // + gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); + if (!gl_vertShader) + { + GL_MSG_Error("LoadShaders: Error creating vertex shader %d\n", i); + continue; + } + + pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); + pglCompileShader(gl_vertShader); + + // check for compile errors + pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + GLchar* infoLog; + GLint logLength; + + pglGetShaderiv(gl_vertShader, GL_INFO_LOG_LENGTH, &logLength); + + infoLog = malloc(logLength); + pglGetShaderInfoLog(gl_vertShader, logLength, NULL, infoLog); + + GL_MSG_Error("LoadShaders: Error compiling vertex shader %d\n%s", i, infoLog); + continue; + } + + // + // Load and compile fragment shader + // + gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); + if (!gl_fragShader) + { + GL_MSG_Error("LoadShaders: Error creating fragment shader %d\n", i); + continue; + } + + pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); + pglCompileShader(gl_fragShader); + + // check for compile errors + pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + GLchar* infoLog; + GLint logLength; + + pglGetShaderiv(gl_fragShader, GL_INFO_LOG_LENGTH, &logLength); + + infoLog = malloc(logLength); + pglGetShaderInfoLog(gl_fragShader, logLength, NULL, infoLog); + + GL_MSG_Error("LoadShaders: Error compiling fragment shader %d\n%s", i, infoLog); + continue; + } + + shader->program = pglCreateProgram(); + pglAttachShader(shader->program, gl_vertShader); + pglAttachShader(shader->program, gl_fragShader); + pglLinkProgram(shader->program); + + // check link status + pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); + + // delete the shader objects + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + + // couldn't link? + if (result != GL_TRUE) + { + shader->program = 0; + shader->custom = false; + GL_MSG_Error("LoadShaders: Error linking shader program %d\n", i); + continue; + } + + // 13062019 +#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); + + // lighting + shader->uniforms[gluniform_poly_color] = GETUNI("poly_color"); + shader->uniforms[gluniform_tint_color] = GETUNI("tint_color"); + shader->uniforms[gluniform_fade_color] = GETUNI("fade_color"); + shader->uniforms[gluniform_lighting] = GETUNI("lighting"); + shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); + shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); + + // misc. (custom shaders) + shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); + +#undef GETUNI + } +#endif +} + +// +// Shader info +// Those are given to the uniforms. +// + +EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) +{ +#ifdef GL_SHADERS + switch (info) + { + case HWD_SHADERINFO_LEVELTIME: + shader_leveltime = value; + break; + default: + break; + } +#else + (void)info; + (void)value; +#endif +} + +// +// Custom shader loading +// +EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment) +{ +#ifdef GL_SHADERS + if (number < 1 || number > MAXSHADERS) + I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS); + + if (fragment) + { + gl_customfragmentshaders[number] = malloc(size+1); + strncpy(gl_customfragmentshaders[number], shader, size); + gl_customfragmentshaders[number][size] = 0; + } + else + { + gl_customvertexshaders[number] = malloc(size+1); + strncpy(gl_customvertexshaders[number], shader, size); + gl_customvertexshaders[number][size] = 0; + } +#else + (void)number; + (void)shader; + (void)size; + (void)fragment; +#endif +} + +EXPORT void HWRAPI(InitCustomShaders) (void) +{ +#ifdef GL_SHADERS + KillShaders(); + LoadShaders(); +#endif +} + +EXPORT void HWRAPI(SetShader) (int shader) +{ +#ifdef GL_SHADERS + if (gl_allowshaders) + { + if ((GLuint)shader != gl_currentshaderprogram) + { + gl_currentshaderprogram = shader; + gl_shaderprogramchanged = true; + } + gl_shadersenabled = true; + return; + } +#else + (void)shader; +#endif + gl_shadersenabled = false; +} + +EXPORT void HWRAPI(UnSetShader) (void) +{ +#ifdef GL_SHADERS + gl_shadersenabled = false; + gl_currentshaderprogram = 0; + pglUseProgram(0); +#endif +} + +EXPORT void HWRAPI(KillShaders) (void) +{ + // unused......................... } // -----------------+ @@ -520,7 +1092,7 @@ boolean SetupGLFunc13(void) // -----------------+ static void SetNoTexture(void) { - // Set small white texture. + // Disable texture. if (tex_downloaded != NOTEXTURE_NUM) { if (NOTEXTURE_NUM == 0) @@ -542,7 +1114,7 @@ static void GLPerspective(GLfloat fovy, GLfloat aspect) const GLfloat zNear = NEAR_CLIPPING_PLANE; const GLfloat zFar = FAR_CLIPPING_PLANE; const GLfloat radians = (GLfloat)(fovy / 2.0f * M_PIl / 180.0f); - const GLfloat sine = sinf(radians); + const GLfloat sine = sin(radians); const GLfloat deltaZ = zFar - zNear; GLfloat cotangent; @@ -605,7 +1177,7 @@ static void GLProject(GLfloat objX, GLfloat objY, GLfloat objZ, // -----------------+ void SetModelView(GLint w, GLint h) { -// DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); +// GL_DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); // The screen textures need to be flushed if the width or height change so that they be remade for the correct size if (screen_width != w || screen_height != h) @@ -615,9 +1187,6 @@ void SetModelView(GLint w, GLint h) screen_height = h; pglViewport(0, 0, w, h); -#ifdef GL_ACCUM_BUFFER_BIT - pglClear(GL_ACCUM_BUFFER_BIT); -#endif pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); @@ -643,7 +1212,7 @@ void SetStates(void) GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; #endif -// DBG_Printf("SetStates()\n"); +// GL_DBG_Printf("SetStates()\n"); // Hurdler: not necessary, is it? pglShadeModel(GL_SMOOTH); // iterate vertice colors @@ -668,7 +1237,7 @@ void SetStates(void) pglDepthRange(0.0f, 1.0f); pglDepthFunc(GL_LEQUAL); - // this set CurrentPolyFlags to the acctual configuration + // this set CurrentPolyFlags to the actual configuration CurrentPolyFlags = 0xffffffff; SetBlend(0); @@ -680,10 +1249,7 @@ void SetStates(void) //pglEnable(GL_CULL_FACE); //pglCullFace(GL_FRONT); - //glFogi(GL_FOG_MODE, GL_EXP); - //pglHint(GL_FOG_HINT, GL_FASTEST); - //pglFogfv(GL_FOG_COLOR, fogcolor); - //pglFogf(GL_FOG_DENSITY, 0.0005f); + pglDisable(GL_FOG); // Lighting for models #ifdef GL_LIGHT_MODEL_AMBIENT @@ -704,7 +1270,7 @@ void SetStates(void) // -----------------+ void Flush(void) { - //DBG_Printf ("HWR_Flush()\n"); + //GL_DBG_Printf ("HWR_Flush()\n"); while (gr_cachehead) { @@ -751,10 +1317,8 @@ INT32 isExtAvailable(const char *extension, const GLubyte *start) // Init : Initialise the OpenGL interface API // Returns : // -----------------+ -EXPORT boolean HWRAPI(Init) (I_Error_t FatalErrorFunction) +EXPORT boolean HWRAPI(Init) (void) { - I_Error_GL = FatalErrorFunction; - DBG_Printf ("%s %s\n", DRIVER_STRING, VERSIONSTRING); return LoadGL(); } @@ -764,7 +1328,7 @@ EXPORT boolean HWRAPI(Init) (I_Error_t FatalErrorFunction) // -----------------+ EXPORT void HWRAPI(ClearMipMapCache) (void) { - // DBG_Printf ("HWR_Flush(exe)\n"); + // GL_DBG_Printf ("HWR_Flush(exe)\n"); Flush(); } @@ -778,7 +1342,7 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 * dst_data) { INT32 i; - // DBG_Printf ("ReadRect()\n"); + // GL_DBG_Printf ("ReadRect()\n"); if (dst_stride == width*3) { GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (height - 1); @@ -826,7 +1390,7 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, // -----------------+ EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip) { - // DBG_Printf ("GClipRect(%d, %d, %d, %d)\n", minx, miny, maxx, maxy); + // GL_DBG_Printf ("GClipRect(%d, %d, %d, %d)\n", minx, miny, maxx, maxy); pglViewport(minx, screen_height-maxy, maxx-minx, maxy-miny); NEAR_CLIPPING_PLANE = nearclip; @@ -850,7 +1414,7 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat * ClearColor) { - // DBG_Printf ("ClearBuffer(%d)\n", alpha); + // GL_DBG_Printf ("ClearBuffer(%d)\n", alpha); GLbitfield ClearMask = 0; if (ColorMask) @@ -885,7 +1449,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, F2DCoord * v2, RGBA_t Color) { - // DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); + // GL_DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); GLfloat p[12]; GLfloat dx, dy; GLfloat angle; @@ -1028,7 +1592,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) else #endif if (PolyFlags & PF_Modulated) - { // mix texture colour with Surface->FlatColor + { // mix texture colour with Surface->PolyColor pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else @@ -1067,200 +1631,229 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) CurrentPolyFlags = PolyFlags; } - // -----------------+ -// SetTexture : The mipmap becomes the current texture source +// UpdateTexture : Updates the texture data. // -----------------+ -EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *pTexInfo) { - if (!pTexInfo) - { - SetNoTexture(); - return; - } - else if (pTexInfo->downloaded) + // Download a mipmap + boolean updatemipmap = true; + static RGBA_t tex[2048*2048]; + const GLvoid *ptex = tex; + INT32 w, h; + GLuint texnum = 0; + + if (!pTexInfo->downloaded) { - if (pTexInfo->downloaded != tex_downloaded) - { - pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); - tex_downloaded = pTexInfo->downloaded; - } + pglGenTextures(1, &texnum); + pTexInfo->downloaded = texnum; + updatemipmap = false; } else - { - // Download a mipmap - static RGBA_t tex[2048*2048]; - const GLvoid *ptex = tex; - INT32 w, h; - GLuint texnum = 0; + texnum = pTexInfo->downloaded; - pglGenTextures(1, &texnum); - //DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->grInfo.data); + //GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->grInfo.data); - w = pTexInfo->width; - h = pTexInfo->height; + w = pTexInfo->width; + h = pTexInfo->height; - if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || - (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; + if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || + (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; - for (j = 0; j < h; j++) + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) { - for (i = 0; i < w; i++) + if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && + (pTexInfo->flags & TF_CHROMAKEYED)) { - if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && - (pTexInfo->flags & TF_CHROMAKEYED)) - { - tex[w*j+i].s.red = 0; - tex[w*j+i].s.green = 0; - tex[w*j+i].s.blue = 0; - tex[w*j+i].s.alpha = 0; - pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it - } - else - { - tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; - tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; - tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; - tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; - } - - pImgData++; + tex[w*j+i].s.red = 0; + tex[w*j+i].s.green = 0; + tex[w*j+i].s.blue = 0; + tex[w*j+i].s.alpha = 0; + pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it + } + else + { + tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; + tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; + tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; + tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; + } - if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) - { - if (!(pTexInfo->flags & TF_CHROMAKEYED)) - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } + pImgData++; + if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) + { + if (!(pTexInfo->flags & TF_CHROMAKEYED)) + tex[w*j+i].s.alpha = *pImgData; + pImgData++; } + } } - else if (pTexInfo->grInfo.format == GR_RGBA) - { - // corona test : passed as ARGB 8888, which is not in glide formats - // Hurdler: not used for coronas anymore, just for dynamic lighting - ptex = pTexInfo->grInfo.data; - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; + } + else if (pTexInfo->grInfo.format == GR_RGBA) + { + // corona test : passed as ARGB 8888, which is not in glide formats + // Hurdler: not used for coronas anymore, just for dynamic lighting + ptex = pTexInfo->grInfo.data; + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; - for (j = 0; j < h; j++) + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = *pImgData; - tex[w*j+i].s.green = *pImgData; - tex[w*j+i].s.blue = *pImgData; - pImgData++; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } + tex[w*j+i].s.red = *pImgData; + tex[w*j+i].s.green = *pImgData; + tex[w*j+i].s.blue = *pImgData; + pImgData++; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; } } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; - for (j = 0; j < h; j++) + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't - tex[w*j+i].s.green = 255; - tex[w*j+i].s.blue = 255; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } + tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't + tex[w*j+i].s.green = 255; + tex[w*j+i].s.blue = 255; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; } } - else - DBG_Printf ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); + } + else + GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); - // the texture number was already generated by pglGenTextures - pglBindTexture(GL_TEXTURE_2D, texnum); - pTexInfo->downloaded = texnum; - tex_downloaded = texnum; + // the texture number was already generated by pglGenTextures + pglBindTexture(GL_TEXTURE_2D, texnum); + tex_downloaded = texnum; + + // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues + if (pTexInfo->flags & TF_TRANSPARENT) + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + } - // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues - if (pTexInfo->flags & TF_TRANSPARENT) + if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); } else { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); } - - if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) + else { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); else pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); } + } + else + { + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + // Control the mipmap level of detail + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); + } else { - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - // Control the mipmap level of detail - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); - } + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); else pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); } + } - if (pTexInfo->flags & TF_WRAPX) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_S); + if (pTexInfo->flags & TF_WRAPX) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_S); - if (pTexInfo->flags & TF_WRAPY) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_T); + if (pTexInfo->flags & TF_WRAPY) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_T); - if (maximumAnisotropy) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); + if (maximumAnisotropy) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); +} +// -----------------+ +// SetTexture : The mipmap becomes the current texture source +// -----------------+ +EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) +{ + if (!pTexInfo) + { + SetNoTexture(); + return; + } + else if (pTexInfo->downloaded) + { + if (pTexInfo->downloaded != tex_downloaded) + { + pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); + tex_downloaded = pTexInfo->downloaded; + } + } + else + { + UpdateTexture(pTexInfo); pTexInfo->nextmipmap = NULL; if (gr_cachetail) { // insertion at the tail @@ -1272,32 +1865,134 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } +static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) +{ +#ifdef GL_SHADERS + if (gl_shadersenabled) + { + gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + if (shader->program) + { + if (gl_shaderprogramchanged) + { + pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); + gl_shaderprogramchanged = false; + } + Shader_SetUniforms(Surface, poly, tint, fade); + return shader; + } + else + pglUseProgram(0); + } + else + pglUseProgram(0); +#else + (void)Surface; + (void)poly; + (void)tint; + (void)fade; +#endif + return NULL; +} + +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) +{ +#ifdef GL_SHADERS + if (gl_shadersenabled) + { + gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + if (!shader->program) + return; -// -----------------+ -// DrawPolygon : Render a polygon, set the texture, set render mode -// -----------------+ -EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, - //FTextureInfo *pTexInfo, - FOutVector *pOutVerts, - FUINT iNumPts, - FBITFIELD PolyFlags) + #define UNIFORM_1(uniform, a, function) \ + if (uniform != -1) \ + function (uniform, a); + + #define UNIFORM_2(uniform, a, b, function) \ + if (uniform != -1) \ + function (uniform, a, b); + + #define UNIFORM_3(uniform, a, b, c, function) \ + if (uniform != -1) \ + function (uniform, a, b, c); + + #define UNIFORM_4(uniform, a, b, c, d, function) \ + if (uniform != -1) \ + function (uniform, a, b, c, d); + + // polygon + UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); + if (Surface != NULL) + { + UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); + } + UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f); + + #undef UNIFORM_1 + #undef UNIFORM_2 + #undef UNIFORM_3 + #undef UNIFORM_4 + } +#else + (void)Surface; + (void)poly; + (void)tint; + (void)fade; +#endif +} + +// code that is common between DrawPolygon and DrawIndexedTriangles +// the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching +static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags) { - FUINT i; - FUINT j; + static GLRGBAFloat poly = {0,0,0,0}; + static GLRGBAFloat tint = {0,0,0,0}; + static GLRGBAFloat fade = {0,0,0,0}; if ((PolyFlags & PF_Corona) && (oglflags & GLF_NOZBUFREAD)) PolyFlags &= ~(PF_NoDepthTest|PF_Corona); SetBlend(PolyFlags); //TODO: inline (#pragma..) - // If Modulated, mix the surface colour to the texture - if ((CurrentPolyFlags & PF_Modulated) && pSurf) - pglColor4ubv((GLubyte*)&pSurf->FlatColor.s); + // PolyColor + if (pSurf) + { + // If Modulated, mix the surface colour to the texture + if (CurrentPolyFlags & PF_Modulated) + { + // Poly color + poly.red = byte2float[pSurf->PolyColor.s.red]; + poly.green = byte2float[pSurf->PolyColor.s.green]; + poly.blue = byte2float[pSurf->PolyColor.s.blue]; + poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; + + pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); + } + + // Tint color + tint.red = byte2float[pSurf->TintColor.s.red]; + tint.green = byte2float[pSurf->TintColor.s.green]; + tint.blue = byte2float[pSurf->TintColor.s.blue]; + tint.alpha = byte2float[pSurf->TintColor.s.alpha]; + + // Fade color + fade.red = byte2float[pSurf->FadeColor.s.red]; + fade.green = byte2float[pSurf->FadeColor.s.green]; + fade.blue = byte2float[pSurf->FadeColor.s.blue]; + fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; + } // this test is added for new coronas' code (without depth buffer) // I think I should do a separate function for drawing coronas, so it will be a little faster if (PolyFlags & PF_Corona) // check to see if we need to draw the corona { + FUINT i; + FUINT j; + //rem: all 8 (or 8.0f) values are hard coded: it can be changed to a higher value GLfloat buf[8][8]; GLfloat cx, cy, cz; @@ -1314,18 +2009,18 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, // I dont know if this is slow or not GLProject(cx, cy, cz, &px, &py, &pz); - //DBG_Printf("Projection: (%f, %f, %f)\n", px, py, pz); + //GL_DBG_Printf("Projection: (%f, %f, %f)\n", px, py, pz); if ((pz < 0.0l) || - (px < -8.0l) || - (py < viewport[1]-8.0l) || - (px > viewport[2]+8.0l) || - (py > viewport[1]+viewport[3]+8.0l)) + (px < -8.0l) || + (py < viewport[1]-8.0l) || + (px > viewport[2]+8.0l) || + (py > viewport[1]+viewport[3]+8.0l)) return; // the damned slow glReadPixels functions :( pglReadPixels((INT32)px-4, (INT32)py, 8, 8, GL_DEPTH_COMPONENT, GL_FLOAT, buf); - //DBG_Printf("DepthBuffer: %f %f\n", buf[0][0], buf[3][3]); + //GL_DBG_Printf("DepthBuffer: %f %f\n", buf[0][0], buf[3][3]); for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) @@ -1338,24 +2033,34 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, if (py > viewport[1]+viewport[3]-4) scalef -= (GLfloat)(8*(4-(viewport[1]+viewport[3]-py))); scalef /= 64; - //DBG_Printf("Scale factor: %f\n", scalef); + //GL_DBG_Printf("Scale factor: %f\n", scalef); if (scalef < 0.05f) return; // GLubyte c[4]; - c[0] = pSurf->FlatColor.s.red; - c[1] = pSurf->FlatColor.s.green; - c[2] = pSurf->FlatColor.s.blue; + c[0] = pSurf->PolyColor.s.red; + c[1] = pSurf->PolyColor.s.green; + c[2] = pSurf->PolyColor.s.blue; - alpha = byte2float[pSurf->FlatColor.s.alpha]; + alpha = byte2float[pSurf->PolyColor.s.alpha]; alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) c[3] = (unsigned char)(alpha * 255); pglColor4ubv(c); } + Shader_Load(pSurf, &poly, &tint, &fade); +} + +// -----------------+ +// DrawPolygon : Render a polygon, set the texture, set render mode +// -----------------+ +EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags) +{ + PreparePolygon(pSurf, pOutVerts, PolyFlags); + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].sow); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); if (PolyFlags & PF_RemoveYWrap) @@ -1368,6 +2073,17 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, Clamp2D(GL_TEXTURE_WRAP_T); } +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray) +{ + PreparePolygon(pSurf, pOutVerts, PolyFlags); + + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); + pglDrawElements(GL_TRIANGLES, iNumPts, GL_UNSIGNED_INT, IndexArray); + + // the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it? +} + typedef struct vbo_vertex_s { float x, y, z; @@ -1630,46 +2346,16 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) model_lighting = Value; break; - case HWD_SET_FOG_COLOR: - { - GLfloat fogcolor[4]; - - fogcolor[0] = byte2float[((Value>>16)&0xff)]; - fogcolor[1] = byte2float[((Value>>8)&0xff)]; - fogcolor[2] = byte2float[((Value)&0xff)]; - fogcolor[3] = 0x0; - pglFogfv(GL_FOG_COLOR, fogcolor); - break; - } - - case HWD_SET_FOG_DENSITY: - pglFogf(GL_FOG_DENSITY, Value*1200/(500*1000000.0f)); - break; - - case HWD_SET_FOG_MODE: - if (Value) + case HWD_SET_SHADERS: + switch (Value) { - pglEnable(GL_FOG); - // experimental code - /* - switch (Value) - { - case 1: - glFogi(GL_FOG_MODE, GL_LINEAR); - pglFogf(GL_FOG_START, -1000.0f); - pglFogf(GL_FOG_END, 2000.0f); - break; - case 2: - glFogi(GL_FOG_MODE, GL_EXP); - break; - case 3: - glFogi(GL_FOG_MODE, GL_EXP2); - break; - } - */ + case 1: + gl_allowshaders = true; + break; + default: + gl_allowshaders = false; + break; } - else - pglDisable(GL_FOG); break; case HWD_SET_TEXTUREFILTERMODE: @@ -1926,10 +2612,11 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) #define BUFFER_OFFSET(i) ((void*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) { - GLfloat ambient[4]; - GLfloat diffuse[4]; + static GLRGBAFloat poly = {0,0,0,0}; + static GLRGBAFloat tint = {0,0,0,0}; + static GLRGBAFloat fade = {0,0,0,0}; float pol = 0.0f; float scalex, scaley, scalez; @@ -1938,8 +2625,12 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 int i; - // Because Otherwise, scaling the screen negatively vertically breaks the lighting + // Because otherwise, scaling the screen negatively vertically breaks the lighting GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; +#ifdef GL_LIGHT_MODEL_AMBIENT + GLfloat ambient[4]; + GLfloat diffuse[4]; +#endif // Affect input model scaling scale *= 0.5f; @@ -1960,16 +2651,23 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pol = 0.0f; } - if (color) + poly.red = byte2float[Surface->PolyColor.s.red]; + poly.green = byte2float[Surface->PolyColor.s.green]; + poly.blue = byte2float[Surface->PolyColor.s.blue]; + poly.alpha = byte2float[Surface->PolyColor.s.alpha]; + +#ifdef GL_LIGHT_MODEL_AMBIENT + if (model_lighting && (!gl_shadersenabled)) // doesn't work with shaders anyway { - ambient[0] = (color[0]/255.0f); - ambient[1] = (color[1]/255.0f); - ambient[2] = (color[2]/255.0f); - ambient[3] = (color[3]/255.0f); - diffuse[0] = (color[0]/255.0f); - diffuse[1] = (color[1]/255.0f); - diffuse[2] = (color[2]/255.0f); - diffuse[3] = (color[3]/255.0f); + ambient[0] = poly.red; + ambient[1] = poly.green; + ambient[2] = poly.blue; + ambient[3] = poly.alpha; + + diffuse[0] = poly.red; + diffuse[1] = poly.green; + diffuse[2] = poly.blue; + diffuse[3] = poly.alpha; if (ambient[0] > 0.75f) ambient[0] = 0.75f; @@ -1977,7 +2675,31 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 ambient[1] = 0.75f; if (ambient[2] > 0.75f) ambient[2] = 0.75f; + + pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); + pglShadeModel(GL_SMOOTH); + + pglEnable(GL_LIGHTING); + pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); + pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); } +#endif + else + pglColor4ubv((GLubyte*)&Surface->PolyColor.s); + + SetBlend((poly.alpha < 1 ? PF_Translucent : (PF_Masked|PF_Occlude))|PF_Modulated); + + tint.red = byte2float[Surface->TintColor.s.red]; + tint.green = byte2float[Surface->TintColor.s.green]; + tint.blue = byte2float[Surface->TintColor.s.blue]; + tint.alpha = byte2float[Surface->TintColor.s.alpha]; + + fade.red = byte2float[Surface->FadeColor.s.red]; + fade.green = byte2float[Surface->FadeColor.s.green]; + fade.blue = byte2float[Surface->FadeColor.s.blue]; + fade.alpha = byte2float[Surface->FadeColor.s.alpha]; + + Shader_Load(Surface, &poly, &tint, &fade); pglEnable(GL_CULL_FACE); pglEnable(GL_NORMALIZE); @@ -2006,31 +2728,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } #endif - if (model_lighting) - { - pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); - pglShadeModel(GL_SMOOTH); - } - - if (color) - { -#ifdef GL_LIGHT_MODEL_AMBIENT - if (model_lighting) - { - pglEnable(GL_LIGHTING); - pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); - pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); - } - else -#endif - pglColor4ubv((GLubyte*)color); - - if (color[3] < 255) - SetBlend(PF_Translucent|PF_Modulated|PF_Clip); - else - SetBlend(PF_Masked|PF_Modulated|PF_Occlude|PF_Clip); - } - pglPushMatrix(); // should be the same as glLoadIdentity //Hurdler: now it seems to work pglTranslatef(pos->x, pos->z, pos->y); @@ -2091,13 +2788,12 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 { short *vertPtr; char *normPtr; - int j; + int j = 0; // Dangit, I soooo want to do this in a GLSL shader... AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3); vertPtr = vertTinyBuffer; normPtr = normTinyBuffer; - j = 0; for (j = 0; j < mesh->numVertices * 3; j++) { @@ -2168,19 +2864,24 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglDisableClientState(GL_NORMAL_ARRAY); pglPopMatrix(); // should be the same as glLoadIdentity - if (color) - pglDisable(GL_LIGHTING); - pglShadeModel(GL_FLAT); pglDisable(GL_CULL_FACE); pglDisable(GL_NORMALIZE); + +#ifdef GL_LIGHT_MODEL_AMBIENT + if (model_lighting && (!gl_shadersenabled)) + { + pglDisable(GL_LIGHTING); + pglShadeModel(GL_FLAT); + } +#endif } // -----------------+ -// HWRAPI DrawMD2 : Draw an MD2 model with glcommands +// HWRAPI DrawModel : Draw a model // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, color); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface); } // -----------------+ @@ -2189,8 +2890,11 @@ EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, EXPORT void HWRAPI(SetTransform) (FTransform *stransform) { static boolean special_splitscreen; + boolean shearing = false; float used_fov; + pglLoadIdentity(); + if (stransform) { used_fov = stransform->fovxangle; @@ -2212,6 +2916,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglTranslatef(-stransform->x, -stransform->z, -stransform->y); special_splitscreen = stransform->splitscreen; + shearing = stransform->shearing; } else { @@ -2222,6 +2927,15 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); + // jimita 14042019 + // Simulate Software's y-shearing + // https://zdoom.org/wiki/Y-shearing + if (shearing) + { + float fdy = stransform->viewaiming * 2; + pglTranslatef(0.0f, -fdy/BASEVIDHEIGHT, 0.0f); + } + if (special_splitscreen) { used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI; @@ -2234,6 +2948,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglMatrixMode(GL_MODELVIEW); pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) + } EXPORT INT32 HWRAPI(GetTextureUsed) (void) @@ -2265,11 +2980,6 @@ EXPORT INT32 HWRAPI(GetTextureUsed) (void) return res; } -EXPORT INT32 HWRAPI(GetRenderVersion) (void) -{ - return VERSION; -} - EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) { INT32 x, y; @@ -2307,6 +3017,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) pglVertexPointer(3, GL_FLOAT, 0, blackBack); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); for(x=0;x<SCREENVERTS-1;x++) { for(y=0;y<SCREENVERTS-1;y++) diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index 1bb97c37c31aec5dcde5524b907bea8c5576f639..f44e0818bbeff0cae3160cd788d67b11587e7961 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -70,10 +70,6 @@ extern FILE *gllogstream; #endif -#ifndef DRIVER_STRING -#define DRIVER_STRING "HWRAPI Init(): SRB2 OpenGL renderer" // Tails -#endif - // ========================================================================== // PROTOS // ========================================================================== @@ -81,13 +77,11 @@ extern FILE *gllogstream; boolean LoadGL(void); void *GetGLFunc(const char *proc); boolean SetupGLfunc(void); -boolean SetupGLFunc13(void); +void SetupGLFunc4(void); void Flush(void); INT32 isExtAvailable(const char *extension, const GLubyte *start); -int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepthBits); void SetModelView(GLint w, GLint h); void SetStates(void); -FUNCMATH float byteasfloat(UINT8 fbyte); #ifndef GL_EXT_texture_filter_anisotropic #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE @@ -123,12 +117,15 @@ static PFNglEnableClientState pglEnableClientState; // GLOBAL // ========================================================================== -extern const GLubyte *gl_extensions; -extern RGBA_t myPaletteData[]; -extern GLint screen_width; -extern GLint screen_height; -extern GLbyte screen_depth; -extern GLint maximumAnisotropy; +extern const GLubyte *gl_version; +extern const GLubyte *gl_renderer; +extern const GLubyte *gl_extensions; + +extern RGBA_t myPaletteData[]; +extern GLint screen_width; +extern GLint screen_height; +extern GLbyte screen_depth; +extern GLint maximumAnisotropy; /** \brief OpenGL flags for video driver */ diff --git a/src/i_system.h b/src/i_system.h index b38748244b9465107686f8d3ba74cebb771db418..dd0b65f6df542d228019f5c3c91d59c5bcd6728c 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -46,6 +46,8 @@ UINT32 I_GetFreeMem(UINT32 *total); */ tic_t I_GetTime(void); +int I_GetTimeMicros(void);// provides microsecond counter for render stats + /** \brief The I_Sleep function \return void diff --git a/src/m_menu.c b/src/m_menu.c index f9061b2513259639aad55948a90904037a2f825f..e4cc189be8a4fff29b4a80f2c72c1e267c9839b1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -316,8 +316,11 @@ static void M_VideoOptions(INT32 choice); menu_t OP_VideoOptionsDef, OP_VideoModeDef, OP_ColorOptionsDef; #ifdef HWRENDER static void M_OpenGLOptionsMenu(void); -menu_t OP_OpenGLOptionsDef, OP_OpenGLFogDef; -#endif +menu_t OP_OpenGLOptionsDef; +#ifdef ALAM_LIGHTING +menu_t OP_OpenGLLightingDef; +#endif // ALAM_LIGHTING +#endif // HWRENDER menu_t OP_SoundOptionsDef; menu_t OP_SoundAdvancedDef; @@ -364,9 +367,6 @@ static void M_DrawVideoMode(void); static void M_DrawColorMenu(void); static void M_DrawScreenshotMenu(void); static void M_DrawMonitorToggles(void); -#ifdef HWRENDER -static void M_OGL_DrawFogMenu(void); -#endif #ifndef NONET static void M_DrawConnectMenu(void); static void M_DrawMPMainMenu(void); @@ -390,9 +390,6 @@ static boolean M_CancelConnect(void); static void M_HandleConnectIP(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); -#ifdef HWRENDER -static void M_HandleFogColor(INT32 choice); -#endif static void M_HandleVideoMode(INT32 choice); static void M_ResetCvars(void); @@ -1412,22 +1409,23 @@ static menuitem_t OP_OpenGLOptionsMenu[] = { {IT_HEADER, NULL, "3D Models", NULL, 0}, {IT_STRING|IT_CVAR, NULL, "Models", &cv_grmodels, 12}, - {IT_STRING|IT_CVAR, NULL, "Model interpolation", &cv_grmodelinterpolation, 22}, - {IT_STRING|IT_CVAR, NULL, "Model lighting", &cv_grmodellighting, 32}, + {IT_STRING|IT_CVAR, NULL, "Frame interpolation", &cv_grmodelinterpolation, 22}, + {IT_STRING|IT_CVAR, NULL, "Ambient lighting", &cv_grmodellighting, 32}, {IT_HEADER, NULL, "General", NULL, 51}, - {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 63}, - {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 73}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 83}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,93}, + {IT_STRING|IT_CVAR, NULL, "Shaders", &cv_grshaders, 63}, + {IT_STRING|IT_CVAR, NULL, "Lack of perspective", &cv_grshearing, 73}, + {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 83}, - {IT_HEADER, NULL, "Miscellaneous", NULL, 112}, - {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 124}, + {IT_HEADER, NULL, "Miscellaneous", NULL, 102}, + {IT_STRING|IT_CVAR, NULL, "Bit depth", &cv_scr_depth, 114}, + {IT_STRING|IT_CVAR, NULL, "Texture filter", &cv_grfiltermode, 124}, + {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 134}, #ifdef ALAM_LIGHTING - {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 134}, + {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 144}, #endif #if defined (_WINDOWS) && (!((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL))) - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 144}, + {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 154}, #endif }; @@ -1439,15 +1437,8 @@ static menuitem_t OP_OpenGLLightingMenu[] = {IT_STRING|IT_CVAR, NULL, "Dynamic lighting", &cv_grdynamiclighting, 20}, {IT_STRING|IT_CVAR, NULL, "Static lighting", &cv_grstaticlighting, 30}, }; -#endif +#endif // ALAM_LIGHTING -static menuitem_t OP_OpenGLFogMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Fog", &cv_grfog, 10}, - {IT_STRING|IT_KEYHANDLER, NULL, "Fog color", M_HandleFogColor, 20}, - {IT_STRING|IT_CVAR, NULL, "Fog density", &cv_grfogdensity, 30}, - {IT_STRING|IT_CVAR, NULL, "Software Fog",&cv_grsoftwarefog,40}, -}; #endif static menuitem_t OP_SoundOptionsMenu[] = @@ -2194,20 +2185,9 @@ menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE( menu_t OP_OpenGLLightingDef = DEFAULTMENUSTYLE( MTREE4(MN_OP_MAIN, MN_OP_VIDEO, MN_OP_OPENGL, MN_OP_OPENGL_LIGHTING), "M_VIDEO", OP_OpenGLLightingMenu, &OP_OpenGLOptionsDef, 60, 40); -#endif -menu_t OP_OpenGLFogDef = -{ - MTREE4(MN_OP_MAIN, MN_OP_VIDEO, MN_OP_OPENGL, MN_OP_OPENGL_FOG), - "M_VIDEO", - sizeof (OP_OpenGLFogMenu)/sizeof (menuitem_t), - &OP_OpenGLOptionsDef, - OP_OpenGLFogMenu, - M_OGL_DrawFogMenu, - 60, 40, - 0, - NULL -}; -#endif +#endif // ALAM_LIGHTING +#endif // HWRENDER + menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE( MTREE2(MN_OP_MAIN, MN_OP_DATA), "M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); @@ -12798,85 +12778,3 @@ static void M_QuitSRB2(INT32 choice) (void)choice; M_StartMessage(quitmsg[M_RandomKey(NUM_QUITMESSAGES)], M_QuitResponse, MM_YESNO); } - -#ifdef HWRENDER -// ===================================================================== -// OpenGL specific options -// ===================================================================== - -#define FOG_COLOR_ITEM 1 -// =================== -// M_OGL_DrawFogMenu() -// =================== -static void M_OGL_DrawFogMenu(void) -{ - INT32 mx, my; - - mx = currentMenu->x; - my = currentMenu->y; - M_DrawGenericMenu(); // use generic drawer for cursor, items and title - V_DrawString(BASEVIDWIDTH - mx - V_StringWidth(cv_grfogcolor.string, 0), - my + currentMenu->menuitems[FOG_COLOR_ITEM].alphaKey, V_YELLOWMAP, cv_grfogcolor.string); - // blink cursor on FOG_COLOR_ITEM if selected - if (itemOn == FOG_COLOR_ITEM && skullAnimCounter < 4) - V_DrawCharacter(BASEVIDWIDTH - mx, - my + currentMenu->menuitems[FOG_COLOR_ITEM].alphaKey, '_' | 0x80,false); -} - -//=================== -// M_HandleFogColor() -//=================== -static void M_HandleFogColor(INT32 choice) -{ - size_t i, l; - char temp[8]; - boolean exitmenu = false; // exit to previous menu and send name change - - switch (choice) - { - case KEY_DOWNARROW: - S_StartSound(NULL, sfx_menu1); - itemOn++; - break; - - case KEY_UPARROW: - S_StartSound(NULL, sfx_menu1); - itemOn--; - break; - - case KEY_ESCAPE: - exitmenu = true; - break; - - case KEY_BACKSPACE: - S_StartSound(NULL, sfx_menu1); - strcpy(temp, cv_grfogcolor.string); - strcpy(cv_grfogcolor.zstring, "000000"); - l = strlen(temp)-1; - for (i = 0; i < l; i++) - cv_grfogcolor.zstring[i + 6 - l] = temp[i]; - break; - - default: - if ((choice >= '0' && choice <= '9') || (choice >= 'a' && choice <= 'f') - || (choice >= 'A' && choice <= 'F')) - { - S_StartSound(NULL, sfx_menu1); - strcpy(temp, cv_grfogcolor.string); - strcpy(cv_grfogcolor.zstring, "000000"); - l = strlen(temp); - for (i = 0; i < l; i++) - cv_grfogcolor.zstring[5 - i] = temp[l - i]; - cv_grfogcolor.zstring[5] = (char)choice; - } - break; - } - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} -#endif diff --git a/src/m_menu.h b/src/m_menu.h index cce5a6a6c12f9e28987e7016f74b7caec66f13f8..73aff53e67df45fb246b8134a5cdb6823af444e6 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -92,8 +92,6 @@ typedef enum MN_OP_COLOR, MN_OP_OPENGL, MN_OP_OPENGL_LIGHTING, - MN_OP_OPENGL_FOG, - MN_OP_OPENGL_COLOR, MN_OP_SOUND, diff --git a/src/p_user.c b/src/p_user.c index e07ddaec5da05b739c07a474949b21ed715d4740..f21da1564c5dd59235a90eef6f549ab8027207f8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8578,7 +8578,7 @@ static void P_MovePlayer(player_t *player) } #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none && cv_fovchange.value) + if (rendermode == render_opengl && cv_fovchange.value) { fixed_t speed; const fixed_t runnyspeed = 20*FRACUNIT; @@ -9988,9 +9988,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (camorbit) //Sev here, I'm guessing this is where orbital cam lives { - if (rendermode == render_opengl) +#ifdef HWRENDER + if (rendermode == render_opengl && !cv_grshearing.value) distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); else +#endif distxy = dist; distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)) + slopez; } diff --git a/src/r_bsp.c b/src/r_bsp.c index 60291da0ff12b64fd5f55ba52e044ce9d966cf56..a430ef04069446eb0aee9452e6acb737ae4332f5 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -798,6 +798,9 @@ static void R_AddPolyObjects(subsector_t *sub) po = (polyobj_t *)(po->link.next); } + // for render stats + rs_numpolyobjects += numpolys; + // sort polyobjects R_SortPolyObjects(sub); @@ -1235,6 +1238,9 @@ void R_RenderBSPNode(INT32 bspnum) { node_t *bsp; INT32 side; + + rs_numbspcalls++; + while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? { bsp = &nodes[bspnum]; diff --git a/src/r_data.c b/src/r_data.c index 831e75bef64276bae116ee376b31e2e3eda52a3c..b7221499650a9048c892dafbabff76264fd7b2f9 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -242,9 +242,10 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph fullalpha = 0xFF; alpha = (UINT8)fullalpha; - // if the background pixel is empty, match software and don't blend anything + // if the background pixel is empty, + // match software and don't blend anything if (!background.s.alpha) - output.rgba = 0; + output.s.alpha = 0; else { UINT8 beta = (0xFF - alpha); diff --git a/src/r_main.c b/src/r_main.c index e47bb06e3fb116b3735988d1c0ac90f93b0b64af..cf7360804338b1e9e9c20f068307b98ea3151fbd 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -33,6 +33,8 @@ #include "z_zone.h" #include "m_random.h" // quake camera shake #include "r_portal.h" +#include "r_main.h" +#include "i_system.h" // I_GetTimeMicros #ifdef HWRENDER #include "hardware/hw_main.h" @@ -97,6 +99,22 @@ lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // Hack to support extra boom colormaps. extracolormap_t *extra_colormaps = NULL; +// Render stats +int rs_prevframetime = 0; +int rs_rendercalltime = 0; +int rs_swaptime = 0; + +int rs_bsptime = 0; + +int rs_sw_portaltime = 0; +int rs_sw_planetime = 0; +int rs_sw_maskedtime = 0; + +int rs_numbspcalls = 0; +int rs_numsprites = 0; +int rs_numdrawnodes = 0; +int rs_numpolyobjects = 0; + static CV_PossibleValue_t drawdist_cons_t[] = { {256, "256"}, {512, "512"}, {768, "768"}, {1024, "1024"}, {1536, "1536"}, {2048, "2048"}, @@ -147,6 +165,8 @@ consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_renderstats = {"renderstats", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + void SplitScreen_OnChange(void) { if (!cv_debug && netgame) @@ -900,11 +920,6 @@ void R_ExecuteSetViewSize(void) R_InitTextureMapping(); -#ifdef HWRENDER - if (rendermode != render_soft) - HWR_InitTextureMapping(); -#endif - // thing clipping for (i = 0; i < viewwidth; i++) screenheightarray[i] = (INT16)viewheight; @@ -1038,29 +1053,34 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) // R_SetupFrame // -// WARNING: a should be unsigned but to add with 2048, it isn't! -#define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)/fovtan) - // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). // 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out) static void R_SetupFreelook(void) { INT32 dy = 0; - if (rendermode == render_soft) + + // clip it in the case we are looking a hardware 90 degrees full aiming + // (lmps, network and use F12...) + if (rendermode == render_soft +#ifdef HWRENDER + || cv_grshearing.value +#endif + ) { - // clip it in the case we are looking a hardware 90 degrees full aiming - // (lmps, network and use F12...) G_SoftwareClipAimingPitch((INT32 *)&aimingangle); - dy = AIMINGTODY(aimingangle) * viewwidth/BASEVIDWIDTH; + } + + if (rendermode == render_soft) + { + dy = (AIMINGTODY(aimingangle)>>FRACBITS) * viewwidth/BASEVIDWIDTH; yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)]; } + centery = (viewheight/2) + dy; centeryfrac = centery<<FRACBITS; } -#undef AIMINGTODY - void R_SetupFrame(player_t *player) { camera_t *thiscam; @@ -1305,6 +1325,38 @@ void R_SkyboxFrame(player_t *player) R_SetupFreelook(); } +boolean R_ViewpointHasChasecam(player_t *player) +{ + boolean chasecam = false; + + if (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer]) + chasecam = (cv_chasecam2.value != 0); + else + chasecam = (cv_chasecam.value != 0); + + if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) + chasecam = true; // force chasecam on + else if (player->spectator) // no spectator chasecam + chasecam = false; // force chasecam off + + return chasecam; +} + +boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox) +{ + boolean chasecam = R_ViewpointHasChasecam(player); + + // cut-away view stuff + if (player->awayviewtics || skybox) + return chasecam; + // use outside cam view + else if (!player->spectator && chasecam) + return true; + + // use the player's eyes view + return false; +} + static void R_PortalFrame(portal_t *portal) { viewx = portal->viewx; @@ -1410,7 +1462,11 @@ void R_RenderPlayerView(player_t *player) mytotal = 0; ProfZeroTimer(); #endif + rs_numbspcalls = rs_numpolyobjects = rs_numdrawnodes = 0; + rs_bsptime = I_GetTimeMicros(); R_RenderBSPNode((INT32)numnodes - 1); + rs_bsptime = I_GetTimeMicros() - rs_bsptime; + rs_numsprites = visspritecount; #ifdef TIMING RDMSR(0x10, &mycount); mytotal += mycount; // 64bit add @@ -1428,6 +1484,7 @@ void R_RenderPlayerView(player_t *player) Portal_AddSkyboxPortals(); // Portal rendering. Hijacks the BSP traversal. + rs_sw_portaltime = I_GetTimeMicros(); if (portal_base) { portal_t *portal; @@ -1467,15 +1524,20 @@ void R_RenderPlayerView(player_t *player) Portal_Remove(portal); } } + rs_sw_portaltime = I_GetTimeMicros() - rs_sw_portaltime; + rs_sw_planetime = I_GetTimeMicros(); R_DrawPlanes(); #ifdef FLOORSPLATS R_DrawVisibleFloorSplats(); #endif + rs_sw_planetime = I_GetTimeMicros() - rs_sw_planetime; // draw mid texture and sprite // And now 3D floors/sides! + rs_sw_maskedtime = I_GetTimeMicros(); R_DrawMasked(masks, nummasks); + rs_sw_maskedtime = I_GetTimeMicros() - rs_sw_maskedtime; free(masks); } diff --git a/src/r_main.h b/src/r_main.h index 0a48df4128dc760cddb6121a989c3527cec6ceba..99a25d86ea4a20f9a4e23f9a8a7ce622b9a1c28e 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -26,7 +26,10 @@ extern INT32 centerx, centery; extern fixed_t centerxfrac, centeryfrac; extern fixed_t projection, projectiony; -extern fixed_t fovtan; // field of view +extern fixed_t fovtan; + +// WARNING: a should be unsigned but to add with 2048, it isn't! +#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160), fovtan) extern size_t validcount, linecount, loopcount, framecount; @@ -71,6 +74,25 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); +// Render stats + +extern consvar_t cv_renderstats; + +extern int rs_prevframetime;// time when previous frame was rendered +extern int rs_rendercalltime; +extern int rs_swaptime; + +extern int rs_bsptime; + +extern int rs_sw_portaltime; +extern int rs_sw_planetime; +extern int rs_sw_maskedtime; + +extern int rs_numbspcalls; +extern int rs_numsprites; +extern int rs_numdrawnodes; +extern int rs_numpolyobjects; + // // REFRESH - the actual rendering functions. // @@ -104,10 +126,13 @@ void R_SetViewSize(void); // do it (sometimes explicitly called) void R_ExecuteSetViewSize(void); +void R_SetupFrame(player_t *player); void R_SkyboxFrame(player_t *player); -void R_SetupFrame(player_t *player); -// Called by G_Drawer. +boolean R_ViewpointHasChasecam(player_t *player); +boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox); + +// Called by D_Display. void R_RenderPlayerView(player_t *player); // add commands related to engine, at game startup diff --git a/src/r_things.c b/src/r_things.c index 228c86a643695c12ef6d5f379fae83b782e6497e..de5eb208f49bdebf4c5041bde1dbc0b883e83b38 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2505,6 +2505,8 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link) node->thickseg = NULL; node->ffloor = NULL; node->sprite = NULL; + + rs_numdrawnodes++; return node; } diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 6a55ac2d6837bd3e76fe5db3165732077143e8a5..c24104b925afab8e35558285b9f6a88dfd95e36e 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -220,6 +220,7 @@ <ClInclude Include="..\hardware\hw3dsdrv.h" /> <ClInclude Include="..\hardware\hw3sound.h" /> <ClInclude Include="..\hardware\hws_data.h" /> + <ClInclude Include="..\hardware\hw_batching.h" /> <ClInclude Include="..\hardware\hw_clip.h" /> <ClInclude Include="..\hardware\hw_data.h" /> <ClInclude Include="..\hardware\hw_defs.h" /> @@ -370,6 +371,7 @@ <ClCompile Include="..\g_game.c" /> <ClCompile Include="..\g_input.c" /> <ClCompile Include="..\hardware\hw3sound.c" /> + <ClCompile Include="..\hardware\hw_batching.c" /> <ClCompile Include="..\hardware\hw_bsp.c" /> <ClCompile Include="..\hardware\hw_cache.c" /> <ClCompile Include="..\hardware\hw_clip.c" /> diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 89ba1b588ab5b149394327b6b5077853772ac5cf..2f0aec7ca3851b6bf1f1760feafec1d50a9d506d 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -219,6 +219,9 @@ <ClInclude Include="..\hardware\hws_data.h"> <Filter>Hw_Hardware</Filter> </ClInclude> + <ClInclude Include="..\hardware\hw_batching.h"> + <Filter>Hw_Hardware</Filter> + </ClInclude> <ClInclude Include="..\hardware\hw_clip.h"> <Filter>Hw_Hardware</Filter> </ClInclude> @@ -636,6 +639,9 @@ <ClCompile Include="..\hardware\hw3sound.c"> <Filter>Hw_Hardware</Filter> </ClCompile> + <ClCompile Include="..\hardware\hw_batching.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> <ClCompile Include="..\hardware\hw_bsp.c"> <Filter>Hw_Hardware</Filter> </ClCompile> diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 5f040023a8032e1086ebec70f8a28891a0b741e1..416c8d2f5531f1ec09d15770a711fa756118c129 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -75,14 +75,17 @@ void *hwSym(const char *funcName,void *handle) void *funcPointer = NULL; #ifdef HWRENDER if (0 == strcmp("SetPalette", funcName)) - funcPointer = &OglSdlSetPalette; + funcPointer = &OglSdlSetPalette; + GETFUNC(Init); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); + GETFUNC(DrawIndexedTriangles); GETFUNC(RenderSkyDome); GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); + GETFUNC(UpdateTexture); GETFUNC(ReadRect); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); @@ -91,7 +94,6 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(DrawModel); GETFUNC(CreateModelVBOs); GETFUNC(SetTransform); - GETFUNC(GetRenderVersion); GETFUNC(PostImgRedraw); GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); @@ -101,6 +103,16 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(MakeScreenTexture); GETFUNC(MakeScreenFinalTexture); GETFUNC(DrawScreenFinalTexture); + + GETFUNC(LoadShaders); + GETFUNC(KillShaders); + GETFUNC(SetShader); + GETFUNC(UnSetShader); + + GETFUNC(SetShaderInfo); + GETFUNC(LoadCustomShader); + GETFUNC(InitCustomShaders); + #else //HWRENDER if (0 == strcmp("FinishUpdate", funcName)) return funcPointer; //&FinishUpdate; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e358308b4cfccd3cc6e4ff6c567bbba18425d970..27e015ef7ca01bfa82727ad7987e62d46d9d5ce0 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -54,6 +54,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include <fcntl.h> #endif +#if defined (_WIN32) +DWORD TimeFunction(int requested_frequency); +#else +int TimeFunction(int requested_frequency); +#endif + #include <stdio.h> #ifdef _WIN32 #include <conio.h> @@ -2063,9 +2069,11 @@ static p_timeGetTime pfntimeGetTime = NULL; // but lower precision on Windows NT // --------- -tic_t I_GetTime(void) +DWORD TimeFunction(int requested_frequency) { - tic_t newtics = 0; + DWORD newtics = 0; + // this var acts as a multiplier if sub-millisecond precision is asked but is not available + int excess_frequency = requested_frequency / 1000; if (!starttickcount) // high precision timer { @@ -2085,7 +2093,7 @@ tic_t I_GetTime(void) if (frequency.LowPart && QueryPerformanceCounter(&currtime)) { - newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * NEWTICRATE + newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * requested_frequency / frequency.QuadPart); } else if (pfntimeGetTime) @@ -2093,11 +2101,19 @@ tic_t I_GetTime(void) currtime.LowPart = pfntimeGetTime(); if (!basetime.LowPart) basetime.LowPart = currtime.LowPart; - newtics = ((currtime.LowPart - basetime.LowPart)/(1000/NEWTICRATE)); + if (requested_frequency > 1000) + newtics = currtime.LowPart - basetime.LowPart * excess_frequency; + else + newtics = (currtime.LowPart - basetime.LowPart)/(1000/requested_frequency); } } else - newtics = (GetTickCount() - starttickcount)/(1000/NEWTICRATE); + { + if (requested_frequency > 1000) + newtics = (GetTickCount() - starttickcount) * excess_frequency; + else + newtics = (GetTickCount() - starttickcount)/(1000/requested_frequency); + } return newtics; } @@ -2119,7 +2135,9 @@ static void I_ShutdownTimer(void) // I_GetTime // returns time in 1/TICRATE second tics // -tic_t I_GetTime (void) + +// millisecond precision only +int TimeFunction(int requested_frequency) { static Uint64 basetime = 0; Uint64 ticks = SDL_GetTicks(); @@ -2129,14 +2147,24 @@ tic_t I_GetTime (void) ticks -= basetime; - ticks = (ticks*TICRATE); + ticks = (ticks*requested_frequency); ticks = (ticks/1000); - return (tic_t)ticks; + return ticks; } #endif +tic_t I_GetTime(void) +{ + return TimeFunction(NEWTICRATE); +} + +int I_GetTimeMicros(void) +{ + return TimeFunction(1000000); +} + // //I_StartupTimer // diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 87445497a8ddb220d11feacb84875d93f3e6195f..99d2b27c5855b46aa0b607a2914f1489aac6149a 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -357,11 +357,7 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) case SDL_SCANCODE_RGUI: return KEY_RIGHTWIN; default: break; } -#ifdef HWRENDER - DBG_Printf("Unknown incoming scancode: %d, represented %c\n", - code, - SDL_GetKeyName(SDL_GetKeyFromScancode(code))); -#endif + return 0; } @@ -1480,6 +1476,7 @@ void VID_CheckGLLoaded(rendermode_t oldrender) #ifdef HWRENDER if (vid_opengl_state == -1) // Well, it didn't work the first time anyway. { + CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); rendermode = oldrender; if (chosenrendermode == render_opengl) // fallback to software rendermode = render_soft; @@ -1828,10 +1825,12 @@ void VID_StartupOpenGL(void) HWD.pfnFinishUpdate = NULL; HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL); HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); + HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); @@ -1841,7 +1840,6 @@ void VID_StartupOpenGL(void) HWD.pfnDrawModel = hwSym("DrawModel",NULL); HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL); - HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); @@ -1852,14 +1850,16 @@ void VID_StartupOpenGL(void) HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - // check gl renderer lib - if (HWD.pfnGetRenderVersion() != VERSION) - { - CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable!\nBe sure you have installed SRB2 properly.\n")); - vid_opengl_state = -1; - } - else - vid_opengl_state = HWD.pfnInit(I_Error) ? 1 : -1; // let load the OpenGL library + HWD.pfnLoadShaders = hwSym("LoadShaders",NULL); + HWD.pfnKillShaders = hwSym("KillShaders",NULL); + HWD.pfnSetShader = hwSym("SetShader",NULL); + HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); + + HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); + HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); + HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL); + + vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library if (vid_opengl_state == -1) { diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 8da2126c8ce35ea2535bc71a414bf279f16b9060..edc69b21d5067c264bf16e6df8739fac8b0dced9 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -37,6 +37,7 @@ #ifdef HWRENDER #include "../hardware/r_opengl/r_opengl.h" +#include "../hardware/hw_main.h" #include "ogl_sdl.h" #include "../i_system.h" #include "hwsym_sdl.h" @@ -90,15 +91,15 @@ boolean LoadGL(void) const char *OGLLibname = NULL; const char *GLULibname = NULL; - if (M_CheckParm ("-OGLlib") && M_IsNextParm()) + if (M_CheckParm("-OGLlib") && M_IsNextParm()) OGLLibname = M_GetNextParm(); if (SDL_GL_LoadLibrary(OGLLibname) != 0) { CONS_Alert(CONS_ERROR, "Could not load OpenGL Library: %s\n" "Falling back to Software mode.\n", SDL_GetError()); - if (!M_CheckParm ("-OGLlib")) - CONS_Alert(CONS_ERROR, "If you know what is the OpenGL library's name, use -OGLlib\n"); + if (!M_CheckParm("-OGLlib")) + CONS_Printf("If you know what is the OpenGL library's name, use -OGLlib\n"); return 0; } @@ -118,7 +119,7 @@ boolean LoadGL(void) GLULibname = NULL; #endif - if (M_CheckParm ("-GLUlib") && M_IsNextParm()) + if (M_CheckParm("-GLUlib") && M_IsNextParm()) GLULibname = M_GetNextParm(); if (GLULibname) @@ -152,31 +153,29 @@ boolean LoadGL(void) */ boolean OglSdlSurface(INT32 w, INT32 h) { - INT32 cbpp; - const GLvoid *glvendor = NULL, *glrenderer = NULL, *glversion = NULL; - - cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; - - glvendor = pglGetString(GL_VENDOR); - // Get info and extensions. - //BP: why don't we make it earlier ? - //Hurdler: we cannot do that before intialising gl context - glrenderer = pglGetString(GL_RENDERER); - glversion = pglGetString(GL_VERSION); - gl_extensions = pglGetString(GL_EXTENSIONS); - - DBG_Printf("Vendor : %s\n", glvendor); - DBG_Printf("Renderer : %s\n", glrenderer); - DBG_Printf("Version : %s\n", glversion); - DBG_Printf("Extensions : %s\n", gl_extensions); + INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; + static boolean first_init = false; + oglflags = 0; + if (!first_init) + { + gl_version = pglGetString(GL_VERSION); + gl_renderer = pglGetString(GL_RENDERER); + gl_extensions = pglGetString(GL_EXTENSIONS); + + GL_DBG_Printf("OpenGL %s\n", gl_version); + GL_DBG_Printf("GPU: %s\n", gl_renderer); + GL_DBG_Printf("Extensions: %s\n", gl_extensions); + } + first_init = true; + if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); else maximumAnisotropy = 1; - SetupGLFunc13(); + SetupGLFunc4(); granisotropicmode_cons_t[1].value = maximumAnisotropy; @@ -222,7 +221,7 @@ void OglSdlFinishUpdate(boolean waitvbl) HWR_DrawScreenFinalTexture(realwidth, realheight); } -EXPORT void HWRAPI( OglSdlSetPalette) (RGBA_t *palette) +EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette) { size_t palsize = (sizeof(RGBA_t) * 256); // on a palette change, you have to reload all of the textures diff --git a/src/v_video.c b/src/v_video.c index 2f546dea2c2073ba1d18d0187fe09e4d286b74d4..5fd3020f65268ddda37e173e8b5966e85afaa8ce 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -418,7 +418,7 @@ void V_SetPalette(INT32 palettenum) LoadMapPalette(); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_SetPalette(&pLocalPalette[palettenum*256]); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) else @@ -432,7 +432,7 @@ void V_SetPaletteLump(const char *pal) { LoadPalette(pal); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_SetPalette(pLocalPalette); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) else @@ -529,7 +529,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca #ifdef HWRENDER //if (rendermode != render_soft && !con_startup) // Why? - if (rendermode != render_soft) + if (rendermode == render_opengl) { HWR_DrawStretchyFixedPatch((GLPatch_t *)patch, x, y, pscale, vscale, scrn, colormap); return; @@ -829,7 +829,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ #ifdef HWRENDER //if (rendermode != render_soft && !con_startup) // Not this again - if (rendermode != render_soft) + if (rendermode == render_opengl) { HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h); return; @@ -1153,7 +1153,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) #ifdef HWRENDER //if (rendermode != render_soft && !con_startup) // Not this again - if (rendermode != render_soft) + if (rendermode == render_opengl) { HWR_DrawFill(x, y, w, h, c); return; @@ -1350,7 +1350,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) return; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { UINT32 hwcolor = V_GetHWConsBackColor(); HWR_DrawConsoleFill(x, y, w, h, c, hwcolor); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. @@ -1547,7 +1547,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U return; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { // ughhhhh please can someone else do this? thanks ~toast 25/7/19 in 38 degrees centigrade w/o AC HWR_DrawFadeFill(x, y, w, h, c, color, strength); // toast two days later - left above comment in 'cause it's funny @@ -1709,7 +1709,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum) size_t size, lflatsize, flatshift; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { HWR_DrawFlatFill(x, y, w, h, flatnum); return; @@ -1819,7 +1819,7 @@ void V_DrawPatchFill(patch_t *pat) void V_DrawFadeScreen(UINT16 color, UINT8 strength) { #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { HWR_FadeScreenMenuBack(color, strength); return; @@ -1848,7 +1848,7 @@ void V_DrawFadeConsBack(INT32 plines) UINT8 *deststop, *buf; #ifdef HWRENDER // not win32 only 19990829 by Kin - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { UINT32 hwcolor = V_GetHWConsBackColor(); HWR_DrawConsoleBack(hwcolor, plines); @@ -1881,7 +1881,7 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color) color = cons_backcolor.value; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { UINT32 hwcolor; switch (color) @@ -3506,8 +3506,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param) INT32 height, yoffset; #ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft) return; #endif diff --git a/src/w_wad.c b/src/w_wad.c index af9f9a7c0a6fcb790e0cc0170938617d00682937..9af661b5762c01530ee2c0e4f9cfe22d177768f1 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -848,6 +848,15 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) wadfiles[numwadfiles] = wadfile; numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded +#ifdef HWRENDER + // Read shaders from file + if (rendermode == render_opengl && (vid_opengl_state == 1)) + { + HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3)); + HWR_LoadShaders(); + } +#endif // HWRENDER + // TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now. switch (wadfile->type) { @@ -1632,21 +1641,6 @@ boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr) return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); } -void W_FlushCachedPatches(void) -{ - if (needpatchflush) - { - Z_FreeTag(PU_CACHE); - Z_FreeTag(PU_PATCH); - Z_FreeTag(PU_HUDGFX); - Z_FreeTag(PU_HWRPATCHINFO); - Z_FreeTag(PU_HWRMODELTEXTURE); - Z_FreeTag(PU_HWRCACHE); - Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRMODELTEXTURE_UNLOCKED); - } - needpatchflush = false; -} - // ========================================================================== // W_CacheLumpName // ========================================================================== @@ -1674,9 +1668,6 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { lumpcache_t *lumpcache = NULL; - if (needpatchflush) - W_FlushCachedPatches(); - if (!TestValidLump(wad, lump)) return NULL; @@ -1727,9 +1718,6 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) GLPatch_t *grPatch; #endif - if (needpatchflush) - W_FlushCachedPatches(); - if (!TestValidLump(wad, lump)) return NULL; @@ -1778,7 +1766,7 @@ void W_UnlockCachedPatch(void *patch) // The hardware code does its own memory management, as its patches // have different lifetimes from software's. #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_UnlockCachedPatch((GLPatch_t*)patch); else #endif diff --git a/src/w_wad.h b/src/w_wad.h index 88b542fca824ef0915f86e380c9f469d933c4638..fddc65529de1dbc8a31f3c730eda7fbb556889f1 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -210,7 +210,6 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag); void W_UnlockCachedPatch(void *patch); -void W_FlushCachedPatches(void); void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5); diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 986eb32dcdf2af6b6bd971452ac445677582b01f..3f6c5e290232a46c9998d9ef9454610d6ba37c13 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -106,6 +106,7 @@ static loadfunc_t hwdFuncTable[] = { {"SetBlend@4", &hwdriver.pfnSetBlend}, {"ClearBuffer@12", &hwdriver.pfnClearBuffer}, {"SetTexture@4", &hwdriver.pfnSetTexture}, + {"UpdateTexture@4", &hwdriver.pfnUpdateTexture}, {"ReadRect@24", &hwdriver.pfnReadRect}, {"GClipRect@20", &hwdriver.pfnGClipRect}, {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, @@ -120,7 +121,7 @@ static loadfunc_t hwdFuncTable[] = { {"FlushScreenTextures@0",&hwdriver.pfnFlushScreenTextures}, {"StartScreenWipe@0", &hwdriver.pfnStartScreenWipe}, {"EndScreenWipe@0", &hwdriver.pfnEndScreenWipe}, - {"DoScreenWipe@4", &hwdriver.pfnDoScreenWipe}, + {"DoScreenWipe@0", &hwdriver.pfnDoScreenWipe}, {"DrawIntermissionBG@0",&hwdriver.pfnDrawIntermissionBG}, {"MakeScreenTexture@0", &hwdriver.pfnMakeScreenTexture}, {"MakeScreenFinalTexture@0", &hwdriver.pfnMakeScreenFinalTexture}, @@ -137,6 +138,7 @@ static loadfunc_t hwdFuncTable[] = { {"SetBlend", &hwdriver.pfnSetBlend}, {"ClearBuffer", &hwdriver.pfnClearBuffer}, {"SetTexture", &hwdriver.pfnSetTexture}, + {"UpdateTexture", &hwdriver.pfnUpdateTexture}, {"ReadRect", &hwdriver.pfnReadRect}, {"GClipRect", &hwdriver.pfnGClipRect}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, diff --git a/src/z_zone.c b/src/z_zone.c index 96dcd0cba5fbd7bb865dc4eb1317a8b3d2efaa6f..2387a11433592e99fb149b85d88863ace01ab016 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -499,17 +499,14 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) // Utility functions // ----------------- -// for renderer switching, free a bunch of stuff +// for renderer switching boolean needpatchflush = false; boolean needpatchrecache = false; // flush all patches from memory -// (also frees memory tagged with PU_CACHE) -// (which are not necessarily patches but I don't care) void Z_FlushCachedPatches(void) { CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n"); - Z_FreeTag(PU_CACHE); Z_FreeTag(PU_PATCH); Z_FreeTag(PU_HUDGFX); Z_FreeTag(PU_HWRPATCHINFO); @@ -808,7 +805,7 @@ static void Command_Memfree_f(void) sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10)); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10));