Jump to content

Is it possible to have multiple viewports?


Tomas
 Share

Recommended Posts

You will need to use multiple buffers and render the scene twice. You can use a pivot (I named it "map_viewport") to mark the position and rotation of the camera for the map. See the following C++-Example to see, how to do that.

If you're using LUA, it should be pretty straight-forward to translate this.

 

Buffer* map_buf;
Pivot* map_viewport;

bool App::Start()
{
   ...
   map_buf = Buffer::Create(100, 100, 1, 1, 0);
   map_viewport = Pivot::Create();
}

bool App::Loop()
{
   ...
   // Clear both buffers
   context->Clear();
   map_buf->Clear();
   // Save the current position and rotation
   Mat4 cur_mat = camera->GetMatrix(true);
   // Set the camera's position and rotation to the pivot's
   camera->SetMatrix(map_viewport->GetMatrix(true), true);

   // Render the world to the map-Buffer
   context->Disable();
   map_buf->Enable();
   world->Render();
   // Restore the position and rotation
   camera->SetMatrix(cur_mat, true);

   // Render the world to the context-Buffer
   context->Enable();
   map_buf->Disable();
   world->Render();

   // Draw the map over the context
   int blendMode = context->GetBlendMode();
   context->SetBlendMode(Blend::Solid);
   context->DrawImage(map_buf->GetColorTexture(), 0, 0, 100, 100);
   context->SetBlendMode(blendMode);

   context->Sync(false);
   return true;    
}

 

Edit: Changed the code to use the transformation-Matrices instead of setting position and rotation, as this should be more efficient

 

Edit2: Changed the blend-mode to Blend::Solid instead of Blend::Alpha

Edited by Ma-Shell
Link to comment
Share on other sites

Like Ma said you can think of it as moving the camera to a spot and taking a picture (this new buffer) from that location then moving the camera back to your player for the normal game to play. Now you have this image/buffer that you can draw anywhere on the screen or as a texture on a model. This moving the camera to a spot, taking a picture from that spot, and moving back to the player happens every frame for video or once for a static image.

Link to comment
Share on other sites

Even with two cameras you would need to go through all this buffer-swapping-stuff and render the scenery twice. The reason for this is that you can only render the world to the currently enabled buffers. Also I don't know, how/whether it is even possible to switch the currently rendered camera.

 

In order to decrease the costs of this you could do something like changing to a less costly render-mode for the map and decreasing the update-frequency, by only performing the rendering to the map-buffer, if at least X milliseconds have passed since the last rendering.

Edited by Ma-Shell
Link to comment
Share on other sites

Well, actually I just found, that you can call camera->Render() instead of world->Render() (though this isn't documented and thus probably not available in LUA) and you can set a Render-Target. This means, you can actually simplify that a bit:

 

Buffer* map_buf;
Camera* map_cam;
bool App::Start()
{
    ...
    map_buf = Buffer::Create(100, 100, 1, 1, 0);
    map_cam = Camera::Create();
    map_cam->SetRenderTarget(map_buf->GetColorTexture());
}
bool App::Loop()
{
    ...
    // Clear both buffers
    context->Clear();
    map_buf->Clear();

    // Render both cameras
    camera->Render();
    map_cam->Render();

    // Draw the map over the context
    int blendMode = context->GetBlendMode();
    context->SetBlendMode(Blend::Solid);
    context->DrawImage(map_buf->GetColorTexture(), 0, 0, 100, 100);
    context->SetBlendMode(blendMode);
    context->Sync(false);
    return true;   
}

 

This kind of cleans the rendering-function a bit.

  • Upvote 1
Link to comment
Share on other sites

Finally got it working. A bit laggy, but working. Theres my code:

 

Script.buffer=0
Script.mapcam=0
function Script:Start()
....
self.camera=Camera:Create()
self.camera:SetRotation(0,0,0)
self.camera:SetPosition(self.entity:GetPosition(true)+Vec3(0,1.8,0))
self.buffer = Buffer:Create(100, 100, 1, 1, 0)
self.mapcam = Camera:Create()
self.mapcam:SetRenderTarget(self.buffer:GetColorTexture())
end
function Script:UpdateWorld()
....
local buff=Buffer:GetCurrent()
Buffer:SetCurrent(self.buffer)
world:Render()
Buffer:SetCurrent(buff)
end
function Script:PostRender(context)
....
context:DrawImage(self.buffer:GetColorTexture(),0,0,100,100)
end

 

Didnt managed to get "camera:Render()" to work. Any ideas? The code actually renders same scene..

Link to comment
Share on other sites

Yeah, as I said, the function is not documented and thus probably not exported to LUA. This means, you actually have no way to choose the rendered camera and should therefore use a pivot to mark the position of the second camera instead, like I did in my first post.

In your UpdateWorld()-function, you then have to swap the position and the buffers and render. Try it like this:

Script.buffer=0
Script.mapcam=0
function Script:Start()
   ....
   self.camera=Camera:Create()
   self.camera:SetRotation(0,0,0)
   self.camera:SetPosition(self.entity:GetPosition(true)+Vec3(0,1.8,0))
   self.buffer = Buffer:Create(100, 100, 1, 1, 0)
   self.mapcam = Pivot:Create()
end
function Script:UpdateWorld()
   ....
   local buff=Buffer:GetCurrent()
   local mat = self.camera:GetMatrix()
   self.camera:SetRenderTarget(self.buffer:GetColorTexture())
   self.camera:SetMatrix(self.mapcam:GetMatrix())
   world:Render()
   self.camera:SetRenderTarget(buf:GetColorTexture())
   self.camera:SetMatrix(mat)
end
function Script:PostRender(context)
   ....
   context:DrawImage(self.buffer:GetColorTexture(),0,0,100,100)
end

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...