Shield Effects [OpenGL]

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
freetimecoder
Posts: 226
Joined: Fri Aug 22, 2008 8:50 pm
Contact:

Shield Effects [OpenGL]

Post by freetimecoder »

Hi,

I think we abused the topic in Beginners Help long enough :D
I created a shield effect:
edit In Action: http://www.youtube.com/watch?v=MMFfVfzthP0&fmt=18
Image

Fast Download: http://www.file-upload.net/download-254 ... ct.7z.html
edit
Put a "permanent" link on my website: http://www.freetimestudio.de/index.php? ... tware&id=9


This is the code:
CShieldManager.h

Code: Select all

#ifndef CSHIELDMANAGER_H_INCLUDED
#define CSHIELDMANAGER_H_INCLUDED
 
#include <irrlicht.h>
using namespace irr;
 
//! The Shield Manager manages shields, impacts and rendering those.
/** All shields and impacts are structs sorted in an array. The shields
are managed in an array attribute of the manager and the impact in an array of
the respective shield.
The manager also has a drawAll method like the scene manager. It is used the same way.
You can add any mesh node as a shield. However, it is recomended that you use nodes that are
transparent with EMT_TRANSPARENT_ADD_COLOR or EMT_TRANSPARENT_ALPHA_CHANNEL. \n
The first texture of the node should be completely transparent (layer 0). \n
The second will be used as a base color map by the shader (layer 1). \n
The third texture will be used for a gradient effect (layer 2). \n*/
class CShieldManager: public video::IShaderConstantSetCallBack
{
private:
    //!Struct to handle the impacts
    struct SImpact
    {
        //Position of the impact in local node space
        core::vector3df pos;
        //Color of the impact
        video::SColorf color;
        //Maximum radius
        f32 radius;
        //To determine when to delete the impact from the shield's array
        u32 startTime;
        u32 endTime;
    };
 
    //!Struct to handle the shield nodes
    struct SShield
    {
        //The node
        scene::ISceneNode *shieldNode;
        //The array of impacts on this shield
        core::array<SImpact> array_Impacts;
    };
 
public:
    //!Constructor
    /**Sets up the manager and creates the shader
        \param psmgr SceneManager of the device
        \param ptimer Timer of the device*/
    CShieldManager(scene::ISceneManager* psmgr, irr::ITimer *ptimer);
 
    //!Destructor
    ~CShieldManager();
 
    //!Renders the shields
    void drawAll();
 
    //!Sets the uniform variables for the shader
    virtual void OnSetConstants(video::IMaterialRendererServices* services,s32 userData);
 
    //!Add a new shield
    /**\return true if it is a new shield, false if the shield already exists
        \param node The node that shall act as a shield */
    bool addShield(scene::ISceneNode *node);
 
    //!Remove a shield
    /**\return true if it shield was removed, false if the shield was not found
        \param node The shield that shall be removed */
    bool removeShield(scene::ISceneNode *node);
 
    //!Add an impact in object space to the shield
    /**\return true if the shield exists and the impact has been added
        \param node The node that acts as a shield
        \param position The position of the impact on the shield in the shieldnode's local space
        \param radius The maximum radius of the impact
        \param duration The impact's lifespan
        \param color The Color of the impact*/
    bool addLocalImpact(const scene::ISceneNode *node, const core::vector3df position,const f32 radius=1, const u32 duration=500, const video::SColorf color = video::SColorf(1,1,1,1));
 
    //!Add an impact in global space to the shield
    /**\return true if the shield exists and the impact has been added
        \param node The node that acts as a shield
        \param position The position of the impact on the shield in global space
        \param radius The maximum radius of the impact
        \param duration The impact's lifespan
        \param color The Color of the impact*/
    bool addGlobalImpact(const scene::ISceneNode *node, core::vector3df &position,const f32 radius=1, const u32 duration=500, const video::SColorf color = video::SColorf(1,1,1,1));
 
    //!Let the manager determine the impact position by using a given ray
    /**\return the local position of the impact when successful, the ray's end otherwise
        \param node The node that acts as a shield
        \param ray The ray that hits the shield
        \param radius The maximum radius of the impact
        \param duration The impact's lifespan
        \param color The Color of the impact*/
    core::vector3df addImpact(const scene::ISceneNode *node, const core::line3df ray, const f32 radius=1, const u32 duration=500, const video::SColorf color = video::SColorf(1,1,1,1));
 
private:
    //To check if the shields are currently visible
    scene::ISceneManager* smgr;
 
    //To draw the shields/impacts
    video::IVideoDriver* driver;
 
    //To erase impacts after their lifetime
    irr::ITimer *timer;
 
    //Manage the shields
    core::array<SShield> array_Shields;
 
    //The shield shader
    int shaderMaterial;
 
    //For compatibility
    //no shader: -1
    //arb shader 0;
    //glsl shader 1;
    int ShaderType;
 
    //The following attributes parameters for the OnSetConstants method
    //Radius of the current impact
    f32 tmp_radius;
    //Position of the current impact
    core::vector3df tmp_position;
    //Color of the current impact
    video::SColorf tmp_color;
};
 
#endif // CSHIELDMANAGER_H_INCLUDED
 
edit Added a fade-out effect (uncomment it for use)
edit Added Viz_fuerte's arb shader
CShieldManager.cpp

Code: Select all

#include "CShieldManager.h"
 
