Render a Quad help?

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
rrg
Posts: 41
Joined: Sun Nov 04, 2007 6:22 pm

Render a Quad help?

Post by rrg »

Hi I was trying to learn how to add a bloom shader to my game. I was going to render to texture to a quad that is next to the camera and apply a bloom shader. I already wrote the bloom.hlsl shader and successfully render to texture a cube the scene. I tested out the shader on the texture cubed and it blooms the texture. I am stuck though on how to build a quad and texture the quad with the render to texture image and position over the camera. This is all new to me and would be very appreciated if anyone could show/tell me exactly what a quad is and how it applied/used to achieve the bloom and other effect that people have created with irrlicht.

Thanks in advance for the help
--------------------------------------------------

For free games visit my website at
FunBox Games

---------------------------------------------------
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

At first You have to create plane mesh (-1,1) and attach it to scene node or You can prepare special scene node eg:

Code: Select all

class CScreenAlignedQuadEntity: public ISceneNode
{
public:
    CScreenAlignedQuadEntity(ISceneNode* parent, ISceneManager* smgr, s32 id) : ISceneNode(parent, smgr, id)
    {
        m_Material.Lighting = false;
        m_Material.ZWriteEnable = false;

        SColor vertexColor(255, 0, 0, 255);
        vector3df nullNormalVector(0.0f, 0.0f, 0.0f);
        
        m_Vertices[0] = S3DVertex(vector3df(-1.0f, 1.0f, 0.0f), nullNormalVector, vertexColor, vector2df(0.0f, 0.0f));
        m_Vertices[1] = S3DVertex(vector3df(1.0f, 1.0f, 0.0f), nullNormalVector, vertexColor, vector2df(1.0f, 0.0f));
        m_Vertices[2] = S3DVertex(vector3df(1.0f, -1.0f, 0.0f), nullNormalVector, vertexColor, vector2df(1.0f, 1.0f));
        m_Vertices[3] = S3DVertex(vector3df(-1.0f, -1.0f, 0.0f), nullNormalVector, vertexColor, vector2df(0.0f, 1.0f));

        m_BBox.reset(m_Vertices[0].Pos);
        
        for(irr::s32 i = 0; i < 4; i++)
        m_BBox.addInternalPoint(m_Vertices[i].Pos);
    }

    void OnRegisterSceneNode()
    {
        if(IsVisible)
        SceneManager->registerNodeForRendering(this);

        irr::scene::ISceneNode::OnRegisterSceneNode();
    }

    void render()
    {
        u16 indices[6] = {0, 2, 3,   0, 1, 2};
        IVideoDriver* driver = SceneManager->getVideoDriver();
        driver->setMaterial(m_Material);
        driver->setTransform(ETS_WORLD, AbsoluteTransformation);
        driver->drawIndexedTriangleList(&m_Vertices[0], 4, &indices[0], 2);
    }

    const aabbox3d<f32>& getBoundingBox() const
    {
        return m_BBox;
    }

    video::SMaterial& getMaterial(u32 num)
    {
        return m_Material;
    }

private:
    aabbox3d<irr::f32> m_BBox;
    S3DVertex m_Vertices[4];
    SMaterial m_Material;
};
Now You have to prepare vertex shader for Your quad similar for this:

Code: Select all

// HLSL / Cg - code support D3D9 and OGL.
void main_v(float4      Position    : POSITION,

        out float4      oPosition   : POSITION,
        out float2      oUV         : TEXCOORD0,

    uniform float2      TexelOffset,
    uniform int2        YUV )
{
    Position = sign(Position);

    oPosition = float4(Position.xy, 0, 1);
    oPosition.xy += TexelOffset;

    oUV.x = 0.5 * (1 + Position.x);
    oUV.y = (YUV.x * 0.5) * (1 - Position.y) + YUV.y;
}
Where:
TexelOffset is:

Code: Select all

float TexelOffsetX = -1.0f / (float)driver->getCurrentRenderTargetSize().Width;
float TexelOffsetY = 1.0f / (float)driver->getCurrentRenderTargetSize().Height;
Instead of current render target size sometimes, You can use viewport size. TexelOffset is important only in Direct3D_Ver < 10, for D3D10 and OpenGL You shouldn't use any offsets.

YUV is:

Code: Select all

// for DirectX
int YUVX = 1;
int YUVY = 0;
// for OpenGL
int YUVX = -1;
int YUVY = 1;
You have to use it if You need one shader for both D3D9 and OGL, eg when You use Cg.

Hope this helps,
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
rrg
Posts: 41
Joined: Sun Nov 04, 2007 6:22 pm

Post by rrg »

Thanks for the help. So let me get this straight, you create a plane and the render function actually renders the quad. After render you apply the shader with the offsets and then if everything is coded correctly it should bloom.

Just a quick question in the render function driver->setTransform(ETS_WORLD, AbsoluteTransformation);

does this position the quad where the camera is?
Also what is the AbsoluteTransformation i know that its suppose to be a c4matrix, is that the camera position matrix?
--------------------------------------------------

For free games visit my website at
FunBox Games

---------------------------------------------------
DavidJE13
Posts: 165
Joined: Tue Jan 09, 2007 7:17 pm

Post by DavidJE13 »

that line actually isn't needed at all. the key line is in the vertex shader;

Code: Select all

    oPosition = float4(Position.xy, 0, 1);
    oPosition.xy += TexelOffset;
this positions the corners of the triangle based on their position *without* using the projection matrix, so the current view makes no difference. (-1,-1,z) will be at the top left corner no matter what z is, etc.

AbsoluteTransformation is a per-node value, which stores the absolute position, rotation, scale of the node relative to the root node. This is usually combined with the camera's absolute transformation and the projection matrix when rendering.
Post Reply