It is a system, in which the shader compilation is done using a struct to store all the options when it comes to compile a shader. The compilation of a shader has many parameters, and some of the can become very long. The ideal thing is to have a structure which
can be easily initialized to store the information needed, and pass this structure to the video driver to create the shaders, and this is it.
It is tested, and it works, though it isn't heavily tested to check that everything works properly, and it isn't completely failsafe, but, makes life easier when it comes to use the shaders.
I want to leave this here so, if people gets minimally interested, it evolves to a fully working compile configuration tool for the shaders.
I have unified the vertex and pixel shader level to a single variable, because i think it is best to leave it that way. I don't know if it makes much sense to have a VS level 2 with a P/FS level 3 or the like, but if all are at the same level, it is sure there won't be any trouble
Code: Select all
enum ETARGETSHADERLEVEL
{
ETSL_PS1 = 1,//pixelShader 1
ETSL_PS2,//pixelShader 2
ETSL_PS3,//pixelShader 3
ETSL_PS4,//pixelShader 4
ETSL_PS5,//pixelShader 5
ETSL_COUNT = 0x7FFFFFFF //32 bit force
};
struct ShaderCompileInfo
{
bool FromFile;
bool HighLevel;
bool IsGeometryShader;
bool IsCG;
core::stringc VertexShader;
core::stringc PixelShader;
core::stringc GeometryShader;
core::stringc VertexEntryPoint;
core::stringc PixelEntryPoint;
core::stringc GeometryEntryPoint;
s32 UserData;
video::IShaderConstantSetCallBack* Constants;
video::E_MATERIAL_TYPE BaseRenderStates;
ETARGETSHADERLEVEL TargetLevel;
scene::E_PRIMITIVE_TYPE GeometryInputPrimitive;
scene::E_PRIMITIVE_TYPE GeometryOutputPrimitive;
u32 MaximumVerticesCreated;
bool checkCompileInfo()//this small function validates the info from this structure.
{
bool retVal = true;
//At least, this is mandatory to be not null.
retVal &= VertexShader.size()>0;
retVal &= PixelShader.size()>0;
retVal &= BaseRenderStates >= video::EMT_SOLID;
if(HighLevel)//if this is highLevel, it must have an entry point.
{
retVal &= VertexEntryPoint.size()>0;
retVal &= PixelEntryPoint.size()>0;
}
if(IsGeometryShader)//Geometry shaders need code and entry point.
{
retVal &= GeometryShader.size()>0;
retVal &= GeometryEntryPoint.size()>0;
}
//I guess CG shaders have more options, but i don't have support for CG languaje enabled in my Irrlicht lib...
//Geometry shaders should have extra check options, but at the time, i am not aware of them.
return retVal;
}
};
video::E_MATERIAL_TYPE compileCustomShaderMaterial(video::IVideoDriver* drv,struct ShaderCompileInfo& info)
{
video::E_VERTEX_SHADER_TYPE vertexshaderLevel;
video::E_PIXEL_SHADER_TYPE pixelshaderLevel;
video::E_GEOMETRY_SHADER_TYPE geometryshaderLevel = video::EGST_GS_4_0;//modify this if needed!
s32 result = -1;
//We compile the shader with the info stored in the shaderCompileInfo structure
if(info.checkCompileInfo())
{
if(drv)
{
switch(info.TargetLevel)
{
case ETSL_PS1:
pixelshaderLevel = video::EPST_PS_1_4;
vertexshaderLevel = video::EVST_VS_1_1;
break;
case ETSL_PS2:
pixelshaderLevel = video::EPST_PS_2_0;
vertexshaderLevel = video::EVST_VS_2_0;
break;
case ETSL_PS3:
pixelshaderLevel = video::EPST_PS_3_0;
vertexshaderLevel = video::EVST_VS_3_0;
break;
case ETSL_PS4:
pixelshaderLevel = video::EPST_PS_4_0;
vertexshaderLevel = video::EVST_VS_4_0;
break;
case ETSL_PS5:
pixelshaderLevel = video::EPST_PS_5_0;
vertexshaderLevel = video::EVST_VS_5_0;
break;
default:
pixelshaderLevel = video::EPST_PS_2_0;//modify if needed
vertexshaderLevel = video::EVST_VS_2_0;
break;
}
if(info.IsGeometryShader)//is it a geometry shader?
{
if(info.HighLevel)//Is a highlevel shader?
{
if(info.FromFile)//Is from files?
{
result = drv->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles(
info.VertexShader,
info.VertexEntryPoint.c_str(),
vertexshaderLevel,
info.PixelShader,
info.PixelEntryPoint.c_str(),
pixelshaderLevel,
info.GeometryShader,
info.GeometryEntryPoint.c_str(),
geometryshaderLevel,
info.GeometryInputPrimitive,
info.GeometryOutputPrimitive,
info.MaximumVerticesCreated,
info.Constants,
info.BaseRenderStates,
info.UserData
);
}
else//The code of the shader is stored on memory
{
result = drv->getGPUProgrammingServices()->addHighLevelShaderMaterial(
info.VertexShader.c_str(),
info.VertexEntryPoint.c_str(),
vertexshaderLevel,
info.PixelShader.c_str(),
info.PixelEntryPoint.c_str(),
pixelshaderLevel,
info.GeometryShader.c_str(),
info.GeometryEntryPoint.c_str(),
geometryshaderLevel,
info.GeometryInputPrimitive,
info.GeometryOutputPrimitive,
info.MaximumVerticesCreated,
info.Constants,
info.BaseRenderStates,
info.UserData
);
}
}//No low level Geometry shader? *shrugs*
}
else//No geometry shader...
{
if(info.HighLevel)//Is it high level?
{
if(info.FromFile)//Is it from files?
{
result = drv->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles(
info.VertexShader,
info.VertexEntryPoint.c_str(),
vertexshaderLevel,
info.PixelShader,
info.PixelEntryPoint.c_str(),
pixelshaderLevel,
info.Constants,
info.BaseRenderStates,
info.UserData
);
}
else//The code is directly provided?
{
result = drv->getGPUProgrammingServices()->addHighLevelShaderMaterial(
info.VertexShader.c_str(),
info.VertexEntryPoint.c_str(),
vertexshaderLevel,
info.PixelShader.c_str(),
info.PixelEntryPoint.c_str(),
pixelshaderLevel,
info.Constants,
info.BaseRenderStates,
info.UserData
);
}
}
else //Low level shader
{
if(info.FromFile)//Code from files?
{
result = drv->getGPUProgrammingServices()->addShaderMaterialFromFiles(
info.VertexShader,
info.PixelShader,
info.Constants,
info.BaseRenderStates,
info.UserData
);
}
else//code from memory?
{
result = drv->getGPUProgrammingServices()->addShaderMaterial(
info.VertexShader.c_str(),
info.PixelShader.c_str(),
info.Constants,
info.BaseRenderStates,
info.UserData
);
}
}
}
}
}
else
{
cout<<"Check Failed"<<endl;
}
return (video::E_MATERIAL_TYPE) result;
//The support for CG isn't implemented.
}