CShieldManager::CShieldManager(scene::ISceneManager* psmgr, irr::ITimer *ptimer){
    //Assign all parameters
    smgr = psmgr;
    driver=psmgr->getVideoDriver();
    timer = ptimer;
 
    ShaderType=-1;
    shaderMaterial = video::EMT_SOLID;
 
    //Witout OpenGL these shaders won't work
    if(!driver->getDriverType()==video::EDT_OPENGL)
        return;
 
    if(driver->queryFeature(video::EVDF_ARB_GLSL)){
        ///GLSL Shader Code
        //Vertex Shader
        const c8 *vertShader = "varying vec3 vertpos;           \n\
                                                                \n\
                        void main(void)                         \n\
                        {                                       \n\
                            vertpos = gl_Vertex.xyz;            \n\
                                                                \n\
                            gl_TexCoord[0] = gl_MultiTexCoord0; \n\
                            gl_Position = ftransform();         \n\
                        }                                       \n\
                        ";
 
        //Fragment Shader
        const c8 *fragShader = "uniform sampler2D ColorMap;                                                                     \n\
                        uniform sampler2D GradientTexture;                                                                      \n\
                        uniform float radius;                                                                                   \n\
                        uniform vec4 color;                                                                                     \n\
                        uniform vec3 current_position;                                                                          \n\
                                                                                                                                \n\
                        varying vec3 vertpos;                                                                                   \n\
                                                                                                                                \n\
                        void main(void)                                                                                         \n\
                        {                                                                                                       \n\
                            vec3 dif =  vertpos - current_position;                                                             \n\
                            float dist = dif.x*dif.x + dif.y*dif.y + dif.z*dif.z;                                               \n\
                                                                                                                                \n\
                            float intensity=1/dist*radius*0.01;                                                                 \n\
                            if(intensity>0.9)                                                                                   \n\
                                intensity=0.9;                                                                                  \n\
                            if(intensity<0)                                                                                     \n\
                                intensity=0;                                                                                    \n\
                                                                                                                                \n\
                            vec4 diffuse = texture2D(ColorMap, vec2(gl_TexCoord[0]));                                           \n\
                            vec4 gradient = vec4(texture2D(GradientTexture,vec2(intensity,1)));                                 \n\
                                                                                                                                \n\
                            vec4 final_color = gradient*diffuse*intensity*color;                                                \n\
                                                                                                                                \n\
                            gl_FragColor=final_color;                                                                           \n\
                        }                                                                                                       \n\
                        ";
 
        ShaderType = 1;
        //Create the shader material
        shaderMaterial = driver->getGPUProgrammingServices()->addHighLevelShaderMaterial(
                vertShader, "main", video::EVST_VS_1_1,
                fragShader, "main", video::EPST_PS_1_1,
                this, video::EMT_ONETEXTURE_BLEND);
    }else{
        if(driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1) && driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)){
            //ARB Shader for compatibility from Viz_fuerte
            const c8 *vertShader = "!!ARBvp1.0\n\
                                    \n\
                                    PARAM c[5] = { program.local[0],\n\
                                              state.matrix.mvp };\n\
                                    \n\
                                    MOV result.texcoord[0], vertex.texcoord[0];\n\
                                    MOV result.texcoord[1].xyz, vertex.position;\n\
                                    DP4 result.position.w, vertex.position, c[4];\n\
                                    DP4 result.position.z, vertex.position, c[3];\n\
                                    DP4 result.position.y, vertex.position, c[2];\n\
                                    DP4 result.position.x, vertex.position, c[1];\n\
                                    END\n\
                                    ";
 
            const c8 *fragShader = "!!ARBfp1.0\n\
                                    OPTION ARB_precision_hint_nicest;\n\
                                    \n\
                                    # texture  ColorMap -> index 0\n\
                                    # texture  GradientTexture -> index 1\n\
                                    \n\
                                    # float    radius -> 0\n\
                                    # float[4] color -> 1\n\
                                    # float[3] current_position -> 2\n\
                                    \n\
                                    \n\
                                    PARAM c[4] = { program.local[0..2],\n\
                                            { 0.0099999998, 0.89999998, 0, 1 } };\n\
                                    TEMP R0;\n\
                                    TEMP R1;\n\
                                    TEMP R2;\n\
                                    ADD R0.xyz, fragment.texcoord[1], -c[2];\n\
                                    MUL R0.y, R0, R0;\n\
                                    MAD R0.x, R0, R0, R0.y;\n\
                                    MAD R0.x, R0.z, R0.z, R0;\n\
                                    RSQ R0.x, R0.x;\n\
                                    RCP R0.x, R0.x;\n\
                                    MUL R0.x, R0, R0;\n\
                                    RCP R0.x, R0.x;\n\
                                    MUL R0.x, R0, c[0];\n\
                                    MUL R0.x, R0, c[3];\n\
                                    ADD R0.y, R0.x, -c[3];\n\
                                    CMP R0.x, -R0.y, c[3].y, R0;\n\
                                    CMP R2.x, R0, c[3].z, R0;\n\
                                    MOV R2.y, c[3].w;\n\
                                    TEX R1, fragment.texcoord[0], texture[0], 2D;\n\
                                    TEX R0, R2, texture[1], 2D;\n\
                                    MUL R0, R0, R1;\n\
                                    MUL R0, R0, R2.x;\n\
                                    MUL result.color, R0, c[1];\n\
                                    END\n\
                                    ";
            ShaderType=0;
            shaderMaterial = driver->getGPUProgrammingServices()->addShaderMaterial(
                    vertShader,fragShader,this, video::EMT_ONETEXTURE_BLEND);
        }
    }
}
 
