[GLSL] Per Fragment Point Lighting

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

[GLSL] Per Fragment Point Lighting

Post by randomMesh »

Hi,

i want to have per fragment lighting for a point light. Problem is that it seems lighting is applied per object and not for the whole scene.
This is what i have:

http://imgur.com/a/ylTcc

This is what i want:

https://i.stack.imgur.com/zcCFD.png

Is it even possible to apply per-fragment-lighting for the whole scene globally with this setup? Or do i need a post processing shader?

main.cpp

Code: Select all

 
#include <irrlicht.h>
 
class MyShaderCallBack: public irr::video::IShaderConstantSetCallBack
{
 
public:
 
    MyShaderCallBack() :
            TextureID(-1), FirstUpdate(true)
    {
    }
 
    virtual void OnSetConstants(irr::video::IMaterialRendererServices* services,
            irr::s32 userData)
    {
        //get shader constant id.
        if (this->FirstUpdate)
        {
            this->TextureID = services->getPixelShaderConstantID("Texture");
            this->FirstUpdate = false;
        }
 
        //set texture
        const irr::s32 TextureLayerID = 0;
        services->setPixelShaderConstant(this->TextureID, &TextureLayerID, 1);
    }
 
private:
 
    irr::s32 TextureID; //sampler2D
 
    bool FirstUpdate;
};
 
int main()
{
    irr::IrrlichtDevice* const device = irr::createDevice(
            irr::video::EDT_OPENGL, irr::core::dimension2du(800, 600));
    if (!device)
        return 1;
    irr::video::IVideoDriver* const driver = device->getVideoDriver();
    irr::scene::ISceneManager* const smgr = device->getSceneManager();
 
    //a camera
    irr::scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
            irr::core::vector3df(1.0f, 5.0, -5.0f));
    camera->setTarget(irr::core::vector3df(1.0f, 0.0f, 0.0f));
 
    //moving light
    {
        irr::scene::ILightSceneNode* light = smgr->addLightSceneNode(0,
                irr::core::vector3df(), irr::video::SColorf(1, 1, 1, 1), 6);
        irr::scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(
                irr::core::vector3df(1.0f, 3.0f, 1.0f), 3.0f, 0.001f);
        light->addAnimator(anim);
        anim->drop();
 
        // attach billboard to light
        irr::scene::IBillboardSceneNode* node = smgr->addBillboardSceneNode(
                light, irr::core::dimension2d<irr::f32>(0.5f, 0.5f));
        node->setMaterialFlag(irr::video::EMF_LIGHTING, false);
        node->setMaterialType(irr::video::EMT_TRANSPARENT_ADD_COLOR);
        node->setMaterialTexture(0,
                driver->getTexture(
                        "./media/particlewhite.bmp"));
    }
 
    //shader
    irr::video::IGPUProgrammingServices* gpu =
            driver->getGPUProgrammingServices();
 
    MyShaderCallBack* mc = new MyShaderCallBack;
 
    irr::s32 shaderMaterialType = gpu->addHighLevelShaderMaterialFromFiles(
            "./shader/ppl.vert", "main", irr::video::EVST_VS_1_1,
            "./shader/ppl.frag", "main", irr::video::EPST_PS_1_1, mc);
 
    if (shaderMaterialType == -1)
    {
        device->getLogger()->log("Shader error");
    }
 
    mc->drop();
 
    //test cube
    irr::scene::IMeshSceneNode* cube = 0;
    for (unsigned int y = 0; y < 3; ++y)
    {
        for (unsigned int x = 0; x < 3; ++x)
        {
            cube = smgr->addCubeSceneNode(1.0f, 0, -1,
                    irr::core::vector3df(x, 0, y));
            cube->setMaterialType(
                    (irr::video::E_MATERIAL_TYPE) shaderMaterialType);
            cube->setMaterialFlag(irr::video::EMF_LIGHTING, false);
            cube->setMaterialTexture(0,
                    driver->getTexture(
                            "./media/wall.bmp"));
        }
    }
 
    while (device->run())
    {
        driver->beginScene();
        smgr->drawAll();
        driver->endScene();
    }
 
    device->drop();
 
    return 0;
}
 
 
Vertex Shader:

Code: Select all

 
varying vec4 eposition;
varying vec3 normal;
varying vec3 diffuseColor;
varying vec3 specularColor;
varying vec3 emissiveColor;
varying vec3 ambientColor;
varying float shininess;
 
