Skip to content

Commit

Permalink
Refactor|Cleanup|Renderer: Less complicated view rendering
Browse files Browse the repository at this point in the history
This commit fixes issues when the game widget does not cover the
entire window.

To summarize, the viewport no longer needs modifying when a frame
is being drawn: it's either the player's game view texture (that
contains only a single full view), or ViewCompositor is drawing the
view layers within the appropriate rectangle in the window and
handles the viewport on its own.
  • Loading branch information
skyjake committed Oct 2, 2016
1 parent 0d9e839 commit 5bce3e7
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 261 deletions.
6 changes: 3 additions & 3 deletions doomsday/apps/client/include/gl/gl_main.h
Expand Up @@ -51,7 +51,7 @@ namespace world { class Material; }

DENG_EXTERN_C int numTexUnits;
DENG_EXTERN_C dd_bool envModAdd;
DENG_EXTERN_C int viewph, viewpw, viewpx, viewpy;
//DENG_EXTERN_C int viewph, viewpw, viewpx, viewpy;
DENG_EXTERN_C float vid_gamma, vid_bright, vid_contrast;
DENG_EXTERN_C int r_detail;

Expand Down Expand Up @@ -125,9 +125,9 @@ void GL_TotalRestore();
*/
void GL_Init2DState();

void GL_SwitchTo3DState(dd_bool push_state, viewport_t const *port, viewdata_t const *viewData);
//void GL_SwitchTo3DState(dd_bool push_state) //, viewport_t const *port, viewdata_t const *viewData);

void GL_Restore2DState(int step, viewport_t const *port, viewdata_t const *viewData);
//void GL_Restore2DState(int step, viewport_t const *port, viewdata_t const *viewData);

void GL_ProjectionMatrix();

Expand Down
4 changes: 2 additions & 2 deletions doomsday/apps/client/include/ui/widgets/gamewidget.h
Expand Up @@ -32,14 +32,14 @@ class GameWidget : public de::GuiWidget
public:
GameWidget(de::String const &name = "game");

/**
/*
* Convenience method for changing and immediately applying a new GL
* viewport. The viewport is automatically normalized in relation to the
* root view size.
*
* This is only intended to support old graphics code that doesn't use libgui.
*/
void glApplyViewport(de::Rectanglei const &rect);
//void glApplyViewport(de::Rectanglei const &rect);

/**
* Pauses the game, if one is currently running and pausing is allowed.
Expand Down
124 changes: 4 additions & 120 deletions doomsday/apps/client/src/gl/gl_main.cpp
Expand Up @@ -45,6 +45,7 @@

#include "world/map.h"
#include "world/p_object.h"
#include "world/p_players.h"

#include "gl/gl_tex.h"
#include "gl/gl_texmanager.h"
Expand Down Expand Up @@ -90,7 +91,7 @@ static dfloat oldgamma, oldcontrast, oldbright;

static dint fogModeDefault;

static viewport_t currentView;
//static viewport_t currentView;

static inline ClientResources &resSys()
{
Expand Down Expand Up @@ -401,124 +402,6 @@ void GL_Init2DState()
glFogfv(GL_FOG_COLOR, fogParams.fogColor);
}

void GL_SwitchTo3DState(dd_bool pushState, viewport_t const *port, viewdata_t const *viewData)
{
DENG2_ASSERT(port && viewData);
DENG_ASSERT_IN_MAIN_THREAD();
DENG_ASSERT_GL_CONTEXT_ACTIVE();

if(pushState)
{
// Push the 2D matrices on the stack.
LIBGUI_GL.glMatrixMode(GL_PROJECTION);
LIBGUI_GL.glPushMatrix();
LIBGUI_GL.glMatrixMode(GL_MODELVIEW);
LIBGUI_GL.glPushMatrix();
}

//glEnable(GL_CULL_FACE);
//glEnable(GL_DEPTH_TEST);
GLState::current()
.setCull(gl::Back)
.setDepthTest(true)
.apply();

std::memcpy(&currentView, port, sizeof(currentView));

//viewpx = port->geometry.topLeft.x + viewData->window.topLeft.x;
//viewpy = port->geometry.topLeft.y + viewData->window.topLeft.y;

viewpx = 0;
viewpy = 0;
viewpw = de::min(port->geometry.width(), viewData->window.width());
viewph = de::min(port->geometry.height(), viewData->window.height());

/*ClientWindow::main().game().glApplyViewport(Rectanglei::fromSize(Vector2i(viewpx, viewpy),
Vector2ui(viewpw, viewph)));*/

// The 3D projection matrix.
GL_ProjectionMatrix();
}