CShieldManager::~CShieldManager(){
    //Erase everything
    for(u32 i=0; i<array_Shields.size();i++){
        while(!array_Shields[i].array_Impacts.empty()){
            array_Shields[i].array_Impacts.erase(0);
        }
    }
    while(!array_Shields.empty()){
        array_Shields.erase(0);
    }
}
 
bool CShieldManager::addShield(scene::ISceneNode *node){
    //Check if shield already exists
    for(u32 i=0; i<array_Shields.size();i++){
        if(array_Shields[i].shieldNode == node){
            //Shield already exists
            return false;
        }
    }
    //Create a new shield
    SShield tmpShield;
    tmpShield.shieldNode = node;
    array_Shields.push_back(tmpShield);
    return true;
}
 
bool CShieldManager::removeShield(scene::ISceneNode *node){
    //Check if shield exists
    for(u32 i=0; i<array_Shields.size();i++){
        if(array_Shields[i].shieldNode == node){
            //Erase all impacts of the shield
            while(!array_Shields[i].array_Impacts.empty()){
                array_Shields[i].array_Impacts.erase(0);
            }
            array_Shields.erase(i);
            return true;
        }
    }
    return false;
}
 
bool CShieldManager::addLocalImpact(const scene::ISceneNode *node, const core::vector3df position,const f32 radius, const u32 duration, const video::SColorf color)
{
    //Find the shield
    for(u32 i=0; i<array_Shields.size();i++){
        if(array_Shields[i].shieldNode == node){
            //Create a new impact
            SImpact tmpImpact;
            tmpImpact.pos = position;
            tmpImpact.startTime = timer->getTime();
            tmpImpact.endTime = timer->getTime()+duration;
            tmpImpact.radius = radius;
            tmpImpact.color = color;
 
            array_Shields[i].array_Impacts.push_back(tmpImpact);
            return true;
        }
    }
    //Shield was not found
    return false;
}
 
bool CShieldManager::addGlobalImpact(const scene::ISceneNode *node, core::vector3df &position,const f32 radius, const u32 duration, const video::SColorf color)
{
    //Find the shield
    for(u32 i=0; i<array_Shields.size();i++){
        if(array_Shields[i].shieldNode == node){
            //Transform the position to local space
            core::matrix4 trans = node->getAbsoluteTransformation();
            trans.makeInverse();
            trans.transformVect(position);
 
            //Create a new impact
            SImpact tmpImpact;
            tmpImpact.pos = position;
            tmpImpact.startTime = timer->getTime();
            tmpImpact.endTime = timer->getTime()+duration;
            tmpImpact.radius = radius;
            tmpImpact.color = color;
 
            array_Shields[i].array_Impacts.push_back(tmpImpact);
            return true;
        }
    }
    //Shield was not found
    return false;
}
 
core::vector3df CShieldManager::addImpact(const scene::ISceneNode *node, const core::line3df ray, const f32 radius, const u32 duration, const video::SColorf color){
    //Check if node pointer is given, otherwise the collision point routine will crash
    if(!node)
        return ray.end;
 
    //Check for intersection
    core::vector3df colPoint;
    core::triangle3df colTris;
    const scene::ISceneNode* outNode;
    if(smgr->getSceneCollisionManager()->getCollisionPoint(ray,
            node->getTriangleSelector(), colPoint,
            colTris, outNode))
    {
        //Intersection found
        //Transform position to local space
        core::vector3df tmpPoint = core::vector3df(colPoint);
        core::matrix4 trans = node->getAbsoluteTransformation();
        trans.makeInverse();
        trans.transformVect(colPoint);
        //Add impact
        addLocalImpact(node,colPoint,radius,duration,color);
        return tmpPoint;
    }
    //No intersection
    return ray.end;
}
 
