This is the code that calls these shaders..
Code: Select all
// Jacques Pretorius 2015..
// Thanks to all the CPU and GPU code-sharing Irrlicht guys out there!!
// Note: This may not be the fastest or most cohesive code, but it should suffice to
// demonstrate the use of the GLSL code..
// = = = = = = = = = = = = = = = = = = = = = =
// #include <IRRLICHT_1_8_1/irrlicht.h> // Change this to suit your implementation..
#include <irrlicht.h> // Like this perhaps..
#include <vector>
// = = = = = = = = = = = = = = = = = = = = = =
//#pragma comment(lib,"irrlicht.lib") // IF WE DONT HAVE A "Libraries" directory in our IDE project tree..
// = = = = = = = = = = = = = = = = = = = = = =
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
// = = = = = = = = = = = = = = = = = = = = = =
#define DIFFUSE 0
#define NORMAL 1
#define SPECULAR 2
#define GLOSS 3
// = = = = = = = = = = = = = = = = = = = = = =
// Variables and Objects..(I like them here as it gives an "overview" of matters)
video::E_DRIVER_TYPE TheDriverType;
core::dimension2d<u32> DeskResolution;
IrrlichtDevice* TheIRRNullDevice; // Used to determine the desktop resolution..
ICameraSceneNode* TheCameraSceneNode;
//---------------------------------------------------------------------------
// - ANIMATED MODELS (DirectX or BLITZ BASIC) -
scene::IAnimatedMesh* AniMesh0001;
scene::IAnimatedMeshSceneNode* AniMeshNode0001;
//
scene::IAnimatedMesh* AniMesh0002;
scene::IAnimatedMeshSceneNode* AniMeshNode0002;
//
// NOTE THE SLIGHT DIFFERENCE BETWEEN SKINNED AND STATIC OBJECTS!
// - STATIC MODELS (WAVEFRONT OBJ - disable *.mtl) -
scene::IMesh* IMesh0003;
scene::IAnimatedMesh* AniMesh0003;
scene::ISceneNode* ISceneNode0003 ;
//
scene::IMesh* IMesh0004;
scene::IAnimatedMesh* AniMesh0004;
scene::ISceneNode* ISceneNode0004 ;
//
//---------------------------------------------------------------------------
video::IGPUProgrammingServices* TheGraphicsProcessorGPU;
s32 IDFIRSTShader;
s32 IDSECONDShader;
int FragShadeCommand; // Used to swich between render methods in the shader..
int VertShadeCommand;
IrrlichtDevice* PrivateDevice;
IVideoDriver* PrivateDriver;
ISceneManager* PrivateSceneManager;
float GlossynessIN; // Now we use maps for gloss..
scene::ISceneNodeAnimator* TheRotationAnimator ;
vector3df LightPosition001;
bool PlayPause; // 1 = Play ; 0 = Pause..
bool PrevPlayPause; // Do things only when change occured..
float AniPlaySpeed; // Playing Speed..
matrix4 TheWorldMatrix; // CAN WE HANDLE CG WITH THIS??
// WITH THIS SHADER IMPLEMENTATION WE FORGET ABOUT ALL THESE!!
// matrix4 TheViewMatrix;
// matrix4 TheProjectionMatrix;
// matrix4 TheInverseViewMatrix;
//---------------------------------------------------------------------------
// = = = = = = = = = = = = = = = = = = = = = =
class VECTROTEKAPP : public irr::IEventReceiver, irr::video::IShaderConstantSetCallBack
{public:
VECTROTEKAPP()
{// - INITIALISATION -
// Create the Irrlicht PrivateDevice.
// - INITIATION -
TheIRRNullDevice = createDevice(video::EDT_NULL); // EDT = Enumerator Display Type.. Just so we know :)
DeskResolution = TheIRRNullDevice->getVideoModeList()->getDesktopResolution(); // Mine..
TheIRRNullDevice->drop();
// PrivateDevice = createDevice(EDT_OPENGL,core::dimension2d<u32>( 1024 , 768 ), 32 ); // OLD METHOD..
// PrivateDevice = createDevice(EDT_DIRECT3D9,DeskResolution,32); // For this use HLSL which resembles Nvidia CG..
PrivateDevice = createDevice(EDT_OPENGL,DeskResolution,32);
PrivateDevice->setEventReceiver(this);
PrivateSceneManager = PrivateDevice->getSceneManager();
PrivateDriver = PrivateDevice->getVideoDriver();
PrivateDevice ->getCursorControl()->setVisible(false);
FragShadeCommand = 1; // Default Normal Shader Operation..
VertShadeCommand = 1; // Default Normal Shader Operation..
PlayPause = 1; // Playing by default..
SKeyMap keyMap[8];
keyMap[0].Action = EKA_MOVE_FORWARD; keyMap[0].KeyCode = KEY_UP;
keyMap[1].Action = EKA_MOVE_FORWARD; keyMap[1].KeyCode = KEY_KEY_W;
keyMap[2].Action = EKA_MOVE_BACKWARD; keyMap[2].KeyCode = KEY_DOWN;
keyMap[3].Action = EKA_MOVE_BACKWARD; keyMap[3].KeyCode = KEY_KEY_S;
keyMap[4].Action = EKA_STRAFE_LEFT; keyMap[4].KeyCode = KEY_LEFT;
keyMap[5].Action = EKA_STRAFE_LEFT; keyMap[5].KeyCode = KEY_KEY_A;
keyMap[6].Action = EKA_STRAFE_RIGHT; keyMap[6].KeyCode = KEY_RIGHT;
keyMap[7].Action = EKA_STRAFE_RIGHT; keyMap[7].KeyCode = KEY_KEY_D;
TheCameraSceneNode = PrivateSceneManager -> addCameraSceneNodeFPS(0, // ISceneNode* parent = 0
200, // f32 rotateSpeed = 100.0f
0.0095, // f32 moveSpeed = 0.5f
-1, // s32 id
keyMap, // SKeyMap* keyMapArray
8); // s32 keyMapSize
// TheCameraSceneNode = PrivateSceneManager->addCameraSceneNodeFPS();
// FOR SPEED CONTROLL YOU MUST HAVE THE KEY CONTROLL SYSTEM INVOKED..
TheCameraSceneNode->setPosition(core::vector3df( 0.0 , 20.0 ,20.0 ));
TheCameraSceneNode->setTarget(core::vector3df( 0.0 , 10.0 , 0.0 ));
TheCameraSceneNode->setFarValue(12000.0f);
PrivateDriver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
// PrivateSceneManager->addSkyDomeSceneNode(PrivateDriver->getTexture("media/000_SKYDOME/SkyDome.jpg"),16,16,1.0,1.5);
//*
ISceneNode* TheSKYBOXIscenenode
= PrivateSceneManager
->addSkyBoxSceneNode(PrivateDriver->getTexture("media/0000_SKY_BOXES/0002_OFFICE_JACK/OFFICE_TOP.png"),
PrivateDriver->getTexture("media/0000_SKY_BOXES/0002_OFFICE_JACK/OFFICE_DOWN.png"),
PrivateDriver->getTexture("media/0000_SKY_BOXES/0002_OFFICE_JACK/OFFICE_FRONT.png"),
PrivateDriver->getTexture("media/0000_SKY_BOXES/0002_OFFICE_JACK/OFFICE_BACK.png"),
PrivateDriver->getTexture("media/0000_SKY_BOXES/0002_OFFICE_JACK/OFFICE_LEFT.png"),
PrivateDriver->getTexture("media/0000_SKY_BOXES/0002_OFFICE_JACK/OFFICE_RIGHT.png"));
//*/
PrivateDriver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
GlossynessIN = 128.0;
TheRotationAnimator = PrivateSceneManager->createRotationAnimator(core::vector3df( 0.3,0.2f,0.4 ));
TheGraphicsProcessorGPU = PrivateDriver->getGPUProgrammingServices();
// I create the shader material for the glass pane.
IDFIRSTShader = TheGraphicsProcessorGPU
->addHighLevelShaderMaterialFromFiles(
"SHADERS/GLSL_002_VERTEX_PROGRAM.vert", // Vertex Program Filename
"main", // Main Vertex Function Name
EVST_VS_2_0, // Vertex Program Profile
"SHADERS/GLSL_001_FRAGMENT_SHADER.frag", // Fragment Shader Filename
"main", // Main Fragment function name
EPST_PS_2_0, // Fragment Shader Profile
this,
EMT_TRANSPARENT_ALPHA_CHANNEL_REF,
0, // ??
EGSL_DEFAULT
);
// OUR NEW TEST SHADER!!
IDSECONDShader = TheGraphicsProcessorGPU
->addHighLevelShaderMaterialFromFiles(
"SHADERS/TEST_VERT.vert", // Vertex Program Filename
"main", // Main Vertex Function Name
EVST_VS_2_0, // Vertex Program Profile
"SHADERS/TEST_FRAG.frag", // Fragment Shader Filename
"main", // Main Fragment function name
EPST_PS_2_0, // Fragment Shader Profile
this //
);
/* EVST_VS_1_1 EVST_VS_2_0 EVST_VS_2_a EVST_VS_3_0 EVST_VS_4_0 EVST_VS_4_1 EVST_VS_5_0 */
/* EPST_PS_1_1 EPST_PS_1_2 EPST_PS_1_3 EPST_PS_1_4 EPST_PS_2_0 EPST_PS_2_a EPST_PS_2_b EPST_PS_3_0 EPST_PS_4_0 EPST_PS_4_1 EPST_PS_5_0 */
//*
// - FIRST ITEM - (ANIMATED)
AniMesh0001 = PrivateSceneManager ->getMesh("Media/0002_FALMER_IK_BAKE/X_001.x");
// Yes! We can open "*.ms3d" from Blender 2.74..
((ISkinnedMesh*)AniMesh0001)->convertMeshToTangents(); // CONVERT A SKINNED MESH TO A SKINNED-TANGENT-MESH!!
AniMeshNode0001 = 0;
AniMeshNode0001 = PrivateSceneManager->addAnimatedMeshSceneNode(AniMesh0001);
// USE THE *.MTL file for an alias object to simplify multitextures..
// We have to automate texture loading!!
// We need a method of naming maps like ID Tech 4 which uses the last letter of the name as a clue to whether it is diffuse, specular or local etc..
// Some kind of string manipulation so that we dont have to do this every time..
// Multiple textures on a model would also allow for more effects..
AniMeshNode0001 -> getMaterial( 0 ).setTexture(DIFFUSE, PrivateDriver->getTexture("Media/0002_FALMER_IK_BAKE/DIFFUSE_MAP.tga"));
AniMeshNode0001 -> getMaterial( 0 ).setTexture(NORMAL, PrivateDriver->getTexture("Media/0002_FALMER_IK_BAKE/NORMAL_MAP.tga"));
AniMeshNode0001 -> getMaterial( 0 ).setTexture(SPECULAR, PrivateDriver->getTexture("Media/0002_FALMER_IK_BAKE/SPECULAR_MAP.tga"));
AniMeshNode0001 -> getMaterial( 0 ).setTexture(GLOSS, PrivateDriver->getTexture("Media/0002_FALMER_IK_BAKE/GLOSS_MAP.tga"));
AniMeshNode0001 -> setMaterialType(E_MATERIAL_TYPE(IDFIRSTShader));
AniMeshNode0001 -> setScale(vector3df( 1.0 , 1.0 , 1.0 )); // Please be sure about why everyone likes BIG Scales!!
AniMeshNode0001 -> setRotation(core::vector3df( 0.0 , 45.0 , 0.0 ));
AniMeshNode0001 -> setPosition(vector3df( -20.0 , 12.0 , 0.0 ));
AniPlaySpeed = 5.0 ;
AniMeshNode0001 -> setAnimationSpeed (AniPlaySpeed) ; // Get this into command..
// AniMeshNode0001 -> setFrameLoop ( 0.0 , 99.0 ); // Automate this..
AniMeshNode0001 -> setFrameLoop ( 0.0 + 1.0 , AniMeshNode0001 -> getEndFrame () + 1.0 ); // Automate this..
// We will controll the sequence here once we have the game running..
/* // Some thing we csn do eith it..
AniMeshNode0001 -> getMaterialCount();
AniMeshNode0001 -> clone();
AniMeshNode0001 -> getAutomaticCulling();
AniMeshNode0001 -> addChild();
AniMeshNode0001 -> getEndFrame ();
AniMeshNode0001 -> setAutomaticCulling ();
AniMeshNode0001 -> setPosition();
AniMeshNode0001 ->
*/
//*/
// - THIRD ITEM - (STATIC)
//*
AniMesh0003 = PrivateSceneManager ->getMesh("Media/0001_DROPSHIP_INTERIOR/OBJ_001.obj"); // N REMEMBER TO DELETE "*.mtl"!! (IRRLICHT does wierd things with it..)
// Dont confuse animesh with skinned mesh..
IMesh0003 = PrivateSceneManager->getMeshManipulator() ->createMeshWithTangents(AniMesh0003->getMesh(0) ,false,false,false,true ); // RECALC NORMALS..
ISceneNode0003 = 0;
ISceneNode0003 = PrivateSceneManager->addMeshSceneNode(IMesh0003);
ISceneNode0003 -> getMaterial( 0 ).setTexture(DIFFUSE, PrivateDriver->getTexture("Media/0001_DROPSHIP_INTERIOR/DIFFUSE_MAP.tga"));
ISceneNode0003 -> getMaterial( 0 ).setTexture(NORMAL, PrivateDriver->getTexture("Media/0001_DROPSHIP_INTERIOR/NORMAL_MAP.tga"));
ISceneNode0003 -> getMaterial( 0 ).setTexture(SPECULAR, PrivateDriver->getTexture("Media/0001_DROPSHIP_INTERIOR/SPECULAR_MAP.tga"));
ISceneNode0003 -> getMaterial( 0 ).setTexture(GLOSS, PrivateDriver->getTexture("Media/0001_DROPSHIP_INTERIOR/GLOSS_MAP.tga"));
ISceneNode0003 -> setMaterialType(E_MATERIAL_TYPE(IDFIRSTShader));
// ISceneNode0003 -> setScale(vector3df( 1.0 , 1.0 , 1.0 ));
ISceneNode0003 -> setScale(vector3df( 0.5 , 0.5 , 0.5 ));
ISceneNode0003 -> setRotation(core::vector3df( 10.0 , 45.0 , 30.0 ));
ISceneNode0003 -> setPosition(vector3df( 20.0 , 20.0 , 0.0 )); //
ISceneNode0003->setDebugDataVisible(EDS_NORMALS); //
//*/
// -- MAIN LOOP --
int OldFps = 0;
while(PrivateDevice->run())
{ // MAIN LOOP
if(PrivateDevice->isWindowActive())
{PrivateDriver->beginScene(true, // backBuffer
true, // zBuffer
SColor( 255 , 207 , 211 , 192 ) // color
);
// Then we switch back to the screen and set our glass pane and
// PrivateDriver->setRenderTarget(0, true, true, SColor( 255 , 207 , 211 , 192 )); // G B R
PrivateSceneManager->drawAll(); // Draw the scene.
PrivateDriver->endScene();
if (PrevPlayPause != PlayPause)
{
if (PlayPause == 0)
{
AniMeshNode0001 -> setAnimationSpeed ( 0 ) ;
}
else if (PlayPause == 1)
{
AniMeshNode0001 -> setAnimationSpeed (AniPlaySpeed) ;
}
}
PrevPlayPause = PlayPause;
if(PrivateDriver->getFPS() != OldFps)
{OldFps = PrivateDriver->getFPS();
core::stringw WindowCaption = "Animated *.x with GLSL Shader.. FPS: ";
WindowCaption += OldFps;
PrivateDevice->setWindowCaption(WindowCaption.c_str());
}
}
} // END MAIN LOOP
// -- END MAIN LOOP --
};
~VECTROTEKAPP()
{// Drop the PrivateDevice when the app is destroyed.
PrivateDevice->drop();
PrivateDevice = NULL;
}
// Here we can change the tint colour based on key input.
virtual bool OnEvent(const irr::SEvent& event)
{if(event.EventType == irr::EET_KEY_INPUT_EVENT)
{if(!event.KeyInput.PressedDown)
{switch(event.KeyInput.Key)
{ // Here we send a value to the Fragment Shader to show how we can control shader operations from our code..
case irr::KEY_KEY_1: FragShadeCommand = 1; break; // Fragemtn Shader " Normal Operation "..
case irr::KEY_KEY_2: FragShadeCommand = 2; break; // Fragment Shader " Mapped Unlit Diffuse "..
case irr::KEY_KEY_3: FragShadeCommand = 3; break; // Fragment Shader " Final Normals "..
case irr::KEY_KEY_4: FragShadeCommand = 4; break; // Fragment Shader " Diffuse Only "..
case irr::KEY_KEY_5: FragShadeCommand = 5; break; // Fragment Shader " Subdued Diffuse ans Specular Only "..
case irr::KEY_KEY_6: FragShadeCommand = 6; break; // Fragment Shader " Tangents "..
case irr::KEY_KEY_7: FragShadeCommand = 7; break; // Fragment Shader " BiNormals "..
case irr::KEY_KEY_8: FragShadeCommand = 8; break; // Fragment Shader " Mapped Normals "..
case irr::KEY_KEY_9: FragShadeCommand = 9; break; // Fragment Shader " VERTEX NORMALS "..
case irr::KEY_KEY_0: FragShadeCommand = 0; break; // Fragment Shader " Special ABmient Interpretation "..
case irr::KEY_KEY_P: PlayPause = !PlayPause; break; // Fragment Shader "PLAY - PAUSE Toggle"..
case irr::KEY_KEY_O: AniPlaySpeed *= 2.0; AniMeshNode0001 -> setAnimationSpeed (AniPlaySpeed) ; break; // "Faster"..
case irr::KEY_KEY_I: AniPlaySpeed *= 0.5; AniMeshNode0001 -> setAnimationSpeed (AniPlaySpeed) ; break; // "Slower"..
case irr::KEY_OEM_4: AniMeshNode0001 -> setCurrentFrame (1) ; break; // 1 is indeed the FIRST FRAME.. "First Frame"..
// AniPlaySpeed;
}
}
}
return false;
}
virtual void OnSetConstants(irr::video::IMaterialRendererServices* PrivateServices, irr::s32 userData)
{
// Here we set the necessary shader constants.
// Both shaders require the same information, so they share this function.
vector3df TheTangent;
vector3df TheBinormal;
//
// MATRICES..
// NEW TESTS TO SEE IF WE CAN GET SKINNED ANIMATED TANGENTS WORKING..
// irr::core::matrix4 matNormal;
irr::core::matrix4 matWorld;
// matWorld.getInverse(matNormal);
// matNormal = matNormal.getTransposed();
// FORGET "HALF ANGLES" and all that jazz...
// This kicks ass!!
TheWorldMatrix = PrivateDriver->getTransform(ETS_WORLD); // THE ONLY ONE!!!!!!
vector3df TheCameraPosition = PrivateSceneManager->getActiveCamera()->getPosition();
LightPosition001 = TheCameraPosition;
PrivateServices->setVertexShaderConstant("mWorld", TheWorldMatrix.pointer(), 16);
// PrivateServices->setVertexShaderConstant("CamPos", &TheCameraPosition.X, 4);
// This is the shader code so we can see how TANGENT, BINORMAL and UV COORDS are passed from OPENGL to the shader..
// UVCoordsXY = gl_MultiTexCoord0.xy;
// Tangent = normalize(gl_MultiTexCoord1);
// Binormal = normalize(gl_MultiTexCoord2);
// Do NOT uncomment the above..
int TexAddress = 0; int TexAddress2 = 1; int TexAddress3 = 2; int TexAddress4 = 3;
PrivateServices->setPixelShaderConstant("DiffuseMap", (int*)(&TexAddress), 1); // Note that this name dont necessarely need to match the name in the shader.. Order does though..
PrivateServices->setPixelShaderConstant("NormalMap", (int*)(&TexAddress2), 1); // AHA!! Must NOT be float as was in example!!
PrivateServices->setPixelShaderConstant("SpecularMap", (int*)(&TexAddress3), 1); // AHA!! Must NOT be float as was in example!!
PrivateServices->setPixelShaderConstant("GlossMap", (int*)(&TexAddress4), 1); // AHA!! Must NOT be float as was in example!!
PrivateServices->setPixelShaderConstant("FShaderCommand", (int*)(&FragShadeCommand), 1); // AFTER GLOSSMAP..
// Note that this name dont necessarely need to match the name in the shader.. Order however is important
// This is what we would have if we opted for RGBA INDIVIDUAL CHANEL UTILISATION..
// This single map would then cater for SPECULAR and GLOSS, and still have TWO MORE FREE CHANNELS available for other things like a "Tangent MAP"..
// Another FOUR CHANNELS would then also be available!
// WE WILL THEN HAVE SPACE FOR AN "EMISSION MAP"!!
// PrivateServices->setPixelShaderConstant("ExtendedEffectsMap", (int*)(&TexAddress4), 1); // AHA!! Must NOT be float as was in example!!
PrivateServices->setPixelShaderConstant("CamPosTEST", &TheCameraPosition.X, 4);
// MAX 4 IMAGES IF WE DONT WANT TO CHANGE IRRLICHT CODE.. THIS MAY A GRAPHICS CARD THING AND NOT SPECIFICALLY AN IRRLICHT THING!!
// SO WE START USING ALPHA CHANNELS OF IMAGES..
// SO FAR WE USE ALPHA FOR DIFFUSE (CLIPMAP) and ALPHA FOR NORMAL MAP (DROPLET SHADING)..
// WE COULD SAVE SPACE AND USE ALPHA FOR SPECULAR MAP AS THE GLOSS MAP...
// THIS WOULD FREE A FOURTH IMAGE THAT WE CAN USE RGB AND ALPHA CHANNELS FOR MORE MAP BASED EFFECTS...
// ANOTHER POSSIBILITY IS THAT WE USE THE SEPARATE RGBA CHANNELS IN AN IMAGE FOR THINGS
// THAT USE SINGLE VALUES LIKE SPECULAR (mono) and GLOSS (single value always)..
// TO DO THIS WE MUST THEN MAKE PEACE WITH THE FACT THAT WE USE SPECULAR (not gloss)
// AS A MONOCHROME VALLUE WHICH IS ACTUALLY PHYSICALLY CORRECT..(SPECULAR IS IN MATHEMATICAL TERMS ATUALLY REFLECTION)
// HAVING COLOUR IN THE SPECULAR MAP MAY NOT NECESSARILY BE PHYSICALLY CORRECT, BUT COULD ENHANCE THE FINAL EFFECT (could it?)..
// THE MORE I THINK ABOUT IT, THE MORE I TEND TOWARD A MONO SPECULAR VALUE BECAUSE A RED, FOR INSTANCE, SPEC COLOUR
// WOULD BE MEANINGLESS ON A BLUE DIFFUSE SURFACE..
// FINALLY, IF WE GO SEPARATE RGBA SINGLE ATTRIBUTES THEN OUR ARTISTS MUST UNDERSTAND THE CHANNEL MIXER IN PHOTOSHOP AND ITS
// COUNTERPART IN OTHER BITMAP EDITORS SUCH AS GIMP..
// WITH CLEVER MATH WE COULD ALSO CALCULATE THE Z OF THE NORMALS GIVEN X AND Y THUS FREEING UP THE "BLUE" CHANNEL FOR EVEN MORE..
// THE FUTURE..
// Reflop Map (what reflects and what does not) would become possible
// once we have "Cubemap Reflection" working like in CG!! (a single value that would work under RGBA mixes)
// PrivateServices->setPixelShaderConstant("PseudoSSSMap", (int*)(&TexAddress4), 1); // Something Im working on that if works would be cool..
PrivateServices->setPixelShaderConstant("mWorld", TheWorldMatrix.pointer(), 16); // HOW ABOUT IT.. THE ONLY MATRIX NEEDED!!
// NEW TEST..
// PrivateServices->setPixelShaderConstant("mWorldNormal", matNormal.pointer(), 16); // HOW ABOUT IT.. THE ONLY MATRIX NEEDED!!
// mWorldNormal
}
};
// = = = = = = = = = = = = = = = = = = = = = =
int main()
{// constructors/destructors used for running etc..
VECTROTEKAPP App;
return 0;
}
// This code was written by Jacques Pretorius "VECTROTEK" in 2015 inspired by all the guys on the IRRLICHT FORUM..
// = = = = = = = = = = = = = = = = = = = = = =