- merged vertex shader sources into one file.

- Started work on supporting ZDoomGL's texture shaders.
- fixed support check for shader based dynamic lights.
- brightmaps are now managed by the texture manager to avoid creating redundant textures for ones that are used multiple times.
- The GL texture manager now can resolve texture redirects.


git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@543 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2009-10-12 21:17:34 +00:00
parent 39e57a292a
commit 84fbeb60ea
14 changed files with 939 additions and 151 deletions

View file

@ -6499,6 +6499,21 @@
RelativePath=".\src\gl\shaders\gl_shader.h"
>
</File>
<File
RelativePath=".\src\gl\shaders\gl_texshader.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\gl\shaders\gl_texshader.h"
>
</File>
<Filter
Name="Shader Sources"
>

View file

@ -62,7 +62,7 @@
//
//==========================================================================
CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (self) gl_RecreateAllAttachedLights();
else gl_DeleteAllAttachedLights();
@ -70,7 +70,7 @@ CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CUSTOM_CVAR (Bool, gl_dynlight_shader, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (!(gl.flags & RFL_TEXTUREBUFFER)) self = false;
if (self && gl.maxuniforms < 1024) self = false;
}
CVAR (Bool, gl_attachedlights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);

View file

@ -92,11 +92,19 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
if (proc_prog_lump != NULL)
{
int pp_lump = Wads.CheckNumForFullName(proc_prog_lump);
if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump);
FMemLump pp_data = Wads.ReadLump(pp_lump);
if (*proc_prog_lump != '#')
{
int pp_lump = Wads.CheckNumForFullName(proc_prog_lump);
if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump);
FMemLump pp_data = Wads.ReadLump(pp_lump);
fp_comb << pp_data.GetString().GetChars();
fp_comb << pp_data.GetString().GetChars();
}
else
{
// Proc_prog_lump is not a lump name but the source itself (from generated shaders)
fp_comb << proc_prog_lump+1;
}
}
hVertProg = gl.CreateShader(GL_VERTEX_SHADER);
@ -151,13 +159,6 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
int texture_index = gl.GetUniformLocation(hShader, "texture2");
if (texture_index > 0) gl.Uniform1i(texture_index, 1);
texture_index = gl.GetUniformLocation(hShader, "lightIndex");
if (texture_index > 0) gl.Uniform1i(texture_index, 13);
texture_index = gl.GetUniformLocation(hShader, "lightRGB");
if (texture_index > 0) gl.Uniform1i(texture_index, 14);
texture_index = gl.GetUniformLocation(hShader, "lightPositions");
if (texture_index > 0) gl.Uniform1i(texture_index, 15);
gl.UseProgram(0);
return !!linked;
}
@ -228,7 +229,7 @@ FShaderContainer::FShaderContainer(const char *ShaderName, const char *ShaderPat
try
{
shader_cm = new FShader;
if (!shader_cm->Load(name, "shaders/glsl/main_colormap.vp", "shaders/glsl/main_colormap.fp", ShaderPath, "\n"))
if (!shader_cm->Load(name, "shaders/glsl/main.vp", "shaders/glsl/main_colormap.fp", ShaderPath, "#define NO_FOG\n#define NO_GLOW\n"))
{
delete shader_cm;
shader_cm = NULL;
@ -372,7 +373,7 @@ struct FEffectShader
static const FEffectShader effectshaders[]=
{
{"fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", NULL, "#define NO_GLOW\n"},
{"spheremap", "shaders/glsl/main_spheremap.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define NO_GLOW\n#define NO_DESATURATE\n"}
{"spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define NO_GLOW\n#define NO_DESATURATE\n#define SPHEREMAP\n#define SPHEREMAP_0\n"}
};

View file

@ -0,0 +1,598 @@
/*
** gl_shaders.cpp
** Routines parsing/managing texture shaders.
**
**---------------------------------------------------------------------------
** Copyright 2003 Timothy Stump
** Copyright 2009 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 "gl/system/gl_system.h"
#include "doomtype.h"
#include "c_cvars.h"
#include "sc_man.h"
#include "textures/textures.h"
#include "gl/shaders/gl_texshader.h"
CVAR(Bool, gl_texture_useshaders, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
//==========================================================================
//
//
//
//==========================================================================
FShaderLayer::FShaderLayer()
{
animate = false;
emissive = false;
blendFuncSrc = GL_SRC_ALPHA;
blendFuncDst = GL_ONE_MINUS_SRC_ALPHA;
offsetX = 0.f;
offsetY = 0.f;
centerX = 0.0f;
centerY = 0.0f;
rotate = 0.f;
rotation = 0.f;
adjustX.SetParams(0.f, 0.f, 0.f);
adjustY.SetParams(0.f, 0.f, 0.f);
scaleX.SetParams(1.f, 1.f, 0.f);
scaleY.SetParams(1.f, 1.f, 0.f);
alpha.SetParams(1.f, 1.f, 0.f);
r.SetParams(1.f, 1.f, 0.f);
g.SetParams(1.f, 1.f, 0.f);
b.SetParams(1.f, 1.f, 0.f);
flags = 0;
layerMask = NULL;
texgen = SHADER_TexGen_None;
warp = false;
warpspeed = 0;
}
//==========================================================================
//
//
//
//==========================================================================
FShaderLayer::FShaderLayer(const FShaderLayer &layer)
{
texture = layer.texture;
animate = layer.animate;
emissive = layer.emissive;
adjustX = layer.adjustX;
adjustY = layer.adjustY;
blendFuncSrc = layer.blendFuncSrc;
blendFuncDst = layer.blendFuncDst;
offsetX = layer.offsetX;
offsetY = layer.offsetY;
centerX = layer.centerX;
centerY = layer.centerX;
rotate = layer.rotate;
rotation = layer.rotation;
scaleX = layer.scaleX;
scaleY = layer.scaleY;
vectorX = layer.vectorX;
vectorY = layer.vectorY;
alpha = layer.alpha;
r = layer.r;
g = layer.g;
b = layer.b;
flags = layer.flags;
if (layer.layerMask)
{
layerMask = new FShaderLayer(*(layer.layerMask));
}
else
{
layerMask = NULL;
}
texgen = layer.texgen;
warp = layer.warp;
warpspeed = layer.warpspeed;
}
//==========================================================================
//
//
//
//==========================================================================
FShaderLayer::~FShaderLayer()
{
if (layerMask)
{
delete layerMask;
layerMask = NULL;
}
}
//==========================================================================
//
//
//
//==========================================================================
void FShaderLayer::Update(float diff)
{
r.Update(diff);
g.Update(diff);
b.Update(diff);
alpha.Update(diff);
vectorY.Update(diff);
vectorX.Update(diff);
scaleX.Update(diff);
scaleY.Update(diff);
adjustX.Update(diff);
adjustY.Update(diff);
offsetX += vectorX * diff;
if (offsetX >= 1.f) offsetX -= 1.f;
if (offsetX < 0.f) offsetX += 1.f;
offsetY += vectorY * diff;
if (offsetY >= 1.f) offsetY -= 1.f;
if (offsetY < 0.f) offsetY += 1.f;
rotation += rotate * diff;
if (rotation > 360.f) rotation -= 360.f;
if (rotation < 0.f) rotation += 360.f;
if (layerMask != NULL) layerMask->Update(diff);
}
//==========================================================================
//
//
//
//==========================================================================
struct FParseKey
{
const char *name;
int value;
};
static const FParseKey CycleTags[]=
{
{"linear", CYCLE_Linear},
{"sin", CYCLE_Sin},
{"cos", CYCLE_Cos},
{"sawtooth", CYCLE_SawTooth},
{"square", CYCLE_Square},
{NULL}
};
static const FParseKey BlendTags[]=
{
{"GL_ZERO", GL_ZERO},
{"GL_ONE", GL_ONE},
{"GL_DST_COLOR", GL_DST_COLOR},
{"GL_ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR},
{"GL_SRC_ALPHA", GL_SRC_ALPHA},
{"GL_ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA},
{"GL_DST_ALPHA", GL_DST_ALPHA},
{"GL_ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA},
{"GL_SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE},
{"GL_SRC_COLOR", GL_SRC_COLOR},
{"GL_ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR},
{NULL}
};
//==========================================================================
//
//
//
//==========================================================================
CycleType FShaderLayer::ParseCycleType(FScanner &sc)
{
if (sc.GetString())
{
int t = sc.MatchString(&CycleTags[0].name, sizeof(CycleTags[0]));
if (t > -1) return CycleType(CycleTags[t].value);
sc.UnGet();
}
return CYCLE_Linear;
}
//==========================================================================
//
//
//
//==========================================================================
bool FShaderLayer::ParseLayer(FScanner &sc)
{
bool retval = true;
float start, end, cycle, r1, r2, g1, g2, b1, b2;
int type;
if (sc.GetString())
{
texture = TexMan.CheckForTexture(sc.String, FTexture::TEX_Wall);
if (!texture.isValid())
{
sc.ScriptMessage("Unknown texture '%s'", sc.String);
retval = false;
}
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
if (sc.End)
{
sc.ScriptError("Unexpected end of file encountered");
return false;
}
if (sc.Compare("alpha"))
{
if (sc.CheckString("cycle"))
{
alpha.ShouldCycle(true);
alpha.SetCycleType(ParseCycleType(sc));
sc.GetFloat();
start = sc.Float;
sc.GetFloat();
end = sc.Float;
sc.GetFloat();
cycle = sc.Float;
alpha.SetParams(start, end, cycle);
}
else
{
sc.MustGetFloat();
alpha.SetParams(float(sc.Float), float(sc.Float), 0.f);
}
}
else if (sc.Compare("animate"))
{
sc.GetString();
animate = sc.Compare("true");
}
else if (sc.Compare("blendfunc"))
{
sc.GetString();
type = sc.MustMatchString(&BlendTags[0].name, sizeof(BlendTags[0]));
blendFuncSrc = BlendTags[type].value;
sc.GetString();
type = sc.MustMatchString(&BlendTags[0].name, sizeof(BlendTags[0]));
blendFuncDst = BlendTags[type].value;
}
else if (sc.Compare("color"))
{
if (sc.CheckString("cycle"))
{
CycleType type = ParseCycleType(sc);
r.ShouldCycle(true);
g.ShouldCycle(true);
b.ShouldCycle(true);
r.SetCycleType(type);
g.SetCycleType(type);
b.SetCycleType(type);
sc.GetFloat();
r1 = float(sc.Float);
sc.GetFloat();
g1 = float(sc.Float);
sc.GetFloat();
b1 = float(sc.Float);
// get color2
sc.GetFloat();
r2 = float(sc.Float);
sc.GetFloat();
g2 = float(sc.Float);
sc.GetFloat();
b2 = float(sc.Float);
// get cycle time
sc.GetFloat();
cycle = sc.Float;
r.SetParams(r1, r2, cycle);
g.SetParams(g1, g2, cycle);
b.SetParams(b1, b2, cycle);
}
else
{
sc.GetFloat();
r1 = float(sc.Float);
sc.GetFloat();
g1 = sc.Float;
sc.GetFloat();
b1 = sc.Float;
r.SetParams(r1, r1, 0.f);
g.SetParams(g1, g1, 0.f);
b.SetParams(b1, b1, 0.f);
}
}
else if (sc.Compare("center"))
{
sc.GetFloat();
centerX = sc.Float;
sc.GetFloat();
centerY = sc.Float;
}
else if (sc.Compare("emissive"))
{
sc.GetString();
emissive = sc.Compare("true");
}
else if (sc.Compare("offset"))
{
if (sc.CheckString("cycle"))
{
adjustX.ShouldCycle(true);
adjustY.ShouldCycle(true);
sc.GetFloat();
r1 = sc.Float;
sc.GetFloat();
r2 = sc.Float;
sc.GetFloat();
g1 = sc.Float;
sc.GetFloat();
g2 = sc.Float;
sc.GetFloat();
cycle = sc.Float;
offsetX = r1;
offsetY = r2;
adjustX.SetParams(0.f, g1 - r1, cycle);
adjustY.SetParams(0.f, g2 - r2, cycle);
}
else
{
sc.GetFloat();
offsetX = sc.Float;
sc.GetFloat();
offsetY = sc.Float;
}
}
else if (sc.Compare("offsetfunc"))
{
adjustX.SetCycleType(ParseCycleType(sc));
adjustY.SetCycleType(ParseCycleType(sc));
}
else if (sc.Compare("mask"))
{
if (layerMask != NULL) delete layerMask;
layerMask = new FShaderLayer;
layerMask->ParseLayer(sc);
}
else if (sc.Compare("rotate"))
{
sc.GetFloat();
rotate = sc.Float;
}
else if (sc.Compare("rotation"))
{
sc.GetFloat();
rotation = sc.Float;
}
else if (sc.Compare("scale"))
{
if (sc.CheckString("cycle"))
{
scaleX.ShouldCycle(true);
scaleY.ShouldCycle(true);
sc.GetFloat();
r1 = sc.Float;
sc.GetFloat();
r2 = sc.Float;
sc.GetFloat();
g1 = sc.Float;
sc.GetFloat();
g2 = sc.Float;
sc.GetFloat();
cycle = sc.Float;
scaleX.SetParams(r1, g1, cycle);
scaleY.SetParams(r2, g2, cycle);
}
else
{
sc.GetFloat();
scaleX.SetParams(sc.Float, sc.Float, 0.f);
sc.GetFloat();
scaleY.SetParams(sc.Float, sc.Float, 0.f);
}
}
else if (sc.Compare("scalefunc"))
{
scaleX.SetCycleType(ParseCycleType(sc));
scaleY.SetCycleType(ParseCycleType(sc));
}
else if (sc.Compare("texgen"))
{
sc.MustGetString();
if (sc.Compare("sphere"))
{
texgen = SHADER_TexGen_Sphere;
}
else
{
texgen = SHADER_TexGen_None;
}
}
else if (sc.Compare("vector"))
{
if (sc.CheckString("cycle"))
{
vectorX.ShouldCycle(true);
vectorY.ShouldCycle(true);
sc.GetFloat();
r1 = sc.Float;
sc.GetFloat();
g1 = sc.Float;
sc.GetFloat();
r2 = sc.Float;
sc.GetFloat();
g2 = sc.Float;
sc.GetFloat();
cycle = sc.Float;
vectorX.SetParams(r1, r2, cycle);
vectorY.SetParams(g1, g2, cycle);
}
else
{
sc.GetFloat();
vectorX.SetParams(sc.Float, sc.Float, 0.f);
sc.GetFloat();
vectorY.SetParams(sc.Float, sc.Float, 0.f);
}
}
else if (sc.Compare("vectorfunc"))
{
vectorX.SetCycleType(ParseCycleType(sc));
vectorY.SetCycleType(ParseCycleType(sc));
}
else if (sc.Compare("warp"))
{
if (sc.CheckNumber())
{
warp = sc.Number >= 0 && sc.Number <= 2? sc.Number : 0;
}
else
{
// compatibility with ZDoomGL
sc.MustGetString();
warp = sc.Compare("true");
}
}
else
{
sc.ScriptError("Unknown keyword '%s' in shader layer", sc.String);
}
}
}
return retval;
}
//==========================================================================
//
//
//
//==========================================================================
FTextureShader::FTextureShader()
{
layers.Clear();
lastUpdate = 0;
}
//==========================================================================
//
//
//
//==========================================================================
bool FTextureShader::ParseShader(FScanner &sc, TArray<FTextureID> &names)
{
bool retval = true;
if (sc.GetString())
{
name = sc.String;
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
if (sc.End)
{
sc.ScriptError("Unexpected end of file encountered");
return false;
}
else if (sc.Compare("layer"))
{
FShaderLayer *lay = new FShaderLayer;
if (lay->ParseLayer(sc))
{
layers.Push(lay);
}
else
{
delete lay;
retval = false;
}
}
else
{
sc.ScriptError("Unknown keyword '%s' in shader", sc.String);
}
}
}
return retval;
}
//==========================================================================
//
//
//
//==========================================================================
void FTextureShader::Update(int framems)
{
float diff = (framems - lastUpdate) / 1000.f;
if (lastUpdate != 0) // && !paused && !bglobal.freeze)
{
for (unsigned int i = 0; i < layers.Size(); i++)
{
layers[i]->Update(diff);
}
}
lastUpdate = framems;
}
//==========================================================================
//
//
//
//==========================================================================
void FTextureShader::FakeUpdate(int framems)
{
lastUpdate = framems;
}

View file

@ -0,0 +1,92 @@
#ifndef __GL_SHADERS_H__
#define __GL_SHADERS_H__
#include "tarray.h"
#include "gl/utility/gl_cycler.h"
enum
{
SHADER_TexGen_None = 0,
SHADER_TexGen_Sphere,
NUM_TexGenTypes
};
//==========================================================================
//
//
//
//==========================================================================
class FShaderLayer
{
public:
FShaderLayer();
FShaderLayer(const FShaderLayer &layer);
~FShaderLayer();
void Update(float diff);
CycleType ParseCycleType(FScanner &sc);
bool ParseLayer(FScanner &sc);
FTextureID texture;
int warpspeed;
unsigned char warp;
bool animate;
bool emissive;
unsigned char texgen;
float centerX, centerY;
float rotation;
float rotate;
float offsetX, offsetY;
FCycler adjustX, adjustY;
FCycler vectorX, vectorY;
FCycler scaleX, scaleY;
FCycler alpha;
FCycler r, g, b;
unsigned int flags;
unsigned int blendFuncSrc, blendFuncDst;
FShaderLayer *layerMask;
};
//==========================================================================
//
//
//
//==========================================================================
class FTextureShader
{
public:
FTextureShader();
bool ParseShader(FScanner &sc, TArray<FTextureID> &names);
bool Available();
bool Setup(float time);
void Update(int framems);
void FakeUpdate(int framems);
FName name;
TDeletingArray <FShaderLayer *> layers; // layers for shader
unsigned int lastUpdate;
};
/*
//extern TArray<FShader *> Shaders[NUM_ShaderClasses];
//extern TArray<FShader *> ShaderLookup[NUM_ShaderClasses];
void GL_InitShaders();
void GL_ReleaseShaders();
void GL_UpdateShaders();
void GL_FakeUpdateShaders();
//void GL_UpdateShader(FShader *shader);
void GL_DrawShaders();
//FShader *GL_ShaderForTexture(FTexture *tex);
bool GL_ParseShader();
*/
#endif // __GL_SHADERS_H__

View file

@ -1,11 +1,8 @@
/*
** gltexture.cpp
** The texture classes for hardware rendering
** (Even though they are named 'gl' there is nothing hardware dependent
** in this file. That is all encapsulated in the FHardwareTexture class.)
**
** gl_material.cpp
**
**---------------------------------------------------------------------------
** Copyright 2004-2005 Christoph Oelckers
** Copyright 2004-2009 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -531,6 +528,7 @@ FGLTexture * FMaterial::ValidateSysTexture(FTexture * tex, bool expand)
//
//===========================================================================
TArray<FMaterial *> FMaterial::mMaterials;
int FMaterial::mMaxBound;
FMaterial::FMaterial(FTexture * tx, bool forceexpand)
{
@ -541,29 +539,52 @@ FMaterial::FMaterial(FTexture * tx, bool forceexpand)
tx->UseType == FTexture::TEX_Decal ||
forceexpand;
tex = tx;
// FIXME: Should let the texture create the FGLTexture object.
FGLTexture *gltex = ValidateSysTexture(tx, expanded);
mTextures.Push(gltex);
// TODO: apply custom shader object here
/* if (tx->CustomShaderDefinition)
{
}
else
*/
// set default shader. Can be warp or brightmap
mShaderIndex = tx->bWarped;
if (!tx->bWarped && gl.shadermodel > 2)
if (tx->bWarped)
{
// todo: Get the proper texture shader
mShaderIndex = tx->bWarped;
expanded = false;
}
else if (gl.shadermodel > 2)
{
tx->CreateDefaultBrightmap();
if (tx->gl_info.Brightmap != NULL)
{
gltex = ValidateSysTexture(tx->gl_info.Brightmap, expanded);
mTextures.Push(gltex);
ValidateSysTexture(tx->gl_info.Brightmap, expanded);
FTextureLayer layer = {tx->gl_info.Brightmap, false};
mTextureLayers.Push(layer);
// todo: Get the proper texture shader
mShaderIndex = 3;
}
}
mTextures.ShrinkToFit();
if (!expanded)
{
// check if the texture is just a simple redirect to a patch
// If so we should use the patch for texture creation to
// avoid eventual redundancies. For textures that need to
// be expanded at the edges this may not be done though.
// Warping can be ignored with SM4 because it's always done
// by shader
tex = tx->GetRedirect(gl.shadermodel < 4);
}
else tex = tx;
// make sure the system texture is valid
mBaseLayer = ValidateSysTexture(tex, expanded);
mTextureLayers.ShrinkToFit();
mMaxBound = -1;
mMaterials.Push(this);
tex->gl_info.Material = this;
tx->gl_info.Material = this;
}
//===========================================================================
@ -574,7 +595,6 @@ FMaterial::FMaterial(FTexture * tx, bool forceexpand)
FMaterial::~FMaterial()
{
//if (tex != NULL && tex->gl_info.Material == this) tex->gl_info.Material = NULL;
for(unsigned i=0;i<mMaterials.Size();i++)
{
if (mMaterials[i]==this)
@ -600,13 +620,24 @@ const WorldTextureInfo * FMaterial::Bind(int cm, int clampmode, int translation)
int softwarewarp = gl_RenderState.SetupShader(tex->bHasCanvas, shaderindex, cm, tex->bWarped? static_cast<FWarpTexture*>(tex)->GetSpeed() : 1.f);
const WorldTextureInfo *inf = mTextures[0]->Bind(0, cm, clampmode, translation, softwarewarp);
const WorldTextureInfo *inf = mBaseLayer->Bind(0, cm, clampmode, translation, softwarewarp);
if (inf != NULL && shaderindex > 0)
{
for(unsigned i=1;i<mTextures.Size();i++)
for(unsigned i=0;i<mTextureLayers.Size();i++)
{
mTextures[i]->Bind(i, CM_DEFAULT, clampmode, 0, false);
maxbound = i;
FTexture *tex;
if (mTextureLayers[i].animated)
{
FTextureID id = mTextureLayers[i].texture->GetID();
tex = TexMan(id);
ValidateSysTexture(tex, false);
}
else
{
tex = mTextureLayers[i].texture;
}
tex->gl_info.SystemTexture->Bind(i+1, CM_DEFAULT, clampmode, 0, false);
maxbound = i+1;
}
}
// unbind everything from the last texture that's still active
@ -633,14 +664,12 @@ const PatchTextureInfo * FMaterial::BindPatch(int cm, int translation)
int softwarewarp = gl_RenderState.SetupShader(tex->bHasCanvas, shaderindex, cm, tex->bWarped? static_cast<FWarpTexture*>(tex)->GetSpeed() : 1.f);
const PatchTextureInfo *inf = mTextures[0]->BindPatch(0, cm, translation, softwarewarp);
if (inf != NULL && shaderindex > 0)
const PatchTextureInfo *inf = mBaseLayer->BindPatch(0, cm, translation, softwarewarp);
// The only multitexture effect usable on sprites is the brightmap.
if (inf != NULL && shaderindex == 3)
{
for(unsigned i=1;i<mTextures.Size();i++)
{
mTextures[i]->BindPatch(i, CM_DEFAULT, 0, softwarewarp);
maxbound = i;
}
mTextureLayers[0].texture->gl_info.SystemTexture->BindPatch(1, CM_DEFAULT, 0, 0);
maxbound = 1;
}
// unbind everything from the last texture that's still active
for(int i=maxbound+1; i<=mMaxBound;i++)
@ -660,21 +689,21 @@ const PatchTextureInfo * FMaterial::BindPatch(int cm, int translation)
void FMaterial::SetWallScaling(fixed_t x, fixed_t y)
{
if (x != mTextures[0]->tempScaleX)
if (x != mBaseLayer->tempScaleX)
{
fixed_t scale_x = FixedMul(x, tex->xScale);
int foo = (mTextures[0]->Width[GLUSE_TEXTURE] << 17) / scale_x;
mTextures[0]->RenderWidth[GLUSE_TEXTURE] = (foo >> 1) + (foo & 1);
mTextures[0]->scalex = scale_x/(float)FRACUNIT;
mTextures[0]->tempScaleX = x;
int foo = (mBaseLayer->Width[GLUSE_TEXTURE] << 17) / scale_x;
mBaseLayer->RenderWidth[GLUSE_TEXTURE] = (foo >> 1) + (foo & 1);
mBaseLayer->scalex = scale_x/(float)FRACUNIT;
mBaseLayer->tempScaleX = x;
}
if (y != mTextures[0]->tempScaleY)
if (y != mBaseLayer->tempScaleY)
{
fixed_t scale_y = FixedMul(y, tex->yScale);
int foo = (mTextures[0]->Height[GLUSE_TEXTURE] << 17) / scale_y;
mTextures[0]->RenderHeight[GLUSE_TEXTURE] = (foo >> 1) + (foo & 1);
mTextures[0]->scaley = scale_y/(float)FRACUNIT;
mTextures[0]->tempScaleY = y;
int foo = (mBaseLayer->Height[GLUSE_TEXTURE] << 17) / scale_y;
mBaseLayer->RenderHeight[GLUSE_TEXTURE] = (foo >> 1) + (foo & 1);
mBaseLayer->scaley = scale_y/(float)FRACUNIT;
mBaseLayer->tempScaleY = y;
}
}
@ -686,15 +715,15 @@ void FMaterial::SetWallScaling(fixed_t x, fixed_t y)
fixed_t FMaterial::RowOffset(fixed_t rowoffset) const
{
if (mTextures[0]->tempScaleX == FRACUNIT)
if (mBaseLayer->tempScaleX == FRACUNIT)
{
if (mTextures[0]->scaley==1.f || tex->bWorldPanning) return rowoffset;
else return quickertoint(rowoffset/mTextures[0]->scaley);
if (mBaseLayer->scaley==1.f || tex->bWorldPanning) return rowoffset;
else return quickertoint(rowoffset/mBaseLayer->scaley);
}
else
{
if (tex->bWorldPanning) return FixedDiv(rowoffset, mTextures[0]->tempScaleY);
else return quickertoint(rowoffset/mTextures[0]->scaley);
if (tex->bWorldPanning) return FixedDiv(rowoffset, mBaseLayer->tempScaleY);
else return quickertoint(rowoffset/mBaseLayer->scaley);
}
}
@ -706,15 +735,15 @@ fixed_t FMaterial::RowOffset(fixed_t rowoffset) const
fixed_t FMaterial::TextureOffset(fixed_t textureoffset) const
{
if (mTextures[0]->tempScaleX == FRACUNIT)
if (mBaseLayer->tempScaleX == FRACUNIT)
{
if (mTextures[0]->scalex==1.f || tex->bWorldPanning) return textureoffset;
else return quickertoint(textureoffset/mTextures[0]->scalex);
if (mBaseLayer->scalex==1.f || tex->bWorldPanning) return textureoffset;
else return quickertoint(textureoffset/mBaseLayer->scalex);
}
else
{
if (tex->bWorldPanning) return FixedDiv(textureoffset, mTextures[0]->tempScaleX);
else return quickertoint(textureoffset/mTextures[0]->scalex);
if (tex->bWorldPanning) return FixedDiv(textureoffset, mBaseLayer->tempScaleX);
else return quickertoint(textureoffset/mBaseLayer->scalex);
}
}
@ -729,10 +758,10 @@ fixed_t FMaterial::TextureAdjustWidth(ETexUse i) const
{
if (tex->bWorldPanning)
{
if (i == GLUSE_PATCH || mTextures[0]->tempScaleX == FRACUNIT) return mTextures[0]->RenderWidth[i];
else return FixedDiv(mTextures[0]->Width[i], mTextures[0]->tempScaleX);
if (i == GLUSE_PATCH || mBaseLayer->tempScaleX == FRACUNIT) return mBaseLayer->RenderWidth[i];
else return FixedDiv(mBaseLayer->Width[i], mBaseLayer->tempScaleX);
}
else return mTextures[0]->Width[i];
else return mBaseLayer->Width[i];
}
//===========================================================================
@ -743,13 +772,13 @@ fixed_t FMaterial::TextureAdjustWidth(ETexUse i) const
void FMaterial::BindToFrameBuffer()
{
if (mTextures[0]->gltexture == NULL)
if (mBaseLayer->gltexture == NULL)
{
// must create the hardware texture first
mTextures[0]->Bind(0, CM_DEFAULT, 0, 0, false);
mBaseLayer->Bind(0, CM_DEFAULT, 0, 0, false);
FHardwareTexture::Unbind(0);
}
mTextures[0]->gltexture->BindToFrameBuffer();
mBaseLayer->gltexture->BindToFrameBuffer();
}
//===========================================================================
@ -806,6 +835,13 @@ void FMaterial::FlushAll()
{
mMaterials[i]->Clean(true);
}
// This is for shader layers. All shader layers must be managed by the texture manager
// so this will catch everything.
for(int i=TexMan.NumTextures()-1;i>=0;i--)
{
FGLTexture *gltex = TexMan.ByIndex(i)->gl_info.SystemTexture;
if (gltex != NULL) gltex->Clean(true);
}
}
//==========================================================================

View file

@ -10,6 +10,7 @@
EXTERN_CVAR(Bool, gl_precache)
struct FRemapTable;
class FTextureShader;
// Two intermediate classes which wrap the low level textures.
@ -145,10 +146,18 @@ public:
class FMaterial
{
struct FTextureLayer
{
FTexture *texture;
bool animated;
};
static TArray<FMaterial *> mMaterials;
TArray<FGLTexture *> mTextures;
static int mMaxBound;
FGLTexture *mBaseLayer;
TArray<FTextureLayer> mTextureLayers;
int mShaderIndex;
int mMaxBound;
void SetupShader(int shaderindex, int &cm);
FGLTexture * ValidateSysTexture(FTexture * tex, bool expand);
@ -162,20 +171,17 @@ public:
const WorldTextureInfo * Bind(int cm, int clamp=0, int translation=0);
const PatchTextureInfo * BindPatch(int cm, int translation=0);
const WorldTextureInfo * GetWorldTextureInfo() { return mTextures[0]->GetWorldTextureInfo(); }
const PatchTextureInfo * GetPatchTextureInfo() { return mTextures[0]->GetPatchTextureInfo(); }
const WorldTextureInfo * GetWorldTextureInfo() { return mBaseLayer->GetWorldTextureInfo(); }
const PatchTextureInfo * GetPatchTextureInfo() { return mBaseLayer->GetPatchTextureInfo(); }
unsigned char * CreateTexBuffer(ETexUse use, int cm, int translation, int & w, int & h, bool allowhires=true)
{
return mTextures[0]->CreateTexBuffer(use, cm, translation, w, h, allowhires, 0);
return mBaseLayer->CreateTexBuffer(use, cm, translation, w, h, allowhires, 0);
}
void Clean(bool f)
{
for(unsigned i=0;i<mTextures.Size();i++)
{
mTextures[i]->Clean(f);
}
mBaseLayer->Clean(f);
}
void BindToFrameBuffer();
@ -185,8 +191,8 @@ public:
void SetWallScaling(fixed_t x, fixed_t y);
int TextureHeight(ETexUse i) const { return mTextures[0]->RenderHeight[i]; }
int TextureWidth(ETexUse i) const { return mTextures[0]->RenderWidth[i]; }
int TextureHeight(ETexUse i) const { return mBaseLayer->RenderHeight[i]; }
int TextureWidth(ETexUse i) const { return mBaseLayer->RenderWidth[i]; }
int GetAreaCount() const { return tex->gl_info.areacount; }
FloatRect *GetAreas() const { return tex->gl_info.areas; }
@ -199,42 +205,42 @@ public:
int GetWidth(ETexUse i) const
{
return mTextures[0]->Width[i];
return mBaseLayer->Width[i];
}
int GetHeight(ETexUse i) const
{
return mTextures[0]->Height[i];
return mBaseLayer->Height[i];
}
int GetLeftOffset(ETexUse i) const
{
return mTextures[0]->LeftOffset[i];
return mBaseLayer->LeftOffset[i];
}
int GetTopOffset(ETexUse i) const
{
return mTextures[0]->TopOffset[i];
return mBaseLayer->TopOffset[i];
}
int GetScaledLeftOffset(ETexUse i) const
{
return DivScale16(mTextures[0]->LeftOffset[i], tex->xScale);
return DivScale16(mBaseLayer->LeftOffset[i], tex->xScale);
}
int GetScaledTopOffset(ETexUse i) const
{
return DivScale16(mTextures[0]->TopOffset[i], tex->yScale);
return DivScale16(mBaseLayer->TopOffset[i], tex->yScale);
}
bool GetTransparent()
{
if (mTextures[0]->bIsTransparent == -1)
if (mBaseLayer->bIsTransparent == -1)
{
if (tex->UseType==FTexture::TEX_Sprite) BindPatch(CM_DEFAULT, 0);
else Bind (CM_DEFAULT, 0, 0);
}
return !!mTextures[0]->bIsTransparent;
return !!mBaseLayer->bIsTransparent;
}
static void DeleteAll();

View file

@ -245,7 +245,8 @@ FTexture::MiscGLInfo::~MiscGLInfo()
if (SystemTexture != NULL) delete SystemTexture;
SystemTexture = NULL;
if (Brightmap != NULL) delete Brightmap;
// this is managed by the texture manager so it may not be deleted here.
//if (Brightmap != NULL) delete Brightmap;
Brightmap = NULL;
if (areas != NULL) delete [] areas;
@ -284,6 +285,7 @@ void FTexture::CreateDefaultBrightmap()
DPrintf("brightmap created for texture '%s'\n", Name);
gl_info.Brightmap = new FBrightmapTexture(this);
gl_info.bBrightmapChecked = 1;
TexMan.AddTexture(gl_info.Brightmap);
return;
}
}
@ -357,6 +359,7 @@ void FTexture::GetGlowColor(float *data)
// Gets the average color of a texture for use as a sky cap color
//
//===========================================================================
PalEntry FTexture::GetSkyCapColor(bool bottom)
{
PalEntry col;
@ -389,6 +392,7 @@ PalEntry FTexture::GetSkyCapColor(bool bottom)
// This was mainly added to speed up one area in E4M6 of 007LTSD
//
//===========================================================================
bool FTexture::FindHoles(const unsigned char * buffer, int w, int h)
{
const unsigned char * li;
@ -503,6 +507,7 @@ void FTexture::CheckTrans(unsigned char * buffer, int size, int trans)
// smooth the edges of transparent fields in the texture
//
//===========================================================================
#ifdef WORDS_BIGENDIAN
#define MSB 0
#define SOME_MASK 0xffffff00
@ -573,8 +578,6 @@ bool FTexture::ProcessData(unsigned char * buffer, int w, int h, bool ispatch)
return true;
}
//===========================================================================
//
// fake brightness maps
@ -598,7 +601,6 @@ FBrightmapTexture::FBrightmapTexture (FTexture *source)
FBrightmapTexture::~FBrightmapTexture ()
{
Unload();
}
const BYTE *FBrightmapTexture::GetColumn (unsigned int column, const Span **spans_out)
@ -752,20 +754,30 @@ void gl_ParseBrightmap(FScanner &sc, int deflump)
Printf("Cannot combine warping with brightmap on texture '%s'\n", tex->Name);
return;
}
FTexture *brightmap = FTexture::CreateTexture(maplump, tex->UseType);
if (!brightmap)
// Brightmap textures are stored in the texture manager so that multiple
// instances of the same textures can be avoided.
FTexture *brightmap;
FTextureID brightmapId = TexMan.FindTextureByLumpNum(maplump);
if (!brightmapId.isValid())
{
Printf("Unable to create texture from '%s' in brightmap definition for '%s'\n",
maplumpname.GetChars(), tex->Name);
return;
// a texture for this lump has not been created yet.
brightmap = FTexture::CreateTexture(maplump, tex->UseType);
if (!brightmap)
{
Printf("Unable to create texture from '%s' in brightmap definition for '%s'\n",
maplumpname.GetChars(), tex->Name);
return;
}
brightmap->gl_info.bBrightmap = true;
}
if (tex->gl_info.Brightmap != NULL)
else
{
// If there is already a brightmap assigned replace it
delete tex->gl_info.Brightmap;
brightmap = TexMan[brightmapId];
}
tex->gl_info.Brightmap = brightmap;
brightmap->gl_info.bBrightmap = true;
}
tex->gl_info.bBrightmapDisablesFullbright = disable_fullbright;
}