void CShieldManager::drawAll(){
 
    for(u32 i=0; i<array_Shields.size();i++)
    {
        array_Shields[i].shieldNode->updateAbsolutePosition();
 
        //Check for dead impacts and delete them
        for(u32 j=0; j<array_Shields[i].array_Impacts.size();){
            if(timer->getTime()>array_Shields[i].array_Impacts[j].endTime){ //If impact is dead
                array_Shields[i].array_Impacts.erase(j);
            }else{
                ++j;
            }
        }
        //I learned this meshbuffer trick from Viz_Fuerte's "Simple but useful projects"
        //Draw shield only when node is visible
        if(!smgr->isCulled(array_Shields[i].shieldNode))
        {
            //Reset the transformation
            driver->setTransform(video::ETS_WORLD,array_Shields[i].shieldNode->getAbsoluteTransformation());
 
            //Draw all impacts
            for(u32 j=0; j<array_Shields[i].array_Impacts.size();j++){
                tmp_position = array_Shields[i].array_Impacts[j].pos;
 
                //Calculate the impact's radius dependant on time
                u32 dif1 = array_Shields[i].array_Impacts[j].endTime-array_Shields[i].array_Impacts[j].startTime;
                u32 dif2 = timer->getTime()-array_Shields[i].array_Impacts[j].startTime;
                //Range from start (0.0) to end (1.0)
                f32 dif = (dif2/(dif1*1.0));
 
 
                ///Different effects for the shield:
                ///You can calculate the impacts radius with a function that uses "dif" as an argument. dif is betweeen 0.0 (life start) and 1.0 (life end)
 
                ///\n These are two preset effects:
                /**1. Absorbing effect:
                \code
                tmp_radius = array_Shields[i].array_Impacts[j].radius*(0.25 - pow((dif-0.5),2));
                tmp_color = array_Shields[i].array_Impacts[j].color;
                \endcode
                */
 
                /**2. Fade-out effect:
                \code
                tmp_radius = array_Shields[i].array_Impacts[j].radius*dif;
                tmp_color = array_Shields[i].array_Impacts[j].color;
                tmp_color.a = 1-dif;
                \endcode
                */
 
                //Using effect 2
                tmp_radius = array_Shields[i].array_Impacts[j].radius*dif;
                tmp_color = array_Shields[i].array_Impacts[j].color;
                tmp_color.a = 1-dif;
 
                //Draw the impact on all materials of the shield node
                for(u32 k=0; k<array_Shields[i].shieldNode->getMaterialCount(); ++k)
                {
                    video::SMaterial material = array_Shields[i].shieldNode->getMaterial(k);
                    material.MaterialType = (video::E_MATERIAL_TYPE)shaderMaterial;
                    material.MaterialTypeParam = pack_texureBlendFunc(video::EBF_SRC_ALPHA,video::EBF_ONE);
                    //Prevent transparency issues
                    material.setFlag(video::EMF_ZWRITE_ENABLE,false);
 
                    driver->setMaterial(material);
                    switch(array_Shields[i].shieldNode->getType()){
                    case scene::ESNT_ANIMATED_MESH:
                        driver->drawMeshBuffer(((scene::IAnimatedMeshSceneNode*)array_Shields[i].shieldNode)->getMesh()->getMeshBuffer(k));
                        break;
                    default:
                        driver->drawMeshBuffer(((scene::IMeshSceneNode*)array_Shields[i].shieldNode)->getMesh()->getMeshBuffer(k));
                        break;
                    };
                }
            }
        }
    }
}
 
//This is called for each impact render
void CShieldManager::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
    switch(ShaderType){
    case 0:
        // Color
        services->setPixelShaderConstant((float*)(&tmp_color),1, 4);
 
        // Radius
        services->setPixelShaderConstant((float*)(&tmp_radius),0, 1);
 
        // Current position
        services->setPixelShaderConstant((float*)(&tmp_position),2, 3);
 
        break;
    case 1:
        // Color
        services->setPixelShaderConstant("color", (float*)(&tmp_color ), 4);
 
        // Radius
        services->setPixelShaderConstant("radius", (float*)(&tmp_radius ), 1);
 
        // Current position
        services->setPixelShaderConstant("current_position", (float*)(&tmp_position ), 3);
 
        //Set the texture layers
        int var0=0;
        services->setPixelShaderConstant("ColorMap", (float*)(&var0), 1);
        int var1=1;
        services->setPixelShaderConstant("GradientTexture", (float*)(&var1), 1);
        break;
    };
}
 
 
main.cpp

Code: Select all

/** \mainpage Irrlicht Shield Effect
 
    Creating a shield is easy. \n
    First you have to create a shield manager:
    \code
    CShieldManager *shieldmanager = new CShieldManager(smgr,device->getTimer());
    \endcode
    This manager works like the ISceneManger from irrlicht, just for shields.\n
 
 
    To add a shield, first create a scene node that you want to use as a shield e.g.
    \code
    scene::IMeshSceneNode shield_node = smgr->addSphereSceneNode(5);
    \endcode
 
    Next configure the material of the node, to make the shield visible from in- and outside
    \code
    shield_node->setMaterialFlag(video::EMF_BACK_FACE_CULLING,false);
    \endcode
    \n
    Then you make the node invisible, so that it does not interfere with the shield render pass
    \code
    shield_node->setbVisible(false);
    \endcode
    \n
    In case you want to use rays to let the manager calculate impacts, you have to create a triangle selector for the node:
    \code
    scene::ITriangleSelector *selector = smgr->createTriangleSelector(shield_node->getMesh(),shield_node);
    shield_node->setTriangleSelector(selector);
    selector->drop();
    \endcode
    At last you add the shield:
    \code
    shieldmanager->addShield(shield_node);
    \endcode
    To add impacts you have to call the addImpact/addLocalImpact/addGlobalImpact function.
    To render the shields, call drawAll after the drawAll of the scene manager, otherwise the shields will be overdrawn by the rest of the scenery.
 
    \n
    \n
    So thats that, have fun! \n
    <a href="http://www.freetimestudio.de">www.freetimestudio.de</a>
*/
 
#include <irrlicht.h>
using namespace irr;
 
#include "CShieldManager.h"
 
//What shield type should be displayed
int shield_config = 3;
//The two shield nodes
scene::IMeshSceneNode *shield_node1;
scene::IAnimatedMeshSceneNode *shield_node2;
//Other attributes of the impacts
f32 radius = 1;
u32 duration = 500;
video::SColorf impact_color(1,1,1,1);
 
video::IVideoDriver *driver;
 
