Shaders and material properties!

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Shaders and material properties!

Post by Luben »

Hi, i'm making a per-pixel blinn-phong lighting shader.
One thing that i require for my shader is the current material properties. The diffuse, specular, ambient and emmisive colors, and the shininess-properties. I thought at first that they should probably be accessible from within my shader, turned out it wasn't, then i turned my train of thought towards setting them in OnSetConstants

Code: Select all

	virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
	{
		...
		services->setVertexShaderConstant("c_AmbientColor", reinterpret_cast<f32*>(&Material.Ambient), 3);
		...
	}
Didn't seem hard, until i realized that the current material isn't accessible from within OnSetConstants.

I knew the parallax material passes SMaterial::MaterialTypeParam to it's shader, so i dug for a while and found out how.
The parallax renderer is a driver dependant class, which is a child of IMaterialRenderer. Hence it can overload OnSetMaterial

Code: Select all

	virtual void OnSetMaterial(SMaterial& material, const SMaterial& lastMaterial,
		bool resetAllRenderstates, IMaterialRendererServices* services) {};
to get it's param.

But the parallax renderer compiles it's shader itself, in a driver dependant way. If i where to do the same thing, i would have to abandond the nice driver independant interfaces made avialable trough IGPUProgrammingServices and IMaterialRendererServices.

Therefore, i suggest a change.
Let us, in the driver dependant shader class(Which is created trough a 'rerouting' call trough IGPUProgrammingServices->addHighlevelshader), which calls the callback OnSetConstants, and which's OnSetMaterial is called when setting the material, store the material properties until OnSetConstants is called. Then we should pass it by reference, like this:

Code: Select all

	virtual void OnSetConstants(video::IMaterialRendererServices* services, const SMaterial &CurrentMaterial, s32 userData);

Then the OnSetConstants can actually use the active material's properties, which is great!

I would reall like to see this in the next release of irrlicht, since it really is an easy thing to implement/change.
It would be really bad if it'd have to wait until the second next release of irrlicht =)


Luben
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

No changes needed. I explain what you have to do in my reply to your PM.
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

reread, i'm looking for materials and not lights =)
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

OK. Still no change needed, though.

It's possible to get at the material properties because I had this problem months ago. There should be a thread of mine somewhere - you'll have to search the forums.
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

Cant find it.

Is the sourceforge server instable as of late, or is it a problem at my end?

I'd really appreciate if you'd post a link to that thread

Thanks
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