void GL_Restore2DState(dint step, viewport_t const *port, viewdata_t const *viewData)
{
DENG2_ASSERT(port && viewData);
DENG_ASSERT_IN_MAIN_THREAD();
DENG_ASSERT_GL_CONTEXT_ACTIVE();

switch(step)
{
case 1: { // After Restore Step 1 normal player sprites are rendered.
dint height = dfloat( port->geometry.width() * viewData->window.height() / viewData->window.width() ) / port->geometry.height() * SCREENHEIGHT;
scalemode_t sm = R_ChooseScaleMode(SCREENWIDTH, SCREENHEIGHT,
port->geometry.width(), port->geometry.height(),
scalemode_t(weaponScaleMode));

LIBGUI_GL.glMatrixMode(GL_PROJECTION);
LIBGUI_GL.glLoadIdentity();

if(SCALEMODE_STRETCH == sm)
{
LIBGUI_GL.glOrtho(0, SCREENWIDTH, height, 0, -1, 1);
}
else
{
// Use an orthographic projection in native screenspace. Then
// translate and scale the projection to produce an aspect
// corrected coordinate space at 4:3, aligned vertically to
// the bottom and centered horizontally in the window.
LIBGUI_GL.glOrtho(0, port->geometry.width(), port->geometry.height(), 0, -1, 1);
LIBGUI_GL.glTranslatef(port->geometry.width()/2, port->geometry.height(), 0);

if(port->geometry.width() >= port->geometry.height())
LIBGUI_GL.glScalef(dfloat( port->geometry.height() ) / SCREENHEIGHT,
dfloat( port->geometry.height() ) / SCREENHEIGHT, 1);
else
LIBGUI_GL.glScalef(dfloat( port->geometry.width() ) / SCREENWIDTH,
dfloat( port->geometry.width() ) / SCREENWIDTH, 1);

// Special case: viewport height is greater than width.
// Apply an additional scaling factor to prevent player sprites
// looking too small.
if(port->geometry.height() > port->geometry.width())
{
dfloat extraScale = (dfloat(port->geometry.height() * 2) / port->geometry.width()) / 2;
LIBGUI_GL.glScalef(extraScale, extraScale, 1);
}

LIBGUI_GL.glTranslatef(-(SCREENWIDTH / 2), -SCREENHEIGHT, 0);
LIBGUI_GL.glScalef(1, dfloat( SCREENHEIGHT ) / height, 1);
}

LIBGUI_GL.glMatrixMode(GL_MODELVIEW);
LIBGUI_GL.glLoadIdentity();

// Depth testing must be disabled so that psprite 1 will be drawn
// on top of psprite 0 (Doom plasma rifle fire).
//glDisable(GL_DEPTH_TEST);
GLState::current().setDepthTest(false).apply();
break; }

case 2: // After Restore Step 2 we're back in 2D rendering mode.
//ClientWindow::main().game().glApplyViewport(currentView.geometry);
LIBGUI_GL.glMatrixMode(GL_PROJECTION);
LIBGUI_GL.glPopMatrix();
LIBGUI_GL.glMatrixMode(GL_MODELVIEW);
LIBGUI_GL.glPopMatrix();
//glDisable(GL_CULL_FACE);
//glDisable(GL_DEPTH_TEST);
GLState::current()
.setCull(gl::None)
.setDepthTest(false)
.apply();
break;

default:
App_Error("GL_Restore2DState: Invalid value, step = %i.", step);
break;
}
}

Rangef GL_DepthClipRange()
{
return Rangef(glNearClip, glFarClip);
Expand All @@ -527,7 +410,8 @@ Rangef GL_DepthClipRange()
Matrix4f GL_GetProjectionMatrix()
{
dfloat const fov = Rend_FieldOfView();
Vector2f const size(viewpw, viewph);
//Vector2f const size(viewpw, viewph);
Vector2f const size = R_Console3DViewRect(displayPlayer).size();
yfov = vrCfg().verticalFieldOfView(fov, size);
return vrCfg().projectionMatrix(Rend_FieldOfView(), size, glNearClip, glFarClip) *
Matrix4f::scale(Vector3f(1, 1, -1));
Expand Down
10 changes: 6 additions & 4 deletions doomsday/apps/client/src/render/rend_main.cpp
Expand Up @@ -238,8 +238,8 @@ dbyte devRendSkyAlways;
// for convenience (since we would have to recalculate the matrix anyway).
dint rAmbient, ambientLight;

dint viewpw, viewph; ///< Viewport size, in pixels.
dint viewpx, viewpy; ///< Viewpoint top left corner, in pixels.
//dint viewpw, viewph; ///< Viewport size, in pixels.
//dint viewpx, viewpy; ///< Viewpoint top left corner, in pixels.

dfloat yfov;

Expand Down Expand Up @@ -377,12 +377,14 @@ dfloat Rend_FieldOfView()
}
else
{
auto const viewRect = R_Console3DViewRect(displayPlayer);

// Correction is applied for wide screens so that when the FOV is kept
// at a certain value (e.g., the default FOV), a 16:9 view has a wider angle
// than a 4:3, but not just scaled linearly since that would go too far
// into the fish eye territory.
dfloat widescreenCorrection = dfloat(viewpw) / dfloat(viewph) / (4.f / 3.f);
if (widescreenCorrection < 1.5) // up to ~16:9
dfloat widescreenCorrection = dfloat(viewRect.width()) / dfloat(viewRect.height()) / (4.f / 3.f);
if (widescreenCorrection < 1.5f) // up to ~16:9
{
widescreenCorrection = (1 + 2 * widescreenCorrection) / 3;
return de::clamp(1.f, widescreenCorrection * fieldOfView, 179.f);
Expand Down

0 comments on commit 5bce3e7

Please sign in to comment.