//!Simple Event receiver to process the space key and change the configuration
class myEventReceiver : public IEventReceiver{
public:
    myEventReceiver(){};
    ~myEventReceiver(){};
    virtual bool OnEvent(const SEvent& event)
    {
        if(event.EventType == EET_KEY_INPUT_EVENT){
            if(!event.KeyInput.PressedDown){
                if(event.KeyInput.Key == KEY_SPACE){
                    //Change the shield textures based on the configuration number
                    shield_config++;
                    shield_config = shield_config%5;
                    switch(shield_config){
                    case 0:
                        impact_color = video::SColorf(0,1,2,1);
                        duration = 500;
                        radius=60;
 
                        shield_node1->setMaterialTexture(0,driver->getTexture("Data/textures/shield_tex.png"));
                        shield_node1->setMaterialTexture(1,driver->getTexture("Data/textures/gradient.png"));
 
                        shield_node2->setMaterialTexture(0,driver->getTexture("Data/textures/shield_tex.png"));
                        shield_node2->setMaterialTexture(1,driver->getTexture("Data/textures/gradient.png"));
                        break;
                    case 1:
                        radius=10;
                        impact_color = video::SColorf(1,1,0,1);
                        duration = 1000;
 
                        shield_node1->setMaterialTexture(0,driver->getTexture("Data/textures/detailmap3.jpg"));
                        shield_node1->setMaterialTexture(1,driver->getTexture("Data/textures/gradient_color.png"));
 
                        shield_node2->setMaterialTexture(0,driver->getTexture("Data/textures/detailmap3.jpg"));
                        shield_node2->setMaterialTexture(1,driver->getTexture("Data/textures/gradient_color.png"));
                        break;
                    case 2:
                        radius=20;
                        impact_color = video::SColorf(0,1,0.5,1);
                        duration = 450;
                        shield_node1->setMaterialTexture(0,driver->getTexture("Data/textures/water.jpg"));
                        shield_node1->setMaterialTexture(1,driver->getTexture("Data/textures/gradient_blinds.png"));
 
                        shield_node2->setMaterialTexture(0,driver->getTexture("Data/textures/water.jpg"));
                        shield_node2->setMaterialTexture(1,driver->getTexture("Data/textures/gradient_blinds.png"));
                        break;
                    case 3:
                        radius=10;
                        impact_color = video::SColorf(3,1,0,1);
                        duration = 500;
                        shield_node1->setMaterialTexture(0,driver->getTexture("Data/textures/wall.jpg"));
                        shield_node1->setMaterialTexture(1,driver->getTexture("Data/textures/gradient_two.png"));
 
                        shield_node2->setMaterialTexture(0,driver->getTexture("Data/textures/wall.jpg"));
                        shield_node2->setMaterialTexture(1,driver->getTexture("Data/textures/gradient_two.png"));
                        break;
                    case 4:
                        radius=5;
                        impact_color = video::SColorf(3,1,0,1);
                        duration = 500;
                        shield_node1->setMaterialTexture(0,driver->getTexture("Data/textures/blank.png"));
                        shield_node1->setMaterialTexture(1,driver->getTexture("Data/textures/blank.png"));
 
                        shield_node2->setMaterialTexture(0,driver->getTexture("Data/textures/blank.png"));
                        shield_node2->setMaterialTexture(1,driver->getTexture("Data/textures/blank.png"));
                        break;
                    };
                    return true;
                }
            }
        }
 
        return false;
    }
};
 
