For example, I have an one mesh (steel ingot) with the original view port (highlighted by red color):
![Image](https://i.imgur.com/LSmQvw6.png)
How it looks like after moving its view port rect taking into consideration that "clipping" effect (shift position vector: -1.0, 0.0):
![Image](https://i.imgur.com/Hzx8Xvf.png)
I did to update the aspect ratio every time when it was necessary to move the view port rect. Although the proportions stayed the same, but it caused changing the mesh scale (it became either smaller or bigger than the original one). It doesn't solve the problem which I described above. Also, if I moved it by (-1, 0) on the screen, it didn't appear on the screen border, but near of it.CuteAlien wrote: ↑Sun May 19, 2024 10:41 am Maybe you are missing some aspect ratio changes? Your first image has 15/8 your second has something like 2 times 7.5/8 (with the images you posted here, I guess real ones are likely not exactly the same).
The camera always renders the full height of your given field of view (ICameraSceneNode::setFOV). The width the camera renders is then calculated from the aspect ratio (ICameraSceneNode::setAspectRatio). So as you noticed - whatever your viewport is, the parts you see in it are the same as long as you don't change those 2 values in the camera. Just scaled to your viewport. If you don't want that scaling you usually set your aspect ratio to the real aspect ratio of your viewport. Which then means some parts of the image width will be clipped.
No, the camera position (it's always to 0, 0, 0) doesn't change. The camera itself is added to the separate scene manager of each mesh object. What I am doing here is moving the view port rect through the screen depending on the mesh location whose size is always equal to the screen one. Why I do it at all: I could contain all meshes in the one manager, however I want to save the perspective constant because the meshes renders are actually just images (they are located on the screen, not in the view or world space).CuteAlien wrote: ↑Sun May 19, 2024 10:41 am edit: That's if I understand what you are doing here... not quite sure I did on reading this second time. Now I get the feeling that maybe you talk about camera shifting instead. Rendering an off-center part (like taking a larger render and then using one of it's corners. If that's the case - check ICameraSceneNode::setLensShift (maybe not yet in Minecraft, but easy to port).
Code: Select all
class HUDScene : virtual public IReferenceCounted
{
public:
HUDScene(scene::ISceneManager *mgr, Client *client,
const HudElement *elem=nullptr, const v3f &mesh_pos=v3f(),
const v3f &mesh_rot=v3f(), bool lighting=false, bool is_hand=false);
~HUDScene();
----------------------------
void step(f32 dtime);
private:
Client *m_client;
scene::ISceneManager *m_smgr;
scene::ICameraSceneNode *m_cam;
MeshHUDSceneNode *m_hud_node;
// Constant rectangle. Actually is (1920, 1008)
core::recti m_original_rect;
// The rect which is continuously updated
core::recti m_rect;
// Position on the screen in the range: [-1.0..1.0]
v2f m_scene_pos{0.0f, 0.0f};
const HudElement *m_hud_elem;
// Last set 'scale.X' hud def field
v3f m_last_relative_scale{1.0f};
// Mainly WIELD_SCALE_FACTOR/WIELD_SCALE_FACTOR_EXTRUDED
// calculated by getOrCreateMesh()
v3f m_last_constant_scale{1.0f};
};
Code: Select all
void HUDScene::step(f32 dtime)
{
-------------------------
// Updates both end points of the rect depending on new m_screen_pos
updateRect();
// Updates the rotation of the mesh object
m_hud_node->setRotation(m_hud_elem->rotation);
// Updates the scale
updateScale();
-------------------------
}
Code: Select all
void HUDScene::updateRect()
{
// Translates m_scene_pos to [0..1] range
v2f uv_pos = m_scene_pos / 2.0f + 0.5f;
// Compares it with the external one which gets from Lua side.
// If they are equal, it is unnecessary to update it
if (uv_pos == m_hud_elem->pos)
return;
// Translates the new position to [-1..-1] and saves it
m_scene_pos = (m_hud_elem->pos - 0.5f) * 2.0f;
// Calculates the shift vector in the pixel coords starting from the screen center
v2s32 new_pos(s32(m_scene_pos.X*m_original_rect.getWidth()/2.0f),
s32(m_scene_pos.Y*m_original_rect.getHeight()/2.0f));
// And adds it with the constant screen rectangle. Thus we gets the shifted rectangle relatively the screen center.
m_rect = m_original_rect + new_pos;
}
Code: Select all
void Hud::drawMeshes()
{
driver->clearBuffers(video::ECBF_DEPTH);
core::recti oldViewPort = driver->getViewPort();
// Loop through all mesh objects
for (const auto &p : m_hud_scenes) {
// Gets a current view port rectangle and set it
driver->setViewPort(p.second->getRect());
// Note: "new_rect" != p.second->getRect() !!! That actually gets clipped if
core::recti new_rect = driver->getViewPort();
// Draws the mesh object and its camera for the given mesh
p.second->getSceneManager()->drawAll();
}
driver->setViewPort(oldViewPort);
}
Thanks for the help! I removed the clipping to the screen rect in COpenGLDriver::setViewPort() and that worked as I wanted:CuteAlien wrote: ↑Fri May 24, 2024 8:53 pm Isn't that what I wrote after the "Ow... or maybe I do get it ..."?
I'm not quite sure what would happen. I searched a bit around the web and found answers from "gpu will just clip it, no problem" to "this is badly defined in OpenGL" to "might depend on the graphic card what happens". If you want to try disabling the clipping in Irrlicht try the following:
In COpenGLDriver::setViewPort remove the 2 lines with rendert (aka the clipping to rendertarget borders).
But I have no idea if this will work in general. Maybe it does, maybe only for rendering to screen but not render-targets (or vice versa), or maybe it just works and that clipping there is useless. It was in there since first svn version, so I have no commit message or any further info about those lines and also could only write my own experiments and then get a ton of people to try the results. Or maybe you can find more info on the web? To me it sounds a bit risky as you basically tell the driver to render outside of the screen-memory and then hope it clips correct, but without changing aspect ratio. (edit: I checked glViewport documentation and it mentions no restrictions ... so maybe it's indeed fine and Irrlicht should get rid of those lines).
The other 2 solutions are:
a) Use render target textures and draw them (they get clipped correct).
b) Use the mixture of changing aspect ratio (to the clipped area) and then use lens-shifting in the camera to get an off-center rendering (you have to port the lens-shifting code first to Minetest as this was added after you split, but it's pretty trivial).