Shaders manager & co
-
- Posts: 60
- Joined: Tue Nov 13, 2007 7:03 pm
- Location: Bucharest - Romania
- Contact:
Shaders manager & co
Hello again
I've made some structures and classes for managing shaders.
I have no where to upload a demo so here is the code in the next posts.
Enjoy
I've made some structures and classes for managing shaders.
I have no where to upload a demo so here is the code in the next posts.
Enjoy
Last edited by radubolovan on Sat May 31, 2008 10:52 am, edited 1 time in total.
-
- Posts: 60
- Joined: Tue Nov 13, 2007 7:03 pm
- Location: Bucharest - Romania
- Contact:
dswshader.h
Code: Select all
/***************************************************************************
* Copyright (C) 2007-2008 by Radu Dumitru Bolovan *
* radubolovan@darkstarlinux.ro *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/**
@author Radu Dumitru Bolovan <radubolovan@darkstarlinux.ro>
*/
#ifndef __DSWHEELS_SHADER_H__
#define __DSWHEELS_SHADER_H__
#include "irrlicht.h"
using namespace irr;
typedef enum _eShaderParamType
{
SH_PARAM_TYPE_VERTEX = 0,
SH_PARAM_TYPE_PIXEL
}eShaderParamType;
typedef enum _eTexParamType
{
SH_TEX_TYPE_DIFFUSE = 0,
SH_TEX_TYPE_BUMP,
SH_TEX_TYPE_SPECULAR
}eTexParamType;
typedef struct _tShaderParam
{
inline _tShaderParam()
{
m_type = SH_PARAM_TYPE_VERTEX;
strcpy( m_name, "" );
m_nVanCount = 0;
m_values = NULL;
}
_tShaderParam( char const* name, float const* values, int nValCount, eShaderParamType type );
~_tShaderParam();
eShaderParamType m_type;
char m_name[256];
float* m_values;
int m_nVanCount;
}tShaderParam;
class DSWShaderCallBack : public video::IShaderConstantSetCallBack
{
public:
inline DSWShaderCallBack() : video::IShaderConstantSetCallBack(){}
~DSWShaderCallBack()
{
uint nIndex;
for( nIndex = 0; nIndex < m_params.size(); nIndex++ )
{
tShaderParam* param = m_params[ nIndex ];
delete param;
}
}
inline void addShaderParam( char const* name, float const* values, int nValCount, const eShaderParamType& type )
{
uint nIndex;
for( nIndex = 0; nIndex < m_params.size(); nIndex++ )
{
if( strcmp( m_params[nIndex]->m_name, name ) == 0 )
return;
}
tShaderParam* param = new tShaderParam( name, values, nValCount, type );
m_params.push_back( param );
}
inline void setParamValues( char const* name, float const* values, int nValCount )
{
uint nIndex;
for( nIndex = 0; nIndex < m_params.size(); nIndex++ )
{
if( strcmp( m_params[nIndex]->m_name, name ) == 0 )
{
if( m_params[nIndex]->m_nVanCount < nValCount )
return;
memcpy( m_params[nIndex]->m_values, values, nValCount * sizeof(float) );
return;
}
}
}
inline void OnSetConstants( video::IMaterialRendererServices* s, s32 userData )
{
uint nIndex;
for( nIndex = 0; nIndex < m_params.size(); nIndex++ )
{
if( m_params[nIndex]->m_type, SH_PARAM_TYPE_VERTEX )
s->setVertexShaderConstant( m_params[nIndex]->m_name, m_params[nIndex]->m_values, m_params[nIndex]->m_nVanCount );
else
s->setPixelShaderConstant( m_params[nIndex]->m_name, m_params[nIndex]->m_values, m_params[nIndex]->m_nVanCount );
}
}
protected:
core::array<tShaderParam*> m_params;
};
class ShaderManager;
class Shader
{
public:
inline Shader()
{
m_shCallback = NULL;
strcpy( m_name, "" );
m_nId = -1;
m_manager = NULL;
}
Shader( char const* name, ShaderManager* man );
~Shader();
int load( c8* vsFileName, c8* psFileName, E_MATERIAL_TYPE matType );
inline int id(){ return m_nId; }
inline void addParam( char const* name, float const* values, int nValCount, const eShaderParamType& type )
{
m_shCallback->addShaderParam( name, values, nValCount, type );
}
inline void setParamValues( char const* name, float const* values, int nValCount )
{
m_shCallback->setParamValues( name, values, nValCount );
}
friend class ShaderManager;
protected:
DSWShaderCallBack* m_shCallback;
char m_name[256];
int m_nId;
ShaderManager* m_manager;
};
class ShaderManager
{
public:
ShaderManager();
~ShaderManager();
void init( char const* szAppDir );
s32 loadShader( char const* shaderName, c8* vsFileName, c8* psFileName, E_MATERIAL_TYPE matType );
s32 getShader( char const* shaderName );
Shader* shader( char const* shaderName ) const;
friend class Shader;
protected:
char m_szAppDir[DSW_MAX_PATH];
E_VERTEX_SHADER_TYPE m_vsType;
E_PIXEL_SHADER_TYPE m_psType;
core::array<Shader*> m_shaders;
video::IVideoDriver* m_driver
};
extern DSWheels::ShaderManager* g_pShaderManager;
#endif //__DSWHEELS_SHADER_H__
Last edited by radubolovan on Mon Jun 02, 2008 8:00 pm, edited 2 times in total.
-
- Posts: 60
- Joined: Tue Nov 13, 2007 7:03 pm
- Location: Bucharest - Romania
- Contact:
dswshader.cpp
Code: Select all
/***************************************************************************
* Copyright (C) 2007-2008 by Radu Dumitru Bolovan *
* radubolovan@darkstarlinux.ro *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/**
@author Radu Dumitru Bolovan <radubolovan@darkstarlinux.ro>
*/
#include "dswshader.h"
_tShaderParam::_tShaderParam( char const* name, float const* values, int nValCount, eShaderParamType type )
{
m_type = type;
strcpy( m_name, name );
m_nVanCount = nValCount;
m_values = (float*)malloc( nValCount * sizeof(float) );
memcpy( m_values, values, nValCount * sizeof(float) );
}
_tShaderParam::~_tShaderParam()
{
if( m_nVanCount > 0 )
{
free( m_values );
}
}
DSWheels::ShaderManager* g_pShaderManager = NULL;
/************************************************************************************/
Shader::Shader( char const* name, ShaderManager* man )
{
m_shCallback = new DSWShaderCallBack();
strcpy( m_name, name );
m_nId = -1;
m_manager = man;
}
Shader::~Shader()
{
delete m_shCallback;
}
int Shader::load( c8* vsFileName, c8* psFileName, E_MATERIAL_TYPE matType )
{
m_nId = m_manager->m_driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles( vsFileName, "main", m_manager->m_vsType, psFileName, "main", m_manager->m_psType, m_shCallback, matType );
return m_nId;
}
/************************************************************************************/
/************************************************************************************/
ShaderManager::ShaderManager()
{
strcpy( m_szAppDir, "" );
m_driver = NULL;
m_vsType = EVST_VS_1_1;
m_psType = EPST_PS_1_1;
}
ShaderManager::~ShaderManager()
{
uint nIndex;
for( nIndex = 0; nIndex < m_shaders.size(); nIndex++ )
{
delete m_shaders[nIndex];
}
}
void ShaderManager::init( char const* szAppDir, video::IVideoDriver* driver )
{
strcpy( m_szAppDir, szAppDir );
video::E_DRIVER_TYPE dType = driver->getDriverType();
if( ( dType == video::EDT_DIRECT3D9 ) || ( dType == video::EDT_DIRECT3D8 ) )
{
if( driver->queryFeature( video::EVDF_VERTEX_SHADER_3_0 ) )
m_vsType = video::EVST_VS_3_0;
else if( driver->queryFeature( video::EVDF_VERTEX_SHADER_2_0 ) )
m_vsType = video::EVST_VS_2_0;
else if( driver->queryFeature( video::EVDF_VERTEX_SHADER_1_1 ) )
m_vsType = video::EVST_VS_1_1;
if( driver->queryFeature( video::EVDF_VERTEX_SHADER_3_0 ) )
m_psType = video::EPST_PS_3_0;
else if( driver->queryFeature( video::EVDF_PIXEL_SHADER_2_0 ) )
m_psType = video::EPST_PS_2_0;
else if( driver->queryFeature( video::EVDF_PIXEL_SHADER_1_4 ) )
m_psType = video::EPST_PS_1_4;
else if( driver->queryFeature( video::EVDF_PIXEL_SHADER_1_3 ) )
m_psType = video::EPST_PS_1_3;
else if( driver->queryFeature( video::EVDF_PIXEL_SHADER_1_2 ) )
m_psType = video::EPST_PS_1_2;
else if( driver->queryFeature( video::EVDF_VERTEX_SHADER_1_1 ) )
m_psType = video::EPST_PS_1_1;
}
else if( dType == video::EDT_OPENGL )
{
m_vsType = EVST_VS_3_0;
m_psType = EPST_PS_3_0;
}
m_driver = driver;
}
s32 ShaderManager::loadShader( char const* shaderName, c8* vsFileName, c8* psFileName, E_MATERIAL_TYPE matType )
{
uint nIndex;
for( nIndex = 0; nIndex < m_shaders.size(); nIndex++ )
{
if( strcmp( m_shaders[nIndex]->m_name, shaderName ) == 0 )
{
return m_shaders[nIndex]->id();
}
}
Shader* sh = new Shader( shaderName, this );
int nRet = sh->load( vsFileName, psFileName, matType );
if( nRet > -1 )
m_shaders.push_back( sh );
return nRet;
}
s32 ShaderManager::getShader( char const* shaderName )
{
uint nIndex;
for( nIndex = 0; nIndex < m_shaders.size(); nIndex++ )
{
if( strcmp( m_shaders[nIndex]->m_name, shaderName ) == 0 )
{
return m_shaders[nIndex]->id();
}
}
return -1;
}
Shader* ShaderManager::shader( char const* shaderName ) const
{
uint nIndex;
for( nIndex = 0; nIndex < m_shaders.size(); nIndex++ )
{
Shader* sh = m_shaders[nIndex];
if( strcmp( sh->m_name, shaderName ) == 0 )
{
return sh;
}
}
return NULL;
}
/************************************************************************************/
Last edited by radubolovan on Mon Jun 02, 2008 7:59 pm, edited 1 time in total.
-
- Posts: 60
- Joined: Tue Nov 13, 2007 7:03 pm
- Location: Bucharest - Romania
- Contact:
Usage
InitialisationsdestroyingUsing
You can change EMT_SOLID with any material type.
Adding to vertex shader parameter(s)
Adding to fragment shader parameter(s)
changing parameters values - you cand do this per frame before smgr->drawAll()
Initialisations
Code: Select all
g_pShaderManager = new ShaderManager();
g_pShaderManager->init( "data_directory", driver );
Code: Select all
delete g_pShaderManager;
Code: Select all
int nShader = g_pShaderManager->loadShader( "my_shader", "path_to_vertex_shader_inside_data_directory", "path_to_fragment_shader_inside_data_directory", video::EMT_SOLID );
Adding to vertex shader parameter(s)
Code: Select all
float fVValue = 1.0f;
g_pShaderManager->shader( "my_shader" )->addParam( "a_Vparameter", &fPValue, 1, SH_PARAM_TYPE_VERTEX );
Code: Select all
float fPValue = 1.0f;
g_pShaderManager->shader( "my_shader" )->addParam( "a_Pparameter", &fPValue, 1, SH_PARAM_TYPE_PIXEL );
Code: Select all
float fNewValue = 5.0f;
g_pShaderManager->shader( "my_shader" )->setParamValues( "a_Vparameter", &fNewValue, 1 );
Last edited by radubolovan on Mon Jun 02, 2008 8:01 pm, edited 1 time in total.
Instead of setting the default to PS 1.1, and VS 1.1, what I like to do is query the maximum supported shader model using driver->queryFeature() and use that instead, it's a good idea to compile for the highest supported shader model even on shaders that fall well below the instruction limit for example PS 3.0, because compiling at a higher model produces much more efficient code and less instructions since the compiler can utilize newly added optimization features.
Cheers
Cheers
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
-
- Posts: 60
- Joined: Tue Nov 13, 2007 7:03 pm
- Location: Bucharest - Romania
- Contact:
You're absolutly right ... see modifications aboveBlindSide wrote:Instead of setting the default to PS 1.1, and VS 1.1, what I like to do is query the maximum supported shader model using driver->queryFeature() and use that instead, it's a good idea to compile for the highest supported shader model even on shaders that fall well below the instruction limit for example PS 3.0, because compiling at a higher model produces much more efficient code and less instructions since the compiler can utilize newly added optimization features.
Cheers
hi radubolovan,
i'm impressed with the posted code above. good job.
i guess the bar is now raised higher, and i'm hoping to see more interesting code posted that build on top of it.
what i'd like to see are presets, shaders that are basically generic and can be applied to a material on-the-fly. then only then i can tweak the parameters and see these changes real-time.
i'm impressed with the posted code above. good job.
i guess the bar is now raised higher, and i'm hoping to see more interesting code posted that build on top of it.
what i'd like to see are presets, shaders that are basically generic and can be applied to a material on-the-fly. then only then i can tweak the parameters and see these changes real-time.
-
- Posts: 60
- Joined: Tue Nov 13, 2007 7:03 pm
- Location: Bucharest - Romania
- Contact:
Hello dlangdev ... I intend to do that (a shader editor), but before ... I want to add some kind of templates ... Something like writting in a file or more many functions as applyLights() for example, then in other file write "include_file.tsh" (sht = shader template) and simply applyLights() ... it's not difficult, but I have to right some code and right now I don't have the time ... but soon
hi radubolovan,
once again, i'd like to express my gratitude to the effort you made, not only that, you posted a real working code here as well.
at the moment, i'm using the code you posted above as a way of getting into a simple hypershader design. no lights are going to be added in this design, though. it's mostly about shaders and its relation to a material.
when implemented, i should be able to have a simple shader objects built onto a simple shader editor.
of course, bump mapping and displacement maps will be there as well.
once again, i'd like to express my gratitude to the effort you made, not only that, you posted a real working code here as well.
at the moment, i'm using the code you posted above as a way of getting into a simple hypershader design. no lights are going to be added in this design, though. it's mostly about shaders and its relation to a material.
when implemented, i should be able to have a simple shader objects built onto a simple shader editor.
of course, bump mapping and displacement maps will be there as well.
-
- Posts: 60
- Joined: Tue Nov 13, 2007 7:03 pm
- Location: Bucharest - Romania
- Contact:
You can export any variables to shader ... any lights variables or ... anything...dlangdev wrote:... no lights are going to be added in this design, though. it's mostly about shaders and its relation to a material.....
example:
Code: Select all
scene::ILightSceneNode* l1 = smgr->addLightSceneNode( ... );
video::SLight ld = l1->getLightData ();
float lightVector[4];
lightVector[0] = ld.AmbientColor.getRed();
lightVector[1] = ld.AmbientColor.getGreen();
lightVector[2] = ld.AmbientColor.getBlue();
lightVector[3] = ld.AmbientColor.getAlpha();
Code: Select all
g_pShaderManager->shader( "my_shader" )->addParam( "light_color", &lightVector[0], 4, SH_PARAM_TYPE_PIXEL );
Code: Select all
uniform float light_color[4];
And you cand export enything you want
[EDIT]
but ... here is an example of shader which is using light with no export (but texture):
vertex shader:
Code: Select all
varying vec4 a_color;
void main()
{
vec3 normal = normalize( gl_NormalMatrix * gl_Normal );
vec3 position = vec3( gl_ModelViewMatrix * gl_Vertex );
vec3 lightVector = normalize( gl_LightSource[0].position.xyz - position );
vec4 diffuse = gl_FrontLightProduct[0].diffuse * max( 0.0, dot( normal,lightVector ) );
a_color = gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + diffuse;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}
Code: Select all
varying vec4 a_color;
uniform sampler2D myTexture;
void main()
{
vec4 col = texture2D( myTexture, vec2( gl_TexCoord[0] ) );
gl_FragColor = col * a_color;
}