int main(int argc, char** argv)
{
    //Set up device and receiver
    myEventReceiver *receiver = new myEventReceiver();
    IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(640,480), 32,false,false,false,receiver);
 
    driver = device->getVideoDriver();
    scene::ISceneManager *smgr = device->getSceneManager();
 
    //Create the camera
    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;
 
    scene::ICameraSceneNode *camera = smgr->addCameraSceneNodeFPS(0,100,0.03,-1,keyMap,8);
    camera->setPosition(core::vector3df(0,10,-40));
    camera->setTarget(core::vector3df(10,5,0));
 
    //Add a light
    smgr->addLightSceneNode(0,core::vector3df(0,20,0),
            video::SColorf(1.0f, 1.0f, 1.0f),
            500.0f);
 
    //Neccessary for textur coordinates changes of the shield nodes
    scene::IMeshManipulator *manipulator = smgr->getMeshManipulator();
 
    ///Create the shield manager
    CShieldManager *shieldmanager = new CShieldManager(smgr,device->getTimer());
 
    //Add the first battle turtle
    scene::IAnimatedMeshSceneNode *battle_turtle1 = smgr->addAnimatedMeshSceneNode(smgr->getMesh("Data/turtle.b3d"));
    battle_turtle1->setMaterialTexture(0,driver->getTexture("Data/turtle_green.jpg"));
    battle_turtle1->setScale(core::vector3df(0.25,0.25,0.25));
    battle_turtle1->setPosition(core::vector3df(0,0,0));
    battle_turtle1->setFrameLoop(0,10);
    battle_turtle1->setAnimationSpeed(15);
 
    //Add the battle turtle's shield
    shield_node1 = smgr->addSphereSceneNode(1,32,battle_turtle1);
    manipulator->scaleTCoords(shield_node1->getMesh(),core::vector2df(6,6),1);
    shield_node1->setMaterialFlag(video::EMF_BACK_FACE_CULLING,false);
    shield_node1->setScale(core::vector3df(20,20,20));
    shield_node1->setVisible(false);
 
    scene::ITriangleSelector *selector = smgr->createTriangleSelector(shield_node1->getMesh(),shield_node1);
    shield_node1->setTriangleSelector(selector);
    selector->drop();
 
    shieldmanager->addShield(shield_node1);
 
 
    //Add the second battle turtle
    scene::IAnimatedMeshSceneNode *battle_turtle2 = smgr->addAnimatedMeshSceneNode(smgr->getMesh("Data/turtle.b3d"));
    battle_turtle2->setMaterialTexture(0,driver->getTexture("Data/turtle_red.jpg"));
    battle_turtle2->setScale(core::vector3df(0.25,0.25,0.25));
    battle_turtle2->setPosition(core::vector3df(10,0,0));
    battle_turtle2->setRotation(core::vector3df(0,180,0));
    battle_turtle2->setFrameLoop(0,10);
    battle_turtle2->setAnimationSpeed(15);
 
    //Add the battle turtle's shield
    shield_node2 = smgr->addAnimatedMeshSceneNode(smgr->getMesh("Data/turtle2.b3d"),battle_turtle2);
    shield_node2->setFrameLoop(0,10);
    shield_node2->setAnimationSpeed(15);
 
    manipulator->scaleTCoords(shield_node2->getMesh(),core::vector2df(6,6),1);
    shield_node2->setMaterialFlag(video::EMF_BACK_FACE_CULLING,false);
    shield_node2->setScale(core::vector3df(1.1,1.1,1.1));
    shield_node2->setVisible(false);
 
    selector = smgr->createTriangleSelector(shield_node2->getMesh(),shield_node2);
    shield_node2->setTriangleSelector(selector);
    selector->drop();
 
    shieldmanager->addShield(shield_node2);
 
    //To draw the shooting rays
    core::array<core::vector3df> battle_rays_1;
    core::array<u32> battle_rays_time_1;
 
    core::array<core::vector3df> battle_rays_2;
    core::array<u32> battle_rays_time_2;
 
    //Little workaround to set up the first shield configuration
    SEvent nEvent;
    nEvent.EventType = EET_KEY_INPUT_EVENT;
    nEvent.KeyInput.Key = KEY_SPACE;
    nEvent.KeyInput.PressedDown = false;
    receiver->OnEvent(nEvent);
 
 
    //FPS measurement
    int lastFPS = -1;
    u32 lastMS = device->getTimer()->getRealTime();
 
    while(device->run())
    {
 
        //Frameindipendence
        u32 difMs = device->getTimer()->getRealTime()-lastMS;
        lastMS = device->getTimer()->getRealTime();
        f32 alignSpeed = difMs/16.0;
        //Move the turtles
        battle_turtle1->setPosition(battle_turtle1->getPosition()+battle_turtle1->getRotation().rotationToDirection()*0.1*alignSpeed);
        battle_turtle1->setRotation(battle_turtle1->getRotation()+core::vector3df(0,0.85,0)*alignSpeed);
 
        battle_turtle2->setPosition(battle_turtle2->getPosition()+battle_turtle2->getRotation().rotationToDirection()*0.1*alignSpeed);
        battle_turtle2->setRotation(battle_turtle2->getRotation()+core::vector3df(0,-0.85,0)*alignSpeed);
 
 
        //Create new rays and impacts randomly
        if(lastMS%(rand()%200+300)==0){
            core::vector3df source = battle_turtle1->getPosition()+core::vector3df(0,5,0);
            core::vector3df target = battle_turtle2->getPosition()+core::vector3df(2-rand()%3,5-rand()%4,2-rand()%3)*0.6;
 
            const core::line3df ray(source,target);
 
            core::vector3df result = shieldmanager->addImpact(shield_node2, ray,radius*250,duration,impact_color);
            core::matrix4 trans = shield_node2->getAbsoluteTransformation();
            trans.makeInverse();
            trans.transformVect(result);
            battle_rays_1.push_back(result);
            battle_rays_time_1.push_back(device->getTimer()->getTime()+500);
        }
 
        if(lastMS%(rand()%200+300)==0){
            core::vector3df source = battle_turtle2->getPosition()+core::vector3df(0,5,0);
            core::vector3df target = battle_turtle1->getPosition()+core::vector3df(4-rand()%9,4-rand()%9,4-rand()%9);
 
            const core::line3df ray(source,target);
            core::vector3df result = shieldmanager->addImpact(shield_node1, ray,radius,duration,impact_color);
            core::matrix4 trans = shield_node1->getAbsoluteTransformation();
            trans.makeInverse();
            trans.transformVect(result);
            battle_rays_2.push_back(result);
            battle_rays_time_2.push_back(device->getTimer()->getTime()+500);
        }
 
        //Draw the scene
        driver->beginScene(true, true, video::SColor(50,50,50,50));
        smgr->drawAll();
 
        ///Draw the shields afterwards, otherwise the regular nodes will overdraw them
        shieldmanager->drawAll();
 
        //Draw the rays
        video::SMaterial material;
        material.Lighting = false;
        material.Thickness = 1;
        material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
        driver->setMaterial(material);
        driver->setTransform(video::ETS_WORLD,core::matrix4());
 
        for(int i = 0;i<battle_rays_1.size();){
            if(battle_rays_time_1[i]<device->getTimer()->getTime()){
                battle_rays_time_1.erase(i);
                battle_rays_1.erase(i);
            }else{
                u32 time = device->getTimer()->getTime();
                f32 dif = (battle_rays_time_1[i]-time)/500.0f;
                core::vector3df result1 = battle_rays_1[i];
                core::matrix4 trans1 = shield_node2->getAbsoluteTransformation();
                trans1.transformVect(result1);
                driver->draw3DLine(battle_turtle1->getPosition()+core::vector3df(0,5,0),result1,video::SColor(255*dif,0,255*dif,0));
                i++;
            }
        }
 
        for(int i = 0;i<battle_rays_2.size();){
            if(battle_rays_time_2[i]<device->getTimer()->getTime()){
                battle_rays_time_2.erase(i);
                battle_rays_2.erase(i);
            }else{
                u32 time = device->getTimer()->getTime();
                f32 dif = (battle_rays_time_2[i]-time)/500.0f;
                core::vector3df result2 = battle_rays_2[i];
                core::matrix4 trans2 = shield_node1->getAbsoluteTransformation();
                trans2.transformVect(result2);
                driver->draw3DLine(battle_turtle2->getPosition()+core::vector3df(0,5,0),result2,video::SColor(255*dif,255*dif,0,0));
                i++;
            }
        }
 
        driver->endScene();
 
 
        //Display the FPS
        int fps = driver->getFPS();
 
        if (lastFPS != fps)
        {
            core::stringw str = L"Shielding - Move with Mouse and WASD/Arrow Keys - Change Shield with Space - FPS:";
            str += fps;
 
            device->setWindowCaption(str.c_str());
            lastFPS = fps;
        }
 
    }
    //Cleanup
    device->drop();
    delete shieldmanager;
 
    return 0;
}
 