View file

@ -146,6 +146,7 @@ FTexture::FTexture (const char *name, int lumpnum)
bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false),
Rotations(0xFFFF), Width(0), Height(0), WidthMask(0), Native(NULL)
{
id.SetInvalid();
if (name != NULL)
{
uppercopy(Name, name);

View file

@ -320,7 +320,7 @@ FTextureID FTextureManager::AddTexture (FTexture *texture)
int trans = Textures.Push (hasher);
Translation.Push (trans);
if (bucket >= 0) HashFirst[bucket] = trans;
return FTextureID(trans);
return (texture->id = FTextureID(trans));
}
//==========================================================================
@ -365,10 +365,15 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, b
newtexture->UseType = oldtexture->UseType;
Textures[index].Texture = newtexture;
newtexture->id = oldtexture->id;
if (free)
{
delete oldtexture;
}
else
{
oldtexture->id.SetInvalid();
}
}
//==========================================================================

View file

@ -123,6 +123,7 @@ public:
fixed_t yScale;
int SourceLump;
FTextureID id;
union
{
@ -179,6 +180,7 @@ public:
virtual bool UseBasePalette();
virtual int GetSourceLump() { return SourceLump; }
virtual FTexture *GetRedirect(bool wantwarped);
FTextureID GetID() const { return id; }
virtual void Unload () = 0;

View file

@ -21,8 +21,73 @@ void main()
#ifndef NO_GLOW
glowdist = glowdistance;
#endif
#ifdef SPHEREMAP
vec3 u = normalize(eyeCoordPos.xyz);
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 r = reflect(u, n);
float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) );
vec2 sst = vec2(r.x/m + 0.5, r.y/m + 0.5);
#endif
#ifndef SPHEREMAP_0
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
#else
gl_TexCoord[0] = sst;
#endif
#if NUM_LAYERS > 1
#ifndef SPHEREMAP_1
gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord0;
#else
gl_TexCoord[1] = sst;
#endif
#endif
#if NUM_LAYERS > 2
#ifndef SPHEREMAP_2
gl_TexCoord[2] = gl_TextureMatrix[2] * gl_MultiTexCoord0;
#else
gl_TexCoord[2] = sst;
#endif
#endif
#if NUM_LAYERS > 3
#ifndef SPHEREMAP_3
gl_TexCoord[3] = gl_TextureMatrix[3] * gl_MultiTexCoord0;
#else
gl_TexCoord[3] = sst;
#endif
#endif
#if NUM_LAYERS > 4
#ifndef SPHEREMAP_4
gl_TexCoord[4] = gl_TextureMatrix[4] * gl_MultiTexCoord0;
#else
gl_TexCoord[4] = sst;
#endif
#endif
#if NUM_LAYERS > 5
#ifndef SPHEREMAP_5
gl_TexCoord[5] = gl_TextureMatrix[5] * gl_MultiTexCoord0;
#else
gl_TexCoord[5] = sst;
#endif
#endif
#if NUM_LAYERS > 6
#ifndef SPHEREMAP_6
gl_TexCoord[6] = gl_TextureMatrix[6] * gl_MultiTexCoord0;
#else
gl_TexCoord[6] = sst;
#endif
#endif
#if NUM_LAYERS > 7
#ifndef SPHEREMAP_7
gl_TexCoord[7] = gl_TextureMatrix[7] * gl_MultiTexCoord0;
#else
gl_TexCoord[7] = sst;
#endif
#endif
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_Position = ftransform();
#ifdef __GLSL_CG_DATA_TYPES
gl_ClipVertex = eyeCoordPos;

View file

@ -1,10 +0,0 @@
void main()
{
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_Position = ftransform();
#ifdef __GLSL_CG_DATA_TYPES
gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
#endif
}

View file

@ -1,35 +0,0 @@
#ifndef NO_FOG
varying vec4 pixelpos;
#endif
#ifndef NO_GLOW
varying vec2 glowdist;
attribute vec2 glowdistance;
#endif
void main()
{
vec4 eyeCoordPos = gl_ModelViewMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
#ifndef NO_FOG
pixelpos.xyz = gl_Vertex.xyz;
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
#endif
#ifndef NO_GLOW
glowdist = glowdistance;
#endif
vec3 u = normalize(eyeCoordPos.xyz);
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 r = reflect(u, n);
float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) );
gl_TexCoord[0].st = vec2(r.x/m + 0.5, r.y/m + 0.5);
gl_Position = ftransform();
#ifdef __GLSL_CG_DATA_TYPES
gl_ClipVertex = eyeCoordPos;
#endif
}