Short question regarding RTT textures and shaders...

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
LovehinaX
Posts: 7
Joined: Wed Nov 08, 2006 12:38 pm

Short question regarding RTT textures and shaders...

Post by LovehinaX »

Hi!

Im rendering my scene into a RTT and then displaying that texture on the screen using the draw2dImage() function. My question is: How can I send this texture to a shader?
An even better question would be: How would I go about sending to a shader, an individual texture that isn't attached or contained within a scene node?

Thanks in advance!
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

In irrlicht you can only apply shaders to nodes, the draw 2d function draws some predefined polygons which can a have shader applied to them like the polygons of a node, however i dont think irlicht has the option to apply shaders to anything but materialable nodes (not the 2d function polygons). You can use a normal mesh node with a quad/ two trianglualr polygons and use the vertex shader to transform these polygons into 2d space like what the 2d function is doing. Sending the texture would just be applying a texture to the node.
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
TheGameMaker
Posts: 275
Joined: Fri May 12, 2006 6:37 pm
Location: Germany

Post by TheGameMaker »

I have what you need^^
Its a Class which give you the power to create a mesh, which is used as onscreen-quad. All you have to do is to set the pixelshader& its constants.
pretty simple isn´t it??
(i gonna releas the code in a few hours but here i´ll post some pre version..)

Code: Select all

#ifndef __POST_PROCESS_EFFECT_BLUR__
#define __POST_PROCESS_EFFECT_BLUR__
#include "irrlicht.h"

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

// the shader callback.. you have to set your shader constants here(just like sampleDist)
class PPE_Blur_callback: public video::IShaderConstantSetCallBack 
{
public:
    float sampleDist;
  virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
  {
    video::IVideoDriver* driver = services->getVideoDriver();
    services->setVertexShaderConstant("sampleDist", reinterpret_cast<f32*>(&sampleDist),1);
	}
};



// and this is the real class.. just replace the pixel shader code in the initiate function whit your one()
//if you use hlsl istead of GLSL, you even hav to replace the Vertexshader code 
class IPostProcessBlur : public scene::ISceneNode 
{
    public:
   core::aabbox3d<f32> Box;
   video::S3DVertex Vertices[6];//the vertices for the onscreenquad
   video::SMaterial Material;
   PPE_Blur_callback* shaderCallback; //the used shadercallback for PPE shader
   video::ITexture* rt0; //the rendertarget
   int mat;
   PPE_Blur_callback* callback;
    
      IPostProcessBlur(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id): scene::ISceneNode(parent, mgr, id)
        {
      Vertices[0] = video::S3DVertex(-1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 0.0f, 1.0f);
      Vertices[1] = video::S3DVertex(-1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 0.0f, 0.0f);
      Vertices[2] = video::S3DVertex( 1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 1.0f, 0.0f);
      Vertices[3] = video::S3DVertex( 1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 1.0f, 1.0f);
      Vertices[4] = video::S3DVertex(-1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 0.0f, 1.0f);
      Vertices[5] = video::S3DVertex( 1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 1.0f, 0.0f);
        }
    

