Change request: render state changes to public

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
tonic
Posts: 69
Joined: Mon Dec 10, 2007 6:18 pm
Contact:

Change request: render state changes to public

Post by tonic »

Could you move the "setRenderStates2DMode" method in video drivers to be public?

I'm asking this so that the 2D setup can be used for custom 2D drawing.


It's of course easy to modify this in the engine, but it's not nice if one has to track a bunch of custom changes and re-apply them each time when updating the engine.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

How do you proceed after setting the render state? All 2d methods will do that for you. In case you need some other draw methods it might be the better thing to add.
tonic
Posts: 69
Joined: Mon Dec 10, 2007 6:18 pm
Contact:

Post by tonic »

I was planning to draw some 2D elements using drawVertexPrimitiveList after calling setRenderStates2DMode. Now that I gave a second look at implementation(s) of drawVertexPrimitiveList, I see it always calls setRenderStates3DMode before drawing anything... so clearly my plan was erroneous. :)

The existing 2D drawing methods aren't enough for the 2D drawing API I was going to port over. I thought it'd be easy enough to just use the common vertex primitive list drawing before realizing it forces the 3D render states.

Correct if I'm not wrong, but shouldn't the drawVertexPrimitiveList work just fine also for 2D drawing if it wouldn't just force the 3d render states and projection?

Could it take a parameter which states if it is going to be used for 2D or 3D drawing? So it would then call either setRenderStates2DMode or setRenderStates3DMode.

Or could there be alternative call, e.g. drawVertexPrimitiveList2D?

I'll probably hack this in anyway somehow. But if you're going to solve this problem (allowing custom 2d drawing through the API) - it'd be nice if you tell what will the change be so that I can do it in similar way for now.


PS. You're right that it could be better to just add new draw methods. However, I think there is probably always some custom project-specific cases which would benefit from this feature.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Well, once you use the drawVertexPrimitiveList or similar methods you are doing 3d rendering. Whether the z coord is fixed or not doesn't matter. You just have to adjust your projection matrix to fit your needs, and continue to use the 3d methods. If there are still things lacking you should give a code example for better understanding.
tonic
Posts: 69
Joined: Mon Dec 10, 2007 6:18 pm
Contact:

Post by tonic »

After looking more at the 2D/3D setup code, I guess your suggestion is the way to go.
tonic
Posts: 69
Joined: Mon Dec 10, 2007 6:18 pm
Contact:

Post by tonic »

I think I found a bug when setting up custom transform for the video driver.

I set up 2D projection as follows:

Code: Select all

        video::IVideoDriver *driver = smgr->getVideoDriver();
        core::matrix4 identity;
        driver->setTransform(video::ETS_WORLD, identity);
        driver->setTransform(video::ETS_VIEW, identity);
        core::matrix4 projection;
        const core::dimension2d<s32> &screenSize = driver->getCurrentRenderTargetSize();
        projection.buildProjectionMatrixOrthoLH(screenSize.Width, -screenSize.Height, 0, 1);
        projection.setTranslation(core::vector3df(-1, 1, 0));
        driver->setTransform(video::ETS_PROJECTION, projection);
After that I can draw 2D stuff using drawVertexPrimitiveList.

However, that works only with Direct3D. When using OpenGL driver, I need to swithch the setTranslation call to this: (note flipped sign)

Code: Select all

        projection.setTranslation(core::vector3df(1, 1, 0));
If I leave out the translation, then the results are identical but the 2D coordinates (0,0) are at center of screen instead of top-left corner of screen which is what I'd like.

I believe setting of custom projection matrix should have identical result no matter which driver is in use. :)

----

Some side-notes, which may be related or helpful:

1. OpenGL FAQ 9.150 says that if one wants to to use left-handed coordinate system, then Z-coordinates in modelview matrix should be flipped. http://www.opengl.org/resources/faq/tec ... ations.htm

I looked at Irrlicht's OpenGLDriver implementation of setTransform, and noticed that it does have a flip for the Z, but it is done for projection matrix rather than modelview matrix.

I tried to move the z-flip to modelview matrix and this indeed fixed the translation issue. However, this breaks other things when using OpenGL driver, e.g. some code which spawns objects where I click on screen gets X-coordinate reversed.

2. OpenGL and Direct3D drivers use different approach for 2D drawing which is why this problem probably hasn't surfaced when writing that code. The OpenGL driver's 2d drawing creates a similar projection matrix what I'm making, but D3D driver uses just identity matrices and scales & flips 2D coordinates on the fly for each draw operation.

---

Edit: Tried also with the software renderer(s). The default software renderer works similarly with D3D. Surprisingly the Burning's software renderer doesn't work at all when other 3D stuff is drawn as well. It seems to ignore re-setting the world/view/projection matrices after drawing all stuff. Instead the drawn triangles just become part of the 3D scene instead of making a 2D layer on top of everything.
Post Reply