mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 13:50:48 +00:00
Merge remote-tracking branch 'remotes/origin/materials'
This commit is contained in:
commit
b327aa737a
35 changed files with 1046 additions and 319 deletions
|
@ -56,6 +56,7 @@
|
||||||
int ScriptDepth;
|
int ScriptDepth;
|
||||||
void gl_InitGlow(FScanner &sc);
|
void gl_InitGlow(FScanner &sc);
|
||||||
void gl_ParseBrightmap(FScanner &sc, int);
|
void gl_ParseBrightmap(FScanner &sc, int);
|
||||||
|
void gl_ParseMaterial(FScanner &sc, int);
|
||||||
void gl_DestroyUserShaders();
|
void gl_DestroyUserShaders();
|
||||||
void gl_ParseHardwareShader(FScanner &sc, int deflump);
|
void gl_ParseHardwareShader(FScanner &sc, int deflump);
|
||||||
void gl_ParseDetailTexture(FScanner &sc);
|
void gl_ParseDetailTexture(FScanner &sc);
|
||||||
|
@ -963,7 +964,8 @@ static const char *CoreKeywords[]=
|
||||||
"hardwareshader",
|
"hardwareshader",
|
||||||
"detail",
|
"detail",
|
||||||
"#include",
|
"#include",
|
||||||
NULL
|
"material",
|
||||||
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -985,6 +987,7 @@ enum
|
||||||
TAG_HARDWARESHADER,
|
TAG_HARDWARESHADER,
|
||||||
TAG_DETAIL,
|
TAG_DETAIL,
|
||||||
TAG_INCLUDE,
|
TAG_INCLUDE,
|
||||||
|
TAG_MATERIAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1342,6 +1345,9 @@ static void DoParseDefs(FScanner &sc, int workingLump)
|
||||||
case TAG_BRIGHTMAP:
|
case TAG_BRIGHTMAP:
|
||||||
gl_ParseBrightmap(sc, workingLump);
|
gl_ParseBrightmap(sc, workingLump);
|
||||||
break;
|
break;
|
||||||
|
case TAG_MATERIAL:
|
||||||
|
gl_ParseMaterial(sc, workingLump);
|
||||||
|
break;
|
||||||
case TAG_HARDWARESHADER:
|
case TAG_HARDWARESHADER:
|
||||||
gl_ParseHardwareShader(sc, workingLump);
|
gl_ParseHardwareShader(sc, workingLump);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -68,7 +68,7 @@ CUSTOM_CVAR(Bool, gl_notexturefill, false, 0)
|
||||||
|
|
||||||
|
|
||||||
void gl_CreateSections();
|
void gl_CreateSections();
|
||||||
void AddAutoBrightmaps();
|
void AddAutoMaterials();
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -364,7 +364,7 @@ void gl_RecalcVertexHeights(vertex_t * v)
|
||||||
void gl_InitData()
|
void gl_InitData()
|
||||||
{
|
{
|
||||||
AdjustSpriteOffsets();
|
AdjustSpriteOffsets();
|
||||||
AddAutoBrightmaps();
|
AddAutoMaterials();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -87,6 +87,8 @@ void FRenderState::Reset()
|
||||||
mSpecialEffect = EFF_NONE;
|
mSpecialEffect = EFF_NONE;
|
||||||
mClipHeight = 0.f;
|
mClipHeight = 0.f;
|
||||||
mClipHeightDirection = 0.f;
|
mClipHeightDirection = 0.f;
|
||||||
|
mGlossiness = 0.0f;
|
||||||
|
mSpecularLevel = 0.0f;
|
||||||
mShaderTimer = 0.0f;
|
mShaderTimer = 0.0f;
|
||||||
ClearClipSplit();
|
ClearClipSplit();
|
||||||
|
|
||||||
|
@ -137,7 +139,7 @@ bool FRenderState::ApplyShader()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : 4, mAlphaThreshold >= 0.f, mPassType);
|
activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : SHADER_NoTexture, mAlphaThreshold >= 0.f, mPassType);
|
||||||
activeShader->Bind();
|
activeShader->Bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +180,7 @@ bool FRenderState::ApplyShader()
|
||||||
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
|
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
|
||||||
activeShader->muClipSplit.Set(mClipSplit);
|
activeShader->muClipSplit.Set(mClipSplit);
|
||||||
activeShader->muViewHeight.Set(viewheight);
|
activeShader->muViewHeight.Set(viewheight);
|
||||||
|
activeShader->muSpecularMaterial.Set(mGlossiness, mSpecularLevel);
|
||||||
|
|
||||||
if (mGlowEnabled)
|
if (mGlowEnabled)
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,6 +94,7 @@ class FRenderState
|
||||||
bool mLastDepthClamp;
|
bool mLastDepthClamp;
|
||||||
float mInterpolationFactor;
|
float mInterpolationFactor;
|
||||||
float mClipHeight, mClipHeightDirection;
|
float mClipHeight, mClipHeightDirection;
|
||||||
|
float mGlossiness, mSpecularLevel;
|
||||||
float mShaderTimer;
|
float mShaderTimer;
|
||||||
|
|
||||||
FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer;
|
FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer;
|
||||||
|
@ -161,6 +162,7 @@ public:
|
||||||
}
|
}
|
||||||
mEffectState = overrideshader >= 0? overrideshader : mat->mShaderIndex;
|
mEffectState = overrideshader >= 0? overrideshader : mat->mShaderIndex;
|
||||||
mShaderTimer = mat->tex->gl_info.shaderspeed;
|
mShaderTimer = mat->tex->gl_info.shaderspeed;
|
||||||
|
SetSpecular(mat->tex->gl_info.Glossiness, mat->tex->gl_info.SpecularLevel);
|
||||||
mat->Bind(clampmode, translation);
|
mat->Bind(clampmode, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,6 +397,12 @@ public:
|
||||||
mObjectColor2 = pe;
|
mObjectColor2 = pe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetSpecular(float glossiness, float specularLevel)
|
||||||
|
{
|
||||||
|
mGlossiness = glossiness;
|
||||||
|
mSpecularLevel = specularLevel;
|
||||||
|
}
|
||||||
|
|
||||||
void SetFog(PalEntry c, float d)
|
void SetFog(PalEntry c, float d)
|
||||||
{
|
{
|
||||||
const float LOG2E = 1.442692f; // = 1/log(2)
|
const float LOG2E = 1.442692f; // = 1/log(2)
|
||||||
|
|
|
@ -331,6 +331,8 @@ void GLSceneDrawer::RenderScene(int recursion)
|
||||||
gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(GLPASS_LIGHTSONLY);
|
gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(GLPASS_LIGHTSONLY);
|
||||||
gl_drawinfo->drawlists[GLDL_TRANSLUCENTBORDER].Draw(GLPASS_LIGHTSONLY);
|
gl_drawinfo->drawlists[GLDL_TRANSLUCENTBORDER].Draw(GLPASS_LIGHTSONLY);
|
||||||
gl_drawinfo->drawlists[GLDL_TRANSLUCENT].Draw(GLPASS_LIGHTSONLY, true);
|
gl_drawinfo->drawlists[GLDL_TRANSLUCENT].Draw(GLPASS_LIGHTSONLY, true);
|
||||||
|
gl_drawinfo->drawlists[GLDL_MODELS].Draw(GLPASS_LIGHTSONLY);
|
||||||
|
SetupWeaponLight();
|
||||||
GLRenderer->mLights->Finish();
|
GLRenderer->mLights->Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@ class GLSceneDrawer
|
||||||
subsector_t *currentsubsector; // used by the line processing code.
|
subsector_t *currentsubsector; // used by the line processing code.
|
||||||
sector_t *currentsector;
|
sector_t *currentsector;
|
||||||
|
|
||||||
|
TMap<DPSprite*, int> weapondynlightindex;
|
||||||
|
|
||||||
|
void SetupWeaponLight();
|
||||||
|
|
||||||
void RenderMultipassStuff();
|
void RenderMultipassStuff();
|
||||||
|
|
||||||
void UnclipSubsector(subsector_t *sub);
|
void UnclipSubsector(subsector_t *sub);
|
||||||
|
|
|
@ -82,6 +82,7 @@ EXTERN_CVAR (Bool, r_debug_disable_vis_filter)
|
||||||
extern TArray<spritedef_t> sprites;
|
extern TArray<spritedef_t> sprites;
|
||||||
extern TArray<spriteframe_t> SpriteFrames;
|
extern TArray<spriteframe_t> SpriteFrames;
|
||||||
extern uint32_t r_renderercaps;
|
extern uint32_t r_renderercaps;
|
||||||
|
extern int modellightindex;
|
||||||
|
|
||||||
enum HWRenderStyle
|
enum HWRenderStyle
|
||||||
{
|
{
|
||||||
|
@ -263,7 +264,25 @@ void GLSprite::CalculateVertices(FVector3 *v)
|
||||||
|
|
||||||
void GLSprite::Draw(int pass)
|
void GLSprite::Draw(int pass)
|
||||||
{
|
{
|
||||||
if (pass == GLPASS_DECALS || pass == GLPASS_LIGHTSONLY) return;
|
if (pass == GLPASS_DECALS) return;
|
||||||
|
|
||||||
|
if (pass == GLPASS_LIGHTSONLY)
|
||||||
|
{
|
||||||
|
if (modelframe)
|
||||||
|
{
|
||||||
|
if (RenderStyle.BlendOp != STYLEOP_Shadow)
|
||||||
|
{
|
||||||
|
if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright)
|
||||||
|
{
|
||||||
|
if (!particle)
|
||||||
|
{
|
||||||
|
dynlightindex = gl_SetDynModelLight(gl_light_sprites ? actor : nullptr, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool additivefog = false;
|
bool additivefog = false;
|
||||||
bool foglayer = false;
|
bool foglayer = false;
|
||||||
|
@ -336,7 +355,7 @@ void GLSprite::Draw(int pass)
|
||||||
if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright)
|
if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright)
|
||||||
{
|
{
|
||||||
if (modelframe && !particle)
|
if (modelframe && !particle)
|
||||||
gl_SetDynModelLight(gl_light_sprites ? actor : NULL);
|
gl_SetDynModelLight(gl_light_sprites ? actor : NULL, dynlightindex);
|
||||||
else
|
else
|
||||||
gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL);
|
gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL);
|
||||||
}
|
}
|
||||||
|
@ -990,7 +1009,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
|
||||||
if (gl_fuzztype != 0 && !gl.legacyMode && !(RenderStyle.Flags & STYLEF_InvertSource))
|
if (gl_fuzztype != 0 && !gl.legacyMode && !(RenderStyle.Flags & STYLEF_InvertSource))
|
||||||
{
|
{
|
||||||
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||||
OverrideShader = gl_fuzztype + 4;
|
OverrideShader = SHADER_NoTexture + gl_fuzztype;
|
||||||
trans = 0.99f; // trans may not be 1 here
|
trans = 0.99f; // trans may not be 1 here
|
||||||
hw_styleflags = STYLEHW_NoAlphaTest;
|
hw_styleflags = STYLEHW_NoAlphaTest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,13 +198,21 @@ void BSPWalkCircle(float x, float y, float radiusSquared, const Callback &callba
|
||||||
BSPNodeWalkCircle(level.HeadNode(), x, y, radiusSquared, callback);
|
BSPNodeWalkCircle(level.HeadNode(), x, y, radiusSquared, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gl_SetDynModelLight(AActor *self)
|
int gl_SetDynModelLight(AActor *self, int dynlightindex)
|
||||||
{
|
{
|
||||||
// Legacy and deferred render paths gets the old flat model light
|
// For deferred light mode this function gets called twice. First time for list upload, and second for draw.
|
||||||
if (gl.lightmethod != LM_DIRECT)
|
if (gl.lightmethod == LM_DEFERRED && dynlightindex != -1)
|
||||||
|
{
|
||||||
|
gl_RenderState.SetDynLight(0, 0, 0);
|
||||||
|
modellightindex = dynlightindex;
|
||||||
|
return dynlightindex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy render path gets the old flat model light
|
||||||
|
if (gl.lightmethod == LM_LEGACY)
|
||||||
{
|
{
|
||||||
gl_SetDynSpriteLight(self, nullptr);
|
gl_SetDynSpriteLight(self, nullptr);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
modellightdata.Clear();
|
modellightdata.Clear();
|
||||||
|
@ -249,6 +257,12 @@ void gl_SetDynModelLight(AActor *self)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_RenderState.SetDynLight(0, 0, 0);
|
dynlightindex = GLRenderer->mLights->UploadLights(modellightdata);
|
||||||
modellightindex = GLRenderer->mLights->UploadLights(modellightdata);
|
|
||||||
|
if (gl.lightmethod != LM_DEFERRED)
|
||||||
|
{
|
||||||
|
gl_RenderState.SetDynLight(0, 0, 0);
|
||||||
|
modellightindex = dynlightindex;
|
||||||
|
}
|
||||||
|
return dynlightindex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,6 +392,8 @@ public:
|
||||||
TArray<lightlist_t> *lightlist;
|
TArray<lightlist_t> *lightlist;
|
||||||
DRotator Angles;
|
DRotator Angles;
|
||||||
|
|
||||||
|
int dynlightindex;
|
||||||
|
|
||||||
void SplitSprite(sector_t * frontsector, bool translucent);
|
void SplitSprite(sector_t * frontsector, bool translucent);
|
||||||
void SetLowerParam();
|
void SetLowerParam();
|
||||||
void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight);
|
void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight);
|
||||||
|
@ -422,6 +424,6 @@ inline float Dist2(float x1,float y1,float x2,float y2)
|
||||||
|
|
||||||
void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec);
|
void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *subsec);
|
||||||
void gl_SetDynSpriteLight(AActor *actor, particle_t *particle);
|
void gl_SetDynSpriteLight(AActor *actor, particle_t *particle);
|
||||||
void gl_SetDynModelLight(AActor *self);
|
int gl_SetDynModelLight(AActor *self, int dynlightindex);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -183,6 +183,39 @@ static bool isBright(DPSprite *psp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLSceneDrawer::SetupWeaponLight()
|
||||||
|
{
|
||||||
|
weapondynlightindex.Clear();
|
||||||
|
|
||||||
|
AActor *camera = r_viewpoint.camera;
|
||||||
|
AActor * playermo = players[consoleplayer].camera;
|
||||||
|
player_t * player = playermo->player;
|
||||||
|
|
||||||
|
// this is the same as in DrawPlayerSprites below
|
||||||
|
if (!player ||
|
||||||
|
!r_drawplayersprites ||
|
||||||
|
!camera->player ||
|
||||||
|
(player->cheats & CF_CHASECAM) ||
|
||||||
|
(r_deathcamera && camera->health <= 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext())
|
||||||
|
{
|
||||||
|
if (psp->GetState() != nullptr)
|
||||||
|
{
|
||||||
|
// set the lighting parameters
|
||||||
|
if (gl_lights && GLRenderer->mLightCount && FixedColormap == CM_DEFAULT && gl_light_sprites)
|
||||||
|
{
|
||||||
|
FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr;
|
||||||
|
if (smf)
|
||||||
|
{
|
||||||
|
weapondynlightindex[psp] = gl_SetDynModelLight(playermo, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// R_DrawPlayerSprites
|
// R_DrawPlayerSprites
|
||||||
|
@ -355,7 +388,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
||||||
{
|
{
|
||||||
// Todo: implement shader selection here
|
// Todo: implement shader selection here
|
||||||
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||||
OverrideShader = gl_fuzztype + 4;
|
OverrideShader = SHADER_NoTexture + gl_fuzztype;
|
||||||
trans = 0.99f; // trans may not be 1 here
|
trans = 0.99f; // trans may not be 1 here
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -422,7 +455,7 @@ void GLSceneDrawer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
||||||
{
|
{
|
||||||
FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr;
|
FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr;
|
||||||
if (smf)
|
if (smf)
|
||||||
gl_SetDynModelLight(playermo);
|
gl_SetDynModelLight(playermo, weapondynlightindex[psp]);
|
||||||
else
|
else
|
||||||
gl_SetDynSpriteLight(playermo, NULL);
|
gl_SetDynSpriteLight(playermo, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,20 +52,202 @@
|
||||||
#include "gl/textures/gl_material.h"
|
#include "gl/textures/gl_material.h"
|
||||||
#include "gl/dynlights/gl_lightbuffer.h"
|
#include "gl/dynlights/gl_lightbuffer.h"
|
||||||
|
|
||||||
//==========================================================================
|
static bool IsGlslWhitespace(char c)
|
||||||
//
|
{
|
||||||
//
|
switch (c)
|
||||||
//
|
{
|
||||||
//==========================================================================
|
case ' ':
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
case '\t':
|
||||||
|
case '\f':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool FShader::Load(const char * name, const char * vert_prog_lump, const char * frag_prog_lump, const char * proc_prog_lump, const char * defines)
|
static FString NextGlslToken(const char *chars, long len, long &pos)
|
||||||
|
{
|
||||||
|
// Eat whitespace
|
||||||
|
long tokenStart = pos;
|
||||||
|
while (tokenStart != len && IsGlslWhitespace(chars[tokenStart]))
|
||||||
|
tokenStart++;
|
||||||
|
|
||||||
|
// Find token end
|
||||||
|
long tokenEnd = tokenStart;
|
||||||
|
while (tokenEnd != len && !IsGlslWhitespace(chars[tokenEnd]) && chars[tokenEnd] != ';')
|
||||||
|
tokenEnd++;
|
||||||
|
|
||||||
|
pos = tokenEnd;
|
||||||
|
return FString(chars + tokenStart, tokenEnd - tokenStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FString RemoveLegacyUserUniforms(FString code)
|
||||||
|
{
|
||||||
|
// User shaders must declare their uniforms via the GLDEFS file.
|
||||||
|
// The following code searches for legacy uniform declarations in the shader itself and replaces them with whitespace.
|
||||||
|
|
||||||
|
long len = (long)code.Len();
|
||||||
|
char *chars = code.LockBuffer();
|
||||||
|
|
||||||
|
long startIndex = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
long matchIndex = code.IndexOf("uniform", startIndex);
|
||||||
|
if (matchIndex == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bool isLegacyUniformName = false;
|
||||||
|
|
||||||
|
bool isKeywordStart = matchIndex == 0 || IsGlslWhitespace(chars[matchIndex - 1]);
|
||||||
|
bool isKeywordEnd = matchIndex + 7 == len || IsGlslWhitespace(chars[matchIndex + 7]);
|
||||||
|
if (isKeywordStart && isKeywordEnd)
|
||||||
|
{
|
||||||
|
long pos = matchIndex + 7;
|
||||||
|
FString type = NextGlslToken(chars, len, pos);
|
||||||
|
FString identifier = NextGlslToken(chars, len, pos);
|
||||||
|
|
||||||
|
isLegacyUniformName = type.Compare("float") == 0 && identifier.Compare("timer") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLegacyUniformName)
|
||||||
|
{
|
||||||
|
long statementEndIndex = code.IndexOf(';', matchIndex + 7);
|
||||||
|
if (statementEndIndex == -1)
|
||||||
|
statementEndIndex = len;
|
||||||
|
for (long i = matchIndex; i <= statementEndIndex; i++)
|
||||||
|
{
|
||||||
|
if (!IsGlslWhitespace(chars[i]))
|
||||||
|
chars[i] = ' ';
|
||||||
|
}
|
||||||
|
startIndex = statementEndIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startIndex = matchIndex + 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code.UnlockBuffer();
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FShader::Load(const char * name, const char * vert_prog_lump, const char * frag_prog_lump, const char * proc_prog_lump, const char * light_fragprog, const char * defines)
|
||||||
{
|
{
|
||||||
static char buffer[10000];
|
static char buffer[10000];
|
||||||
FString error;
|
FString error;
|
||||||
|
|
||||||
int i_lump = Wads.CheckNumForFullName("shaders/glsl/shaderdefs.i", 0);
|
FString i_data;
|
||||||
if (i_lump == -1) I_Error("Unable to load 'shaders/glsl/shaderdefs.i'");
|
|
||||||
FMemLump i_data = Wads.ReadLump(i_lump);
|
// these settings are actually pointless but there seem to be some old ATI drivers that fail to compile the shader without setting the precision here.
|
||||||
|
i_data += "precision highp int;\n";
|
||||||
|
i_data += "precision highp float;\n";
|
||||||
|
|
||||||
|
i_data += "uniform vec4 uCameraPos;\n";
|
||||||
|
i_data += "uniform int uTextureMode;\n";
|
||||||
|
i_data += "uniform float uClipHeight;\n";
|
||||||
|
i_data += "uniform float uClipHeightDirection;\n";
|
||||||
|
i_data += "uniform vec2 uClipSplit;\n";
|
||||||
|
i_data += "uniform vec4 uClipLine;\n";
|
||||||
|
i_data += "uniform float uAlphaThreshold;\n";
|
||||||
|
|
||||||
|
// colors
|
||||||
|
i_data += "uniform vec4 uObjectColor;\n";
|
||||||
|
i_data += "uniform vec4 uObjectColor2;\n";
|
||||||
|
i_data += "uniform vec4 uDynLightColor;\n";
|
||||||
|
i_data += "uniform vec4 uFogColor;\n";
|
||||||
|
i_data += "uniform float uDesaturationFactor;\n";
|
||||||
|
i_data += "uniform float uInterpolationFactor;\n";
|
||||||
|
|
||||||
|
// Fixed colormap stuff
|
||||||
|
i_data += "uniform int uFixedColormap;\n"; // 0, when no fixed colormap, 1 for a light value, 2 for a color blend, 3 for a fog layer
|
||||||
|
i_data += "uniform vec4 uFixedColormapStart;\n";
|
||||||
|
i_data += "uniform vec4 uFixedColormapRange;\n";
|
||||||
|
|
||||||
|
// Glowing walls stuff
|
||||||
|
i_data += "uniform vec4 uGlowTopPlane;\n";
|
||||||
|
i_data += "uniform vec4 uGlowTopColor;\n";
|
||||||
|
i_data += "uniform vec4 uGlowBottomPlane;\n";
|
||||||
|
i_data += "uniform vec4 uGlowBottomColor;\n";
|
||||||
|
|
||||||
|
i_data += "uniform vec4 uSplitTopPlane;\n";
|
||||||
|
i_data += "uniform vec4 uSplitBottomPlane;\n";
|
||||||
|
|
||||||
|
// Lighting + Fog
|
||||||
|
i_data += "uniform vec4 uLightAttr;\n";
|
||||||
|
i_data += "#define uLightLevel uLightAttr.a\n";
|
||||||
|
i_data += "#define uFogDensity uLightAttr.b\n";
|
||||||
|
i_data += "#define uLightFactor uLightAttr.g\n";
|
||||||
|
i_data += "#define uLightDist uLightAttr.r\n";
|
||||||
|
i_data += "uniform int uFogEnabled;\n";
|
||||||
|
i_data += "uniform int uPalLightLevels;\n";
|
||||||
|
i_data += "uniform float uGlobVis;\n"; // uGlobVis = R_GetGlobVis(r_visibility) / 32.0
|
||||||
|
|
||||||
|
// dynamic lights
|
||||||
|
i_data += "uniform int uLightIndex;\n";
|
||||||
|
|
||||||
|
// Software fuzz scaling
|
||||||
|
i_data += "uniform int uViewHeight;\n";
|
||||||
|
|
||||||
|
// Blinn glossiness and specular level
|
||||||
|
i_data += "uniform vec2 uSpecularMaterial;\n";
|
||||||
|
|
||||||
|
// quad drawer stuff
|
||||||
|
i_data += "#ifdef USE_QUAD_DRAWER\n";
|
||||||
|
i_data += "uniform mat4 uQuadVertices;\n";
|
||||||
|
i_data += "uniform mat4 uQuadTexCoords;\n";
|
||||||
|
i_data += "uniform int uQuadMode;\n";
|
||||||
|
i_data += "#endif\n";
|
||||||
|
|
||||||
|
// matrices
|
||||||
|
i_data += "uniform mat4 ProjectionMatrix;\n";
|
||||||
|
i_data += "uniform mat4 ViewMatrix;\n";
|
||||||
|
i_data += "uniform mat4 ModelMatrix;\n";
|
||||||
|
i_data += "uniform mat4 NormalViewMatrix;\n";
|
||||||
|
i_data += "uniform mat4 NormalModelMatrix;\n";
|
||||||
|
i_data += "uniform mat4 TextureMatrix;\n";
|
||||||
|
|
||||||
|
// light buffers
|
||||||
|
i_data += "#ifdef SHADER_STORAGE_LIGHTS\n";
|
||||||
|
i_data += "layout(std430, binding = 1) buffer LightBufferSSO\n";
|
||||||
|
i_data += "{\n";
|
||||||
|
i_data += " vec4 lights[];\n";
|
||||||
|
i_data += "};\n";
|
||||||
|
i_data += "#elif defined NUM_UBO_LIGHTS\n";
|
||||||
|
i_data += "uniform LightBufferUBO\n";
|
||||||
|
i_data += "{\n";
|
||||||
|
i_data += " vec4 lights[NUM_UBO_LIGHTS];\n";
|
||||||
|
i_data += "};\n";
|
||||||
|
i_data += "#endif\n";
|
||||||
|
|
||||||
|
// textures
|
||||||
|
i_data += "uniform sampler2D tex;\n";
|
||||||
|
i_data += "uniform sampler2D ShadowMap;\n";
|
||||||
|
i_data += "uniform sampler2D texture2;\n";
|
||||||
|
i_data += "uniform sampler2D texture3;\n";
|
||||||
|
i_data += "uniform sampler2D texture4;\n";
|
||||||
|
i_data += "uniform sampler2D texture5;\n";
|
||||||
|
i_data += "uniform sampler2D texture6;\n";
|
||||||
|
|
||||||
|
// timer data
|
||||||
|
i_data += "uniform float timer;\n"; // To do: we must search user shaders for this declaration and remove it
|
||||||
|
|
||||||
|
// material types
|
||||||
|
i_data += "#if defined(SPECULAR)\n";
|
||||||
|
i_data += "#define normaltexture texture2\n";
|
||||||
|
i_data += "#define speculartexture texture3\n";
|
||||||
|
i_data += "#define brighttexture texture4\n";
|
||||||
|
i_data += "#elif defined(PBR)\n";
|
||||||
|
i_data += "#define normaltexture texture2\n";
|
||||||
|
i_data += "#define metallictexture texture3\n";
|
||||||
|
i_data += "#define roughnesstexture texture4\n";
|
||||||
|
i_data += "#define aotexture texture5\n";
|
||||||
|
i_data += "#define brighttexture texture6\n";
|
||||||
|
i_data += "#else\n";
|
||||||
|
i_data += "#define brighttexture texture2\n";
|
||||||
|
i_data += "#endif\n";
|
||||||
|
|
||||||
int vp_lump = Wads.CheckNumForFullName(vert_prog_lump, 0);
|
int vp_lump = Wads.CheckNumForFullName(vert_prog_lump, 0);
|
||||||
if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump);
|
if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump);
|
||||||
|
@ -120,14 +302,19 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
||||||
vp_comb << "#define SUPPORTS_SHADOWMAPS\n";
|
vp_comb << "#define SUPPORTS_SHADOWMAPS\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
vp_comb << defines << i_data.GetString().GetChars();
|
vp_comb << defines << i_data.GetChars();
|
||||||
FString fp_comb = vp_comb;
|
FString fp_comb = vp_comb;
|
||||||
|
|
||||||
|
vp_comb << "#line 1\n";
|
||||||
|
fp_comb << "#line 1\n";
|
||||||
|
|
||||||
vp_comb << vp_data.GetString().GetChars() << "\n";
|
vp_comb << vp_data.GetString().GetChars() << "\n";
|
||||||
fp_comb << fp_data.GetString().GetChars() << "\n";
|
fp_comb << fp_data.GetString().GetChars() << "\n";
|
||||||
|
|
||||||
if (proc_prog_lump != NULL)
|
if (proc_prog_lump != NULL)
|
||||||
{
|
{
|
||||||
|
fp_comb << "#line 1\n";
|
||||||
|
|
||||||
if (*proc_prog_lump != '#')
|
if (*proc_prog_lump != '#')
|
||||||
{
|
{
|
||||||
int pp_lump = Wads.CheckNumForFullName(proc_prog_lump);
|
int pp_lump = Wads.CheckNumForFullName(proc_prog_lump);
|
||||||
|
@ -141,7 +328,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
||||||
|
|
||||||
fp_comb.Substitute("vec4 frag = ProcessTexel();", "vec4 frag = Process(vec4(1.0));");
|
fp_comb.Substitute("vec4 frag = ProcessTexel();", "vec4 frag = Process(vec4(1.0));");
|
||||||
}
|
}
|
||||||
fp_comb << pp_data.GetString().GetChars();
|
fp_comb << RemoveLegacyUserUniforms(pp_data.GetString()).GetChars();
|
||||||
fp_comb.Substitute("gl_TexCoord[0]", "vTexCoord"); // fix old custom shaders.
|
fp_comb.Substitute("gl_TexCoord[0]", "vTexCoord"); // fix old custom shaders.
|
||||||
|
|
||||||
if (pp_data.GetString().IndexOf("ProcessLight") < 0)
|
if (pp_data.GetString().IndexOf("ProcessLight") < 0)
|
||||||
|
@ -159,6 +346,14 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (light_fragprog)
|
||||||
|
{
|
||||||
|
int pp_lump = Wads.CheckNumForFullName(light_fragprog);
|
||||||
|
if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog);
|
||||||
|
FMemLump pp_data = Wads.ReadLump(pp_lump);
|
||||||
|
fp_comb << pp_data.GetString().GetChars() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (gl.flags & RFL_NO_CLIP_PLANES)
|
if (gl.flags & RFL_NO_CLIP_PLANES)
|
||||||
{
|
{
|
||||||
// On ATI's GL3 drivers we have to disable gl_ClipDistance because it's hopelessly broken.
|
// On ATI's GL3 drivers we have to disable gl_ClipDistance because it's hopelessly broken.
|
||||||
|
@ -254,6 +449,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
||||||
muClipHeight.Init(hShader, "uClipHeight");
|
muClipHeight.Init(hShader, "uClipHeight");
|
||||||
muClipHeightDirection.Init(hShader, "uClipHeightDirection");
|
muClipHeightDirection.Init(hShader, "uClipHeightDirection");
|
||||||
muAlphaThreshold.Init(hShader, "uAlphaThreshold");
|
muAlphaThreshold.Init(hShader, "uAlphaThreshold");
|
||||||
|
muSpecularMaterial.Init(hShader, "uSpecularMaterial");
|
||||||
muViewHeight.Init(hShader, "uViewHeight");
|
muViewHeight.Init(hShader, "uViewHeight");
|
||||||
muTimer.Init(hShader, "timer");
|
muTimer.Init(hShader, "timer");
|
||||||
|
|
||||||
|
@ -326,9 +522,10 @@ bool FShader::Bind()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, bool usediscard, EPassType passType)
|
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType)
|
||||||
{
|
{
|
||||||
FString defines;
|
FString defines;
|
||||||
|
defines += shaderdefines;
|
||||||
// this can't be in the shader code due to ATI strangeness.
|
// this can't be in the shader code due to ATI strangeness.
|
||||||
if (gl.MaxLights() == 128) defines += "#define MAXLIGHTS128\n";
|
if (gl.MaxLights() == 128) defines += "#define MAXLIGHTS128\n";
|
||||||
if (!usediscard) defines += "#define NO_ALPHATEST\n";
|
if (!usediscard) defines += "#define NO_ALPHATEST\n";
|
||||||
|
@ -338,7 +535,7 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
shader = new FShader(ShaderName);
|
shader = new FShader(ShaderName);
|
||||||
if (!shader->Load(ShaderName, "shaders/glsl/main.vp", "shaders/glsl/main.fp", ShaderPath, defines.GetChars()))
|
if (!shader->Load(ShaderName, "shaders/glsl/main.vp", "shaders/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars()))
|
||||||
{
|
{
|
||||||
I_FatalError("Unable to load shader %s\n", ShaderName);
|
I_FatalError("Unable to load shader %s\n", ShaderName);
|
||||||
}
|
}
|
||||||
|
@ -375,26 +572,31 @@ struct FDefaultShader
|
||||||
{
|
{
|
||||||
const char * ShaderName;
|
const char * ShaderName;
|
||||||
const char * gettexelfunc;
|
const char * gettexelfunc;
|
||||||
|
const char * lightfunc;
|
||||||
|
const char * Defines;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note: the FIRST_USER_SHADER constant in gl_shader.h needs
|
// Note: the MaterialShaderIndex enum in gl_shader.h needs to be updated whenever this array is modified.
|
||||||
// to be updated whenever the size of this array is modified.
|
|
||||||
static const FDefaultShader defaultshaders[]=
|
static const FDefaultShader defaultshaders[]=
|
||||||
{
|
{
|
||||||
{"Default", "shaders/glsl/func_normal.fp"},
|
{"Default", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{"Warp 1", "shaders/glsl/func_warp1.fp"},
|
{"Warp 1", "shaders/glsl/func_warp1.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{"Warp 2", "shaders/glsl/func_warp2.fp"},
|
{"Warp 2", "shaders/glsl/func_warp2.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{"Brightmap","shaders/glsl/func_brightmap.fp"},
|
{"Brightmap","shaders/glsl/func_brightmap.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{"No Texture", "shaders/glsl/func_notexture.fp"},
|
{"Specular", "shaders/glsl/func_normal.fp", "shaders/glsl/material_specular.fp", "#define SPECULAR\n#define NORMALMAP\n"},
|
||||||
{"Basic Fuzz", "shaders/glsl/fuzz_standard.fp"},
|
{"SpecularBrightmap", "shaders/glsl/func_brightmap.fp", "shaders/glsl/material_specular.fp", "#define SPECULAR\n#define NORMALMAP\n"},
|
||||||
{"Smooth Fuzz", "shaders/glsl/fuzz_smooth.fp"},
|
{"PBR","shaders/glsl/func_normal.fp", "shaders/glsl/material_pbr.fp", "#define PBR\n#define NORMALMAP\n"},
|
||||||
{"Swirly Fuzz", "shaders/glsl/fuzz_swirly.fp"},
|
{"PBRBrightmap","shaders/glsl/func_brightmap.fp", "shaders/glsl/material_pbr.fp", "#define PBR\n#define NORMALMAP\n"},
|
||||||
{"Translucent Fuzz", "shaders/glsl/fuzz_smoothtranslucent.fp"},
|
{"No Texture", "shaders/glsl/func_notexture.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{"Jagged Fuzz", "shaders/glsl/fuzz_jagged.fp"},
|
{"Basic Fuzz", "shaders/glsl/fuzz_standard.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{"Noise Fuzz", "shaders/glsl/fuzz_noise.fp"},
|
{"Smooth Fuzz", "shaders/glsl/fuzz_smooth.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{"Smooth Noise Fuzz", "shaders/glsl/fuzz_smoothnoise.fp"},
|
{"Swirly Fuzz", "shaders/glsl/fuzz_swirly.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{"Software Fuzz", "shaders/glsl/fuzz_software.fp"},
|
{"Translucent Fuzz", "shaders/glsl/fuzz_smoothtranslucent.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
{NULL,NULL}
|
{"Jagged Fuzz", "shaders/glsl/fuzz_jagged.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
|
{"Noise Fuzz", "shaders/glsl/fuzz_noise.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
|
{"Smooth Noise Fuzz", "shaders/glsl/fuzz_smoothnoise.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
|
{"Software Fuzz", "shaders/glsl/fuzz_software.fp", "shaders/glsl/material_normal.fp", ""},
|
||||||
|
{nullptr,nullptr,nullptr,nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
static TArray<FString> usershaders;
|
static TArray<FString> usershaders;
|
||||||
|
@ -405,15 +607,16 @@ struct FEffectShader
|
||||||
const char *vp;
|
const char *vp;
|
||||||
const char *fp1;
|
const char *fp1;
|
||||||
const char *fp2;
|
const char *fp2;
|
||||||
|
const char *fp3;
|
||||||
const char *defines;
|
const char *defines;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const FEffectShader effectshaders[]=
|
static const FEffectShader effectshaders[]=
|
||||||
{
|
{
|
||||||
{ "fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", NULL, "#define NO_ALPHATEST\n" },
|
{ "fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", nullptr, nullptr, "#define NO_ALPHATEST\n" },
|
||||||
{ "spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define SPHEREMAP\n#define NO_ALPHATEST\n" },
|
{ "spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", "#define SPHEREMAP\n#define NO_ALPHATEST\n" },
|
||||||
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", NULL, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||||
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", NULL, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||||
};
|
};
|
||||||
|
|
||||||
FShaderManager::FShaderManager()
|
FShaderManager::FShaderManager()
|
||||||
|
@ -524,8 +727,8 @@ FShaderCollection::~FShaderCollection()
|
||||||
|
|
||||||
void FShaderCollection::CompileShaders(EPassType passType)
|
void FShaderCollection::CompileShaders(EPassType passType)
|
||||||
{
|
{
|
||||||
mTextureEffects.Clear();
|
mMaterialShaders.Clear();
|
||||||
mTextureEffectsNAT.Clear();
|
mMaterialShadersNAT.Clear();
|
||||||
for (int i = 0; i < MAX_EFFECTS; i++)
|
for (int i = 0; i < MAX_EFFECTS; i++)
|
||||||
{
|
{
|
||||||
mEffectShaders[i] = NULL;
|
mEffectShaders[i] = NULL;
|
||||||
|
@ -533,12 +736,12 @@ void FShaderCollection::CompileShaders(EPassType passType)
|
||||||
|
|
||||||
for(int i=0;defaultshaders[i].ShaderName != NULL;i++)
|
for(int i=0;defaultshaders[i].ShaderName != NULL;i++)
|
||||||
{
|
{
|
||||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, true, passType);
|
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, passType);
|
||||||
mTextureEffects.Push(shc);
|
mMaterialShaders.Push(shc);
|
||||||
if (i <= 3)
|
if (i < SHADER_NoTexture)
|
||||||
{
|
{
|
||||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, false, passType);
|
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType);
|
||||||
mTextureEffectsNAT.Push(shc);
|
mMaterialShadersNAT.Push(shc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,15 +750,15 @@ void FShaderCollection::CompileShaders(EPassType passType)
|
||||||
FString name = ExtractFileBase(usershaders[i]);
|
FString name = ExtractFileBase(usershaders[i]);
|
||||||
FName sfn = name;
|
FName sfn = name;
|
||||||
|
|
||||||
FShader *shc = Compile(sfn, usershaders[i], true, passType);
|
FShader *shc = Compile(sfn, usershaders[i], "shaders/glsl/material_normal.fp", "", true, passType);
|
||||||
mTextureEffects.Push(shc);
|
mMaterialShaders.Push(shc);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0;i<MAX_EFFECTS;i++)
|
for(int i=0;i<MAX_EFFECTS;i++)
|
||||||
{
|
{
|
||||||
FShader *eff = new FShader(effectshaders[i].ShaderName);
|
FShader *eff = new FShader(effectshaders[i].ShaderName);
|
||||||
if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1,
|
if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1,
|
||||||
effectshaders[i].fp2, effectshaders[i].defines))
|
effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines))
|
||||||
{
|
{
|
||||||
delete eff;
|
delete eff;
|
||||||
}
|
}
|
||||||
|
@ -571,21 +774,21 @@ void FShaderCollection::CompileShaders(EPassType passType)
|
||||||
|
|
||||||
void FShaderCollection::Clean()
|
void FShaderCollection::Clean()
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < mTextureEffectsNAT.Size(); i++)
|
for (unsigned int i = 0; i < mMaterialShadersNAT.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mTextureEffectsNAT[i] != NULL) delete mTextureEffectsNAT[i];
|
if (mMaterialShadersNAT[i] != NULL) delete mMaterialShadersNAT[i];
|
||||||
}
|
}
|
||||||
for (unsigned int i = 0; i < mTextureEffects.Size(); i++)
|
for (unsigned int i = 0; i < mMaterialShaders.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mTextureEffects[i] != NULL) delete mTextureEffects[i];
|
if (mMaterialShaders[i] != NULL) delete mMaterialShaders[i];
|
||||||
}
|
}
|
||||||
for (int i = 0; i < MAX_EFFECTS; i++)
|
for (int i = 0; i < MAX_EFFECTS; i++)
|
||||||
{
|
{
|
||||||
if (mEffectShaders[i] != NULL) delete mEffectShaders[i];
|
if (mEffectShaders[i] != NULL) delete mEffectShaders[i];
|
||||||
mEffectShaders[i] = NULL;
|
mEffectShaders[i] = NULL;
|
||||||
}
|
}
|
||||||
mTextureEffects.Clear();
|
mMaterialShaders.Clear();
|
||||||
mTextureEffectsNAT.Clear();
|
mMaterialShadersNAT.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -598,9 +801,9 @@ int FShaderCollection::Find(const char * shn)
|
||||||
{
|
{
|
||||||
FName sfn = shn;
|
FName sfn = shn;
|
||||||
|
|
||||||
for(unsigned int i=0;i<mTextureEffects.Size();i++)
|
for(unsigned int i=0;i<mMaterialShaders.Size();i++)
|
||||||
{
|
{
|
||||||
if (mTextureEffects[i]->mName == sfn)
|
if (mMaterialShaders[i]->mName == sfn)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -638,19 +841,19 @@ void FShaderCollection::ApplyMatrices(VSMatrix *proj, VSMatrix *view)
|
||||||
VSMatrix norm;
|
VSMatrix norm;
|
||||||
norm.computeNormalMatrix(*view);
|
norm.computeNormalMatrix(*view);
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < SHADER_NoTexture; i++)
|
||||||
{
|
{
|
||||||
mTextureEffects[i]->ApplyMatrices(proj, view, &norm);
|
mMaterialShaders[i]->ApplyMatrices(proj, view, &norm);
|
||||||
mTextureEffectsNAT[i]->ApplyMatrices(proj, view, &norm);
|
mMaterialShadersNAT[i]->ApplyMatrices(proj, view, &norm);
|
||||||
}
|
}
|
||||||
mTextureEffects[4]->ApplyMatrices(proj, view, &norm);
|
mMaterialShaders[SHADER_NoTexture]->ApplyMatrices(proj, view, &norm);
|
||||||
if (gl_fuzztype != 0)
|
if (gl_fuzztype != 0)
|
||||||
{
|
{
|
||||||
mTextureEffects[4 + gl_fuzztype]->ApplyMatrices(proj, view, &norm);
|
mMaterialShaders[SHADER_NoTexture + gl_fuzztype]->ApplyMatrices(proj, view, &norm);
|
||||||
}
|
}
|
||||||
for (unsigned i = 12; i < mTextureEffects.Size(); i++)
|
for (unsigned i = FIRST_USER_SHADER; i < mMaterialShaders.Size(); i++)
|
||||||
{
|
{
|
||||||
mTextureEffects[i]->ApplyMatrices(proj, view, &norm);
|
mMaterialShaders[i]->ApplyMatrices(proj, view, &norm);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < MAX_EFFECTS; i++)
|
for (int i = 0; i < MAX_EFFECTS; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -285,6 +285,7 @@ class FShader
|
||||||
FBufferedUniform1f muClipHeightDirection;
|
FBufferedUniform1f muClipHeightDirection;
|
||||||
FBufferedUniform1f muAlphaThreshold;
|
FBufferedUniform1f muAlphaThreshold;
|
||||||
FBufferedUniform1i muViewHeight;
|
FBufferedUniform1i muViewHeight;
|
||||||
|
FBufferedUniform2f muSpecularMaterial;
|
||||||
FBufferedUniform1f muTimer;
|
FBufferedUniform1f muTimer;
|
||||||
|
|
||||||
int lights_index;
|
int lights_index;
|
||||||
|
@ -316,7 +317,7 @@ public:
|
||||||
|
|
||||||
~FShader();
|
~FShader();
|
||||||
|
|
||||||
bool Load(const char * name, const char * vert_prog_lump, const char * fragprog, const char * fragprog2, const char *defines);
|
bool Load(const char * name, const char * vert_prog_lump, const char * fragprog, const char * fragprog2, const char * light_fragprog, const char *defines);
|
||||||
|
|
||||||
void SetColormapColor(float r, float g, float b, float r1, float g1, float b1);
|
void SetColormapColor(float r, float g, float b, float r1, float g1, float b1);
|
||||||
void SetGlowParams(float *topcolors, float topheight, float *bottomcolors, float bottomheight);
|
void SetGlowParams(float *topcolors, float topheight, float *bottomcolors, float bottomheight);
|
||||||
|
@ -356,8 +357,8 @@ private:
|
||||||
|
|
||||||
class FShaderCollection
|
class FShaderCollection
|
||||||
{
|
{
|
||||||
TArray<FShader*> mTextureEffects;
|
TArray<FShader*> mMaterialShaders;
|
||||||
TArray<FShader*> mTextureEffectsNAT;
|
TArray<FShader*> mMaterialShadersNAT;
|
||||||
FShader *mEffectShaders[MAX_EFFECTS];
|
FShader *mEffectShaders[MAX_EFFECTS];
|
||||||
|
|
||||||
void Clean();
|
void Clean();
|
||||||
|
@ -366,20 +367,20 @@ class FShaderCollection
|
||||||
public:
|
public:
|
||||||
FShaderCollection(EPassType passType);
|
FShaderCollection(EPassType passType);
|
||||||
~FShaderCollection();
|
~FShaderCollection();
|
||||||
FShader *Compile(const char *ShaderName, const char *ShaderPath, bool usediscard, EPassType passType);
|
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType);
|
||||||
int Find(const char *mame);
|
int Find(const char *mame);
|
||||||
FShader *BindEffect(int effect);
|
FShader *BindEffect(int effect);
|
||||||
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
|
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
|
||||||
|
|
||||||
void ResetFixedColormap()
|
void ResetFixedColormap()
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < mTextureEffects.Size(); i++)
|
for (unsigned i = 0; i < mMaterialShaders.Size(); i++)
|
||||||
{
|
{
|
||||||
mTextureEffects[i]->currentfixedcolormap = -1;
|
mMaterialShaders[i]->currentfixedcolormap = -1;
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < mTextureEffectsNAT.Size(); i++)
|
for (unsigned i = 0; i < mMaterialShadersNAT.Size(); i++)
|
||||||
{
|
{
|
||||||
mTextureEffectsNAT[i]->currentfixedcolormap = -1;
|
mMaterialShadersNAT[i]->currentfixedcolormap = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,17 +389,37 @@ public:
|
||||||
// indices 0-2 match the warping modes, 3 is brightmap, 4 no texture, the following are custom
|
// indices 0-2 match the warping modes, 3 is brightmap, 4 no texture, the following are custom
|
||||||
if (!alphateston && eff <= 3)
|
if (!alphateston && eff <= 3)
|
||||||
{
|
{
|
||||||
return mTextureEffectsNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway
|
return mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway
|
||||||
}
|
}
|
||||||
if (eff < mTextureEffects.Size())
|
if (eff < mMaterialShaders.Size())
|
||||||
{
|
{
|
||||||
return mTextureEffects[eff];
|
return mMaterialShaders[eff];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FIRST_USER_SHADER 13
|
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
|
enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -438,7 +438,7 @@ int FMaterial::mMaxBound;
|
||||||
|
|
||||||
FMaterial::FMaterial(FTexture * tx, bool expanded)
|
FMaterial::FMaterial(FTexture * tx, bool expanded)
|
||||||
{
|
{
|
||||||
mShaderIndex = 0;
|
mShaderIndex = SHADER_Default;
|
||||||
tex = tx;
|
tex = tx;
|
||||||
|
|
||||||
// TODO: apply custom shader object here
|
// TODO: apply custom shader object here
|
||||||
|
@ -449,7 +449,7 @@ FMaterial::FMaterial(FTexture * tx, bool expanded)
|
||||||
*/
|
*/
|
||||||
if (tx->bWarped)
|
if (tx->bWarped)
|
||||||
{
|
{
|
||||||
mShaderIndex = tx->bWarped;
|
mShaderIndex = tx->bWarped; // This picks SHADER_Warp1 or SHADER_Warp2
|
||||||
tx->gl_info.shaderspeed = static_cast<FWarpTexture*>(tx)->GetSpeed();
|
tx->gl_info.shaderspeed = static_cast<FWarpTexture*>(tx)->GetSpeed();
|
||||||
}
|
}
|
||||||
else if (tx->bHasCanvas)
|
else if (tx->bHasCanvas)
|
||||||
|
@ -468,13 +468,37 @@ FMaterial::FMaterial(FTexture * tx, bool expanded)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (tx->gl_info.Normal && tx->gl_info.Specular)
|
||||||
|
{
|
||||||
|
for (auto &texture : { tx->gl_info.Normal, tx->gl_info.Specular })
|
||||||
|
{
|
||||||
|
ValidateSysTexture(texture, expanded);
|
||||||
|
mTextureLayers.Push({ texture, false });
|
||||||
|
}
|
||||||
|
mShaderIndex = SHADER_Specular;
|
||||||
|
}
|
||||||
|
else if (tx->gl_info.Normal && tx->gl_info.Metallic && tx->gl_info.Roughness && tx->gl_info.AmbientOcclusion)
|
||||||
|
{
|
||||||
|
for (auto &texture : { tx->gl_info.Normal, tx->gl_info.Metallic, tx->gl_info.Roughness, tx->gl_info.AmbientOcclusion })
|
||||||
|
{
|
||||||
|
ValidateSysTexture(texture, expanded);
|
||||||
|
mTextureLayers.Push({ texture, false });
|
||||||
|
}
|
||||||
|
mShaderIndex = SHADER_PBR;
|
||||||
|
}
|
||||||
|
|
||||||
tx->CreateDefaultBrightmap();
|
tx->CreateDefaultBrightmap();
|
||||||
if (tx->gl_info.Brightmap != NULL)
|
if (tx->gl_info.Brightmap != NULL)
|
||||||
{
|
{
|
||||||
ValidateSysTexture(tx->gl_info.Brightmap, expanded);
|
ValidateSysTexture(tx->gl_info.Brightmap, expanded);
|
||||||
FTextureLayer layer = {tx->gl_info.Brightmap, false};
|
FTextureLayer layer = {tx->gl_info.Brightmap, false};
|
||||||
mTextureLayers.Push(layer);
|
mTextureLayers.Push(layer);
|
||||||
mShaderIndex = 3;
|
if (mShaderIndex == SHADER_Specular)
|
||||||
|
mShaderIndex = SHADER_SpecularBrightmap;
|
||||||
|
else if (mShaderIndex == SHADER_PBR)
|
||||||
|
mShaderIndex = SHADER_PBRBrightmap;
|
||||||
|
else
|
||||||
|
mShaderIndex = SHADER_Brightmap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -804,7 +828,7 @@ void FMaterial::GetTexCoordInfo(FTexCoordInfo *tci, float x, float y) const
|
||||||
|
|
||||||
int FMaterial::GetAreas(FloatRect **pAreas) const
|
int FMaterial::GetAreas(FloatRect **pAreas) const
|
||||||
{
|
{
|
||||||
if (mShaderIndex == 0) // texture splitting can only be done if there's no attached effects
|
if (mShaderIndex == SHADER_Default) // texture splitting can only be done if there's no attached effects
|
||||||
{
|
{
|
||||||
FTexture *tex = mBaseLayer->tex;
|
FTexture *tex = mBaseLayer->tex;
|
||||||
*pAreas = tex->gl_info.areas;
|
*pAreas = tex->gl_info.areas;
|
||||||
|
|
|
@ -191,10 +191,17 @@ FTexture::MiscGLInfo::MiscGLInfo() throw()
|
||||||
mIsTransparent = -1;
|
mIsTransparent = -1;
|
||||||
shaderspeed = 1.f;
|
shaderspeed = 1.f;
|
||||||
shaderindex = 0;
|
shaderindex = 0;
|
||||||
|
Glossiness = 10.0f;
|
||||||
|
SpecularLevel = 0.1f;
|
||||||
|
|
||||||
Material[1] = Material[0] = NULL;
|
Material[1] = Material[0] = NULL;
|
||||||
SystemTexture[1] = SystemTexture[0] = NULL;
|
SystemTexture[1] = SystemTexture[0] = NULL;
|
||||||
Brightmap = NULL;
|
Brightmap = NULL;
|
||||||
|
Normal = NULL;
|
||||||
|
Specular = NULL;
|
||||||
|
Metallic = NULL;
|
||||||
|
Roughness = NULL;
|
||||||
|
AmbientOcclusion = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
FTexture::MiscGLInfo::~MiscGLInfo()
|
FTexture::MiscGLInfo::~MiscGLInfo()
|
||||||
|
@ -542,6 +549,124 @@ int FBrightmapTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotat
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Parses a material definition
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void gl_ParseMaterial(FScanner &sc, int deflump)
|
||||||
|
{
|
||||||
|
int type = FTexture::TEX_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 = FTexture::TEX_Wall;
|
||||||
|
else if (sc.Compare("flat")) type = FTexture::TEX_Flat;
|
||||||
|
else if (sc.Compare("sprite")) type = FTexture::TEX_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, FTexture::TEX_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->gl_info.Brightmap,
|
||||||
|
&tex->gl_info.Normal,
|
||||||
|
&tex->gl_info.Specular,
|
||||||
|
&tex->gl_info.Metallic,
|
||||||
|
&tex->gl_info.Roughness,
|
||||||
|
&tex->gl_info.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;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -638,26 +763,51 @@ void gl_ParseBrightmap(FScanner &sc, int deflump)
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
// Search auto paths for extra material textures
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void AddAutoBrightmaps()
|
struct AutoTextureSearchPath
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
ptrdiff_t offset;
|
||||||
|
|
||||||
|
void SetTexture(FTexture *material, FTexture *texture) const
|
||||||
|
{
|
||||||
|
*reinterpret_cast<FTexture**>(reinterpret_cast<uint8_t*>(&material->gl_info) + offset) = texture;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static AutoTextureSearchPath autosearchpaths[] =
|
||||||
|
{
|
||||||
|
{ "brightmaps/auto/", offsetof(FTexture::MiscGLInfo, Brightmap) }, // For backwards compatibility
|
||||||
|
{ "materials/brightmaps/auto/", offsetof(FTexture::MiscGLInfo, Brightmap) },
|
||||||
|
{ "materials/normalmaps/auto/", offsetof(FTexture::MiscGLInfo, Normal) },
|
||||||
|
{ "materials/specular/auto/", offsetof(FTexture::MiscGLInfo, Specular) },
|
||||||
|
{ "materials/metallic/auto/", offsetof(FTexture::MiscGLInfo, Metallic) },
|
||||||
|
{ "materials/roughness/auto/", offsetof(FTexture::MiscGLInfo, Roughness) },
|
||||||
|
{ "materials/ao/auto/", offsetof(FTexture::MiscGLInfo, AmbientOcclusion) }
|
||||||
|
};
|
||||||
|
|
||||||
|
void AddAutoMaterials()
|
||||||
{
|
{
|
||||||
int num = Wads.GetNumLumps();
|
int num = Wads.GetNumLumps();
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
const char *name = Wads.GetLumpFullName(i);
|
const char *name = Wads.GetLumpFullName(i);
|
||||||
if (strstr(name, "brightmaps/auto/") == name)
|
for (const AutoTextureSearchPath &searchpath : autosearchpaths)
|
||||||
{
|
{
|
||||||
TArray<FTextureID> list;
|
if (strstr(name, searchpath.path) == name)
|
||||||
FString texname = ExtractFileBase(name, false);
|
|
||||||
TexMan.ListTextures(texname, list);
|
|
||||||
auto bmtex = TexMan.FindTexture(name, FTexture::TEX_Any, FTextureManager::TEXMAN_TryAny);
|
|
||||||
for (auto texid : list)
|
|
||||||
{
|
{
|
||||||
bmtex->bMasked = false;
|
TArray<FTextureID> list;
|
||||||
TexMan[texid]->gl_info.Brightmap = bmtex;
|
FString texname = ExtractFileBase(name, false);
|
||||||
|
TexMan.ListTextures(texname, list);
|
||||||
|
auto bmtex = TexMan.FindTexture(name, FTexture::TEX_Any, FTextureManager::TEXMAN_TryAny);
|
||||||
|
for (auto texid : list)
|
||||||
|
{
|
||||||
|
bmtex->bMasked = false;
|
||||||
|
searchpath.SetTexture(TexMan[texid], bmtex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,6 +328,11 @@ protected:
|
||||||
Rotations = other->Rotations;
|
Rotations = other->Rotations;
|
||||||
gl_info = other->gl_info;
|
gl_info = other->gl_info;
|
||||||
gl_info.Brightmap = NULL;
|
gl_info.Brightmap = NULL;
|
||||||
|
gl_info.Normal = NULL;
|
||||||
|
gl_info.Specular = NULL;
|
||||||
|
gl_info.Metallic = NULL;
|
||||||
|
gl_info.Roughness = NULL;
|
||||||
|
gl_info.AmbientOcclusion = NULL;
|
||||||
gl_info.areas = NULL;
|
gl_info.areas = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +367,13 @@ public:
|
||||||
FMaterial *Material[2];
|
FMaterial *Material[2];
|
||||||
FGLTexture *SystemTexture[2];
|
FGLTexture *SystemTexture[2];
|
||||||
FTexture *Brightmap;
|
FTexture *Brightmap;
|
||||||
|
FTexture *Normal; // Normal map texture
|
||||||
|
FTexture *Specular; // Specular light texture for the diffuse+normal+specular light model
|
||||||
|
FTexture *Metallic; // Metalness texture for the physically based rendering (PBR) light model
|
||||||
|
FTexture *Roughness; // Roughness texture for PBR
|
||||||
|
FTexture *AmbientOcclusion; // Ambient occlusion texture for PBR
|
||||||
|
float Glossiness;
|
||||||
|
float SpecularLevel;
|
||||||
PalEntry GlowColor;
|
PalEntry GlowColor;
|
||||||
int GlowHeight;
|
int GlowHeight;
|
||||||
FloatRect *areas;
|
FloatRect *areas;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
uniform sampler2D tex;
|
|
||||||
uniform sampler2D texture2;
|
|
||||||
in vec4 vTexCoord;
|
in vec4 vTexCoord;
|
||||||
in vec4 vColor;
|
in vec4 vColor;
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
uniform sampler2D texture2;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
@ -7,6 +6,6 @@ vec4 ProcessTexel()
|
||||||
|
|
||||||
vec4 ProcessLight(vec4 color)
|
vec4 ProcessLight(vec4 color)
|
||||||
{
|
{
|
||||||
vec4 brightpix = desaturate(texture(texture2, vTexCoord.st));
|
vec4 brightpix = desaturate(texture(brighttexture, vTexCoord.st));
|
||||||
return vec4(min (color.rgb + brightpix.rgb, 1.0), color.a);
|
return vec4(min (color.rgb + brightpix.rgb, 1.0), color.a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//created by Evil Space Tomato
|
//created by Evil Space Tomato
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//created by Evil Space Tomato
|
//created by Evil Space Tomato
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//created by Evil Space Tomato
|
//created by Evil Space Tomato
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//created by Evil Space Tomato
|
//created by Evil Space Tomato
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//created by Evil Space Tomato
|
//created by Evil Space Tomato
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// Fuzz effect as rendered by the software renderer
|
// Fuzz effect as rendered by the software renderer
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
#define FUZZTABLE 50
|
#define FUZZTABLE 50
|
||||||
#define FUZZ_RANDOM_X_SIZE 100
|
#define FUZZ_RANDOM_X_SIZE 100
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//created by Evil Space Tomato
|
//created by Evil Space Tomato
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//created by Evil Space Tomato
|
//created by Evil Space Tomato
|
||||||
uniform float timer;
|
|
||||||
|
|
||||||
vec4 ProcessTexel()
|
vec4 ProcessTexel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,26 +12,10 @@ out vec4 FragFog;
|
||||||
out vec4 FragNormal;
|
out vec4 FragNormal;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SHADER_STORAGE_LIGHTS
|
|
||||||
layout(std430, binding = 1) buffer LightBufferSSO
|
|
||||||
{
|
|
||||||
vec4 lights[];
|
|
||||||
};
|
|
||||||
#elif defined NUM_UBO_LIGHTS
|
|
||||||
/*layout(std140)*/ uniform LightBufferUBO
|
|
||||||
{
|
|
||||||
vec4 lights[NUM_UBO_LIGHTS];
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
|
||||||
uniform sampler2D ShadowMap;
|
|
||||||
|
|
||||||
vec4 Process(vec4 color);
|
vec4 Process(vec4 color);
|
||||||
vec4 ProcessTexel();
|
vec4 ProcessTexel();
|
||||||
vec4 ProcessLight(vec4 color);
|
vec4 ProcessLight(vec4 color);
|
||||||
|
vec3 ProcessMaterial(vec3 material, vec3 color);
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -237,47 +221,21 @@ float shadowmapAttenuation(vec4 lightpos, float shadowIndex)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
float shadowAttenuation(vec4 lightpos, float lightcolorA)
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// Standard lambertian diffuse light calculation
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
float diffuseContribution(vec3 lightDirection, vec3 normal)
|
|
||||||
{
|
{
|
||||||
return max(dot(normal, lightDirection), 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// Calculates the brightness of a dynamic point light
|
|
||||||
// Todo: Find a better way to define which lighting model to use.
|
|
||||||
// (Specular mode has been removed for now.)
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
float pointLightAttenuation(vec4 lightpos, float lightcolorA)
|
|
||||||
{
|
|
||||||
float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
|
|
||||||
if (attenuation == 0.0) return 0.0;
|
|
||||||
#ifdef SUPPORTS_SHADOWMAPS
|
|
||||||
float shadowIndex = abs(lightcolorA) - 1.0;
|
float shadowIndex = abs(lightcolorA) - 1.0;
|
||||||
attenuation *= shadowmapAttenuation(lightpos, shadowIndex);
|
return shadowmapAttenuation(lightpos, shadowIndex);
|
||||||
#endif
|
|
||||||
if (lightcolorA >= 0.0) // Sign bit is the attenuated light flag
|
|
||||||
{
|
|
||||||
return attenuation;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
|
|
||||||
float diffuseAmount = diffuseContribution(lightDirection, normalize(vWorldNormal.xyz));
|
|
||||||
return attenuation * diffuseAmount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
float shadowAttenuation(vec4 lightpos, float lightcolorA)
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle, float lightCosOuterAngle)
|
float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle, float lightCosOuterAngle)
|
||||||
{
|
{
|
||||||
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
|
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
|
||||||
|
@ -285,6 +243,62 @@ float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle
|
||||||
return smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir);
|
return smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Adjust normal vector according to the normal map
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
#if defined(NORMALMAP)
|
||||||
|
mat3 cotangent_frame(vec3 n, vec3 p, vec2 uv)
|
||||||
|
{
|
||||||
|
// get edge vectors of the pixel triangle
|
||||||
|
vec3 dp1 = dFdx(p);
|
||||||
|
vec3 dp2 = dFdy(p);
|
||||||
|
vec2 duv1 = dFdx(uv);
|
||||||
|
vec2 duv2 = dFdy(uv);
|
||||||
|
|
||||||
|
// solve the linear system
|
||||||
|
vec3 dp2perp = cross(n, dp2); // cross(dp2, n);
|
||||||
|
vec3 dp1perp = cross(dp1, n); // cross(n, dp1);
|
||||||
|
vec3 t = dp2perp * duv1.x + dp1perp * duv2.x;
|
||||||
|
vec3 b = dp2perp * duv1.y + dp1perp * duv2.y;
|
||||||
|
|
||||||
|
// construct a scale-invariant frame
|
||||||
|
float invmax = inversesqrt(max(dot(t,t), dot(b,b)));
|
||||||
|
return mat3(t * invmax, b * invmax, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ApplyNormalMap()
|
||||||
|
{
|
||||||
|
#define WITH_NORMALMAP_UNSIGNED
|
||||||
|
#define WITH_NORMALMAP_GREEN_UP
|
||||||
|
//#define WITH_NORMALMAP_2CHANNEL
|
||||||
|
|
||||||
|
vec3 interpolatedNormal = normalize(vWorldNormal.xyz);
|
||||||
|
|
||||||
|
vec3 map = texture(normaltexture, vTexCoord.st).xyz;
|
||||||
|
#if defined(WITH_NORMALMAP_UNSIGNED)
|
||||||
|
map = map * 255./127. - 128./127.; // Math so "odd" because 0.5 cannot be precisely described in an unsigned format
|
||||||
|
#endif
|
||||||
|
#if defined(WITH_NORMALMAP_2CHANNEL)
|
||||||
|
map.z = sqrt(1 - dot(map.xy, map.xy));
|
||||||
|
#endif
|
||||||
|
#if defined(WITH_NORMALMAP_GREEN_UP)
|
||||||
|
map.y = -map.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mat3 tbn = cotangent_frame(interpolatedNormal, pixelpos.xyz, vTexCoord.st);
|
||||||
|
vec3 bumpedNormal = normalize(tbn * map);
|
||||||
|
return bumpedNormal;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
vec3 ApplyNormalMap()
|
||||||
|
{
|
||||||
|
return normalize(vWorldNormal.xyz);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// Calculate light
|
// Calculate light
|
||||||
|
@ -299,7 +313,7 @@ float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
vec4 getLightColor(float fogdist, float fogfactor)
|
vec4 getLightColor(vec4 material, float fogdist, float fogfactor)
|
||||||
{
|
{
|
||||||
vec4 color = vColor;
|
vec4 color = vColor;
|
||||||
|
|
||||||
|
@ -341,56 +355,9 @@ vec4 getLightColor(float fogdist, float fogfactor)
|
||||||
color = ProcessLight(color);
|
color = ProcessLight(color);
|
||||||
|
|
||||||
//
|
//
|
||||||
// apply dynamic lights (except additive)
|
// apply dynamic lights
|
||||||
//
|
//
|
||||||
|
return vec4(ProcessMaterial(material.rgb, color.rgb), material.a * vColor.a);
|
||||||
vec4 dynlight = uDynLightColor;
|
|
||||||
|
|
||||||
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
|
||||||
if (uLightIndex >= 0)
|
|
||||||
{
|
|
||||||
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
|
||||||
if (lightRange.z > lightRange.x)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// modulated lights
|
|
||||||
//
|
|
||||||
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
|
||||||
{
|
|
||||||
vec4 lightpos = lights[i];
|
|
||||||
vec4 lightcolor = lights[i+1];
|
|
||||||
vec4 lightspot1 = lights[i+2];
|
|
||||||
vec4 lightspot2 = lights[i+3];
|
|
||||||
|
|
||||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
|
||||||
if (lightspot1.w == 1.0)
|
|
||||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
|
||||||
lightcolor.rgb *= attenuation;
|
|
||||||
dynlight.rgb += lightcolor.rgb;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// subtractive lights
|
|
||||||
//
|
|
||||||
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
|
||||||
{
|
|
||||||
vec4 lightpos = lights[i];
|
|
||||||
vec4 lightcolor = lights[i+1];
|
|
||||||
vec4 lightspot1 = lights[i+2];
|
|
||||||
vec4 lightspot2 = lights[i+3];
|
|
||||||
|
|
||||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
|
||||||
if (lightspot1.w == 1.0)
|
|
||||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
|
||||||
lightcolor.rgb *= attenuation;
|
|
||||||
dynlight.rgb -= lightcolor.rgb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
color.rgb = clamp(color.rgb + desaturate(dynlight).rgb, 0.0, 1.4);
|
|
||||||
|
|
||||||
// prevent any unintentional messing around with the alpha.
|
|
||||||
return vec4(color.rgb, vColor.a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -470,37 +437,7 @@ void main()
|
||||||
fogfactor = exp2 (uFogDensity * fogdist);
|
fogfactor = exp2 (uFogDensity * fogdist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frag = getLightColor(frag, fogdist, fogfactor);
|
||||||
frag *= getLightColor(fogdist, fogfactor);
|
|
||||||
|
|
||||||
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
|
|
||||||
if (uLightIndex >= 0)
|
|
||||||
{
|
|
||||||
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
|
||||||
if (lightRange.w > lightRange.z)
|
|
||||||
{
|
|
||||||
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
|
|
||||||
|
|
||||||
//
|
|
||||||
// additive lights - these can be done after the alpha test.
|
|
||||||
//
|
|
||||||
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
|
||||||
{
|
|
||||||
vec4 lightpos = lights[i];
|
|
||||||
vec4 lightcolor = lights[i+1];
|
|
||||||
vec4 lightspot1 = lights[i+2];
|
|
||||||
vec4 lightspot2 = lights[i+3];
|
|
||||||
|
|
||||||
float attenuation = pointLightAttenuation(lightpos, lightcolor.a);
|
|
||||||
if (lightspot1.w == 1.0)
|
|
||||||
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
|
||||||
lightcolor.rgb *= attenuation;
|
|
||||||
addlight.rgb += lightcolor.rgb;
|
|
||||||
}
|
|
||||||
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// colored fog
|
// colored fog
|
||||||
|
|
5
wadsrc/static/shaders/glsl/material_nolight.fp
Normal file
5
wadsrc/static/shaders/glsl/material_nolight.fp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
vec3 ProcessMaterial(vec3 material, vec3 color)
|
||||||
|
{
|
||||||
|
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||||
|
}
|
80
wadsrc/static/shaders/glsl/material_normal.fp
Normal file
80
wadsrc/static/shaders/glsl/material_normal.fp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
|
||||||
|
vec3 lightContribution(int i, vec3 normal)
|
||||||
|
{
|
||||||
|
vec4 lightpos = lights[i];
|
||||||
|
vec4 lightcolor = lights[i+1];
|
||||||
|
vec4 lightspot1 = lights[i+2];
|
||||||
|
vec4 lightspot2 = lights[i+3];
|
||||||
|
|
||||||
|
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
||||||
|
if (lightpos.w < lightdistance)
|
||||||
|
return vec3(0.0); // Early out lights touching surface but not this fragment
|
||||||
|
|
||||||
|
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
|
||||||
|
|
||||||
|
if (lightspot1.w == 1.0)
|
||||||
|
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||||
|
|
||||||
|
if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag
|
||||||
|
{
|
||||||
|
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
||||||
|
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attenuation > 0.0) // Skip shadow map test if possible
|
||||||
|
{
|
||||||
|
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||||
|
return lightcolor.rgb * attenuation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return vec3(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ProcessMaterial(vec3 material, vec3 color)
|
||||||
|
{
|
||||||
|
if (uLightIndex >= 0)
|
||||||
|
{
|
||||||
|
vec4 dynlight = uDynLightColor;
|
||||||
|
vec3 normal = ApplyNormalMap();
|
||||||
|
|
||||||
|
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||||
|
|
||||||
|
if (lightRange.z > lightRange.x)
|
||||||
|
{
|
||||||
|
// modulated lights
|
||||||
|
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||||
|
{
|
||||||
|
dynlight.rgb += lightContribution(i, normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// subtractive lights
|
||||||
|
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||||
|
{
|
||||||
|
dynlight.rgb -= lightContribution(i, normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 frag = material * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
|
||||||
|
|
||||||
|
if (lightRange.w > lightRange.z)
|
||||||
|
{
|
||||||
|
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
|
||||||
|
|
||||||
|
// additive lights
|
||||||
|
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
||||||
|
{
|
||||||
|
addlight.rgb += lightContribution(i, normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||||
|
}
|
||||||
|
}
|
189
wadsrc/static/shaders/glsl/material_pbr.fp
Normal file
189
wadsrc/static/shaders/glsl/material_pbr.fp
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
|
||||||
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
|
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness * roughness;
|
||||||
|
float a2 = a * a;
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
float NdotH2 = NdotH*NdotH;
|
||||||
|
|
||||||
|
float nom = a2;
|
||||||
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
|
denom = PI * denom * denom;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float r = (roughness + 1.0);
|
||||||
|
float k = (r * r) / 8.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
|
{
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||||
|
{
|
||||||
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
|
||||||
|
{
|
||||||
|
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float quadraticDistanceAttenuation(vec4 lightpos)
|
||||||
|
{
|
||||||
|
float strength = (1.0 + lightpos.w * lightpos.w * 0.25) * 0.5;
|
||||||
|
|
||||||
|
vec3 distVec = lightpos.xyz - pixelpos.xyz;
|
||||||
|
float attenuation = strength / (1.0 + dot(distVec, distVec));
|
||||||
|
if (attenuation <= 1.0 / 256.0) return 0.0;
|
||||||
|
|
||||||
|
return attenuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ProcessMaterial(vec3 albedo, vec3 ambientLight)
|
||||||
|
{
|
||||||
|
vec3 worldpos = pixelpos.xyz;
|
||||||
|
|
||||||
|
albedo = pow(albedo, vec3(2.2)); // sRGB to linear
|
||||||
|
ambientLight = pow(ambientLight, vec3(2.2));
|
||||||
|
|
||||||
|
float metallic = texture(metallictexture, vTexCoord.st).r;
|
||||||
|
float roughness = texture(roughnesstexture, vTexCoord.st).r;
|
||||||
|
float ao = texture(aotexture, vTexCoord.st).r;
|
||||||
|
|
||||||
|
vec3 N = ApplyNormalMap();
|
||||||
|
vec3 V = normalize(uCameraPos.xyz - worldpos);
|
||||||
|
|
||||||
|
vec3 F0 = mix(vec3(0.04), albedo, metallic);
|
||||||
|
|
||||||
|
vec3 Lo = uDynLightColor.rgb;
|
||||||
|
|
||||||
|
if (uLightIndex >= 0)
|
||||||
|
{
|
||||||
|
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||||
|
if (lightRange.z > lightRange.x)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// modulated lights
|
||||||
|
//
|
||||||
|
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||||
|
{
|
||||||
|
vec4 lightpos = lights[i];
|
||||||
|
vec4 lightcolor = lights[i+1];
|
||||||
|
vec4 lightspot1 = lights[i+2];
|
||||||
|
vec4 lightspot2 = lights[i+3];
|
||||||
|
|
||||||
|
vec3 L = normalize(lightpos.xyz - worldpos);
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
|
||||||
|
float attenuation = quadraticDistanceAttenuation(lightpos);
|
||||||
|
if (lightspot1.w == 1.0)
|
||||||
|
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||||
|
if (lightcolor.a < 0.0)
|
||||||
|
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
|
||||||
|
|
||||||
|
if (attenuation > 0.0)
|
||||||
|
{
|
||||||
|
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||||
|
|
||||||
|
vec3 radiance = lightcolor.rgb * attenuation;
|
||||||
|
|
||||||
|
// cook-torrance brdf
|
||||||
|
float NDF = DistributionGGX(N, H, roughness);
|
||||||
|
float G = GeometrySmith(N, V, L, roughness);
|
||||||
|
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
|
||||||
|
|
||||||
|
vec3 kS = F;
|
||||||
|
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
|
||||||
|
|
||||||
|
vec3 nominator = NDF * G * F;
|
||||||
|
float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0);
|
||||||
|
vec3 specular = nominator / max(denominator, 0.001);
|
||||||
|
|
||||||
|
Lo += (kD * albedo / PI + specular) * radiance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// subtractive lights
|
||||||
|
//
|
||||||
|
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||||
|
{
|
||||||
|
vec4 lightpos = lights[i];
|
||||||
|
vec4 lightcolor = lights[i+1];
|
||||||
|
vec4 lightspot1 = lights[i+2];
|
||||||
|
vec4 lightspot2 = lights[i+3];
|
||||||
|
|
||||||
|
vec3 L = normalize(lightpos.xyz - worldpos);
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
|
||||||
|
float attenuation = quadraticDistanceAttenuation(lightpos);
|
||||||
|
if (lightspot1.w == 1.0)
|
||||||
|
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||||
|
if (lightcolor.a < 0.0)
|
||||||
|
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
|
||||||
|
|
||||||
|
if (attenuation > 0.0)
|
||||||
|
{
|
||||||
|
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
|
||||||
|
|
||||||
|
vec3 radiance = lightcolor.rgb * attenuation;
|
||||||
|
|
||||||
|
// cook-torrance brdf
|
||||||
|
float NDF = DistributionGGX(N, H, roughness);
|
||||||
|
float G = GeometrySmith(N, V, L, roughness);
|
||||||
|
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
|
||||||
|
|
||||||
|
vec3 kS = F;
|
||||||
|
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
|
||||||
|
|
||||||
|
vec3 nominator = NDF * G * F;
|
||||||
|
float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0);
|
||||||
|
vec3 specular = nominator / max(denominator, 0.001);
|
||||||
|
|
||||||
|
Lo -= (kD * albedo / PI + specular) * radiance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretend we sampled the sector light level from an irradiance map
|
||||||
|
|
||||||
|
vec3 F = fresnelSchlickRoughness(clamp(dot(N, V), 0.0, 1.0), F0, roughness);
|
||||||
|
|
||||||
|
vec3 kS = F;
|
||||||
|
vec3 kD = 1.0 - kS;
|
||||||
|
|
||||||
|
vec3 irradiance = ambientLight; // texture(irradianceMap, N).rgb
|
||||||
|
vec3 diffuse = irradiance * albedo;
|
||||||
|
|
||||||
|
//kD *= 1.0 - metallic;
|
||||||
|
//const float MAX_REFLECTION_LOD = 4.0;
|
||||||
|
//vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb;
|
||||||
|
//vec2 envBRDF = texture(brdfLUT, vec2(clamp(dot(N, V), 0.0, 1.0), roughness)).rg;
|
||||||
|
//vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
|
||||||
|
|
||||||
|
//vec3 ambient = (kD * diffuse + specular) * ao;
|
||||||
|
vec3 ambient = (kD * diffuse) * ao;
|
||||||
|
|
||||||
|
vec3 color = ambient + Lo;
|
||||||
|
|
||||||
|
// Tonemap (reinhard) and apply sRGB gamma
|
||||||
|
//color = color / (color + vec3(1.0));
|
||||||
|
return pow(color, vec3(1.0 / 2.2));
|
||||||
|
}
|
97
wadsrc/static/shaders/glsl/material_specular.fp
Normal file
97
wadsrc/static/shaders/glsl/material_specular.fp
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
|
||||||
|
vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA)
|
||||||
|
{
|
||||||
|
vec4 lightpos = lights[i];
|
||||||
|
vec4 lightspot1 = lights[i+2];
|
||||||
|
vec4 lightspot2 = lights[i+3];
|
||||||
|
|
||||||
|
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
|
||||||
|
if (lightpos.w < lightdistance)
|
||||||
|
return vec2(0.0); // Early out lights touching surface but not this fragment
|
||||||
|
|
||||||
|
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
|
||||||
|
|
||||||
|
if (lightspot1.w == 1.0)
|
||||||
|
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
|
||||||
|
|
||||||
|
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
|
||||||
|
|
||||||
|
if (lightcolorA < 0.0) // Sign bit is the attenuated light flag
|
||||||
|
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
|
||||||
|
|
||||||
|
if (attenuation > 0.0) // Skip shadow map test if possible
|
||||||
|
attenuation *= shadowAttenuation(lightpos, lightcolorA);
|
||||||
|
|
||||||
|
if (attenuation <= 0.0)
|
||||||
|
return vec2(0.0);
|
||||||
|
|
||||||
|
float glossiness = uSpecularMaterial.x;
|
||||||
|
float specularLevel = uSpecularMaterial.y;
|
||||||
|
|
||||||
|
vec3 halfdir = normalize(viewdir + lightdir);
|
||||||
|
float specAngle = clamp(dot(halfdir, normal), 0.0f, 1.0f);
|
||||||
|
float phExp = glossiness * 4.0f;
|
||||||
|
return vec2(attenuation, attenuation * specularLevel * pow(specAngle, phExp));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ProcessMaterial(vec3 material, vec3 color)
|
||||||
|
{
|
||||||
|
if (uLightIndex >= 0)
|
||||||
|
{
|
||||||
|
vec4 dynlight = uDynLightColor;
|
||||||
|
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
vec3 normal = ApplyNormalMap();
|
||||||
|
vec3 viewdir = normalize(uCameraPos.xyz - pixelpos.xyz);
|
||||||
|
|
||||||
|
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
|
||||||
|
|
||||||
|
if (lightRange.z > lightRange.x)
|
||||||
|
{
|
||||||
|
// modulated lights
|
||||||
|
for(int i=lightRange.x; i<lightRange.y; i+=4)
|
||||||
|
{
|
||||||
|
vec4 lightcolor = lights[i+1];
|
||||||
|
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||||
|
dynlight.rgb += lightcolor.rgb * attenuation.x;
|
||||||
|
specular.rgb += lightcolor.rgb * attenuation.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// subtractive lights
|
||||||
|
for(int i=lightRange.y; i<lightRange.z; i+=4)
|
||||||
|
{
|
||||||
|
vec4 lightcolor = lights[i+1];
|
||||||
|
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||||
|
dynlight.rgb -= lightcolor.rgb * attenuation.x;
|
||||||
|
specular.rgb -= lightcolor.rgb * attenuation.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dynlight.rgb = clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
|
||||||
|
specular.rgb = clamp(desaturate(specular).rgb, 0.0, 1.4);
|
||||||
|
|
||||||
|
vec4 materialSpec = texture(speculartexture, vTexCoord.st);
|
||||||
|
vec3 frag = material * dynlight.rgb + materialSpec.rgb * specular.rgb;
|
||||||
|
|
||||||
|
if (lightRange.w > lightRange.z)
|
||||||
|
{
|
||||||
|
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
|
||||||
|
|
||||||
|
// additive lights
|
||||||
|
for(int i=lightRange.z; i<lightRange.w; i+=4)
|
||||||
|
{
|
||||||
|
vec4 lightcolor = lights[i+1];
|
||||||
|
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
|
||||||
|
addlight.rgb += lightcolor.rgb * attenuation.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,68 +0,0 @@
|
||||||
// This file contains common data definitions for both vertex and fragment shader
|
|
||||||
|
|
||||||
// these settings are actually pointless but there seem to be some old ATI drivers that fail to compile the shader without setting the precision here.
|
|
||||||
precision highp int;
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
uniform vec4 uCameraPos;
|
|
||||||
uniform int uTextureMode;
|
|
||||||
uniform float uClipHeight, uClipHeightDirection;
|
|
||||||
uniform vec2 uClipSplit;
|
|
||||||
uniform vec4 uClipLine;
|
|
||||||
|
|
||||||
uniform float uAlphaThreshold;
|
|
||||||
|
|
||||||
|
|
||||||
// colors
|
|
||||||
uniform vec4 uObjectColor;
|
|
||||||
uniform vec4 uObjectColor2;
|
|
||||||
uniform vec4 uDynLightColor;
|
|
||||||
uniform vec4 uFogColor;
|
|
||||||
uniform float uDesaturationFactor;
|
|
||||||
uniform float uInterpolationFactor;
|
|
||||||
|
|
||||||
// Fixed colormap stuff
|
|
||||||
uniform int uFixedColormap; // 0, when no fixed colormap, 1 for a light value, 2 for a color blend, 3 for a fog layer
|
|
||||||
uniform vec4 uFixedColormapStart;
|
|
||||||
uniform vec4 uFixedColormapRange;
|
|
||||||
|
|
||||||
// Glowing walls stuff
|
|
||||||
uniform vec4 uGlowTopPlane;
|
|
||||||
uniform vec4 uGlowTopColor;
|
|
||||||
uniform vec4 uGlowBottomPlane;
|
|
||||||
uniform vec4 uGlowBottomColor;
|
|
||||||
|
|
||||||
uniform vec4 uSplitTopPlane;
|
|
||||||
uniform vec4 uSplitBottomPlane;
|
|
||||||
|
|
||||||
// Lighting + Fog
|
|
||||||
uniform vec4 uLightAttr;
|
|
||||||
#define uLightLevel uLightAttr.a
|
|
||||||
#define uFogDensity uLightAttr.b
|
|
||||||
#define uLightFactor uLightAttr.g
|
|
||||||
#define uLightDist uLightAttr.r
|
|
||||||
uniform int uFogEnabled;
|
|
||||||
uniform int uPalLightLevels;
|
|
||||||
uniform float uGlobVis; // uGlobVis = R_GetGlobVis(r_visibility) / 32.0
|
|
||||||
|
|
||||||
// dynamic lights
|
|
||||||
uniform int uLightIndex;
|
|
||||||
|
|
||||||
// Software fuzz scaling
|
|
||||||
uniform int uViewHeight;
|
|
||||||
|
|
||||||
// quad drawer stuff
|
|
||||||
#ifdef USE_QUAD_DRAWER
|
|
||||||
uniform mat4 uQuadVertices;
|
|
||||||
uniform mat4 uQuadTexCoords;
|
|
||||||
uniform int uQuadMode;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// matrices
|
|
||||||
uniform mat4 ProjectionMatrix;
|
|
||||||
uniform mat4 ViewMatrix;
|
|
||||||
uniform mat4 ModelMatrix;
|
|
||||||
uniform mat4 NormalViewMatrix;
|
|
||||||
uniform mat4 NormalModelMatrix;
|
|
||||||
uniform mat4 TextureMatrix;
|
|
||||||
|
|
Loading…
Reference in a new issue