Skip to content

Commit

Permalink
Add test for light wireframe shader
Browse files Browse the repository at this point in the history
Since the Shader interface doesn't expose very much information that can be
examined in tests, the shader system now attaches an internal dummy Material to
any shader which doesn't have a Material of its own. Currently this internal
Material only exposes the name used to construct the shader, and it is this
which is tested to confirm that the light wireframe shader matches the
editor_color value.

In order to make it easier to construct this new InternalMaterial class, all
public virtuals on the Material interface are now non-pure, with empty default
implementations. This in turn required a couple of method signatures to be
changed to return by value rather than by const reference.
  • Loading branch information
Matthew Mott committed Feb 13, 2021
1 parent b8dbc7d commit e52ceae
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 207 deletions.
4 changes: 2 additions & 2 deletions include/ieclasscolours.h
Expand Up @@ -11,7 +11,7 @@ namespace eclass

/**
* Manages the entity class colour overrides that are applied
* to certain eclasses as defined in the currently active
* to certain eclasses as defined in the currently active
* colour scheme.
*/
class IColourManager :
Expand All @@ -28,7 +28,7 @@ class IColourManager :
virtual void addOverrideColour(const std::string& eclass, const Vector3& colour) = 0;

// Applies a possible colour override to the given entity class
virtual void applyColours(const IEntityClassPtr& eclass) = 0;
virtual void applyColours(IEntityClass& eclass) = 0;

// Visit each override definition with the given functor
virtual void foreachOverrideColour(const std::function<void(const std::string&, const Vector3&)>& functor) = 0;
Expand Down
172 changes: 72 additions & 100 deletions include/ishaders.h
Expand Up @@ -26,12 +26,15 @@ typedef std::shared_ptr<MapExpression> MapExpressionPtr;
} // namespace shaders

/**
* \brief
* Interface for a material shader.
* \brief Interface for a material shader.
*
* A material shader consists of global parameters, an editor image, and zero
* or more shader layers (including diffusemap, bumpmap and specularmap
* textures which are handled specially).
*
* A material shader consists of global parameters, an editor image, and zero or
* more shader layers (including diffusemap, bumpmap and specularmap textures
* which are handled specially).
* Most material shaders are defined in .mtr files within the mod asset tree,
* but there are also internal materials generated for Radiant-specific
* internal OpenGL shaders, such as those used to render wireframes.
*/
class Material
{
Expand Down Expand Up @@ -135,7 +138,7 @@ class Material
SORT_POST_PROCESS = 100 // after a screen copy to texture
};

// Deform Type
// Deform Type
enum DeformType
{
DEFORM_NONE,
Expand Down Expand Up @@ -168,165 +171,134 @@ class Material

virtual ~Material() {}

/**
* \brief
* Return the editor image texture for this shader.
*/
virtual TexturePtr getEditorImage() = 0;
/// Return the editor image texture for this shader.
virtual TexturePtr getEditorImage() { return {}; }

/**
* \brief
* Return true if the editor image is no tex for this shader.
*/
virtual bool isEditorImageNoTex() = 0;
/// Return true if the editor image is no tex for this shader.
virtual bool isEditorImageNoTex() { return false; }

/**
* \brief
* Get the string name of this shader.
*/
/// Get the string name of this material
virtual std::string getName() const = 0;

virtual bool IsInUse() const = 0;
virtual void SetInUse(bool bInUse) = 0;
// test if it's a true shader, or a default shader created to wrap around a texture
virtual bool IsDefault() const = 0;
// get shader file name (ie the file where this one is defined)
virtual const char* getShaderFileName() const = 0;
virtual bool IsInUse() const { return true; }
virtual void SetInUse(bool bInUse) {}

/// Return true if this is an internal material not corresponding to a .mtr
virtual bool IsDefault() const { return false; }

/// get shader file name (ie the file where this one is defined)
virtual const char* getShaderFileName() const { return ""; }

// Returns the VFS info structure of the file this shader is defined in
virtual const vfs::FileInfo& getShaderFileInfo() const = 0;
virtual const vfs::FileInfo* getShaderFileInfo() const { return nullptr; }

/**
* \brief
* Return the requested sort position of this material.
* \brief Return the requested sort position of this material.
*
* greebo: D3 is using floating points for the sort value but
* as far as I can see only rounded numbers have been used.
*/
virtual int getSortRequest() const = 0;
virtual int getSortRequest() const { return 0; }

/**
* \brief
* Return a polygon offset if one is defined. The default is 0.
*/
virtual float getPolygonOffset() const = 0;
/// Return a polygon offset if one is defined. The default is 0.
virtual float getPolygonOffset() const { return 0; }

/**
* Get the desired texture repeat behaviour.
*/
virtual ClampType getClampType() const = 0;
/// Get the desired texture repeat behaviour.
virtual ClampType getClampType() const { return CLAMP_REPEAT; }

// Get the cull type (none, back, front)
virtual CullType getCullType() const = 0;
/// Get the cull type (none, back, front)
virtual CullType getCullType() const { return CULL_BACK; }

/**
* Get the global material flags (translucent, noshadows, etc.)
*/
virtual int getMaterialFlags() const = 0;
/// Get the global material flags (translucent, noshadows, etc.)
virtual int getMaterialFlags() const { return 0; }

/**
* Surface flags (areaportal, nonsolid, etc.)
*/
virtual int getSurfaceFlags() const = 0;
/// Surface flags (areaportal, nonsolid, etc.)
virtual int getSurfaceFlags() const { return 0; }

/**
* Surface Type (wood, stone, surfType15, ...)
*/
virtual SurfaceType getSurfaceType() const = 0;
/// Surface Type (wood, stone, surfType15, ...)
virtual SurfaceType getSurfaceType() const { return SURFTYPE_DEFAULT; }

/**
* Get the deform type of this material
*/
virtual DeformType getDeformType() const = 0;
/// Get the deform type of this material
virtual DeformType getDeformType() const { return DEFORM_NONE; }

/**
* Returns the spectrum of this shader, -1 means "no defined spectrum"
*/
virtual int getSpectrum() const = 0;
/// Returns the spectrum of this shader, -1 means "no defined spectrum"
virtual int getSpectrum() const { return -1; }

/**
* Retrieves the decal info structure of this material.
*/
virtual const DecalInfo& getDecalInfo() const = 0;
/// Retrieves the decal info structure of this material.
virtual DecalInfo getDecalInfo() const { return {}; }

/**
* Returns the coverage type of this material, also needed
* by the map compiler.
*/
virtual Coverage getCoverage() const = 0;
/// Returns the coverage type of this material, also needed by the map compiler.
virtual Coverage getCoverage() const { return MC_OPAQUE; }

/**
* Returns the raw shader definition block, as parsed by the material manager.
* The definition is lacking the outermost curly braces.
*/
virtual std::string getDefinition() = 0;
virtual std::string getDefinition() { return {}; }

/** Determine whether this is an ambient light shader, i.e. the
* material def contains the global "ambientLight" keyword.
*/
virtual bool isAmbientLight() const = 0;
virtual bool isAmbientLight() const { return false; }

/** Determine whether this is an blend light shader, i.e. the
* material def contains the global "blendLight" keyword.
*/
virtual bool isBlendLight() const = 0;
virtual bool isBlendLight() const { return false; }

/** Determine whether this is an fog light shader, i.e. the
* material def contains the global "fogLight" keyword.
*/
virtual bool isFogLight() const = 0;
virtual bool isFogLight() const { return false; }

/**
* For light shaders: implicitly no-shadows lights (ambients, fogs, etc)
* For light shaders: implicitly no-shadows lights (ambients, fogs, etc)
* will never cast shadows but individual light entities can also override this value.
*/
virtual bool lightCastsShadows() const = 0;
virtual bool lightCastsShadows() const { return true; }

// returns true if the material will generate shadows, not making a
// distinction between global and no-self shadows
virtual bool surfaceCastsShadow() const = 0;
virtual bool surfaceCastsShadow() const { return true; }

/**
* returns true if the material will draw anything at all. Triggers, portals,
* etc, will not have anything to draw. A not drawn surface can still castShadow,
* which can be used to make a simplified shadow hull for a complex object set as noShadow.
*/
virtual bool isDrawn() const = 0;
virtual bool isDrawn() const { return true; }

/**
* a discrete surface will never be merged with other surfaces by dmap, which is
* necessary to prevent mutliple gui surfaces, mirrors, autosprites, and some other
* special effects from being combined into a single surface
* guis, merging sprites or other effects, mirrors and remote views are always discrete
*/
virtual bool isDiscrete() const = 0;
virtual bool isDiscrete() const { return false; }

virtual ShaderLayer* firstLayer() const = 0;
/// Return the first material layer, if any
virtual ShaderLayer* firstLayer() const { return nullptr; }

/**
* \brief
* Return a std::vector containing all layers in this material shader.
* \brief Return a std::vector containing all layers in this material
* shader.
*
* This includes all diffuse, bump, specular or blend layers.
*/
virtual const ShaderLayerVector& getAllLayers() const = 0;
virtual ShaderLayerVector getAllLayers() const { return {}; }

virtual TexturePtr lightFalloffImage() = 0;
/// Return the 2D light falloff texture, if this is a light shader
virtual TexturePtr lightFalloffImage() { return {}; }

// greebo: Returns the description as defined in the material
virtual std::string getDescription() const = 0;
virtual std::string getDescription() const { return {}; }

/**
* greebo: Returns TRUE if the shader is visible, FALSE if it
* is filtered or disabled in any other way.
*/
virtual bool isVisible() const = 0;
/// Return TRUE if the shader is visible, FALSE if it is filtered or
/// disabled in any other way.
virtual bool isVisible() const { return true; }

/**
* greebo: Sets the visibility of this shader.
*/
virtual void setVisible(bool visible) = 0;
/// Sets the visibility of this shader.
virtual void setVisible(bool visible) {}
};

typedef std::shared_ptr<Material> MaterialPtr;
Expand Down Expand Up @@ -383,12 +355,12 @@ class MaterialManager
virtual bool isRealised() = 0;

// Signal which is invoked when the materials defs have been parsed
// Note that the DEF files might be parsed in a separate thread so
// any call acquiring material info might need to block and wait for
// Note that the DEF files might be parsed in a separate thread so
// any call acquiring material info might need to block and wait for
// that background call to finish before it can yield results.
virtual sigc::signal<void>& signal_DefsLoaded() = 0;

// Signal invoked when the material defs have been unloaded due
// Signal invoked when the material defs have been unloaded due
// to a filesystem or other configuration change
virtual sigc::signal<void>& signal_DefsUnloaded() = 0;

Expand Down Expand Up @@ -454,7 +426,7 @@ class MaterialManager
/**
* Creates a new shader expression for the given string. This can be used to create standalone
* expression objects for unit testing purposes.
*/
*/
virtual shaders::IShaderExpressionPtr createShaderExpressionFromString(const std::string& exprStr) = 0;
};

Expand Down
2 changes: 1 addition & 1 deletion libs/wxutil/preview/GuiRenderer.cpp
Expand Up @@ -112,7 +112,7 @@ void GuiRenderer::render(const gui::IGuiWindowDefPtr& window, bool ignoreFilter)
if (window->backgroundShader != NULL && (matcolor[3] > 0 || _ignoreVisibility))
{
// Get the diffuse layer
const ShaderLayerVector& layers = window->backgroundShader->getAllLayers();
const ShaderLayerVector layers = window->backgroundShader->getAllLayers();

TexturePtr tex;

Expand Down
10 changes: 4 additions & 6 deletions radiantcore/eclass/EClassColourManager.cpp
Expand Up @@ -12,17 +12,15 @@ void EClassColourManager::addOverrideColour(const std::string& eclass, const Vec
_overrideChangedSignal.emit(eclass, false); // false ==> colour added
}

void EClassColourManager::applyColours(const IEntityClassPtr& eclass)
void EClassColourManager::applyColours(IEntityClass& eclass)
{
assert(eclass);

auto foundOverride = _overrides.find(eclass->getName());
auto foundOverride = _overrides.find(eclass.getName());

if (foundOverride != _overrides.end())
{
rDebug() << "Applying colour " << foundOverride->second << " to eclass " << eclass->getName() << std::endl;
rDebug() << "Applying colour " << foundOverride->second << " to eclass " << eclass.getName() << std::endl;

eclass->setColour(foundOverride->second);
eclass.setColour(foundOverride->second);
}
}

Expand Down
2 changes: 1 addition & 1 deletion radiantcore/eclass/EClassColourManager.h
Expand Up @@ -17,7 +17,7 @@ class EClassColourManager :
// IColourManager implementation

void addOverrideColour(const std::string& eclass, const Vector3& colour) override;
void applyColours(const IEntityClassPtr& eclass) override;
void applyColours(IEntityClass& eclass) override;
void foreachOverrideColour(const std::function<void(const std::string&, const Vector3&)>& functor) override;
void removeOverrideColour(const std::string& eclass) override;
void clearOverrideColours() override;
Expand Down
10 changes: 5 additions & 5 deletions radiantcore/eclass/EClassManager.cpp
Expand Up @@ -66,7 +66,7 @@ IEntityClassPtr EClassManager::findOrInsert(const std::string& name, bool has_br
eclass = Doom3EntityClass::create(lName, true);

// Any overrides should also apply to entityDefs that are crated on the fly
GlobalEclassColourManager().applyColours(eclass);
GlobalEclassColourManager().applyColours(*eclass);

// Try to insert the class
return insertUnique(eclass);
Expand Down Expand Up @@ -204,7 +204,7 @@ void EClassManager::applyColours()

void EClassManager::realise()
{
if (_realised)
if (_realised)
{
return; // nothing to do anymore
}
Expand Down Expand Up @@ -338,7 +338,7 @@ void EClassManager::shutdownModule()

// Unrealise ourselves and wait for threads to finish
unrealise();

// Don't notify anyone anymore
_defsReloadedSignal.clear();

Expand Down Expand Up @@ -366,15 +366,15 @@ void EClassManager::onEclassOverrideColourChanged(const std::string& eclass, boo
}
else
{
GlobalEclassColourManager().applyColours(foundEclass->second);
GlobalEclassColourManager().applyColours(*foundEclass->second);
}
}

// This takes care of relading the entityDefs and refreshing the scenegraph
void EClassManager::reloadDefsCmd(const cmd::ArgumentList& args)
{
radiant::ScopedLongRunningOperation operation(_("Reloading Defs"));

reloadDefs();
}

Expand Down

0 comments on commit e52ceae

Please sign in to comment.