varying vec2 Tex2DCoord;
 
void main()
{
    // Position in clip space
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
 
    // Position in eye space
    eposition = gl_ModelViewMatrix * gl_Vertex;
 
    // Normal in eye space
    normal = mat3(gl_ModelViewMatrix) * gl_Normal;
 
    // Retrieves diffuse, specular emissive, and ambient color from the OpenGL state.
    diffuseColor = vec3(gl_FrontMaterial.diffuse);
    specularColor = vec3(gl_FrontMaterial.specular);
    emissiveColor = vec3(gl_FrontMaterial.emission);
    ambientColor = vec3(gl_FrontMaterial.ambient);
    shininess = gl_FrontMaterial.shininess;
 
    Tex2DCoord = vec2(gl_MultiTexCoord0);
}
 
Fragment Shader:

Code: Select all

 
varying vec4 eposition;
varying vec3 normal;
varying vec3 diffuseColor;
varying vec3 specularColor;
varying vec3 emissiveColor;
varying vec3 ambientColor;
varying float shininess;
 
uniform sampler2D Texture;
varying vec2 Tex2DCoord;
 
void main()
{
    const vec3 lightColor = vec3(1, 1, 1);
    const vec3 globalAmbient = vec3(0.2, 0.2, 0.2);
 
    // Position in eye space
    vec3 P = vec3(eposition);
 
    // Normalize normal in eye space
    vec3 N = normalize(normal);
 
    // Compute the emissive term
    vec3 emissive = emissiveColor;
 
    // Compute the ambient term
    vec3 ambient = ambientColor * globalAmbient;
 
    // Compute the diffuse term
    // Normalized vector toward the light source
    vec3 L = normalize(vec3(gl_LightSource[0].position) - P);
    float diffuseLight = max(dot(N, L), 0);
    vec3 diffuse = diffuseColor * lightColor * diffuseLight;
 
    // Compute the specular term
    vec3 V = normalize(-P);      // Normalized vector toward the viewpoint
    vec3 H = normalize(L + V); // Normalized vector that is halfway between V and L
    float specularLight = pow(max(dot(N, H), 0), shininess);
    if (diffuseLight <= 0)
        specularLight = 0;
    vec3 specular = specularColor * lightColor * specularLight;
 
    // Define the final vertex color
    gl_FragColor.xyz = emissive + ambient + diffuse + specular;
    gl_FragColor.w = 1.0;
 
    gl_FragColor *= texture2D(Texture, Tex2DCoord);
}
 
 
"Whoops..."
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: [GLSL] Per Fragment Point Lighting

Post by CuteAlien »

Did you check your cube-normals? For this to work I think each side should have their own 4 vertices (none shared) and vertex normals going along the plane-normal for each side.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: [GLSL] Per Fragment Point Lighting

Post by randomMesh »

I am using the standard Irrlicht cube mesh with 12 vertices and 36 indices. I guess this is not sufficient, then.
"Whoops..."
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: [GLSL] Per Fragment Point Lighting

Post by CuteAlien »

No, I don't think that works well for this case. You will need 24 vertices for this one.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: [GLSL] Per Fragment Point Lighting

Post by randomMesh »

Using a mesh with 24 vertices fixed it. You guys really should change the geometry creator to produce proper cube meshes. :p
"Whoops..."
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: [GLSL] Per Fragment Point Lighting

Post by CuteAlien »

Well... proper depends on the use-case. Having this optional would be nice I guess.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: [GLSL] Per Fragment Point Lighting

Post by randomMesh »

CuteAlien wrote:proper depends on the use-case.
8 or 24. 12 ist nichts Halbes und nichts Ganzes.
CuteAlien wrote:Having this optional would be nice I guess.
Yes, i agree. Maybe an enum like this:

Code: Select all

 
enum E_CUBE_QUALITY
{
    ECQ_8 = 0,
    ECQ_12,
    ECQ_24
};
 
Default should be 24 vertices though.
Last edited by randomMesh on Thu May 25, 2017 4:42 pm, edited 1 time in total.
"Whoops..."
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: [GLSL] Per Fragment Point Lighting

Post by CuteAlien »

I suppose the idea behind 12 is that it's probably the minimum needed for texturing.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply