diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 308e8d818a..f3de02a360 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1055,7 +1055,6 @@ set (PCH_SOURCES gl/renderer/gl_postprocess.cpp gl/renderer/gl_postprocessstate.cpp gl/shaders/gl_shader.cpp - gl/shaders/gl_texshader.cpp gl/shaders/gl_shaderprogram.cpp gl/shaders/gl_postprocessshader.cpp gl/shaders/gl_shadowmapshader.cpp @@ -1144,6 +1143,7 @@ set (PCH_SOURCES intermission/intermission.cpp intermission/intermission_parse.cpp r_data/colormaps.cpp + r_data/gldefs.cpp r_data/a_dynlightdata.cpp r_data/r_translate.cpp r_data/sprites.cpp diff --git a/src/d_main.cpp b/src/d_main.cpp index ac732ff21e..3568a19306 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -176,6 +176,7 @@ extern bool gameisdead; extern bool demorecording; extern bool M_DemoNoPlay; // [RH] if true, then skip any demos in the loop extern bool insave; +extern TDeletingArray LightDefaults; // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -2772,6 +2773,7 @@ void D_DoomMain (void) DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods FS_Close(); // destroy the global FraggleScript. DeinitMenus(); + LightDefaults.Clear(); // this can leak heap memory if it isn't cleared. // delete DoomStartupInfo data DoomStartupInfo.Name = (const char*)0; diff --git a/src/g_shared/a_dynlight.cpp b/src/g_shared/a_dynlight.cpp index 1858a9a929..7f23f871e0 100644 --- a/src/g_shared/a_dynlight.cpp +++ b/src/g_shared/a_dynlight.cpp @@ -793,6 +793,147 @@ void ADynamicLight::OnDestroy() } +//========================================================================== +// +// +// +//========================================================================== + +void AActor::AttachLight(unsigned int count, const FLightDefaults *lightdef) +{ + ADynamicLight *light; + + if (count < AttachedLights.Size()) + { + light = barrier_cast(AttachedLights[count]); + assert(light != NULL); + } + else + { + light = Spawn(Pos(), NO_REPLACE); + light->target = this; + light->owned = true; + light->ObjectFlags |= OF_Transient; + //light->lightflags |= LF_ATTENUATE; + AttachedLights.Push(light); + } + light->flags2&=~MF2_DORMANT; + lightdef->ApplyProperties(light); +} + +//========================================================================== +// +// per-state light adjustment +// +//========================================================================== +extern TArray StateLights; + +void AActor::SetDynamicLights() +{ + TArray & LightAssociations = GetInfo()->LightAssociations; + unsigned int count = 0; + + if (state == NULL) return; + if (LightAssociations.Size() > 0) + { + ADynamicLight *lights, *tmpLight; + unsigned int i; + + lights = tmpLight = NULL; + + for (i = 0; i < LightAssociations.Size(); i++) + { + if (LightAssociations[i]->Sprite() == sprite && + (LightAssociations[i]->Frame()==frame || LightAssociations[i]->Frame()==-1)) + { + AttachLight(count++, LightAssociations[i]->Light()); + } + } + } + if (count == 0 && state->Light > 0) + { + for(int i= state->Light; StateLights[i] != NULL; i++) + { + if (StateLights[i] != (FLightDefaults*)-1) + { + AttachLight(count++, StateLights[i]); + } + } + } + + for(;countflags2 |= MF2_DORMANT; + memset(AttachedLights[count]->args, 0, 3*sizeof(args[0])); + } +} + +//========================================================================== +// +// Needed for garbage collection +// +//========================================================================== + +size_t AActor::PropagateMark() +{ + for (unsigned i = 0; i it; + AActor * a; + ADynamicLight * l; + + while ((a=it.Next())) + { + a->AttachedLights.Clear(); + } + + TThinkerIterator it2; + + l=it2.Next(); + while (l) + { + ADynamicLight * ll = it2.Next(); + if (l->owned) l->Destroy(); + l=ll; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void AActor::RecreateAllAttachedLights() +{ + TThinkerIterator it; + AActor * a; + + while ((a=it.Next())) + { + a->SetDynamicLights(); + } +} + +//========================================================================== +// +// CCMDs +// +//========================================================================== + CCMD(listlights) { int walls, sectors, subsecs; diff --git a/src/g_shared/a_dynlight.h b/src/g_shared/a_dynlight.h index b659507d12..adfaa3a4f0 100644 --- a/src/g_shared/a_dynlight.h +++ b/src/g_shared/a_dynlight.h @@ -8,17 +8,28 @@ EXTERN_CVAR(Bool, gl_attachedlights) class ADynamicLight; class FSerializer; -class FLightDefaults; +enum ELightType +{ + PointLight, + PulseLight, + FlickerLight, + RandomFlickerLight, + SectorLight, + DummyLight, + ColorPulseLight, + ColorFlickerLight, + RandomColorFlickerLight +}; enum { - LIGHT_RED = 0, - LIGHT_GREEN = 1, - LIGHT_BLUE = 2, - LIGHT_INTENSITY = 3, - LIGHT_SECONDARY_INTENSITY = 4, - LIGHT_SCALE = 3, + LIGHT_RED = 0, + LIGHT_GREEN = 1, + LIGHT_BLUE = 2, + LIGHT_INTENSITY = 3, + LIGHT_SECONDARY_INTENSITY = 4, + LIGHT_SCALE = 3, }; enum LightFlag @@ -32,24 +43,111 @@ enum LightFlag LF_SPOT = 64 }; +//========================================================================== +// +// Light definitions +// +//========================================================================== +class FLightDefaults +{ +public: + FLightDefaults(FName name, ELightType type); + + void ApplyProperties(ADynamicLight * light) const; + FName GetName() const { return m_Name; } + void SetParameter(double p) { m_Param = p; } + void SetArg(int arg, int val) { m_Args[arg] = val; } + int GetArg(int arg) { return m_Args[arg]; } + uint8_t GetAttenuate() const { return m_attenuate; } + void SetOffset(float* ft) { m_Pos.X = ft[0]; m_Pos.Z = ft[1]; m_Pos.Y = ft[2]; } + void SetSubtractive(bool subtract) { m_subtractive = subtract; } + void SetAdditive(bool add) { m_additive = add; } + void SetDontLightSelf(bool add) { m_dontlightself = add; } + void SetAttenuate(bool on) { m_attenuate = on; } + void SetHalo(bool halo) { m_halo = halo; } + void SetDontLightActors(bool on) { m_dontlightactors = on; } + void SetSpot(bool spot) { m_spot = spot; } + void SetSpotInnerAngle(double angle) { m_spotInnerAngle = angle; } + void SetSpotOuterAngle(double angle) { m_spotOuterAngle = angle; } + + void OrderIntensities() + { + if (m_Args[LIGHT_INTENSITY] > m_Args[LIGHT_SECONDARY_INTENSITY]) + { + std::swap(m_Args[LIGHT_INTENSITY], m_Args[LIGHT_SECONDARY_INTENSITY]); + m_swapped = true; + } + } + +protected: + FName m_Name; + int m_Args[5] = { 0,0,0,0,0 }; + double m_Param = 0; + DVector3 m_Pos = { 0,0,0 }; + ELightType m_type; + int8_t m_attenuate = -1; + bool m_subtractive = false; + bool m_additive = false; + bool m_halo = false; + bool m_dontlightself = false; + bool m_dontlightactors = false; + bool m_swapped = false; + bool m_spot = false; + double m_spotInnerAngle = 10.0; + double m_spotOuterAngle = 25.0; +}; + +//========================================================================== +// +// Light associations (intermediate parser data) +// +//========================================================================== + +class FLightAssociation +{ +public: + //FLightAssociation(); + FLightAssociation(FName actorName, const char *frameName, FName lightName) + : m_ActorName(actorName), m_AssocLight(lightName) + { + strncpy(m_FrameName, frameName, 8); + } + + FName ActorName() { return m_ActorName; } + const char *FrameName() { return m_FrameName; } + FName Light() { return m_AssocLight; } + void ReplaceLightName(FName newName) { m_AssocLight = newName; } +protected: + char m_FrameName[8]; + FName m_ActorName, m_AssocLight; +}; + + +//========================================================================== +// +// Light associations per actor class +// +//========================================================================== + +class FInternalLightAssociation +{ +public: + FInternalLightAssociation(FLightAssociation * asso); + int Sprite() const { return m_sprite; } + int Frame() const { return m_frame; } + const FLightDefaults *Light() const { return m_AssocLight; } +protected: + int m_sprite; + int m_frame; + FLightDefaults * m_AssocLight; +}; + + + typedef TFlags LightFlags; DEFINE_TFLAGS_OPERATORS(LightFlags) -enum ELightType -{ - PointLight, - PulseLight, - FlickerLight, - RandomFlickerLight, - SectorLight, - DummyLight, - ColorPulseLight, - ColorFlickerLight, - RandomColorFlickerLight -}; - - struct FLightNode { FLightNode ** prevTarget; diff --git a/src/gl/dynlights/gl_glow.cpp b/src/gl/dynlights/gl_glow.cpp index 9d44e38af1..86818106ea 100644 --- a/src/gl/dynlights/gl_glow.cpp +++ b/src/gl/dynlights/gl_glow.cpp @@ -33,75 +33,6 @@ #include "gl/dynlights/gl_glow.h" -//=========================================================================== -// -// Reads glow definitions from GLDEFS -// -//=========================================================================== -void gl_InitGlow(FScanner &sc) -{ - sc.MustGetStringName("{"); - while (!sc.CheckString("}")) - { - sc.MustGetString(); - if (sc.Compare("FLATS")) - { - sc.MustGetStringName("{"); - while (!sc.CheckString("}")) - { - sc.MustGetString(); - FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Flat,FTextureManager::TEXMAN_TryAny); - FTexture *tex = TexMan[flump]; - if (tex) tex->gl_info.bAutoGlowing = tex->bGlowing = tex->gl_info.bFullbright = true; - } - } - else if (sc.Compare("WALLS")) - { - sc.MustGetStringName("{"); - while (!sc.CheckString("}")) - { - sc.MustGetString(); - FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Wall,FTextureManager::TEXMAN_TryAny); - FTexture *tex = TexMan[flump]; - if (tex) tex->gl_info.bAutoGlowing = tex->bGlowing = tex->gl_info.bFullbright = true; - } - } - else if (sc.Compare("TEXTURE")) - { - sc.SetCMode(true); - sc.MustGetString(); - FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Flat,FTextureManager::TEXMAN_TryAny); - FTexture *tex = TexMan[flump]; - sc.MustGetStringName(","); - sc.MustGetString(); - PalEntry color = V_GetColor(NULL, sc.String); - //sc.MustGetStringName(","); - //sc.MustGetNumber(); - if (sc.CheckString(",")) - { - if (sc.CheckNumber()) - { - if (tex) tex->gl_info.GlowHeight = sc.Number; - if (!sc.CheckString(",")) goto skip_fb; - } - - sc.MustGetStringName("fullbright"); - if (tex) tex->gl_info.bFullbright = true; - } - skip_fb: - sc.SetCMode(false); - - if (tex && color != 0) - { - tex->gl_info.bAutoGlowing = false; - tex->bGlowing = true; - tex->GlowColor = color; - } - } - } -} - - //========================================================================== // // Checks whether a sprite should be affected by a glow diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index a068cc4986..82c67e00b8 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -62,6 +62,7 @@ #include "gl/shaders/gl_fxaashader.h" #include "gl/shaders/gl_presentshader.h" #include "gl/shaders/gl_postprocessshader.h" +#include "gl/shaders/gl_postprocessshaderinstance.h" #include "gl/stereo3d/gl_stereo3d.h" #include "r_videoscale.h" diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 5b737f125e..2d5cc232f0 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -60,6 +60,7 @@ #include "gl/shaders/gl_present3dRowshader.h" #include "gl/shaders/gl_shadowmapshader.h" #include "gl/shaders/gl_postprocessshader.h" +#include "gl/shaders/gl_postprocessshaderinstance.h" #include "gl/stereo3d/gl_stereo3d.h" #include "gl/textures/gl_material.h" #include "gl/textures/gl_samplers.h" diff --git a/src/gl/shaders/gl_postprocessshader.cpp b/src/gl/shaders/gl_postprocessshader.cpp index 459e35b9f4..1eae66ec2f 100644 --- a/src/gl/shaders/gl_postprocessshader.cpp +++ b/src/gl/shaders/gl_postprocessshader.cpp @@ -33,6 +33,7 @@ #include "gl/renderer/gl_postprocessstate.h" #include "gl/renderer/gl_renderbuffers.h" #include "gl/shaders/gl_postprocessshader.h" +#include "gl/shaders/gl_postprocessshaderinstance.h" #include "textures/textures.h" #include "textures/bitmap.h" diff --git a/src/gl/shaders/gl_postprocessshader.h b/src/gl/shaders/gl_postprocessshader.h index 23b8c1864e..523b8d8d02 100644 --- a/src/gl/shaders/gl_postprocessshader.h +++ b/src/gl/shaders/gl_postprocessshader.h @@ -1,10 +1,5 @@ #pragma once -#include "gl_shaderprogram.h" -#include - -class PostProcessShaderInstance; - enum class PostProcessUniformType { Undefined, @@ -35,38 +30,3 @@ struct PostProcessShader extern TArray PostProcessShaders; -class PostProcessShaderInstance -{ -public: - PostProcessShaderInstance(PostProcessShader *desc) : Desc(desc) { } - ~PostProcessShaderInstance(); - - void Run(); - - PostProcessShader *Desc; - -private: - bool IsShaderSupported(); - void CompileShader(); - void UpdateUniforms(); - void BindTextures(); - - FShaderProgram mProgram; - FBufferedUniformSampler mInputTexture; - std::map mTextureHandles; -}; - -class FCustomPostProcessShaders -{ -public: - FCustomPostProcessShaders(); - ~FCustomPostProcessShaders(); - - void Run(FString target); - -private: - std::vector> mShaders; - - FCustomPostProcessShaders(const FCustomPostProcessShaders &) = delete; - FCustomPostProcessShaders &operator=(const FCustomPostProcessShaders &) = delete; -}; diff --git a/src/gl/shaders/gl_postprocessshaderinstance.h b/src/gl/shaders/gl_postprocessshaderinstance.h new file mode 100644 index 0000000000..2b3e8e5d9b --- /dev/null +++ b/src/gl/shaders/gl_postprocessshaderinstance.h @@ -0,0 +1,42 @@ +#pragma once + +#include "gl_shaderprogram.h" +#include + +struct PostProcessShader; + +class PostProcessShaderInstance +{ +public: + PostProcessShaderInstance(PostProcessShader *desc) : Desc(desc) { } + ~PostProcessShaderInstance(); + + void Run(); + + PostProcessShader *Desc; + +private: + bool IsShaderSupported(); + void CompileShader(); + void UpdateUniforms(); + void BindTextures(); + + FShaderProgram mProgram; + FBufferedUniformSampler mInputTexture; + std::map mTextureHandles; +}; + +class FCustomPostProcessShaders +{ +public: + FCustomPostProcessShaders(); + ~FCustomPostProcessShaders(); + + void Run(FString target); + +private: + std::vector> mShaders; + + FCustomPostProcessShaders(const FCustomPostProcessShaders &) = delete; + FCustomPostProcessShaders &operator=(const FCustomPostProcessShaders &) = delete; +}; diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index f4ebfa26a4..f1a6bec3e5 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -599,7 +599,7 @@ static const FDefaultShader defaultshaders[]= {nullptr,nullptr,nullptr,nullptr} }; -static TArray usershaders; +TArray usershaders; struct FEffectShader { @@ -872,157 +872,6 @@ void gl_DestroyUserShaders() // todo } -//========================================================================== -// -// Parses a shader definition -// -//========================================================================== - -void gl_ParseHardwareShader(FScanner &sc, int deflump) -{ - sc.MustGetString(); - if (sc.Compare("postprocess")) - { - sc.MustGetString(); - - PostProcessShader shaderdesc; - shaderdesc.Target = sc.String; - shaderdesc.Target.ToLower(); - - bool validTarget = false; - if (sc.Compare("beforebloom")) validTarget = true; - if (sc.Compare("scene")) validTarget = true; - if (sc.Compare("screen")) validTarget = true; - if (!validTarget) - sc.ScriptError("Invalid target '%s' for postprocess shader",sc.String); - - sc.MustGetToken('{'); - while (!sc.CheckToken('}')) - { - sc.MustGetString(); - if (sc.Compare("shader")) - { - sc.MustGetString(); - shaderdesc.ShaderLumpName = sc.String; - - sc.MustGetNumber(); - shaderdesc.ShaderVersion = sc.Number; - if (sc.Number > 450 || sc.Number < 330) - sc.ScriptError("Shader version must be in range 330 to 450!"); - } - else if (sc.Compare("name")) - { - sc.MustGetString(); - shaderdesc.Name = sc.String; - } - else if (sc.Compare("uniform")) - { - sc.MustGetString(); - FString uniformType = sc.String; - uniformType.ToLower(); - - sc.MustGetString(); - FString uniformName = sc.String; - - PostProcessUniformType parsedType = PostProcessUniformType::Undefined; - - if (uniformType.Compare("int") == 0) - parsedType = PostProcessUniformType::Int; - else if (uniformType.Compare("float") == 0) - parsedType = PostProcessUniformType::Float; - else if (uniformType.Compare("vec2") == 0) - parsedType = PostProcessUniformType::Vec2; - else if (uniformType.Compare("vec3") == 0) - parsedType = PostProcessUniformType::Vec3; - else - sc.ScriptError("Unrecognized uniform type '%s'", sc.String); - - if (parsedType != PostProcessUniformType::Undefined) - shaderdesc.Uniforms[uniformName].Type = parsedType; - } - else if (sc.Compare("texture")) - { - sc.MustGetString(); - FString textureName = sc.String; - - sc.MustGetString(); - FString textureSource = sc.String; - - shaderdesc.Textures[textureName] = textureSource; - } - else if (sc.Compare("enabled")) - { - shaderdesc.Enabled = true; - } - else - { - sc.ScriptError("Unknown keyword '%s'", sc.String); - } - } - - PostProcessShaders.Push(shaderdesc); - } - else - { - ETextureType type = ETextureType::Any; - - if (sc.Compare("texture")) type = ETextureType::Wall; - else if (sc.Compare("flat")) type = ETextureType::Flat; - else if (sc.Compare("sprite")) type = ETextureType::Sprite; - else sc.UnGet(); - - bool disable_fullbright = false; - bool thiswad = false; - bool iwad = false; - int maplump = -1; - FString maplumpname; - float speed = 1.f; - - sc.MustGetString(); - FTextureID no = TexMan.CheckForTexture(sc.String, type); - FTexture *tex = TexMan[no]; - - sc.MustGetToken('{'); - while (!sc.CheckToken('}')) - { - sc.MustGetString(); - if (sc.Compare("shader")) - { - sc.MustGetString(); - maplumpname = sc.String; - } - else if (sc.Compare("speed")) - { - sc.MustGetFloat(); - speed = float(sc.Float); - } - } - if (!tex) - { - return; - } - - if (maplumpname.IsNotEmpty()) - { - if (tex->bWarped != 0) - { - Printf("Cannot combine warping with hardware shader on texture '%s'\n", tex->Name.GetChars()); - return; - } - tex->gl_info.shaderspeed = speed; - for (unsigned i = 0; i < usershaders.Size(); i++) - { - if (!usershaders[i].CompareNoCase(maplumpname)) - { - tex->gl_info.shaderindex = i + FIRST_USER_SHADER; - return; - } - } - tex->gl_info.shaderindex = usershaders.Push(maplumpname) + FIRST_USER_SHADER; - } - } -} - static bool IsConsolePlayer(player_t *player) { AActor *activator = player ? player->mo : nullptr; diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index 0ee8677843..5aa1fdedc2 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -405,28 +405,6 @@ public: } }; -enum MaterialShaderIndex -{ - SHADER_Default, - SHADER_Warp1, - SHADER_Warp2, - SHADER_Brightmap, - SHADER_Specular, - SHADER_SpecularBrightmap, - SHADER_PBR, - SHADER_PBRBrightmap, - SHADER_NoTexture, - SHADER_BasicFuzz, - SHADER_SmoothFuzz, - SHADER_SwirlyFuzz, - SHADER_TranslucentFuzz, - SHADER_JaggedFuzz, - SHADER_NoiseFuzz, - SHADER_SmoothNoiseFuzz, - SHADER_SoftwareFuzz, - FIRST_USER_SHADER -}; - enum { LIGHTBUF_BINDINGPOINT = 1 diff --git a/src/gl/textures/gl_texture.cpp b/src/gl/textures/gl_texture.cpp index 541204472e..4f7a6b1047 100644 --- a/src/gl/textures/gl_texture.cpp +++ b/src/gl/textures/gl_texture.cpp @@ -166,274 +166,6 @@ void FTexture::SetSpriteAdjust() } } -//========================================================================== -// -// Parses a material definition -// -//========================================================================== - -void gl_ParseMaterial(FScanner &sc, int deflump) -{ - ETextureType type = ETextureType::Any; - bool disable_fullbright = false; - bool disable_fullbright_specified = false; - bool thiswad = false; - bool iwad = false; - - FTexture *textures[6]; - const char *keywords[7] = { "brightmap", "normal", "specular", "metallic", "roughness", "ao", nullptr }; - const char *notFound[6] = { "Brightmap", "Normalmap", "Specular texture", "Metallic texture", "Roughness texture", "Ambient occlusion texture" }; - memset(textures, 0, sizeof(textures)); - - sc.MustGetString(); - if (sc.Compare("texture")) type = ETextureType::Wall; - else if (sc.Compare("flat")) type = ETextureType::Flat; - else if (sc.Compare("sprite")) type = ETextureType::Sprite; - else sc.UnGet(); - - sc.MustGetString(); - FTextureID no = TexMan.CheckForTexture(sc.String, type, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_Overridable); - FTexture *tex = TexMan[no]; - - sc.MustGetToken('{'); - while (!sc.CheckToken('}')) - { - sc.MustGetString(); - if (sc.Compare("disablefullbright")) - { - // This can also be used without a brightness map to disable - // fullbright in rotations that only use brightness maps on - // other angles. - disable_fullbright = true; - disable_fullbright_specified = true; - } - else if (sc.Compare("thiswad")) - { - // only affects textures defined in the WAD containing the definition file. - thiswad = true; - } - else if (sc.Compare ("iwad")) - { - // only affects textures defined in the IWAD. - iwad = true; - } - else if (sc.Compare("glossiness")) - { - sc.MustGetFloat(); - if (tex) - tex->gl_info.Glossiness = sc.Float; - } - else if (sc.Compare("specularlevel")) - { - sc.MustGetFloat(); - if (tex) - tex->gl_info.SpecularLevel = sc.Float; - } - else - { - for (int i = 0; keywords[i] != nullptr; i++) - { - if (sc.Compare (keywords[i])) - { - sc.MustGetString(); - if (textures[i]) - Printf("Multiple %s definitions in texture %s\n", keywords[i], tex? tex->Name.GetChars() : "(null)"); - textures[i] = TexMan.FindTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny); - if (!textures[i]) - Printf("%s '%s' not found in texture '%s'\n", notFound[i], sc.String, tex? tex->Name.GetChars() : "(null)"); - break; - } - } - } - } - if (!tex) - { - return; - } - if (thiswad || iwad) - { - bool useme = false; - int lumpnum = tex->GetSourceLump(); - - if (lumpnum != -1) - { - if (iwad && Wads.GetLumpFile(lumpnum) <= Wads.GetIwadNum()) useme = true; - if (thiswad && Wads.GetLumpFile(lumpnum) == deflump) useme = true; - } - if (!useme) return; - } - - FTexture **bindings[6] = - { - &tex->Brightmap, - &tex->Normal, - &tex->Specular, - &tex->Metallic, - &tex->Roughness, - &tex->AmbientOcclusion - }; - for (int i = 0; keywords[i] != nullptr; i++) - { - if (textures[i]) - { - textures[i]->bMasked = false; - *bindings[i] = textures[i]; - } - } - - if (disable_fullbright_specified) - tex->gl_info.bDisableFullbright = disable_fullbright; -} - -//========================================================================== -// -// Parses a brightmap definition -// -//========================================================================== - -void gl_ParseBrightmap(FScanner &sc, int deflump) -{ - ETextureType type = ETextureType::Any; - bool disable_fullbright=false; - bool thiswad = false; - bool iwad = false; - FTexture *bmtex = NULL; - - sc.MustGetString(); - if (sc.Compare("texture")) type = ETextureType::Wall; - else if (sc.Compare("flat")) type = ETextureType::Flat; - else if (sc.Compare("sprite")) type = ETextureType::Sprite; - else sc.UnGet(); - - sc.MustGetString(); - FTextureID no = TexMan.CheckForTexture(sc.String, type, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_Overridable); - FTexture *tex = TexMan[no]; - - sc.MustGetToken('{'); - while (!sc.CheckToken('}')) - { - sc.MustGetString(); - if (sc.Compare("disablefullbright")) - { - // This can also be used without a brightness map to disable - // fullbright in rotations that only use brightness maps on - // other angles. - disable_fullbright = true; - } - else if (sc.Compare("thiswad")) - { - // only affects textures defined in the WAD containing the definition file. - thiswad = true; - } - else if (sc.Compare ("iwad")) - { - // only affects textures defined in the IWAD. - iwad = true; - } - else if (sc.Compare ("map")) - { - sc.MustGetString(); - - if (bmtex != NULL) - { - Printf("Multiple brightmap definitions in texture %s\n", tex? tex->Name.GetChars() : "(null)"); - } - - bmtex = TexMan.FindTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny); - - if (bmtex == NULL) - Printf("Brightmap '%s' not found in texture '%s'\n", sc.String, tex? tex->Name.GetChars() : "(null)"); - } - } - if (!tex) - { - return; - } - if (thiswad || iwad) - { - bool useme = false; - int lumpnum = tex->GetSourceLump(); - - if (lumpnum != -1) - { - if (iwad && Wads.GetLumpFile(lumpnum) <= Wads.GetIwadNum()) useme = true; - if (thiswad && Wads.GetLumpFile(lumpnum) == deflump) useme = true; - } - if (!useme) return; - } - - if (bmtex != NULL) - { - /* I do not think this is needed any longer - if (tex->bWarped != 0) - { - Printf("Cannot combine warping with brightmap on texture '%s'\n", tex->Name.GetChars()); - return; - } - */ - - bmtex->bMasked = false; - tex->Brightmap = bmtex; - } - tex->gl_info.bDisableFullbright = disable_fullbright; -} - -//========================================================================== -// -// Parses a GLBoom+ detail texture definition -// -// Syntax is this: -// detail -// { -// (walls | flats) [default_detail_name [width [height [offset_x [offset_y]]]]] -// { -// texture_name [detail_name [width [height [offset_x [offset_y]]]]] -// } -// } -// This merely parses the block and returns no error if valid. The feature -// is not actually implemented, so nothing else happens. -//========================================================================== - -void gl_ParseDetailTexture(FScanner &sc) -{ - while (!sc.CheckToken('}')) - { - sc.MustGetString(); - if (sc.Compare("walls") || sc.Compare("flats")) - { - if (!sc.CheckToken('{')) - { - sc.MustGetString(); // Default detail texture - if (sc.CheckFloat()) // Width - if (sc.CheckFloat()) // Height - if (sc.CheckFloat()) // OffsX - if (sc.CheckFloat()) // OffsY - { - // Nothing - } - } - else sc.UnGet(); - sc.MustGetToken('{'); - while (!sc.CheckToken('}')) - { - sc.MustGetString(); // Texture - if (sc.GetString()) // Detail texture - { - if (sc.CheckFloat()) // Width - if (sc.CheckFloat()) // Height - if (sc.CheckFloat()) // OffsX - if (sc.CheckFloat()) // OffsY - { - // Nothing - } - } - else sc.UnGet(); - } - } - } -} - - //========================================================================== // // DFrameBuffer :: PrecacheTexture diff --git a/src/r_data/a_dynlightdata.cpp b/src/r_data/a_dynlightdata.cpp index 320f51019c..24a55ab714 100644 --- a/src/r_data/a_dynlightdata.cpp +++ b/src/r_data/a_dynlightdata.cpp @@ -53,13 +53,6 @@ #include "a_dynlight.h" #include "textures/skyboxtexture.h" -int ScriptDepth; -void gl_InitGlow(FScanner &sc); -void gl_ParseBrightmap(FScanner &sc, int); -void gl_ParseMaterial(FScanner &sc, int); -void gl_DestroyUserShaders(); -void gl_ParseHardwareShader(FScanner &sc, int deflump); -void gl_ParseDetailTexture(FScanner &sc); //========================================================================== // @@ -77,89 +70,6 @@ inline PClassActor * GetRealType(PClassActor * ti) return ti; } - - -//========================================================================== -// -// Light associations -// -//========================================================================== -class FLightAssociation -{ -public: - //FLightAssociation(); - FLightAssociation(FName actorName, const char *frameName, FName lightName) - : m_ActorName(actorName), m_AssocLight(lightName) - { - strncpy(m_FrameName, frameName, 8); - } - - FName ActorName() { return m_ActorName; } - const char *FrameName() { return m_FrameName; } - FName Light() { return m_AssocLight; } - void ReplaceLightName(FName newName) { m_AssocLight = newName; } -protected: - char m_FrameName[8]; - FName m_ActorName, m_AssocLight; -}; - -TArray LightAssociations; - - -//========================================================================== -// -// Light definitions -// -//========================================================================== -class FLightDefaults -{ -public: - FLightDefaults(FName name, ELightType type); - - void ApplyProperties(ADynamicLight * light) const; - FName GetName() const { return m_Name; } - void SetParameter(double p) { m_Param = p; } - void SetArg(int arg, int val) { m_Args[arg] = val; } - int GetArg(int arg) { return m_Args[arg]; } - uint8_t GetAttenuate() const { return m_attenuate; } - void SetOffset(float* ft) { m_Pos.X = ft[0]; m_Pos.Z = ft[1]; m_Pos.Y = ft[2]; } - void SetSubtractive(bool subtract) { m_subtractive = subtract; } - void SetAdditive(bool add) { m_additive = add; } - void SetDontLightSelf(bool add) { m_dontlightself = add; } - void SetAttenuate(bool on) { m_attenuate = on; } - void SetHalo(bool halo) { m_halo = halo; } - void SetDontLightActors(bool on) { m_dontlightactors = on; } - void SetSpot(bool spot) { m_spot = spot; } - void SetSpotInnerAngle(double angle) { m_spotInnerAngle = angle; } - void SetSpotOuterAngle(double angle) { m_spotOuterAngle = angle; } - - void OrderIntensities() - { - if (m_Args[LIGHT_INTENSITY] > m_Args[LIGHT_SECONDARY_INTENSITY]) - { - std::swap(m_Args[LIGHT_INTENSITY], m_Args[LIGHT_SECONDARY_INTENSITY]); - m_swapped = true; - } - } - -protected: - FName m_Name; - int m_Args[5] = { 0,0,0,0,0 }; - double m_Param = 0; - DVector3 m_Pos = { 0,0,0 }; - ELightType m_type; - int8_t m_attenuate = -1; - bool m_subtractive = false; - bool m_additive = false; - bool m_halo = false; - bool m_dontlightself = false; - bool m_dontlightactors = false; - bool m_swapped = false; - bool m_spot = false; - double m_spotInnerAngle = 10.0; - double m_spotOuterAngle = 25.0; -}; - TDeletingArray LightDefaults; //----------------------------------------------------------------------------- @@ -225,95 +135,9 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const //========================================================================== -static const char *LightTags[]= -{ - "color", - "size", - "secondarySize", - "offset", - "chance", - "interval", - "scale", - "frame", - "light", - "{", - "}", - "subtractive", - "additive", - "halo", - "dontlightself", - "attenuate", - "dontlightactors", - "spot", - nullptr -}; - - -enum { - LIGHTTAG_COLOR, - LIGHTTAG_SIZE, - LIGHTTAG_SECSIZE, - LIGHTTAG_OFFSET, - LIGHTTAG_CHANCE, - LIGHTTAG_INTERVAL, - LIGHTTAG_SCALE, - LIGHTTAG_FRAME, - LIGHTTAG_LIGHT, - LIGHTTAG_OPENBRACE, - LIGHTTAG_CLOSEBRACE, - LIGHTTAG_SUBTRACTIVE, - LIGHTTAG_ADDITIVE, - LIGHTTAG_HALO, - LIGHTTAG_DONTLIGHTSELF, - LIGHTTAG_ATTENUATE, - LIGHTTAG_DONTLIGHTACTORS, - LIGHTTAG_SPOT -}; - - extern int ScriptDepth; - -//========================================================================== -// -// -// -//========================================================================== - -inline float ParseFloat(FScanner &sc) -{ - sc.MustGetFloat(); - - return float(sc.Float); -} - - -inline int ParseInt(FScanner &sc) -{ - sc.MustGetNumber(); - - return sc.Number; -} - - -inline char *ParseString(FScanner &sc) -{ - sc.GetString(); - - return sc.String; -} - - -static void ParseTriple(FScanner &sc, float floatVal[3]) -{ - for (int i = 0; i < 3; i++) - { - floatVal[i] = ParseFloat(sc); - } -} - - -static void AddLightDefaults(FLightDefaults *defaults) +void AddLightDefaults(FLightDefaults *defaults) { FLightDefaults *temp; unsigned int i; @@ -340,711 +164,6 @@ static void AddLightDefaults(FLightDefaults *defaults) LightDefaults.Push(defaults); } - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -static void ParsePointLight(FScanner &sc) -{ - int type; - float floatTriple[3]; - int intVal; - FLightDefaults *defaults; - - // get name - sc.GetString(); - FName name = sc.String; - - // check for opening brace - sc.GetString(); - if (sc.Compare("{")) - { - defaults = new FLightDefaults(name, PointLight); - ScriptDepth++; - while (ScriptDepth) - { - sc.GetString(); - type = sc.MatchString(LightTags); - switch (type) - { - case LIGHTTAG_OPENBRACE: - ScriptDepth++; - break; - case LIGHTTAG_CLOSEBRACE: - ScriptDepth--; - break; - case LIGHTTAG_COLOR: - ParseTriple(sc, floatTriple); - defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); - defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); - defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); - break; - case LIGHTTAG_OFFSET: - ParseTriple(sc, floatTriple); - defaults->SetOffset(floatTriple); - break; - case LIGHTTAG_SIZE: - intVal = clamp(ParseInt(sc), 1, 1024); - defaults->SetArg(LIGHT_INTENSITY, intVal); - break; - case LIGHTTAG_SUBTRACTIVE: - defaults->SetSubtractive(ParseInt(sc) != 0); - break; - case LIGHTTAG_ADDITIVE: - defaults->SetAdditive(ParseInt(sc) != 0); - break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTSELF: - defaults->SetDontLightSelf(ParseInt(sc) != 0); - break; - case LIGHTTAG_ATTENUATE: - defaults->SetAttenuate(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTACTORS: - defaults->SetDontLightActors(ParseInt(sc) != 0); - break; - case LIGHTTAG_SPOT: - { - float innerAngle = ParseFloat(sc); - float outerAngle = ParseFloat(sc); - defaults->SetSpot(true); - defaults->SetSpotInnerAngle(innerAngle); - defaults->SetSpotOuterAngle(outerAngle); - } - break; - default: - sc.ScriptError("Unknown tag: %s\n", sc.String); - } - } - AddLightDefaults(defaults); - } - else - { - sc.ScriptError("Expected '{'.\n"); - } -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -static void ParsePulseLight(FScanner &sc) -{ - int type; - float floatVal, floatTriple[3]; - int intVal; - FLightDefaults *defaults; - - // get name - sc.GetString(); - FName name = sc.String; - - // check for opening brace - sc.GetString(); - if (sc.Compare("{")) - { - defaults = new FLightDefaults(name, PulseLight); - ScriptDepth++; - while (ScriptDepth) - { - sc.GetString(); - type = sc.MatchString(LightTags); - switch (type) - { - case LIGHTTAG_OPENBRACE: - ScriptDepth++; - break; - case LIGHTTAG_CLOSEBRACE: - ScriptDepth--; - break; - case LIGHTTAG_COLOR: - ParseTriple(sc, floatTriple); - defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); - defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); - defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); - break; - case LIGHTTAG_OFFSET: - ParseTriple(sc, floatTriple); - defaults->SetOffset(floatTriple); - break; - case LIGHTTAG_SIZE: - intVal = clamp(ParseInt(sc), 1, 1024); - defaults->SetArg(LIGHT_INTENSITY, intVal); - break; - case LIGHTTAG_SECSIZE: - intVal = clamp(ParseInt(sc), 1, 1024); - defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal); - break; - case LIGHTTAG_INTERVAL: - floatVal = ParseFloat(sc); - defaults->SetParameter(floatVal * TICRATE); - break; - case LIGHTTAG_SUBTRACTIVE: - defaults->SetSubtractive(ParseInt(sc) != 0); - break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTSELF: - defaults->SetDontLightSelf(ParseInt(sc) != 0); - break; - case LIGHTTAG_ATTENUATE: - defaults->SetAttenuate(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTACTORS: - defaults->SetDontLightActors(ParseInt(sc) != 0); - break; - case LIGHTTAG_SPOT: - { - float innerAngle = ParseFloat(sc); - float outerAngle = ParseFloat(sc); - defaults->SetSpot(true); - defaults->SetSpotInnerAngle(innerAngle); - defaults->SetSpotOuterAngle(outerAngle); - } - break; - default: - sc.ScriptError("Unknown tag: %s\n", sc.String); - } - } - defaults->OrderIntensities(); - - AddLightDefaults(defaults); - } - else - { - sc.ScriptError("Expected '{'.\n"); - } -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -void ParseFlickerLight(FScanner &sc) -{ - int type; - float floatVal, floatTriple[3]; - int intVal; - FLightDefaults *defaults; - - // get name - sc.GetString(); - FName name = sc.String; - - // check for opening brace - sc.GetString(); - if (sc.Compare("{")) - { - defaults = new FLightDefaults(name, FlickerLight); - ScriptDepth++; - while (ScriptDepth) - { - sc.GetString(); - type = sc.MatchString(LightTags); - switch (type) - { - case LIGHTTAG_OPENBRACE: - ScriptDepth++; - break; - case LIGHTTAG_CLOSEBRACE: - ScriptDepth--; - break; - case LIGHTTAG_COLOR: - ParseTriple(sc, floatTriple); - defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); - defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); - defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); - break; - case LIGHTTAG_OFFSET: - ParseTriple(sc, floatTriple); - defaults->SetOffset(floatTriple); - break; - case LIGHTTAG_SIZE: - intVal = clamp(ParseInt(sc), 1, 1024); - defaults->SetArg(LIGHT_INTENSITY, intVal); - break; - case LIGHTTAG_SECSIZE: - intVal = clamp(ParseInt(sc), 1, 1024); - defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal); - break; - case LIGHTTAG_CHANCE: - floatVal = ParseFloat(sc); - defaults->SetParameter(floatVal*360.); - break; - case LIGHTTAG_SUBTRACTIVE: - defaults->SetSubtractive(ParseInt(sc) != 0); - break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTSELF: - defaults->SetDontLightSelf(ParseInt(sc) != 0); - break; - case LIGHTTAG_ATTENUATE: - defaults->SetAttenuate(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTACTORS: - defaults->SetDontLightActors(ParseInt(sc) != 0); - break; - case LIGHTTAG_SPOT: - { - float innerAngle = ParseFloat(sc); - float outerAngle = ParseFloat(sc); - defaults->SetSpot(true); - defaults->SetSpotInnerAngle(innerAngle); - defaults->SetSpotOuterAngle(outerAngle); - } - break; - default: - sc.ScriptError("Unknown tag: %s\n", sc.String); - } - } - defaults->OrderIntensities(); - AddLightDefaults(defaults); - } - else - { - sc.ScriptError("Expected '{'.\n"); - } -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -void ParseFlickerLight2(FScanner &sc) -{ - int type; - float floatVal, floatTriple[3]; - int intVal; - FLightDefaults *defaults; - - // get name - sc.GetString(); - FName name = sc.String; - - // check for opening brace - sc.GetString(); - if (sc.Compare("{")) - { - defaults = new FLightDefaults(name, RandomFlickerLight); - ScriptDepth++; - while (ScriptDepth) - { - sc.GetString(); - type = sc.MatchString(LightTags); - switch (type) - { - case LIGHTTAG_OPENBRACE: - ScriptDepth++; - break; - case LIGHTTAG_CLOSEBRACE: - ScriptDepth--; - break; - case LIGHTTAG_COLOR: - ParseTriple(sc, floatTriple); - defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); - defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); - defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); - break; - case LIGHTTAG_OFFSET: - ParseTriple(sc, floatTriple); - defaults->SetOffset(floatTriple); - break; - case LIGHTTAG_SIZE: - intVal = clamp(ParseInt(sc), 1, 1024); - defaults->SetArg(LIGHT_INTENSITY, intVal); - break; - case LIGHTTAG_SECSIZE: - intVal = clamp(ParseInt(sc), 1, 1024); - defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal); - break; - case LIGHTTAG_INTERVAL: - floatVal = ParseFloat(sc); - defaults->SetParameter(floatVal * 360.); - break; - case LIGHTTAG_SUBTRACTIVE: - defaults->SetSubtractive(ParseInt(sc) != 0); - break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTSELF: - defaults->SetDontLightSelf(ParseInt(sc) != 0); - break; - case LIGHTTAG_ATTENUATE: - defaults->SetAttenuate(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTACTORS: - defaults->SetDontLightActors(ParseInt(sc) != 0); - break; - case LIGHTTAG_SPOT: - { - float innerAngle = ParseFloat(sc); - float outerAngle = ParseFloat(sc); - defaults->SetSpot(true); - defaults->SetSpotInnerAngle(innerAngle); - defaults->SetSpotOuterAngle(outerAngle); - } - break; - default: - sc.ScriptError("Unknown tag: %s\n", sc.String); - } - } - if (defaults->GetArg(LIGHT_SECONDARY_INTENSITY) < defaults->GetArg(LIGHT_INTENSITY)) - { - int v = defaults->GetArg(LIGHT_SECONDARY_INTENSITY); - defaults->SetArg(LIGHT_SECONDARY_INTENSITY, defaults->GetArg(LIGHT_INTENSITY)); - defaults->SetArg(LIGHT_INTENSITY, v); - } - AddLightDefaults(defaults); - } - else - { - sc.ScriptError("Expected '{'.\n"); - } -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -static void ParseSectorLight(FScanner &sc) -{ - int type; - float floatVal; - float floatTriple[3]; - FLightDefaults *defaults; - - // get name - sc.GetString(); - FName name = sc.String; - - // check for opening brace - sc.GetString(); - if (sc.Compare("{")) - { - defaults = new FLightDefaults(name, SectorLight); - ScriptDepth++; - while (ScriptDepth) - { - sc.GetString(); - type = sc.MatchString(LightTags); - switch (type) - { - case LIGHTTAG_OPENBRACE: - ScriptDepth++; - break; - case LIGHTTAG_CLOSEBRACE: - ScriptDepth--; - break; - case LIGHTTAG_COLOR: - ParseTriple(sc, floatTriple); - defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); - defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); - defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); - break; - case LIGHTTAG_OFFSET: - ParseTriple(sc, floatTriple); - defaults->SetOffset(floatTriple); - break; - case LIGHTTAG_SCALE: - floatVal = ParseFloat(sc); - defaults->SetArg(LIGHT_SCALE, clamp((int)(floatVal * 255), 1, 1024)); - break; - case LIGHTTAG_SUBTRACTIVE: - defaults->SetSubtractive(ParseInt(sc) != 0); - break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTSELF: - defaults->SetDontLightSelf(ParseInt(sc) != 0); - break; - case LIGHTTAG_ATTENUATE: - defaults->SetAttenuate(ParseInt(sc) != 0); - break; - case LIGHTTAG_DONTLIGHTACTORS: - defaults->SetDontLightActors(ParseInt(sc) != 0); - break; - case LIGHTTAG_SPOT: - { - float innerAngle = ParseFloat(sc); - float outerAngle = ParseFloat(sc); - defaults->SetSpot(true); - defaults->SetSpotInnerAngle(innerAngle); - defaults->SetSpotOuterAngle(outerAngle); - } - break; - default: - sc.ScriptError("Unknown tag: %s\n", sc.String); - } - } - AddLightDefaults(defaults); - } - else - { - sc.ScriptError("Expected '{'.\n"); - } -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -static void AddLightAssociation(const char *actor, const char *frame, const char *light) -{ - FLightAssociation *temp; - unsigned int i; - FLightAssociation assoc(actor, frame, light); - - for (i = 0; i < LightAssociations.Size(); i++) - { - temp = &LightAssociations[i]; - if (temp->ActorName() == assoc.ActorName()) - { - if (strcmp(temp->FrameName(), assoc.FrameName()) == 0) - { - temp->ReplaceLightName(assoc.Light()); - return; - } - } - } - - LightAssociations.Push(assoc); -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -static void ParseFrame(FScanner &sc, FString name) -{ - int type, startDepth; - FString frameName; - - // get name - sc.GetString(); - if (strlen(sc.String) > 8) - { - sc.ScriptError("Name longer than 8 characters: %s\n", sc.String); - } - frameName = sc.String; - - startDepth = ScriptDepth; - - // check for opening brace - sc.GetString(); - if (sc.Compare("{")) - { - ScriptDepth++; - while (ScriptDepth > startDepth) - { - sc.GetString(); - type = sc.MatchString(LightTags); - switch (type) - { - case LIGHTTAG_OPENBRACE: - ScriptDepth++; - break; - case LIGHTTAG_CLOSEBRACE: - ScriptDepth--; - break; - case LIGHTTAG_LIGHT: - ParseString(sc); - AddLightAssociation(name, frameName, sc.String); - break; - default: - sc.ScriptError("Unknown tag: %s\n", sc.String); - } - } - } - else - { - sc.ScriptError("Expected '{'.\n"); - } -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -void ParseObject(FScanner &sc) -{ - int type; - FString name; - - // get name - sc.GetString(); - name = sc.String; - if (!PClass::FindActor(name)) - sc.ScriptMessage("Warning: dynamic lights attached to non-existent actor %s\n", name.GetChars()); - - // check for opening brace - sc.GetString(); - if (sc.Compare("{")) - { - ScriptDepth++; - while (ScriptDepth) - { - sc.GetString(); - type = sc.MatchString(LightTags); - switch (type) - { - case LIGHTTAG_OPENBRACE: - ScriptDepth++; - break; - case LIGHTTAG_CLOSEBRACE: - ScriptDepth--; - break; - case LIGHTTAG_FRAME: - ParseFrame(sc, name); - break; - default: - sc.ScriptError("Unknown tag: %s\n", sc.String); - } - } - } - else - { - sc.ScriptError("Expected '{'.\n"); - } -} - - -//========================================================================== -// -// -// -//========================================================================== - -// these are the core types available in the *DEFS lump -static const char *CoreKeywords[]= -{ - "pointlight", - "pulselight", - "flickerlight", - "flickerlight2", - "sectorlight", - "object", - "clearlights", - "shader", - "clearshaders", - "skybox", - "glow", - "brightmap", - "disable_fullbright", - "hardwareshader", - "detail", - "#include", - "material", - nullptr -}; - - -enum -{ - LIGHT_POINT, - LIGHT_PULSE, - LIGHT_FLICKER, - LIGHT_FLICKER2, - LIGHT_SECTOR, - LIGHT_OBJECT, - LIGHT_CLEAR, - TAG_SHADER, - TAG_CLEARSHADERS, - TAG_SKYBOX, - TAG_GLOW, - TAG_BRIGHTMAP, - TAG_DISABLE_FB, - TAG_HARDWARESHADER, - TAG_DETAIL, - TAG_INCLUDE, - TAG_MATERIAL -}; - - -//========================================================================== -// -// This is only here so any shader definition for ZDoomGL can be skipped -// There is no functionality for this stuff! -// -//========================================================================== -bool ParseShader(FScanner &sc) -{ - int ShaderDepth = 0; - - if (sc.GetString()) - { - char *tmp; - - tmp = strstr(sc.String, "{"); - while (tmp) - { - ShaderDepth++; - tmp++; - tmp = strstr(tmp, "{"); - } - - tmp = strstr(sc.String, "}"); - while (tmp) - { - ShaderDepth--; - tmp++; - tmp = strstr(tmp, "}"); - } - - if (ShaderDepth == 0) return true; - } - return false; -} - -//========================================================================== -// -// Light associations per actor class -// -//========================================================================== - -class FInternalLightAssociation -{ -public: - FInternalLightAssociation(FLightAssociation * asso); - int Sprite() const { return m_sprite; } - int Frame() const { return m_frame; } - const FLightDefaults *Light() const { return m_AssocLight; } -protected: - int m_sprite; - int m_frame; - FLightDefaults * m_AssocLight; -}; - //========================================================================== // // @@ -1089,18 +208,16 @@ FInternalLightAssociation::FInternalLightAssociation(FLightAssociation * asso) // State lights // //========================================================================== -TArray ParsedStateLights; +static TArray ParsedStateLights; TArray StateLights; - - //========================================================================== // // // //========================================================================== -void InitializeActorLights() +void InitializeActorLights(TArray &LightAssociations) { for(unsigned int i=0;iActorInfo()->LightAssociations.Push(iasso); } } - // we don't need the parser data for the light associations anymore - LightAssociations.Clear(); - LightAssociations.ShrinkToFit(); StateLights.Resize(ParsedStateLights.Size()+1); for(unsigned i=0; i(AttachedLights[count]); - assert(light != NULL); - } - else - { - light = Spawn(Pos(), NO_REPLACE); - light->target = this; - light->owned = true; - light->ObjectFlags |= OF_Transient; - //light->lightflags |= LF_ATTENUATE; - AttachedLights.Push(light); - } - light->flags2&=~MF2_DORMANT; - lightdef->ApplyProperties(light); -} - -//========================================================================== -// -// per-state light adjustment -// -//========================================================================== - -void AActor::SetDynamicLights() -{ - TArray & LightAssociations = GetInfo()->LightAssociations; - unsigned int count = 0; - - if (state == NULL) return; - if (LightAssociations.Size() > 0) - { - ADynamicLight *lights, *tmpLight; - unsigned int i; - - lights = tmpLight = NULL; - - for (i = 0; i < LightAssociations.Size(); i++) - { - if (LightAssociations[i]->Sprite() == sprite && - (LightAssociations[i]->Frame()==frame || LightAssociations[i]->Frame()==-1)) - { - AttachLight(count++, LightAssociations[i]->Light()); - } - } - } - if (count == 0 && state->Light > 0) - { - for(int i= state->Light; StateLights[i] != NULL; i++) - { - if (StateLights[i] != (FLightDefaults*)-1) - { - AttachLight(count++, StateLights[i]); - } - } - } - - for(;countflags2 |= MF2_DORMANT; - memset(AttachedLights[count]->args, 0, 3*sizeof(args[0])); - } -} - -//========================================================================== -// -// Needed for garbage collection -// -//========================================================================== - -size_t AActor::PropagateMark() -{ - for (unsigned i = 0; i it; - AActor * a; - ADynamicLight * l; - - while ((a=it.Next())) - { - a->AttachedLights.Clear(); - } - - TThinkerIterator it2; - - l=it2.Next(); - while (l) - { - ADynamicLight * ll = it2.Next(); - if (l->owned) l->Destroy(); - l=ll; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void AActor::RecreateAllAttachedLights() -{ - TThinkerIterator it; - AActor * a; - - while ((a=it.Next())) - { - a->SetDynamicLights(); - } -} - - -//========================================================================== -// -// -// -//========================================================================== -static void DoParseDefs(FScanner &sc, int workingLump) -{ - int recursion=0; - int lump, type; - - // Get actor class name. - while (true) - { - sc.SavePos(); - if (!sc.GetToken ()) - { - return; - } - type = sc.MatchString(CoreKeywords); - switch (type) - { - case TAG_INCLUDE: - { - sc.MustGetString(); - // This is not using sc.Open because it can print a more useful error message when done here - lump = Wads.CheckNumForFullName(sc.String, true); - if (lump==-1) - sc.ScriptError("Lump '%s' not found", sc.String); - - FScanner newscanner(lump); - DoParseDefs(newscanner, lump); - break; - } - case LIGHT_POINT: - ParsePointLight(sc); - break; - case LIGHT_PULSE: - ParsePulseLight(sc); - break; - case LIGHT_FLICKER: - ParseFlickerLight(sc); - break; - case LIGHT_FLICKER2: - ParseFlickerLight2(sc); - break; - case LIGHT_SECTOR: - ParseSectorLight(sc); - break; - case LIGHT_OBJECT: - ParseObject(sc); - break; - case LIGHT_CLEAR: - // This has been intentionally removed - break; - case TAG_SHADER: - ParseShader(sc); - break; - case TAG_CLEARSHADERS: - break; - case TAG_SKYBOX: - ParseGldefSkybox(sc); - break; - case TAG_GLOW: - gl_InitGlow(sc); - break; - case TAG_BRIGHTMAP: - gl_ParseBrightmap(sc, workingLump); - break; - case TAG_MATERIAL: - gl_ParseMaterial(sc, workingLump); - break; - case TAG_HARDWARESHADER: - gl_ParseHardwareShader(sc, workingLump); - break; - case TAG_DETAIL: - gl_ParseDetailTexture(sc); - break; - case TAG_DISABLE_FB: - { - /* not implemented. - sc.MustGetString(); - const PClass *cls = PClass::FindClass(sc.String); - if (cls) GetDefaultByType(cls)->renderflags |= RF_NEVERFULLBRIGHT; - */ - } - break; - default: - sc.ScriptError("Error parsing defs. Unknown tag: %s.\n", sc.String); - break; - } - } -} - -//========================================================================== -// -// -// -//========================================================================== - -static void LoadGLDefs(const char *defsLump) -{ - int workingLump, lastLump; - static const char *gldefsnames[] = { "GLDEFS", defsLump, nullptr }; - - lastLump = 0; - while ((workingLump = Wads.FindLumpMulti(gldefsnames, &lastLump)) != -1) - { - FScanner sc(workingLump); - DoParseDefs(sc, workingLump); - } -} - - -//========================================================================== -// -// -// -//========================================================================== - -void ParseGLDefs() -{ - const char *defsLump = NULL; - - LightAssociations.Clear(); - LightDefaults.Clear(); - gl_DestroyUserShaders(); - switch (gameinfo.gametype) - { - case GAME_Heretic: - defsLump = "HTICDEFS"; - break; - case GAME_Hexen: - defsLump = "HEXNDEFS"; - break; - case GAME_Strife: - defsLump = "STRFDEFS"; - break; - case GAME_Doom: - defsLump = "DOOMDEFS"; - break; - case GAME_Chex: - defsLump = "CHEXDEFS"; - break; - default: // silence GCC - break; - } - ParseVavoomSkybox(); - LoadGLDefs(defsLump); - InitializeActorLights(); -} - //========================================================================== // // diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp new file mode 100644 index 0000000000..9b38360351 --- /dev/null +++ b/src/r_data/gldefs.cpp @@ -0,0 +1,1589 @@ +/* +** gldefs.cpp +** GLDEFS parser +** +**--------------------------------------------------------------------------- +** Copyright 2003 Timothy Stump +** Copyright 2005-2018 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ +#include +#include "i_system.h" +#include "doomtype.h" +#include "c_cvars.h" +#include "c_dispatch.h" +#include "m_random.h" +#include "sc_man.h" +#include "templates.h" +#include "w_wad.h" +#include "gi.h" +#include "r_state.h" +#include "stats.h" +#include "zstring.h" +#include "d_dehacked.h" +#include "v_text.h" +#include "g_levellocals.h" +#include "a_dynlight.h" +#include "textures/skyboxtexture.h" +#include "gl/shaders/gl_postprocessshader.h" + +void AddLightDefaults(FLightDefaults *defaults); +void AddLightAssociation(const char *actor, const char *frame, const char *light); +void InitializeActorLights(TArray &LightAssociations); + +extern TArray usershaders; +extern TDeletingArray LightDefaults; + + +//----------------------------------------------------------------------------- +// +// ParseVavoomSkybox +// +//----------------------------------------------------------------------------- + +static void ParseVavoomSkybox() +{ + int lump = Wads.CheckNumForName("SKYBOXES"); + + if (lump < 0) return; + + FScanner sc(lump); + while (sc.GetString()) + { + int facecount=0; + int maplump = -1; + bool error = false; + FSkyBox * sb = new FSkyBox; + sb->Name = sc.String; + sb->Name.ToUpper(); + sb->fliptop = true; + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + if (facecount<6) + { + sc.MustGetStringName("{"); + sc.MustGetStringName("map"); + sc.MustGetString(); + + maplump = Wads.CheckNumForFullName(sc.String, true); + + FTexture *tex = TexMan.FindTexture(sc.String, ETextureType::Wall, FTextureManager::TEXMAN_TryAny); + if (tex == NULL) + { + sc.ScriptMessage("Texture '%s' not found in Vavoom skybox '%s'\n", sc.String, sb->Name.GetChars()); + error = true; + } + sb->faces[facecount] = tex; + sc.MustGetStringName("}"); + } + facecount++; + } + if (facecount != 6) + { + sc.ScriptError("%s: Skybox definition requires 6 faces", sb->Name.GetChars()); + } + sb->SetSize(); + if (!error) TexMan.AddTexture(sb); + } +} + + + +//========================================================================== +// +// light definition keywords +// +//========================================================================== + + +static const char *LightTags[]= +{ + "color", + "size", + "secondarySize", + "offset", + "chance", + "interval", + "scale", + "frame", + "light", + "{", + "}", + "subtractive", + "additive", + "halo", + "dontlightself", + "attenuate", + "dontlightactors", + "spot", + nullptr +}; + + +enum { + LIGHTTAG_COLOR, + LIGHTTAG_SIZE, + LIGHTTAG_SECSIZE, + LIGHTTAG_OFFSET, + LIGHTTAG_CHANCE, + LIGHTTAG_INTERVAL, + LIGHTTAG_SCALE, + LIGHTTAG_FRAME, + LIGHTTAG_LIGHT, + LIGHTTAG_OPENBRACE, + LIGHTTAG_CLOSEBRACE, + LIGHTTAG_SUBTRACTIVE, + LIGHTTAG_ADDITIVE, + LIGHTTAG_HALO, + LIGHTTAG_DONTLIGHTSELF, + LIGHTTAG_ATTENUATE, + LIGHTTAG_DONTLIGHTACTORS, + LIGHTTAG_SPOT +}; + +//========================================================================== +// +// Top level keywords +// +//========================================================================== + +// these are the core types available in the *DEFS lump +static const char *CoreKeywords[]= +{ + "pointlight", + "pulselight", + "flickerlight", + "flickerlight2", + "sectorlight", + "object", + "clearlights", + "shader", + "clearshaders", + "skybox", + "glow", + "brightmap", + "disable_fullbright", + "hardwareshader", + "detail", + "#include", + "material", + nullptr +}; + + +enum +{ + LIGHT_POINT, + LIGHT_PULSE, + LIGHT_FLICKER, + LIGHT_FLICKER2, + LIGHT_SECTOR, + LIGHT_OBJECT, + LIGHT_CLEAR, + TAG_SHADER, + TAG_CLEARSHADERS, + TAG_SKYBOX, + TAG_GLOW, + TAG_BRIGHTMAP, + TAG_DISABLE_FB, + TAG_HARDWARESHADER, + TAG_DETAIL, + TAG_INCLUDE, + TAG_MATERIAL +}; + +//========================================================================== +// +// GLDEFS parser +// +//========================================================================== + +class GLDefsParser +{ + FScanner sc; + int workingLump; + int ScriptDepth = 0; + TArray &LightAssociations; + + //========================================================================== + // + // This is only here so any shader definition for ZDoomGL can be skipped + // There is no functionality for this stuff! + // + //========================================================================== + + bool ParseShader() + { + int ShaderDepth = 0; + + if (sc.GetString()) + { + char *tmp; + + tmp = strstr(sc.String, "{"); + while (tmp) + { + ShaderDepth++; + tmp++; + tmp = strstr(tmp, "{"); + } + + tmp = strstr(sc.String, "}"); + while (tmp) + { + ShaderDepth--; + tmp++; + tmp = strstr(tmp, "}"); + } + + if (ShaderDepth == 0) return true; + } + return false; + } + + //========================================================================== + // + // Parses a GLBoom+ detail texture definition + // + // Syntax is this: + // detail + // { + // (walls | flats) [default_detail_name [width [height [offset_x [offset_y]]]]] + // { + // texture_name [detail_name [width [height [offset_x [offset_y]]]]] + // } + // } + // This merely parses the block and returns no error if valid. The feature + // is not actually implemented, so nothing else happens. + // + // The semantics of this are too horrible to comprehend (default detail texture???) + // so if this ever gets done, the parser will look different. + //========================================================================== + + void ParseDetailTexture() + { + while (!sc.CheckToken('}')) + { + sc.MustGetString(); + if (sc.Compare("walls") || sc.Compare("flats")) + { + if (!sc.CheckToken('{')) + { + sc.MustGetString(); // Default detail texture + if (sc.CheckFloat()) // Width + if (sc.CheckFloat()) // Height + if (sc.CheckFloat()) // OffsX + if (sc.CheckFloat()) // OffsY + { + // Nothing + } + } + else sc.UnGet(); + sc.MustGetToken('{'); + while (!sc.CheckToken('}')) + { + sc.MustGetString(); // Texture + if (sc.GetString()) // Detail texture + { + if (sc.CheckFloat()) // Width + if (sc.CheckFloat()) // Height + if (sc.CheckFloat()) // OffsX + if (sc.CheckFloat()) // OffsY + { + // Nothing + } + } + else sc.UnGet(); + } + } + } + } + + + //========================================================================== + // + // + // + //========================================================================== + + float ParseFloat(FScanner &sc) + { + sc.MustGetFloat(); + return float(sc.Float); + } + + + int ParseInt(FScanner &sc) + { + sc.MustGetNumber(); + return sc.Number; + } + + + char *ParseString(FScanner &sc) + { + sc.GetString(); + return sc.String; + } + + + void ParseTriple(FScanner &sc, float floatVal[3]) + { + for (int i = 0; i < 3; i++) + { + floatVal[i] = ParseFloat(sc); + } + } + + + //----------------------------------------------------------------------------- + // + // + // + //----------------------------------------------------------------------------- + + void AddLightAssociation(const char *actor, const char *frame, const char *light) + { + FLightAssociation *temp; + unsigned int i; + FLightAssociation assoc(actor, frame, light); + + for (i = 0; i < LightAssociations.Size(); i++) + { + temp = &LightAssociations[i]; + if (temp->ActorName() == assoc.ActorName()) + { + if (strcmp(temp->FrameName(), assoc.FrameName()) == 0) + { + temp->ReplaceLightName(assoc.Light()); + return; + } + } + } + + LightAssociations.Push(assoc); + } + + //----------------------------------------------------------------------------- + // + // Note: The different light type parsers really could use some consolidation... + // + //----------------------------------------------------------------------------- + + void ParsePointLight() + { + int type; + float floatTriple[3]; + int intVal; + FLightDefaults *defaults; + + // get name + sc.GetString(); + FName name = sc.String; + + // check for opening brace + sc.GetString(); + if (sc.Compare("{")) + { + defaults = new FLightDefaults(name, PointLight); + ScriptDepth++; + while (ScriptDepth) + { + sc.GetString(); + type = sc.MatchString(LightTags); + switch (type) + { + case LIGHTTAG_OPENBRACE: + ScriptDepth++; + break; + case LIGHTTAG_CLOSEBRACE: + ScriptDepth--; + break; + case LIGHTTAG_COLOR: + ParseTriple(sc, floatTriple); + defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); + defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); + defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); + break; + case LIGHTTAG_OFFSET: + ParseTriple(sc, floatTriple); + defaults->SetOffset(floatTriple); + break; + case LIGHTTAG_SIZE: + intVal = clamp(ParseInt(sc), 1, 1024); + defaults->SetArg(LIGHT_INTENSITY, intVal); + break; + case LIGHTTAG_SUBTRACTIVE: + defaults->SetSubtractive(ParseInt(sc) != 0); + break; + case LIGHTTAG_ADDITIVE: + defaults->SetAdditive(ParseInt(sc) != 0); + break; + case LIGHTTAG_HALO: + defaults->SetHalo(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTSELF: + defaults->SetDontLightSelf(ParseInt(sc) != 0); + break; + case LIGHTTAG_ATTENUATE: + defaults->SetAttenuate(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; + case LIGHTTAG_SPOT: + { + float innerAngle = ParseFloat(sc); + float outerAngle = ParseFloat(sc); + defaults->SetSpot(true); + defaults->SetSpotInnerAngle(innerAngle); + defaults->SetSpotOuterAngle(outerAngle); + } + break; + default: + sc.ScriptError("Unknown tag: %s\n", sc.String); + } + } + AddLightDefaults(defaults); + } + else + { + sc.ScriptError("Expected '{'.\n"); + } + } + + //----------------------------------------------------------------------------- + // + // + // + //----------------------------------------------------------------------------- + + void ParsePulseLight() + { + int type; + float floatVal, floatTriple[3]; + int intVal; + FLightDefaults *defaults; + + // get name + sc.GetString(); + FName name = sc.String; + + // check for opening brace + sc.GetString(); + if (sc.Compare("{")) + { + defaults = new FLightDefaults(name, PulseLight); + ScriptDepth++; + while (ScriptDepth) + { + sc.GetString(); + type = sc.MatchString(LightTags); + switch (type) + { + case LIGHTTAG_OPENBRACE: + ScriptDepth++; + break; + case LIGHTTAG_CLOSEBRACE: + ScriptDepth--; + break; + case LIGHTTAG_COLOR: + ParseTriple(sc, floatTriple); + defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); + defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); + defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); + break; + case LIGHTTAG_OFFSET: + ParseTriple(sc, floatTriple); + defaults->SetOffset(floatTriple); + break; + case LIGHTTAG_SIZE: + intVal = clamp(ParseInt(sc), 1, 1024); + defaults->SetArg(LIGHT_INTENSITY, intVal); + break; + case LIGHTTAG_SECSIZE: + intVal = clamp(ParseInt(sc), 1, 1024); + defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal); + break; + case LIGHTTAG_INTERVAL: + floatVal = ParseFloat(sc); + defaults->SetParameter(floatVal * TICRATE); + break; + case LIGHTTAG_SUBTRACTIVE: + defaults->SetSubtractive(ParseInt(sc) != 0); + break; + case LIGHTTAG_HALO: + defaults->SetHalo(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTSELF: + defaults->SetDontLightSelf(ParseInt(sc) != 0); + break; + case LIGHTTAG_ATTENUATE: + defaults->SetAttenuate(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; + case LIGHTTAG_SPOT: + { + float innerAngle = ParseFloat(sc); + float outerAngle = ParseFloat(sc); + defaults->SetSpot(true); + defaults->SetSpotInnerAngle(innerAngle); + defaults->SetSpotOuterAngle(outerAngle); + } + break; + default: + sc.ScriptError("Unknown tag: %s\n", sc.String); + } + } + defaults->OrderIntensities(); + + AddLightDefaults(defaults); + } + else + { + sc.ScriptError("Expected '{'.\n"); + } + } + + + //----------------------------------------------------------------------------- + // + // + // + //----------------------------------------------------------------------------- + + void ParseFlickerLight() + { + int type; + float floatVal, floatTriple[3]; + int intVal; + FLightDefaults *defaults; + + // get name + sc.GetString(); + FName name = sc.String; + + // check for opening brace + sc.GetString(); + if (sc.Compare("{")) + { + defaults = new FLightDefaults(name, FlickerLight); + ScriptDepth++; + while (ScriptDepth) + { + sc.GetString(); + type = sc.MatchString(LightTags); + switch (type) + { + case LIGHTTAG_OPENBRACE: + ScriptDepth++; + break; + case LIGHTTAG_CLOSEBRACE: + ScriptDepth--; + break; + case LIGHTTAG_COLOR: + ParseTriple(sc, floatTriple); + defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); + defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); + defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); + break; + case LIGHTTAG_OFFSET: + ParseTriple(sc, floatTriple); + defaults->SetOffset(floatTriple); + break; + case LIGHTTAG_SIZE: + intVal = clamp(ParseInt(sc), 1, 1024); + defaults->SetArg(LIGHT_INTENSITY, intVal); + break; + case LIGHTTAG_SECSIZE: + intVal = clamp(ParseInt(sc), 1, 1024); + defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal); + break; + case LIGHTTAG_CHANCE: + floatVal = ParseFloat(sc); + defaults->SetParameter(floatVal*360.); + break; + case LIGHTTAG_SUBTRACTIVE: + defaults->SetSubtractive(ParseInt(sc) != 0); + break; + case LIGHTTAG_HALO: + defaults->SetHalo(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTSELF: + defaults->SetDontLightSelf(ParseInt(sc) != 0); + break; + case LIGHTTAG_ATTENUATE: + defaults->SetAttenuate(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; + case LIGHTTAG_SPOT: + { + float innerAngle = ParseFloat(sc); + float outerAngle = ParseFloat(sc); + defaults->SetSpot(true); + defaults->SetSpotInnerAngle(innerAngle); + defaults->SetSpotOuterAngle(outerAngle); + } + break; + default: + sc.ScriptError("Unknown tag: %s\n", sc.String); + } + } + defaults->OrderIntensities(); + AddLightDefaults(defaults); + } + else + { + sc.ScriptError("Expected '{'.\n"); + } + } + + + //----------------------------------------------------------------------------- + // + // + // + //----------------------------------------------------------------------------- + + void ParseFlickerLight2() + { + int type; + float floatVal, floatTriple[3]; + int intVal; + FLightDefaults *defaults; + + // get name + sc.GetString(); + FName name = sc.String; + + // check for opening brace + sc.GetString(); + if (sc.Compare("{")) + { + defaults = new FLightDefaults(name, RandomFlickerLight); + ScriptDepth++; + while (ScriptDepth) + { + sc.GetString(); + type = sc.MatchString(LightTags); + switch (type) + { + case LIGHTTAG_OPENBRACE: + ScriptDepth++; + break; + case LIGHTTAG_CLOSEBRACE: + ScriptDepth--; + break; + case LIGHTTAG_COLOR: + ParseTriple(sc, floatTriple); + defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); + defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); + defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); + break; + case LIGHTTAG_OFFSET: + ParseTriple(sc, floatTriple); + defaults->SetOffset(floatTriple); + break; + case LIGHTTAG_SIZE: + intVal = clamp(ParseInt(sc), 1, 1024); + defaults->SetArg(LIGHT_INTENSITY, intVal); + break; + case LIGHTTAG_SECSIZE: + intVal = clamp(ParseInt(sc), 1, 1024); + defaults->SetArg(LIGHT_SECONDARY_INTENSITY, intVal); + break; + case LIGHTTAG_INTERVAL: + floatVal = ParseFloat(sc); + defaults->SetParameter(floatVal * 360.); + break; + case LIGHTTAG_SUBTRACTIVE: + defaults->SetSubtractive(ParseInt(sc) != 0); + break; + case LIGHTTAG_HALO: + defaults->SetHalo(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTSELF: + defaults->SetDontLightSelf(ParseInt(sc) != 0); + break; + case LIGHTTAG_ATTENUATE: + defaults->SetAttenuate(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; + case LIGHTTAG_SPOT: + { + float innerAngle = ParseFloat(sc); + float outerAngle = ParseFloat(sc); + defaults->SetSpot(true); + defaults->SetSpotInnerAngle(innerAngle); + defaults->SetSpotOuterAngle(outerAngle); + } + break; + default: + sc.ScriptError("Unknown tag: %s\n", sc.String); + } + } + if (defaults->GetArg(LIGHT_SECONDARY_INTENSITY) < defaults->GetArg(LIGHT_INTENSITY)) + { + int v = defaults->GetArg(LIGHT_SECONDARY_INTENSITY); + defaults->SetArg(LIGHT_SECONDARY_INTENSITY, defaults->GetArg(LIGHT_INTENSITY)); + defaults->SetArg(LIGHT_INTENSITY, v); + } + AddLightDefaults(defaults); + } + else + { + sc.ScriptError("Expected '{'.\n"); + } + } + + + //----------------------------------------------------------------------------- + // + // + // + //----------------------------------------------------------------------------- + + void ParseSectorLight() + { + int type; + float floatVal; + float floatTriple[3]; + FLightDefaults *defaults; + + // get name + sc.GetString(); + FName name = sc.String; + + // check for opening brace + sc.GetString(); + if (sc.Compare("{")) + { + defaults = new FLightDefaults(name, SectorLight); + ScriptDepth++; + while (ScriptDepth) + { + sc.GetString(); + type = sc.MatchString(LightTags); + switch (type) + { + case LIGHTTAG_OPENBRACE: + ScriptDepth++; + break; + case LIGHTTAG_CLOSEBRACE: + ScriptDepth--; + break; + case LIGHTTAG_COLOR: + ParseTriple(sc, floatTriple); + defaults->SetArg(LIGHT_RED, clamp((int)(floatTriple[0] * 255), 0, 255)); + defaults->SetArg(LIGHT_GREEN, clamp((int)(floatTriple[1] * 255), 0, 255)); + defaults->SetArg(LIGHT_BLUE, clamp((int)(floatTriple[2] * 255), 0, 255)); + break; + case LIGHTTAG_OFFSET: + ParseTriple(sc, floatTriple); + defaults->SetOffset(floatTriple); + break; + case LIGHTTAG_SCALE: + floatVal = ParseFloat(sc); + defaults->SetArg(LIGHT_SCALE, clamp((int)(floatVal * 255), 1, 1024)); + break; + case LIGHTTAG_SUBTRACTIVE: + defaults->SetSubtractive(ParseInt(sc) != 0); + break; + case LIGHTTAG_HALO: + defaults->SetHalo(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTSELF: + defaults->SetDontLightSelf(ParseInt(sc) != 0); + break; + case LIGHTTAG_ATTENUATE: + defaults->SetAttenuate(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; + case LIGHTTAG_SPOT: + { + float innerAngle = ParseFloat(sc); + float outerAngle = ParseFloat(sc); + defaults->SetSpot(true); + defaults->SetSpotInnerAngle(innerAngle); + defaults->SetSpotOuterAngle(outerAngle); + } + break; + default: + sc.ScriptError("Unknown tag: %s\n", sc.String); + } + } + AddLightDefaults(defaults); + } + else + { + sc.ScriptError("Expected '{'.\n"); + } + } + + //----------------------------------------------------------------------------- + // + // + // + //----------------------------------------------------------------------------- + + void ParseFrame(const FString &name) + { + int type, startDepth; + FString frameName; + + // get name + sc.GetString(); + if (strlen(sc.String) > 8) + { + sc.ScriptError("Name longer than 8 characters: %s\n", sc.String); + } + frameName = sc.String; + + startDepth = ScriptDepth; + + // check for opening brace + sc.GetString(); + if (sc.Compare("{")) + { + ScriptDepth++; + while (ScriptDepth > startDepth) + { + sc.GetString(); + type = sc.MatchString(LightTags); + switch (type) + { + case LIGHTTAG_OPENBRACE: + ScriptDepth++; + break; + case LIGHTTAG_CLOSEBRACE: + ScriptDepth--; + break; + case LIGHTTAG_LIGHT: + ParseString(sc); + AddLightAssociation(name, frameName, sc.String); + break; + default: + sc.ScriptError("Unknown tag: %s\n", sc.String); + } + } + } + else + { + sc.ScriptError("Expected '{'.\n"); + } + } + + //----------------------------------------------------------------------------- + // + // + // + //----------------------------------------------------------------------------- + + void ParseObject() + { + int type; + FString name; + + // get name + sc.GetString(); + name = sc.String; + if (!PClass::FindActor(name)) + sc.ScriptMessage("Warning: dynamic lights attached to non-existent actor %s\n", name.GetChars()); + + // check for opening brace + sc.GetString(); + if (sc.Compare("{")) + { + ScriptDepth++; + while (ScriptDepth) + { + sc.GetString(); + type = sc.MatchString(LightTags); + switch (type) + { + case LIGHTTAG_OPENBRACE: + ScriptDepth++; + break; + case LIGHTTAG_CLOSEBRACE: + ScriptDepth--; + break; + case LIGHTTAG_FRAME: + ParseFrame(name); + break; + default: + sc.ScriptError("Unknown tag: %s\n", sc.String); + } + } + } + else + { + sc.ScriptError("Expected '{'.\n"); + } + } + + + //----------------------------------------------------------------------------- + // + // + // + //----------------------------------------------------------------------------- + + void ParseGldefSkybox() + { + int facecount=0; + + sc.MustGetString(); + + FSkyBox * sb = new FSkyBox; + sb->Name = sc.String; + sb->Name.ToUpper(); + if (sc.CheckString("fliptop")) + { + sb->fliptop = true; + } + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (facecount<6) + { + sb->faces[facecount] = TexMan[TexMan.GetTexture(sc.String, ETextureType::Wall, FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_Overridable)]; + } + facecount++; + } + if (facecount != 3 && facecount != 6) + { + sc.ScriptError("%s: Skybox definition requires either 3 or 6 faces", sb->Name.GetChars()); + } + sb->SetSize(); + TexMan.AddTexture(sb); + } + + //=========================================================================== + // + // Reads glow definitions from GLDEFS + // + //=========================================================================== + + void ParseGlow() + { + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("FLATS")) + { + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Flat,FTextureManager::TEXMAN_TryAny); + FTexture *tex = TexMan[flump]; + if (tex) tex->gl_info.bAutoGlowing = tex->bGlowing = tex->gl_info.bFullbright = true; + } + } + else if (sc.Compare("WALLS")) + { + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Wall,FTextureManager::TEXMAN_TryAny); + FTexture *tex = TexMan[flump]; + if (tex) tex->gl_info.bAutoGlowing = tex->bGlowing = tex->gl_info.bFullbright = true; + } + } + else if (sc.Compare("TEXTURE")) + { + sc.SetCMode(true); + sc.MustGetString(); + FTextureID flump=TexMan.CheckForTexture(sc.String, ETextureType::Flat,FTextureManager::TEXMAN_TryAny); + FTexture *tex = TexMan[flump]; + sc.MustGetStringName(","); + sc.MustGetString(); + PalEntry color = V_GetColor(NULL, sc.String); + //sc.MustGetStringName(","); + //sc.MustGetNumber(); + if (sc.CheckString(",")) + { + if (sc.CheckNumber()) + { + if (tex) tex->gl_info.GlowHeight = sc.Number; + if (!sc.CheckString(",")) goto skip_fb; + } + + sc.MustGetStringName("fullbright"); + if (tex) tex->gl_info.bFullbright = true; + } + skip_fb: + sc.SetCMode(false); + + if (tex && color != 0) + { + tex->gl_info.bAutoGlowing = false; + tex->bGlowing = true; + tex->GlowColor = color; + } + } + } + } + + + //========================================================================== + // + // Parses a brightmap definition + // + //========================================================================== + + void ParseBrightmap() + { + ETextureType type = ETextureType::Any; + bool disable_fullbright=false; + bool thiswad = false; + bool iwad = false; + FTexture *bmtex = NULL; + + sc.MustGetString(); + if (sc.Compare("texture")) type = ETextureType::Wall; + else if (sc.Compare("flat")) type = ETextureType::Flat; + else if (sc.Compare("sprite")) type = ETextureType::Sprite; + else sc.UnGet(); + + sc.MustGetString(); + FTextureID no = TexMan.CheckForTexture(sc.String, type, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_Overridable); + FTexture *tex = TexMan[no]; + + sc.MustGetToken('{'); + while (!sc.CheckToken('}')) + { + sc.MustGetString(); + if (sc.Compare("disablefullbright")) + { + // This can also be used without a brightness map to disable + // fullbright in rotations that only use brightness maps on + // other angles. + disable_fullbright = true; + } + else if (sc.Compare("thiswad")) + { + // only affects textures defined in the WAD containing the definition file. + thiswad = true; + } + else if (sc.Compare ("iwad")) + { + // only affects textures defined in the IWAD. + iwad = true; + } + else if (sc.Compare ("map")) + { + sc.MustGetString(); + + if (bmtex != NULL) + { + Printf("Multiple brightmap definitions in texture %s\n", tex? tex->Name.GetChars() : "(null)"); + } + + bmtex = TexMan.FindTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny); + + if (bmtex == NULL) + Printf("Brightmap '%s' not found in texture '%s'\n", sc.String, tex? tex->Name.GetChars() : "(null)"); + } + } + if (!tex) + { + return; + } + if (thiswad || iwad) + { + bool useme = false; + int lumpnum = tex->GetSourceLump(); + + if (lumpnum != -1) + { + if (iwad && Wads.GetLumpFile(lumpnum) <= Wads.GetIwadNum()) useme = true; + if (thiswad && Wads.GetLumpFile(lumpnum) == workingLump) useme = true; + } + if (!useme) return; + } + + if (bmtex != NULL) + { + /* I do not think this is needed any longer + if (tex->bWarped != 0) + { + Printf("Cannot combine warping with brightmap on texture '%s'\n", tex->Name.GetChars()); + return; + } + */ + + bmtex->bMasked = false; + tex->Brightmap = bmtex; + } + tex->gl_info.bDisableFullbright = disable_fullbright; + } + + + //========================================================================== + // + // Parses a material definition + // + //========================================================================== + + void ParseMaterial() + { + ETextureType type = ETextureType::Any; + bool disable_fullbright = false; + bool disable_fullbright_specified = false; + bool thiswad = false; + bool iwad = false; + + FTexture *textures[6]; + const char *keywords[7] = { "brightmap", "normal", "specular", "metallic", "roughness", "ao", nullptr }; + const char *notFound[6] = { "Brightmap", "Normalmap", "Specular texture", "Metallic texture", "Roughness texture", "Ambient occlusion texture" }; + memset(textures, 0, sizeof(textures)); + + sc.MustGetString(); + if (sc.Compare("texture")) type = ETextureType::Wall; + else if (sc.Compare("flat")) type = ETextureType::Flat; + else if (sc.Compare("sprite")) type = ETextureType::Sprite; + else sc.UnGet(); + + sc.MustGetString(); + FTextureID no = TexMan.CheckForTexture(sc.String, type, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_Overridable); + FTexture *tex = TexMan[no]; + + sc.MustGetToken('{'); + while (!sc.CheckToken('}')) + { + sc.MustGetString(); + if (sc.Compare("disablefullbright")) + { + // This can also be used without a brightness map to disable + // fullbright in rotations that only use brightness maps on + // other angles. + disable_fullbright = true; + disable_fullbright_specified = true; + } + else if (sc.Compare("thiswad")) + { + // only affects textures defined in the WAD containing the definition file. + thiswad = true; + } + else if (sc.Compare ("iwad")) + { + // only affects textures defined in the IWAD. + iwad = true; + } + else if (sc.Compare("glossiness")) + { + sc.MustGetFloat(); + if (tex) + tex->gl_info.Glossiness = (float)sc.Float; + } + else if (sc.Compare("specularlevel")) + { + sc.MustGetFloat(); + if (tex) + tex->gl_info.SpecularLevel = (float)sc.Float; + } + else + { + for (int i = 0; keywords[i] != nullptr; i++) + { + if (sc.Compare (keywords[i])) + { + sc.MustGetString(); + if (textures[i]) + Printf("Multiple %s definitions in texture %s\n", keywords[i], tex? tex->Name.GetChars() : "(null)"); + textures[i] = TexMan.FindTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_TryAny); + if (!textures[i]) + Printf("%s '%s' not found in texture '%s'\n", notFound[i], sc.String, tex? tex->Name.GetChars() : "(null)"); + break; + } + } + } + } + if (!tex) + { + return; + } + if (thiswad || iwad) + { + bool useme = false; + int lumpnum = tex->GetSourceLump(); + + if (lumpnum != -1) + { + if (iwad && Wads.GetLumpFile(lumpnum) <= Wads.GetIwadNum()) useme = true; + if (thiswad && Wads.GetLumpFile(lumpnum) == workingLump) useme = true; + } + if (!useme) return; + } + + FTexture **bindings[6] = + { + &tex->Brightmap, + &tex->Normal, + &tex->Specular, + &tex->Metallic, + &tex->Roughness, + &tex->AmbientOcclusion + }; + for (int i = 0; keywords[i] != nullptr; i++) + { + if (textures[i]) + { + textures[i]->bMasked = false; + *bindings[i] = textures[i]; + } + } + + if (disable_fullbright_specified) + tex->gl_info.bDisableFullbright = disable_fullbright; + } + + + //========================================================================== + // + // Parses a shader definition + // + //========================================================================== + + void ParseHardwareShader() + { + sc.MustGetString(); + if (sc.Compare("postprocess")) + { + sc.MustGetString(); + + PostProcessShader shaderdesc; + shaderdesc.Target = sc.String; + shaderdesc.Target.ToLower(); + + bool validTarget = false; + if (sc.Compare("beforebloom")) validTarget = true; + if (sc.Compare("scene")) validTarget = true; + if (sc.Compare("screen")) validTarget = true; + if (!validTarget) + sc.ScriptError("Invalid target '%s' for postprocess shader",sc.String); + + sc.MustGetToken('{'); + while (!sc.CheckToken('}')) + { + sc.MustGetString(); + if (sc.Compare("shader")) + { + sc.MustGetString(); + shaderdesc.ShaderLumpName = sc.String; + + sc.MustGetNumber(); + shaderdesc.ShaderVersion = sc.Number; + if (sc.Number > 450 || sc.Number < 330) + sc.ScriptError("Shader version must be in range 330 to 450!"); + } + else if (sc.Compare("name")) + { + sc.MustGetString(); + shaderdesc.Name = sc.String; + } + else if (sc.Compare("uniform")) + { + sc.MustGetString(); + FString uniformType = sc.String; + uniformType.ToLower(); + + sc.MustGetString(); + FString uniformName = sc.String; + + PostProcessUniformType parsedType = PostProcessUniformType::Undefined; + + if (uniformType.Compare("int") == 0) + parsedType = PostProcessUniformType::Int; + else if (uniformType.Compare("float") == 0) + parsedType = PostProcessUniformType::Float; + else if (uniformType.Compare("vec2") == 0) + parsedType = PostProcessUniformType::Vec2; + else if (uniformType.Compare("vec3") == 0) + parsedType = PostProcessUniformType::Vec3; + else + sc.ScriptError("Unrecognized uniform type '%s'", sc.String); + + if (parsedType != PostProcessUniformType::Undefined) + shaderdesc.Uniforms[uniformName].Type = parsedType; + } + else if (sc.Compare("texture")) + { + sc.MustGetString(); + FString textureName = sc.String; + + sc.MustGetString(); + FString textureSource = sc.String; + + shaderdesc.Textures[textureName] = textureSource; + } + else if (sc.Compare("enabled")) + { + shaderdesc.Enabled = true; + } + else + { + sc.ScriptError("Unknown keyword '%s'", sc.String); + } + } + + PostProcessShaders.Push(shaderdesc); + } + else + { + ETextureType type = ETextureType::Any; + + if (sc.Compare("texture")) type = ETextureType::Wall; + else if (sc.Compare("flat")) type = ETextureType::Flat; + else if (sc.Compare("sprite")) type = ETextureType::Sprite; + else sc.UnGet(); + + bool disable_fullbright = false; + bool thiswad = false; + bool iwad = false; + int maplump = -1; + FString maplumpname; + float speed = 1.f; + + sc.MustGetString(); + FTextureID no = TexMan.CheckForTexture(sc.String, type); + FTexture *tex = TexMan[no]; + + sc.MustGetToken('{'); + while (!sc.CheckToken('}')) + { + sc.MustGetString(); + if (sc.Compare("shader")) + { + sc.MustGetString(); + maplumpname = sc.String; + } + else if (sc.Compare("speed")) + { + sc.MustGetFloat(); + speed = float(sc.Float); + } + } + if (!tex) + { + return; + } + + if (maplumpname.IsNotEmpty()) + { + if (tex->bWarped != 0) + { + Printf("Cannot combine warping with hardware shader on texture '%s'\n", tex->Name.GetChars()); + return; + } + tex->gl_info.shaderspeed = speed; + for (unsigned i = 0; i < usershaders.Size(); i++) + { + if (!usershaders[i].CompareNoCase(maplumpname)) + { + tex->gl_info.shaderindex = i + FIRST_USER_SHADER; + return; + } + } + tex->gl_info.shaderindex = usershaders.Push(maplumpname) + FIRST_USER_SHADER; + } + } + } + + + +public: + //========================================================================== + // + // + // + //========================================================================== + void DoParseDefs() + { + int recursion=0; + int lump, type; + + // Get actor class name. + while (true) + { + sc.SavePos(); + if (!sc.GetToken ()) + { + return; + } + type = sc.MatchString(CoreKeywords); + switch (type) + { + case TAG_INCLUDE: + { + sc.MustGetString(); + // This is not using sc.Open because it can print a more useful error message when done here + lump = Wads.CheckNumForFullName(sc.String, true); + if (lump==-1) + sc.ScriptError("Lump '%s' not found", sc.String); + + GLDefsParser newscanner(lump, LightAssociations); + newscanner.DoParseDefs(); + break; + } + case LIGHT_POINT: + ParsePointLight(); + break; + case LIGHT_PULSE: + ParsePulseLight(); + break; + case LIGHT_FLICKER: + ParseFlickerLight(); + break; + case LIGHT_FLICKER2: + ParseFlickerLight2(); + break; + case LIGHT_SECTOR: + ParseSectorLight(); + break; + case LIGHT_OBJECT: + ParseObject(); + break; + case LIGHT_CLEAR: + // This has been intentionally removed + break; + case TAG_SHADER: + ParseShader(); + break; + case TAG_CLEARSHADERS: + break; + case TAG_SKYBOX: + ParseGldefSkybox(); + break; + case TAG_GLOW: + ParseGlow(); + break; + case TAG_BRIGHTMAP: + ParseBrightmap(); + break; + case TAG_MATERIAL: + ParseMaterial(); + break; + case TAG_HARDWARESHADER: + ParseHardwareShader(); + break; + case TAG_DETAIL: + ParseDetailTexture(); + break; + case TAG_DISABLE_FB: + { + /* not implemented. + sc.MustGetString(); + const PClass *cls = PClass::FindClass(sc.String); + if (cls) GetDefaultByType(cls)->renderflags |= RF_NEVERFULLBRIGHT; + */ + } + break; + default: + sc.ScriptError("Error parsing defs. Unknown tag: %s.\n", sc.String); + break; + } + } + } + + GLDefsParser(int lumpnum, TArray &la) + : sc(lumpnum), workingLump(lumpnum), LightAssociations(la) + { + } +}; + +//========================================================================== +// +// +// +//========================================================================== + +void LoadGLDefs(const char *defsLump) +{ + TArray LightAssociations; + int workingLump, lastLump; + static const char *gldefsnames[] = { "GLDEFS", defsLump, nullptr }; + + lastLump = 0; + while ((workingLump = Wads.FindLumpMulti(gldefsnames, &lastLump)) != -1) + { + GLDefsParser sc(workingLump, LightAssociations); + sc.DoParseDefs(); + } + InitializeActorLights(LightAssociations); +} + + +//========================================================================== +// +// +// +//========================================================================== + +void ParseGLDefs() +{ + const char *defsLump = NULL; + + LightDefaults.Clear(); + //gl_DestroyUserShaders(); function says 'todo' + switch (gameinfo.gametype) + { + case GAME_Heretic: + defsLump = "HTICDEFS"; + break; + case GAME_Hexen: + defsLump = "HEXNDEFS"; + break; + case GAME_Strife: + defsLump = "STRFDEFS"; + break; + case GAME_Doom: + defsLump = "DOOMDEFS"; + break; + case GAME_Chex: + defsLump = "CHEXDEFS"; + break; + default: // silence GCC + break; + } + ParseVavoomSkybox(); + LoadGLDefs(defsLump); +} diff --git a/src/textures/skyboxtexture.cpp b/src/textures/skyboxtexture.cpp index c851a91a11..f5d8450b2a 100644 --- a/src/textures/skyboxtexture.cpp +++ b/src/textures/skyboxtexture.cpp @@ -108,96 +108,5 @@ bool FSkyBox::UseBasePalette() void FSkyBox::Unload () { - //for(int i=0;i<6;i++) if (faces[i]) faces[i]->Unload(); -} - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -void ParseGldefSkybox(FScanner &sc) -{ - int facecount=0; - - sc.MustGetString(); - - FSkyBox * sb = new FSkyBox; - sb->Name = sc.String; - sb->Name.ToUpper(); - if (sc.CheckString("fliptop")) - { - sb->fliptop = true; - } - sc.MustGetStringName("{"); - while (!sc.CheckString("}")) - { - sc.MustGetString(); - if (facecount<6) - { - sb->faces[facecount] = TexMan[TexMan.GetTexture(sc.String, ETextureType::Wall, FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_Overridable)]; - } - facecount++; - } - if (facecount != 3 && facecount != 6) - { - sc.ScriptError("%s: Skybox definition requires either 3 or 6 faces", sb->Name.GetChars()); - } - sb->SetSize(); - TexMan.AddTexture(sb); -} - -//----------------------------------------------------------------------------- -// -// gl_ParseVavoomSkybox -// -//----------------------------------------------------------------------------- - -void ParseVavoomSkybox() -{ - int lump = Wads.CheckNumForName("SKYBOXES"); - - if (lump < 0) return; - - FScanner sc(lump); - while (sc.GetString()) - { - int facecount=0; - int maplump = -1; - bool error = false; - FSkyBox * sb = new FSkyBox; - sb->Name = sc.String; - sb->Name.ToUpper(); - sb->fliptop = true; - sc.MustGetStringName("{"); - while (!sc.CheckString("}")) - { - if (facecount<6) - { - sc.MustGetStringName("{"); - sc.MustGetStringName("map"); - sc.MustGetString(); - - maplump = Wads.CheckNumForFullName(sc.String, true); - - FTexture *tex = TexMan.FindTexture(sc.String, ETextureType::Wall, FTextureManager::TEXMAN_TryAny); - if (tex == NULL) - { - sc.ScriptMessage("Texture '%s' not found in Vavoom skybox '%s'\n", sc.String, sb->Name.GetChars()); - error = true; - } - sb->faces[facecount] = tex; - sc.MustGetStringName("}"); - } - facecount++; - } - if (facecount != 6) - { - sc.ScriptError("%s: Skybox definition requires 6 faces", sb->Name.GetChars()); - } - sb->SetSize(); - if (!error) TexMan.AddTexture(sb); - } } diff --git a/src/textures/textures.h b/src/textures/textures.h index c42a1124d1..566097e773 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -44,6 +44,29 @@ #include "r_data/r_translate.h" #include +enum MaterialShaderIndex +{ + SHADER_Default, + SHADER_Warp1, + SHADER_Warp2, + SHADER_Brightmap, + SHADER_Specular, + SHADER_SpecularBrightmap, + SHADER_PBR, + SHADER_PBRBrightmap, + SHADER_NoTexture, + SHADER_BasicFuzz, + SHADER_SmoothFuzz, + SHADER_SwirlyFuzz, + SHADER_TranslucentFuzz, + SHADER_JaggedFuzz, + SHADER_NoiseFuzz, + SHADER_SmoothNoiseFuzz, + SHADER_SoftwareFuzz, + FIRST_USER_SHADER +}; + + struct FloatRect { float left,top; diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 019b01e7e8..3e4b88d1a7 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1351,7 +1351,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n _CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF); // Use this to break at a specific allocation number. - //_crtBreakAlloc = 53039; + _crtBreakAlloc = 177312; #endif DoMain (hInstance);