There is another cool shield effect created by Sudi!
Image

You can also see it in action in this video.
The source code can be found here.

greetings
Last edited by freetimecoder on Sat Sep 01, 2012 9:57 am, edited 9 times in total.
shadowslair
Posts: 758
Joined: Mon Mar 31, 2008 3:32 pm
Location: Bulgaria

Post by shadowslair »

Haha! Cyborg turtle anyone?! It was kinda strange to see a turtle with a shield, so I made some quick space texture in 20 minutes just for fun. :D
http://img14.imageshack.us/img14/8783/turtle1d.jpg
http://img46.imageshack.us/img46/2978/turtle1b.jpg

Shield lookin` pretty cool. :wink:
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

Looks really great from the screenshots, but I'm guessing you need to see it moving to get a real idea of what it looks like. Any chance of a video for us non-Windows users who are too lazy/drunk to compile it to see what it looks like? :D
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

yeah, looks great in action !!! :)
but unfortunately only for openGL, isn't it ??? :cry:
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
freetimecoder
Posts: 226
Joined: Fri Aug 22, 2008 8:50 pm
Contact:

Post by freetimecoder »

Hi,

Thanks for the cyborg texture :)

I uploaded a video:
http://www.youtube.com/watch?v=MMFfVfzthP0&fmt=18

Yes it is OpenGL (glsl), I think a conversion to HLSL would be easy, but I don't know how to code HLSL.
Darktib
Posts: 167
Joined: Sun Mar 23, 2008 8:25 pm
Location: France

Post by Darktib »

Outstanding!

But for me, I just see black effect (on both the sphere shield and the other turtle) when a turtle is hit...

Console output:

Code: Select all

Irrlicht Engine version 1.7.0-beta
Microsoft Windows XP Personal Service Pack 3 (Build 2600)
Using renderer: OpenGL 2.1.2
GeForce 6800 LE/PCI/SSE2: NVIDIA Corporation
OpenGL driver version is 1.2 or better.
GLSL version: 1.2
GLSL shader failed to compile
0(1) : error C1115: unable to find compatible overloaded function "pow(float, int)"
0(1) : warning C7011: implicit cast from "int" to "float"

Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Loaded mesh: Data/turtle.b3d
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/turtle1.jpg
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/textures/transparent.png
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Could not open file of texture: turtle1.dds
Loaded mesh: Data/turtle2.b3d
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/textures/blank.png
Resizing window (640 480)
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/textures/shield_tex.png
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/textures/gradient.png
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/textures/detailmap3.jpg
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/textures/gradient_color.png
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/textures/water.jpg
Loaded texture: D:/Irrlicht/ShieldingEffect_bin_src/Copie de ShieldingEffect_bin_src/Data/textures/gradient_blinds.png
The file turtle1.dds is not found (and doesn't exist...) but it has apparently no consequences.
The problem might come from my version of OpenGL.


edit: I've corrected the bug: the pow function is useless, because you're using it to retrieve a squared distance.

The best is to remove the 'sqrt' call and the 'pow' call : it compiles, and it runs faster.

Here is the modified shader:

Code: Select all

	const c8 *fragShader = "uniform sampler2D ColorMap;                                                                     \
                    uniform sampler2D GradientTexture;                                                                      \
                    uniform float radius;                                                                                   \
                    uniform vec4 color;                                                                                     \
                    uniform vec3 current_position;                                                                          \
                                                                                                                            \
                    varying vec3 vertpos;                                                                                   \
                                                                                                                            \
                    void main(void)                                                                                         \
                    {                                                                                                       \
                        vec3 dif =  vertpos - current_position;                                                             \
                        float dist = dif.x*dif.x + dif.y*dif.y + dif.z*dif.z;                                               \
                                                                                                                            \
                        float intensity=(1.0/dist)*radius*0.01;                                                             \
                        if(intensity>0.9)                                                                                   \
                            intensity=0.9;	                                                                                \
                        if(intensity<0)                                                                                     \
                            intensity=0;	                                                                                \
                                                                                                                            \
                        vec4 diffuse = texture2D(ColorMap, vec2(gl_TexCoord[0]));                                           \
                        vec4 gradient = vec4(texture2D(GradientTexture,vec2(intensity,1)));                                 \
                                                                                                                            \
                        vec4 final_color = gradient*diffuse*intensity*color;                                                \
                                                                                                                            \
                        gl_FragColor=final_color;                                                                           \
                    }                                                                                                       \
                    ";
freetimecoder
Posts: 226
Joined: Fri Aug 22, 2008 8:50 pm
Contact:

Re: Shield Effects

Post by freetimecoder »

~sorry wrong button ~
Last edited by freetimecoder on Tue May 25, 2010 8:33 am, edited 1 time in total.
freetimecoder
Posts: 226
Joined: Fri Aug 22, 2008 8:50 pm
Contact:

Post by freetimecoder »

Code: Select all

0(1) : error C1115: unable to find compatible overloaded function "pow(float, int)" 
Yes I think it is because your glsl version. But you are right, this function was useless :oops: Overlooked it when optimizing the code. I testet out several pow values before.

greetings
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

Post by trivtn »

Nice !
There's something is fantastic, there's nothing is absolute.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

The video looks really cool, again, nice work :)

I do have one suggestion: I have a hunch that the effect would look better if the impact texture grew and faded to transparent so it looks like the energy is dissipating, instead of growing and then shrinking again.
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

bitplane wrote: I do have one suggestion: I have a hunch that the effect would look better if the impact texture grew and faded to transparent so it looks like the energy is dissipating, instead of growing and then shrinking again.
Check my shield effect it does it.
Video
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Turtles!
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
freetimecoder
Posts: 226
Joined: Fri Aug 22, 2008 8:50 pm
Contact:

Post by freetimecoder »

bitplane wrote:I have a hunch that the effect would look better if the impact texture grew and faded to transparent so it looks like the energy is dissipating.
You can easily change the look of the effect. To make it fade out, you have to replace these lines in CShieldManager.cpp

Code: Select all

                tmp_radius = array_Shields[i].array_Impacts[j].radius*(0.25 - pow((dif-0.5),2));
                tmp_color = array_Shields[i].array_Impacts[j].color;
with

Code: Select all

                tmp_radius = array_Shields[i].array_Impacts[j].radius*dif;
                tmp_color = array_Shields[i].array_Impacts[j].color;
                tmp_color.a = 1-dif;
and

Code: Select all

               material.MaterialTypeParam = pack_texureBlendFunc(video::EBF_ONE,video::EBF_ONE_MINUS_SRC_COLOR); 
with

Code: Select all

					material.MaterialTypeParam = pack_texureBlendFunc(video::EBF_SRC_ALPHA,video::EBF_ONE);
(I will change the blend function anyway, it looks better this way)

edit: Ok I changed the blend function and added the effect (commented it out though) into the code of the first post.

greetings
Viz_Fuerte
Posts: 91
Joined: Sun Oct 19, 2008 5:29 pm
Location: Valencia (Spain)
Contact:

Post by Viz_Fuerte »

I have translated the code of GLSL to ARB, for not be getting compatibility issues or bugs.

PD: :D !! This effect I like !! Congratulations :D

------------

shield.vp

Code: Select all

!!ARBvp1.0

PARAM c[5] = { program.local[0],
	       state.matrix.mvp };

MOV result.texcoord[0], vertex.texcoord[0];
MOV result.texcoord[1].xyz, vertex.position;
DP4 result.position.w, vertex.position, c[4];
DP4 result.position.z, vertex.position, c[3];
DP4 result.position.y, vertex.position, c[2];
DP4 result.position.x, vertex.position, c[1];
END
shield.fp

Code: Select all

!!ARBfp1.0
OPTION ARB_precision_hint_nicest;

# texture  ColorMap -> index 0
# texture  GradientTexture -> index 1

# float    radius -> 0
# float[4] color -> 1
# float[3] current_position -> 2


PARAM c[4] = { program.local[0..2],
	     { 0.0099999998, 0.89999998, 0, 1 } };
TEMP R0;
TEMP R1;
TEMP R2;
ADD R0.xyz, fragment.texcoord[1], -c[2];
MUL R0.y, R0, R0;
MAD R0.x, R0, R0, R0.y;
MAD R0.x, R0.z, R0.z, R0;
RSQ R0.x, R0.x;
RCP R0.x, R0.x;
MUL R0.x, R0, R0;
RCP R0.x, R0.x;
MUL R0.x, R0, c[0];
MUL R0.x, R0, c[3];
ADD R0.y, R0.x, -c[3];
CMP R0.x, -R0.y, c[3].y, R0;
CMP R2.x, R0, c[3].z, R0;
MOV R2.y, c[3].w;
TEX R1, fragment.texcoord[0], texture[0], 2D;
TEX R0, R2, texture[1], 2D;
MUL R0, R0, R1;
MUL R0, R0, R2.x;
MUL result.color, R0, c[1];
END
Remember to use addShaderMaterialFromFile and use OnSetConstants correctly, sample:

Code: Select all

// Color
services->setPixelShaderConstant((float*)(&tmp_color),1, 4);

// Radius
services->setPixelShaderConstant((float*)(&tmp_radius),0, 1);

// Current position
services->setPixelShaderConstant((float*)(&tmp_position),2, 3);
I hope you find it useful :wink:
freetimecoder
Posts: 226
Joined: Fri Aug 22, 2008 8:50 pm
Contact:

Post by freetimecoder »

Have you tried it with the arb code?
I would be glad to implement it, but it does not show anything unless I set a non-transparent texture to the first texture (layer 0). But that does not look good.
I use texture layer 1 for the base color and layer 2 for the gradient texture.
I do not know how to fix this, since I do not know arb.

greetings
Post Reply