2016-03-01 15:47:10 +00:00
//-----------------------------------------------------------------------------
//
2017-04-17 11:33:19 +00:00
// Copyright 1993-1996 id Software
// Copyright 1994-1996 Raven Software
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
2016-03-01 15:47:10 +00:00
//
2017-04-17 11:33:19 +00:00
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
2016-03-01 15:47:10 +00:00
//
2017-04-17 11:33:19 +00:00
// This program is distributed in the hope that it will be useful,
2016-03-01 15:47:10 +00:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
2017-04-17 11:33:19 +00:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
2016-03-01 15:47:10 +00:00
//
2017-04-17 11:33:19 +00:00
//-----------------------------------------------------------------------------
2016-03-01 15:47:10 +00:00
//
// DESCRIPTION:
// Sky rendering. The DOOM sky is a texture map like any
// wall, wrapping around. 1024 columns equal 360 degrees.
// The default sky map is 256 columns and repeats 4 times
// on a 320 screen.
//
//
//-----------------------------------------------------------------------------
// Needed for FRACUNIT.
# include "m_fixed.h"
# include "c_cvars.h"
# include "g_level.h"
# include "r_sky.h"
# include "r_utility.h"
# include "v_text.h"
2017-01-08 17:45:30 +00:00
# include "g_levellocals.h"
2016-03-01 15:47:10 +00:00
//
// sky mapping
//
FTextureID skyflatnum ;
FTextureID sky1texture , sky2texture ;
2016-04-16 01:30:05 +00:00
double skytexturemid ;
2016-04-23 03:54:04 +00:00
double skyscale ;
float skyiscale ;
2016-03-01 15:47:10 +00:00
bool skystretch ;
fixed_t sky1cyl , sky2cyl ;
double sky1pos , sky2pos ;
2018-04-27 22:18:49 +00:00
float hw_sky1pos , hw_sky2pos ;
2016-03-01 15:47:10 +00:00
2016-10-20 07:56:45 +00:00
CUSTOM_CVAR ( Int , testskyoffset , 0 , 0 )
{
R_InitSkyMap ( ) ;
}
2016-03-01 15:47:10 +00:00
// [RH] Stretch sky texture if not taller than 128 pixels?
2016-10-19 22:59:51 +00:00
// Also now controls capped skies. 0 = normal, 1 = stretched, 2 = capped
CUSTOM_CVAR ( Int , r_skymode , 2 , CVAR_ARCHIVE )
2016-03-01 15:47:10 +00:00
{
R_InitSkyMap ( ) ;
}
2018-04-28 10:34:09 +00:00
CVAR ( Float , skyoffset , 0 , 0 ) // for testing
2016-10-20 07:56:45 +00:00
2016-04-23 03:54:04 +00:00
int freelookviewheight ;
2016-03-01 15:47:10 +00:00
//==========================================================================
//
// R_InitSkyMap
//
// Called whenever the view size changes.
//
//==========================================================================
void R_InitSkyMap ( )
{
int skyheight ;
FTexture * skytex1 , * skytex2 ;
2016-10-22 07:57:26 +00:00
// Do not allow the null texture which has no bitmap and will crash.
if ( sky1texture . isNull ( ) )
{
2018-03-25 18:26:16 +00:00
sky1texture = TexMan . CheckForTexture ( " -noflat- " , ETextureType : : Any ) ;
2016-10-22 07:57:26 +00:00
}
if ( sky2texture . isNull ( ) )
{
2018-03-25 18:26:16 +00:00
sky2texture = TexMan . CheckForTexture ( " -noflat- " , ETextureType : : Any ) ;
2016-10-22 07:57:26 +00:00
}
2016-03-01 15:47:10 +00:00
skytex1 = TexMan ( sky1texture , true ) ;
skytex2 = TexMan ( sky2texture , true ) ;
2016-10-22 07:57:26 +00:00
if ( skytex1 = = nullptr )
2016-03-01 15:47:10 +00:00
return ;
2018-12-06 00:11:04 +00:00
if ( ( level . flags & LEVEL_DOUBLESKY ) & & skytex1 - > GetDisplayHeight ( ) ! = skytex2 - > GetDisplayHeight ( ) )
2016-03-01 15:47:10 +00:00
{
Printf ( TEXTCOLOR_BOLD " Both sky textures must be the same height. " TEXTCOLOR_NORMAL " \n " ) ;
sky2texture = sky1texture ;
}
// There are various combinations for sky rendering depending on how tall the sky is:
// h < 128: Unstretched and tiled, centered on horizon
// 128 <= h < 200: Can possibly be stretched. When unstretched, the baseline is
// 28 rows below the horizon so that the top of the texture
// aligns with the top of the screen when looking straight ahead.
// When stretched, it is scaled to 228 pixels with the baseline
// in the same location as an unstretched 128-tall sky, so the top
// of the texture aligns with the top of the screen when looking
// fully up.
// h == 200: Unstretched, baseline is on horizon, and top is at the top of
// the screen when looking fully up.
// h > 200: Unstretched, but the baseline is shifted down so that the top
// of the texture is at the top of the screen when looking fully up.
2018-12-06 00:11:04 +00:00
skyheight = skytex1 - > GetDisplayHeight ( ) ;
2016-03-01 15:47:10 +00:00
if ( skyheight > = 128 & & skyheight < 200 )
{
2016-10-19 22:59:51 +00:00
skystretch = ( r_skymode = = 1
2016-03-01 15:47:10 +00:00
& & skyheight > = 128
& & level . IsFreelookAllowed ( )
2017-01-13 10:11:14 +00:00
& & ! ( level . flags & LEVEL_FORCETILEDSKY ) ) ? 1 : 0 ;
2018-12-06 00:11:04 +00:00
}
else skystretch = false ;
// Anything below is only for the software renderer (todo - move it there!)
// Note: I don't think it is good that this stuff gets cached globally.
// For something that only needs to be once per frame it is rather pointless and makes it hard to swap out the underlying textures based on user settings.
FSoftwareTexture * sskytex1 = skytex1 - > GetSoftwareTexture ( ) ;
FSoftwareTexture * sskytex2 = skytex2 - > GetSoftwareTexture ( ) ;
skytexturemid = 0 ;
if ( skyheight > = 128 & & skyheight < 200 )
{
2016-04-16 01:30:05 +00:00
skytexturemid = - 28 ;
2016-03-01 15:47:10 +00:00
}
else if ( skyheight > 200 )
{
2018-12-06 00:11:04 +00:00
skytexturemid = ( 200 - skyheight ) * sskytex1 - > GetScale ( ) . Y + ( ( r_skymode = = 2 & & ! ( level . flags & LEVEL_FORCETILEDSKY ) ) ? skytex1 - > GetSkyOffset ( ) + testskyoffset : 0 ) ;
2016-03-01 15:47:10 +00:00
}
if ( viewwidth ! = 0 & & viewheight ! = 0 )
{
2016-04-23 03:54:04 +00:00
skyiscale = float ( r_Yaspect / freelookviewheight ) ;
skyscale = freelookviewheight / r_Yaspect ;
2016-03-01 15:47:10 +00:00
2017-03-11 22:28:07 +00:00
skyiscale * = float ( r_viewpoint . FieldOfView . Degrees / 90. ) ;
skyscale * = float ( 90. / r_viewpoint . FieldOfView . Degrees ) ;
2016-03-01 15:47:10 +00:00
}
if ( skystretch )
{
2016-04-23 03:54:04 +00:00
skyscale * = ( double ) SKYSTRETCH_HEIGHT / skyheight ;
skyiscale * = skyheight / ( float ) SKYSTRETCH_HEIGHT ;
skytexturemid * = skyheight / ( double ) SKYSTRETCH_HEIGHT ;
2016-03-01 15:47:10 +00:00
}
// The standard Doom sky texture is 256 pixels wide, repeated 4 times over 360 degrees,
// giving a total sky width of 1024 pixels. So if the sky texture is no wider than 1024,
// we map it to a cylinder with circumfrence 1024. For larger ones, we use the width of
// the texture as the cylinder's circumfrence.
2018-12-06 00:11:04 +00:00
sky1cyl = MAX ( sskytex1 - > GetWidth ( ) , fixed_t ( sskytex1 - > GetScale ( ) . X * 1024 ) ) ;
sky2cyl = MAX ( sskytex2 - > GetWidth ( ) , fixed_t ( sskytex2 - > GetScale ( ) . Y * 1024 ) ) ;
2016-03-01 15:47:10 +00:00
}
//==========================================================================
//
// R_UpdateSky
//
// Performs sky scrolling
//
//==========================================================================
2017-11-16 01:33:08 +00:00
void R_UpdateSky ( uint64_t mstime )
2016-03-01 15:47:10 +00:00
{
// Scroll the sky
double ms = ( double ) mstime * FRACUNIT ;
sky1pos = ms * level . skyspeed1 ;
sky2pos = ms * level . skyspeed2 ;
2018-04-27 22:18:49 +00:00
// The hardware renderer uses a different value range and clamps it to a single rotation
hw_sky1pos = ( float ) ( fmod ( ( double ( mstime ) * level . skyspeed1 ) , 1024. ) * ( 90. / 256. ) ) ;
hw_sky2pos = ( float ) ( fmod ( ( double ( mstime ) * level . skyspeed2 ) , 1024. ) * ( 90. / 256. ) ) ;
2016-03-01 15:47:10 +00:00
}