sio2, if this is the thread you mentioned ( http://irrlicht.sourceforge.net/phpBB2/ ... r+material ), i'll have to ask you exactly how did you do it? When inheriting from IMaterialRenderer, you do open up for making a OnSetMaterial, but that function shouldn't be called by the 'host', right? so how do you do it? :?
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

*bumps*
Some have said that they found a way, but not actually told how... or maybe i'm stupid, if that's the case please tell me ^^
If you don't have anything nice to say, don't say anything at all.
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

i would have to abandond the nice driver independant interfaces made avialable trough IGPUProgrammingServices and IMaterialRendererServices.
Well keeping the driver independent options would be pointless because your shader would only run on one driver.

If you write two versions of the shader one for each driver, why not write the driver dpendent material classes as well like the irrlicht included shaders.

If i were you i would just make my own class (out side of the dll like the shader tutorial)that manges all the lights via sorting lists and just apply the shader via shadingclass->getMaterial().

Its easier to get data in and out of the shader through an easy class than material params.

You can even have one class for all drivers if you just load a diffrent shader string code.
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

omaremad wrote: Well keeping the driver independent options would be pointless because your shader would only run on one driver.

If you write two versions of the shader one for each driver, why not write the driver dpendent material classes as well like the irrlicht included shaders.
I don't understand why they made the internal renderers device dependant either. If the intention was for us to write our own device dependant renderers, why did they bother to make the device independand interfaces then?
If i were you i would just make my own class (out side of the dll like the shader tutorial)that manges all the lights via sorting lists and just apply the shader via shadingclass->getMaterial().

Its easier to get data in and out of the shader through an easy class than material params.

You can even have one class for all drivers if you just load a diffrent shader string code.
I could do that, but then i'd have to compile the shaders myself. I dont want to do that, and i believe that the original intent was to let irrlicht handle that part, and just provide us with an interface to do the important stuff, like settings shader variables in a callback.
The internal renderers are probably made while developing the shader support, as a "teach-it-yourself"-example.
Also, if i make my own class, then i have to set up a dx sdk etc, which i dont want to.

Besides the material, what else is there to send to the shader that i can not get elsewhere? You mention an easy class for shader-io. I already have one, and it's called IShaderConstantSetCallBack. Beside the current lack of material values, is there any problem for which i have to make a new class in order to solve?

Of course i have to make my own class, but instead of inheriting from IMaterialRenderer, i inherit from IShaderConstantSetCallBack. In the tutorial, we inherit from IShaderConstantSetCallBack, and do not compile the shaders ourself.
If you don't have anything nice to say, don't say anything at all.
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

What do you mean by compiling shaders? irrlicht doesnt compile shaders, it justs sends them to the driver which does it. Want asm code for shaders? just use cg.exe in the cg toolkit with is basically the same shader compiler in the nvidida drivers (with cg suppourt) and in .exe.

when i talk about a shader class i talk about using the shader functions within your own class and not like the ones built into irrlicht. Its allot easier that.

here is an example

Code: Select all

#include "CHdrModule.h"
class HDRShaderCallBack : public video::IShaderConstantSetCallBack
{
public:
    int type;
    CHdrModule*module;
    virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
    { // set light color
        //f32 col[4]={module->getblursize(),module->getexposure(),module->getfocalx(),module->getfocaly()};


        // services->setVertexShaderConstant("scope", reinterpret_cast<f32*>(&col), 4);

        if(type==1)
        {
            int c[] =
                {
                    0,1,2,3
                }
                ; // sampler2d IDs
            services->setPixelShaderConstant("baseMap", (float*)&c[0], 1);
            services->setPixelShaderConstant("Texture", (float*)&c[1], 1);
            /*services->setPixelShaderConstant("shrunk", (float*)&c[2], 1);
            services->setPixelShaderConstant("shrunkalpha", (float*)&c[3], 1);*/
        }

        else
        {
            int c[] =
                {
                    0,1,2,3
                };
            services->setPixelShaderConstant("waves", (float*)&c[0], 1);
            core::matrix4 worldViewProj;


            worldViewProj = module->driver->getTransform(video::ETS_VIEW);

            core::vector3df pos = module->device->getSceneManager()->
                                  getActiveCamera()->getAbsolutePosition();
            services->setVertexShaderConstant("vViewPosition", reinterpret_cast<f32*>(&pos), 3);
            services->setVertexShaderConstant("matView", &worldViewProj.M[0], 16);
        }


    }

    HDRShaderCallBack(CHdrModule*m_module,int shadertype)
    {
        module=m_module;
        type=shadertype;
    };
};
see the callback can easily pull data from my own shader class called chdr module, its allot easier than using the same inheritance style found in the built in irrlicht materials.
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

What do you mean by compiling shaders? irrlicht doesnt compile shaders
Irrlicht does compile the shaders for me, it handles all the booring device dependant code to do it. Sorry for that misunderstanding.

when i talk about a shader class i talk about using the shader functions within your own class and not like the ones built into irrlicht. Its allot easier that.
Seems like i misunderstood you. I though you where promoting the 'built in'-style.


When you set the type in the constructor, does that mean you are using the same class to implement two different shaders, one 100% vertex & one 100% pixel? And that you are using your module as a parameter storage?
What i need is a way to get access to the current material. It's as simple as that.

Code: Select all

    virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
    {
        //Get and pass SMaterial::Ambient
    };

So i still want the material to be passed as a parameter to OnSetConstants. Hope i didn't missunderstand again =)
If you don't have anything nice to say, don't say anything at all.
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

I guess your not the only one thats misunderstanding :wink:. I thought you wanted to make your shaders in the same style as the parallax ones.

For a driver independent solution you can use the hack we were disucussing here

http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=19889

Its through the scene manager, i think getting the current node being rendered should be a useful feautre for other stuff too.
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

I think so too, but i dont want to edit the source myself ;) Either i'll find another solution or i'll make sure some official irr-dev implements it.

Right now i'm trying a rerouting material, which takes a materialid as parameter on creation, gets the IMaterialRenderer trough the driver, takes over the name and renames the old material, and then reroutes the calls to the real material, stealing any parameter it might be interested in. It works, somewhat, at least on the built in materials, but when i reroute to my own shader it hangs whenever i do a services->set...ShaderConstant(...). Dunno why, trying to find out now =P
If you don't have anything nice to say, don't say anything at all.
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

I am going to annoy bitplane till he implements this. Ill got to IRC.
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

I've got the hijacking class to work now. My new material hijacks and reroutes the renderer to the old renderer, but steals the material in OnSetMaterial.
The problem i had with ->set...ShaderConstant was quite hard to track down, and it ended with me setting the material's materialtype to the 'host' in OnSetMaterial, so that the right IMaterialRenderer was passed etc... It works quite well, actually, if anyone is interested in knowing how it was done in detail just ask. Maybe i'll put this and my shader in the wiki...

Thanks for all the help, everyone =)
If you don't have anything nice to say, don't say anything at all.
Post Reply