X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=include%2Fishaders.h;h=ac447090cbd99fb9cde9aeade1cf8d833113e375;hb=17f10f6affeb825b156a97c9633f9774f8b33c57;hp=5ade595666e77c935b24a9b8ee25134adc9613e7;hpb=830125fad042fad35dc029b6eb57c8156ad7e176;p=xonotic%2Fnetradiant.git diff --git a/include/ishaders.h b/include/ishaders.h index 5ade5956..ac447090 100644 --- a/include/ishaders.h +++ b/include/ishaders.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1999-2007 id Software, Inc. and contributors. + Copyright (C) 1999-2006 Id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. @@ -19,267 +19,175 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -//----------------------------------------------------------------------------- -// -// -// DESCRIPTION: -// a set of functions to manipulate textures in Radiant -// - -#ifndef __ISHADERS_H_ -#define __ISHADERS_H_ - -#define SHADERS_MAJOR "shaders" -// define a GUID for this interface so plugins can access and reference it -// {D42F798A-DF57-11d3-A3EE-0004AC96D4C3} -static const GUID QERShadersTable_GUID = -{ 0xd42f798a, 0xdf57, 0x11d3, { 0xa3, 0xee, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } }; - -// NOTES ABOUT SYNTAX: -// if a function starts by 'Try' it means that if the requested thing could not be found / loaded it will return nothing / NULL -// otherwise a default object will be created -// the _QERShadersTable is also used by shader code inside Radiant. but for speed and "keep it simple" consideration you -// can get the static equivalent of the func pointers by adding 'QERApp_' (access to _QERShadersTable is better thought .. -// see the note to move all the shader language out of Radiant below) - -/*! - \todo FIXME TTimo - fix the reference count strategy - - define the policy. It seems the initial policy of doing an inc ref when you create the shader is not good - (it doesn't work, and it's not being used right) - so, when you request an IShader and store it, incref it yourself - as a debugging safe check: push the created increfed objects into a list, and scan them at next idle loop - to make sure they have been decref'ed ? (sounds easy, may not be that much). - */ +#if !defined( INCLUDED_ISHADERS_H ) +#define INCLUDED_ISHADERS_H + +#include "generic/constant.h" +#include "generic/callbackfwd.h" + +enum +{ + QER_TRANS = 1 << 0, + QER_NOCARVE = 1 << 1, + QER_NODRAW = 1 << 2, + QER_NONSOLID = 1 << 3, + QER_WATER = 1 << 4, + QER_LAVA = 1 << 5, + QER_FOG = 1 << 6, + QER_ALPHATEST = 1 << 7, + QER_CULL = 1 << 8, + QER_AREAPORTAL = 1 << 9, + QER_CLIP = 1 << 10, + QER_BOTCLIP = 1 << 11, +}; + +struct qtexture_t; + +template class BasicVector3; +typedef BasicVector3 Vector3; +typedef Vector3 Colour3; + +typedef unsigned char BlendFactor; +const BlendFactor BLEND_ZERO = 0; +const BlendFactor BLEND_ONE = 1; +const BlendFactor BLEND_SRC_COLOUR = 2; +const BlendFactor BLEND_ONE_MINUS_SRC_COLOUR = 3; +const BlendFactor BLEND_SRC_ALPHA = 4; +const BlendFactor BLEND_ONE_MINUS_SRC_ALPHA = 5; +const BlendFactor BLEND_DST_COLOUR = 6; +const BlendFactor BLEND_ONE_MINUS_DST_COLOUR = 7; +const BlendFactor BLEND_DST_ALPHA = 8; +const BlendFactor BLEND_ONE_MINUS_DST_ALPHA = 9; +const BlendFactor BLEND_SRC_ALPHA_SATURATE = 10; + +class BlendFunc +{ +public: +BlendFunc( BlendFactor src, BlendFactor dst ) : m_src( src ), m_dst( dst ){ +} +BlendFactor m_src; +BlendFactor m_dst; +}; + +class ShaderLayer +{ +public: +virtual qtexture_t* texture() const = 0; +virtual BlendFunc blendFunc() const = 0; +virtual bool clampToBorder() const = 0; +virtual float alphaTest() const = 0; +}; + +typedef Callback1 ShaderLayerCallback; + class IShader { public: -virtual ~IShader() { } +enum EAlphaFunc +{ + eAlways, + eEqual, + eLess, + eGreater, + eLEqual, + eGEqual, +}; +enum ECull +{ + eCullNone, + eCullBack, +}; // Increment the number of references to this object virtual void IncRef() = 0; // Decrement the reference count virtual void DecRef() = 0; // get/set the qtexture_t* Radiant uses to represent this shader object virtual qtexture_t* getTexture() const = 0; -virtual void setTexture( qtexture_t *pTex ) = 0; +virtual qtexture_t* getDiffuse() const = 0; +virtual qtexture_t* getBump() const = 0; +virtual qtexture_t* getSpecular() const = 0; // get shader name virtual const char* getName() const = 0; -// is this shader in use? -// NOTE: this flag can mean this shader has been in use at least once since the last rescan of in-use stuff -// (rescan of in-use happens in several cases, user command or during a texture directory load) -// NOTE: this is used to draw the green outline in the texture window -// NOTE: when does Radiant set the InUse flag? Whenever Select_SetTexture is called (well that doesn't necessarily means the texture actually gets in use, but that's close enough) virtual bool IsInUse() const = 0; -virtual void SetInUse( bool ) = 0; -// is this shader displayed in the texture browser? -// NOTE: if IsInUse() == true, the shader will always be displayed in the texture window and this flag ingored -virtual bool IsDisplayed() const = 0; -virtual void SetDisplayed( bool ) = 0; +virtual void SetInUse( bool bInUse ) = 0; // get the editor flags (QER_NOCARVE QER_TRANS) -virtual int getFlags() = 0; +virtual int getFlags() const = 0; // get the transparency value -virtual float getTrans() = 0; +virtual float getTrans() const = 0; // test if it's a true shader, or a default shader created to wrap around a texture -virtual bool IsDefault() = 0; -// test if it's a plain color shader, i.e. a shader we use on plain color stuff (like info_playerstart) -virtual bool IsColor() = 0; -// get the related color then! -virtual void getColor( vec3_t v ) = 0; +virtual bool IsDefault() const = 0; // get the alphaFunc -virtual void getAlphaFunc( int *func, float *ref ) = 0; +virtual void getAlphaFunc( EAlphaFunc *func, float *ref ) = 0; +virtual BlendFunc getBlendFunc() const = 0; // get the cull type -virtual int getCull() = 0; +virtual ECull getCull() = 0; // get shader file name (ie the file where this one is defined) virtual const char* getShaderFileName() const = 0; -}; -// NOTE: how to move all the shader language out of Radiant in a plugin? -// -> change this _QERShadersTable into an IShadersManager -// -> let the plugin create an instance of IShadersManager -// -> make sure Radiant uses this IShadersManager to load / query the shaders - -// NOTE: shader and texture names used must be full path, ie. most often with "textures/" prefix -// (since shaders are defined in .shader files with textures/) - -// free all shaders -// free the shaders, will not free the qtexture_t* -typedef void ( WINAPI * PFN_FREESHADERS )(); -// reload all the shaders -// this will free everything (shaders and their textures), then reload all in use stuff -typedef void ( WINAPI * PFN_RELOADSHADERS )(); -// load all shaders in a given directory -// this will scan the list of in-memory shaders, and load the related qtexture_t if needed -typedef int ( WINAPI * PFN_LOADSHADERSFROMDIR )( const char* path ); -// load a shader file (ie a set of shaders) -// after LoadShaderFile shaders will be in memory, next step is to load the qtexture_t Radiant uses to represent them -// if a shader with the same name exists, new one will not be loaded - don't use this to refresh the shaders! -typedef void ( WINAPI * PFN_LOADSHADERFILE )( const char* filename ); -// tell if a given shader exists in our shader table -// NOTE: this doesn't tell wether it's corresponding qtexture is loaded -typedef int ( WINAPI * PFN_HASSHADER )( const char* name ); -// return the shader for a given name -// if the qtexture is not already in memory, will try loading it -// if the qtexture could not be found, will use default -// will return NULL on shader not found -typedef IShader* ( WINAPI * PFN_TRYSHADERFORNAME )( const char* name ); -// return the shader for a given name -// if the qtexture is not already in memory, will try loading it -// will create a default shader if not found (will use a default texture) -typedef IShader* ( WINAPI * PFN_SHADERFORNAME )( const char* name ); -// query / load a texture -// will not try loading a shader, will look for the actual image file .. -// returns NULL on file not found -// NOTE: strategy for file lookup: -// paths must be relative, ie. textures/me/myfile -// if a 3-letters filename extension (such as .jpg or .tga) is provided, it will get loaded first -// if not found or no extension, will try loading after adding .tga and .jpg (in this order) -typedef qtexture_t* ( WINAPI * PFN_TRYTEXTUREFORNAME )( const char* filename ); -// query / load a texture -// will not try loading a shader, will look for the actual image file .. -// on file not found will use the "texture not found" -typedef qtexture_t* ( WINAPI * PFN_TEXTUREFORNAME )( const char* filename ); -// get the number of active shaders -// these are the shaders currently loaded, that have an associated qtexture_t* -typedef int ( WINAPI * PFN_GETACTIVESHADERCOUNT )(); -// for stuff that needs to be represented by a plain texture -// the shader will get a "color" name, use GetColor to get the actual color -typedef IShader* ( WINAPI * PFN_COLORSHADERFORNAME )( const char* name ); -// reload a shaderfile - update shaders and their display properties/qtexture_t if needed -// will not reload the texture files -// will switch to "show in use" atfer use -// filename must be reletive path of the shader, ex. scripts/gothic_wall.shader -typedef void ( WINAPI * PFN_RELOADSHADERFILE )( const char* filename ); -// retrieve a shader if exists, without loading the textures for it etc. -// use this function if you want special info on a shader -typedef IShader* ( WINAPI * PFN_SHADERFORNAMENOLOAD )( const char* name ); -// force the "in use" flag on all active shaders -typedef void ( WINAPI * PFN_ACTIVESHADERSSETINUSE )( bool b ); -// sort the shaders in alphabetical order, we use the order in the texture inspector -typedef void ( WINAPI * PFN_SORTACTIVESHADERS )(); -// check if there exists an active shader with the given texture name (loaded or not, doesn't matter) -// (used to detect the textures we need to create a default shader for .. while scanning a directory) -typedef IShader* ( WINAPI * PFN_ACTIVESHADERFORTEXTURENAME )( char * ); -// create a shader to wrap around a texture name, we use this when loading a texture directory and some textures -// are not present as shaders -typedef IShader* ( WINAPI * PFN_CREATESHADERFORTEXTURENAME )( const char* name ); -// switch the IsDisplayed flag on all the active shaders -typedef void ( WINAPI * PFN_ACTIVESHADERSSETDISPLAYED )( bool b ); -// retrieve an active shader based on index -typedef IShader* ( WINAPI * PFN_ACTIVESHADERFORINDEX )( int i ); -// will cleanup a texture name and force it to the right format -// the debug version is painfully slow, but will detect more problems -// the idea being to avoid loading the same file several time because of uppercase/lowercase etc. -typedef const char* ( WINAPI * PFN_CLEANTEXTURENAME )( const char* name, bool bAddTexture ); - -struct _QERShadersTable -{ - int m_nSize; - PFN_FREESHADERS m_pfnFreeShaders; - PFN_RELOADSHADERS m_pfnReloadShaders; - PFN_LOADSHADERSFROMDIR m_pfnLoadShadersFromDir; - PFN_LOADSHADERFILE m_pfnLoadShaderFile; - PFN_RELOADSHADERFILE m_pfnReloadShaderFile; - PFN_HASSHADER m_pfnHasShader; - PFN_TRYSHADERFORNAME m_pfnTry_Shader_ForName; - PFN_SHADERFORNAME m_pfnShader_ForName; - PFN_TRYTEXTUREFORNAME m_pfnTry_Texture_ForName; - PFN_TEXTUREFORNAME m_pfnTexture_ForName; - PFN_GETACTIVESHADERCOUNT m_pfnGetActiveShaderCount; - PFN_COLORSHADERFORNAME m_pfnColorShader_ForName; - PFN_SHADERFORNAMENOLOAD m_pfnShader_ForName_NoLoad; - PFN_ACTIVESHADERSSETINUSE m_pfnActiveShaders_SetInUse; - PFN_SORTACTIVESHADERS m_pfnSortActiveShaders; - PFN_ACTIVESHADERFORTEXTURENAME m_pfnActiveShader_ForTextureName; - PFN_CREATESHADERFORTEXTURENAME m_pfnCreateShader_ForTextureName; - PFN_ACTIVESHADERSSETDISPLAYED m_pfnActiveShaders_SetDisplayed; - PFN_ACTIVESHADERFORINDEX m_pfnActiveShader_ForIndex; - PFN_CLEANTEXTURENAME m_pfnCleanTextureName; +virtual const ShaderLayer* firstLayer() const = 0; +virtual void forEachLayer( const ShaderLayerCallback& layer ) const = 0; + +virtual qtexture_t* lightFalloffImage() const = 0; }; -/*! - \todo FIXME fix the QERApp_ prototyping on shaders module - make it homogeneous with other modules, should be straight calls - */ +typedef struct _GSList GSList; +typedef Callback1 ShaderNameCallback; -#ifdef USE_SHADERSTABLE_DEFINE - #ifndef __SHADERSTABLENAME - #define __SHADERSTABLENAME g_ShadersTable - #endif -#define QERApp_Shader_ForName __SHADERSTABLENAME.m_pfnShader_ForName -#define QERApp_Texture_ForName2 __SHADERSTABLENAME.m_pfnTexture_ForName -#define QERApp_FreeShaders __SHADERSTABLENAME.m_pfnFreeShaders -#define QERApp_ReloadShaders __SHADERSTABLENAME.m_pfnReloadShaders -#define QERApp_SortActiveShaders __SHADERSTABLENAME.m_pfnSortActiveShaders -#define QERApp_ReloadShaderFile __SHADERSTABLENAME.m_pfnReloadShaderFile -#define QERApp_LoadShaderFile __SHADERSTABLENAME.m_pfnLoadShaderFile -#define QERApp_HasShader __SHADERSTABLENAME.m_pfnHasShader -#define QERApp_Try_Shader_ForName __SHADERSTABLENAME.m_pfnTry_Shader_ForName -#define QERApp_Try_Texture_ForName __SHADERSTABLENAME.m_pfnTry_Texture_ForName -#define QERApp_ColorShader_ForName __SHADERSTABLENAME.m_pfnColorShader_ForName -#define QERApp_Shader_ForName_NoLoad __SHADERSTABLENAME.m_pfnShader_ForName_NoLoad -#define QERApp_LoadShadersFromDir __SHADERSTABLENAME.m_pfnLoadShadersFromDir -#define QERApp_LoadShadersFromDir __SHADERSTABLENAME.m_pfnLoadShadersFromDir -#define QERApp_CreateShader_ForTextureName __SHADERSTABLENAME.m_pfnCreateShader_ForTextureName -#define QERApp_GetActiveShaderCount __SHADERSTABLENAME.m_pfnGetActiveShaderCount -#define QERApp_ActiveShaders_SetDisplayed __SHADERSTABLENAME.m_pfnActiveShaders_SetDisplayed -#define QERApp_ActiveShader_ForIndex __SHADERSTABLENAME.m_pfnActiveShader_ForIndex -#define QERApp_ActiveShaders_SetInUse __SHADERSTABLENAME.m_pfnActiveShaders_SetInUse -#define QERApp_ActiveShader_ForTextureName __SHADERSTABLENAME.m_pfnActiveShader_ForTextureName -#define QERApp_ActiveShader_ForIndex __SHADERSTABLENAME.m_pfnActiveShader_ForIndex -#define QERApp_CleanTextureName __SHADERSTABLENAME.m_pfnCleanTextureName -#endif +class ModuleObserver; -#define APPSHADERS_MAJOR "appshaders" -// FIXME: remove -static const GUID QERAppShadersTable_GUID = -{ 0xec3008a8, 0xbd0b, 0x11d4, { 0x82, 0x51, 0x20, 0x4c, 0x4f, 0x4f, 0x50, 0x20 } }; - -// g_qeglobals.d_qtextures is used internally by the editor for actual camera drawing -typedef qtexture_t** ( WINAPI * PFN_QTEXTURES )(); -// g_qeglobals.d_qtexmap is a map for fast access -typedef GHashTable* ( WINAPI * PFN_QTEXMAP )(); -// d_texturewin -//++timo NOTE: this same function is also in isurface.h table, we would eventually have to merge some stuff -typedef texturewin_t* ( *PFN_QEGLOBALSTEXTUREWIN )(); -// Texture_SetTexture -//++timo NOTE: this one may have to be reorganized too .. putting it here is a bit clumsy -// NOTE: the C++ function used internally has a lot of default values -typedef void ( WINAPI * PFN_TEXTURESETTEXTURE )( texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef ); -// Texture_ShowInuse -typedef void ( WINAPI * PFN_TEXTURESHOWINUSE )(); -// BuildShaderList -typedef void ( *PFN_BUILDSHADERLIST )(); -// PreloadShaders -typedef void ( *PFN_PRELOADSHADERS )(); - -// a table that Radiant makes available to the shader module in return -struct _QERAppShadersTable +class ShaderSystem { - int m_nSize; - PFN_QTEXTURES m_pfnQTextures; - PFN_QTEXMAP m_pfnQTexmap; - PFN_QEGLOBALSTEXTUREWIN m_pfnQeglobalsTexturewin; - PFN_TEXTURESETTEXTURE m_pfnTexture_SetTexture; - PFN_TEXTURESHOWINUSE m_pfnTexture_ShowInuse; - PFN_BUILDSHADERLIST m_pfnBuildShaderList; - PFN_PRELOADSHADERS m_pfnPreloadShaders; +public: +INTEGER_CONSTANT( Version, 1 ); +STRING_CONSTANT( Name, "shaders" ); +// NOTE: shader and texture names used must be full path. +// Shaders usable as textures have prefix equal to getTexturePrefix() + +virtual void realise() = 0; +virtual void unrealise() = 0; +virtual void refresh() = 0; +// activate the shader for a given name and return it +// will return the default shader if name is not found +virtual IShader* getShaderForName( const char* name ) = 0; + +virtual void foreachShaderName( const ShaderNameCallback& callback ) = 0; + +// iterate over the list of active shaders +virtual void beginActiveShadersIterator() = 0; +virtual bool endActiveShadersIterator() = 0; +virtual IShader* dereferenceActiveShadersIterator() = 0; +virtual void incrementActiveShadersIterator() = 0; + +virtual void setActiveShadersChangedNotify( const Callback& notify ) = 0; + +virtual void attach( ModuleObserver& observer ) = 0; +virtual void detach( ModuleObserver& observer ) = 0; + +virtual void setLightingEnabled( bool enabled ) = 0; + +virtual const char* getTexturePrefix() const = 0; }; -#ifdef USE_APPSHADERSTABLE_DEFINE - #ifndef __APPSHADERTABLENAME - #define __APPSHADERTABLENAME g_AppShadersTable - #endif -#define Texture_ShowInuse __APPSHADERTABLENAME.m_pfnTexture_ShowInuse -#endif +#include "modulesystem.h" -/*! - NOTE TTimo: there is an important distinction between SHADER_NOT_FOUND and SHADER_NOTEX: - SHADER_NOT_FOUND means we didn't find the raw texture or the shader for this - SHADER_NOTEX means we recognize this as a shader script, but we are missing the texture to represent it - this was in the initial design of the shader code since early GtkRadiant alpha, and got sort of foxed in 1.2 and put back in - */ -#define SHADER_NOT_FOUND "textures/radiant/notex" -#define SHADER_NOTEX "textures/radiant/shadernotex" ///< Q3 tech specific +template +class GlobalModule; +typedef GlobalModule GlobalShadersModule; + +template +class GlobalModuleRef; +typedef GlobalModuleRef GlobalShadersModuleRef; + +inline ShaderSystem& GlobalShaderSystem(){ + return GlobalShadersModule::getTable(); +} + + +#define QERApp_Shader_ForName GlobalShaderSystem().getShaderForName +#define QERApp_ActiveShaders_IteratorBegin GlobalShaderSystem().beginActiveShadersIterator +#define QERApp_ActiveShaders_IteratorAtEnd GlobalShaderSystem().endActiveShadersIterator +#define QERApp_ActiveShaders_IteratorCurrent GlobalShaderSystem().dereferenceActiveShadersIterator +#define QERApp_ActiveShaders_IteratorIncrement GlobalShaderSystem().incrementActiveShadersIterator #endif