    void initiate(unsigned int size,float sampleDist,scene::ISceneManager* smgr)
   {
static stringc vertShader =
"varying vec2 vTexCoord;"
"void main(void)"
"{"

  " vec2 Position;"
  " Position.xy = sign(gl_Vertex.xy);"
  " gl_Position = vec4(Position.xy, 0.0, 1.0);"
   "vTexCoord =Position.xy *.5 + .5;"
"}";
static stringc fragShader =
"uniform sampler2D texture[2];"
"varying vec2 vTexCoord;"
"uniform float sampleDist;"
"uniform float sampleStrength;"
"uniform float saturation;"
"uniform float coloringStrength;"
"uniform vec4  coloring;"

"void main()"
"{"
"   vec2 samples[12]; "
"   samples[0]  = vTexCoord + sampleDist * vec2(-0.326212, -0.405805);"
"   samples[1]  = vTexCoord + sampleDist * vec2(-0.840144, -0.073580);"
"   samples[2]  = vTexCoord + sampleDist * vec2(-0.695914,  0.457137);"
"   samples[3]  = vTexCoord + sampleDist * vec2(-0.203345,  0.620716);"
"   samples[4]  = vTexCoord + sampleDist * vec2(0.962340, -0.194983);"
"   samples[5]  = vTexCoord + sampleDist * vec2(0.473434, -0.480026);"
"   samples[6]  = vTexCoord + sampleDist * vec2(0.519456,  0.767022);"
"   samples[7]  = vTexCoord + sampleDist * vec2(0.185461, -0.893124);"
"   samples[8]  = vTexCoord + sampleDist * vec2(0.507431,  0.064425);"
"   samples[9]  = vTexCoord + sampleDist * vec2(0.896420,  0.412458);"
"   samples[10]  = vTexCoord + sampleDist * vec2(-0.321940, -0.932615);"
"   samples[11]  = vTexCoord + sampleDist * vec2(-0.791559, -0.597705);"
"   vec4 sample = texture2D(texture[0], vTexCoord);"
"   vec4 avg = sample;"
"   vec4 col;"
"   for (int i = 0; i < 12; i++)"
"   {"
"      col=texture2D(texture[0],samples[i]);"
"      float intensity=col.r+col.g+col.b;"
"      avg += col;  "
"   }"
"   avg /= 13.0;"
"   gl_FragColor = avg;"
"}";
video::IVideoDriver* driver = smgr->getVideoDriver();
video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();

      callback= new PPE_Blur_callback;
      callback->sampleDist=sampleDist;
      Material.MaterialType=(E_MATERIAL_TYPE)gpu->addHighLevelShaderMaterial
        (
               vertShader.c_str(), "main", video::EVST_VS_1_1,
               fragShader.c_str(), "main", video::EPST_PS_1_1,
               callback, (video::EMT_SOLID)
        );
        
      
      rt0 = driver->createRenderTargetTexture(core::dimension2d<s32>(size,size));
      Material.Wireframe = false;
      Material.Lighting = false;
      Material.Textures[0]=rt0;
    }
    
    
    
    
   virtual void OnPreRender(){}
   
   virtual void render()
   {
      u16 indices[] = {0,1,2,3,4,5};
      video::IVideoDriver* driver = SceneManager->getVideoDriver();

      driver->setMaterial(Material);
      driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
      driver->drawIndexedTriangleList(&Vertices[0], 6, &indices[0], 2);
   }
   //Renders the Post-Process Effect

  virtual u32 getMaterialCount(){return 1;} 
  virtual video::SMaterial& getMaterial(s32 i){return (Material);}
  virtual const core::aabbox3d<f32>& getBoundingBox() const{return Box;}
};


#endif
the render code is based on an other node i found here in the forum, but this code was old, and doesn´t work for some (unknow) reasons, so i modefied it heavily...

All you have to do, for to use it, is

Code: Select all

    IPostProcessBlur *BlurFilter = new IPostProcessBlur(smgr->getRootSceneNode(), smgr, 666);
    BlurFilter->initiate(512,0.0005,smgr);
and in your main loop:

Code: Select all

	driver->beginScene(true, true, 0);
			driver->setRenderTarget(BlurFilter->rt0, true, true, video::SColor(0,0,0,0));
			smgr->drawAll();
                        driver->setRenderTarget(0);
			BlurFilter->render();
		}
	driver->endScene();
hope this helps...
tgm[/code]
LovehinaX
Posts: 7
Joined: Wed Nov 08, 2006 12:38 pm

Post by LovehinaX »

Thanks for replaying!

It seams like one cant send individual textures to shaders in IRRLicht, but thats fine... I solved my problem by using my own "quad", which I exported from Blender...

BTW: Thanks TheGameMaker for taking the time to write some code for me, but I think that thats a bit to advanced for me... :(
Post Reply