mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 07:12:07 +00:00
Merge branch 'feature-stereo'
This commit is contained in:
commit
3ed18bd7fe
7 changed files with 368 additions and 18 deletions
|
@ -758,7 +758,13 @@ CL_CalcViewValues(void)
|
||||||
ops = ps; /* don't interpolate */
|
ops = ps; /* don't interpolate */
|
||||||
}
|
}
|
||||||
|
|
||||||
lerp = cl.lerpfrac;
|
if(cl_paused->value){
|
||||||
|
lerp = 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lerp = cl.lerpfrac;
|
||||||
|
}
|
||||||
|
|
||||||
/* calculate the origin */
|
/* calculate the origin */
|
||||||
if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
|
if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
|
||||||
|
|
|
@ -95,6 +95,11 @@ cvar_t *hand;
|
||||||
cvar_t *gender;
|
cvar_t *gender;
|
||||||
cvar_t *gender_auto;
|
cvar_t *gender_auto;
|
||||||
|
|
||||||
|
|
||||||
|
cvar_t *cl_stereo;
|
||||||
|
cvar_t *cl_stereo_separation;
|
||||||
|
cvar_t *cl_stereo_convergence;
|
||||||
|
|
||||||
cvar_t *cl_vwep;
|
cvar_t *cl_vwep;
|
||||||
|
|
||||||
client_static_t cls;
|
client_static_t cls;
|
||||||
|
@ -529,6 +534,10 @@ CL_InitLocal(void)
|
||||||
cl_paused = Cvar_Get("paused", "0", 0);
|
cl_paused = Cvar_Get("paused", "0", 0);
|
||||||
cl_timedemo = Cvar_Get("timedemo", "0", 0);
|
cl_timedemo = Cvar_Get("timedemo", "0", 0);
|
||||||
|
|
||||||
|
cl_stereo = Cvar_Get( "cl_stereo", "0", CVAR_ARCHIVE );
|
||||||
|
cl_stereo_separation = Cvar_Get( "cl_stereo_separation", "-0.4", CVAR_ARCHIVE );
|
||||||
|
cl_stereo_convergence = Cvar_Get( "cl_stereo_convergence", "1", CVAR_ARCHIVE );
|
||||||
|
|
||||||
rcon_client_password = Cvar_Get("rcon_password", "", 0);
|
rcon_client_password = Cvar_Get("rcon_password", "", 0);
|
||||||
rcon_address = Cvar_Get("rcon_address", "", 0);
|
rcon_address = Cvar_Get("rcon_address", "", 0);
|
||||||
|
|
||||||
|
|
|
@ -492,7 +492,6 @@ SCR_DrawLoading(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scr_draw_loading = false;
|
|
||||||
Draw_GetPicSize(&w, &h, "loading");
|
Draw_GetPicSize(&w, &h, "loading");
|
||||||
Draw_PicScaled((viddef.width - w * scale) / 2, (viddef.height - h * scale) / 2, "loading", scale);
|
Draw_PicScaled((viddef.width - w * scale) / 2, (viddef.height - h * scale) / 2, "loading", scale);
|
||||||
}
|
}
|
||||||
|
@ -609,6 +608,9 @@ SCR_BeginLoadingPlaque(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
SCR_UpdateScreen();
|
SCR_UpdateScreen();
|
||||||
|
|
||||||
|
scr_draw_loading = false;
|
||||||
|
|
||||||
SCR_StopCinematic();
|
SCR_StopCinematic();
|
||||||
cls.disable_screen = Sys_Milliseconds();
|
cls.disable_screen = Sys_Milliseconds();
|
||||||
cls.disable_servercount = cl.servercount;
|
cls.disable_servercount = cl.servercount;
|
||||||
|
@ -1441,9 +1443,18 @@ SCR_UpdateScreen(void)
|
||||||
return; /* not initialized yet */
|
return; /* not initialized yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
separation[0] = 0;
|
if ( cl_stereo->value )
|
||||||
separation[1] = 0;
|
{
|
||||||
numframes = 1;
|
numframes = 2;
|
||||||
|
separation[0] = -cl_stereo_separation->value / 2;
|
||||||
|
separation[1] = +cl_stereo_separation->value / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
separation[0] = 0;
|
||||||
|
separation[1] = 0;
|
||||||
|
numframes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < numframes; i++)
|
for (i = 0; i < numframes; i++)
|
||||||
{
|
{
|
||||||
|
@ -1454,8 +1465,14 @@ SCR_UpdateScreen(void)
|
||||||
/* loading plaque over black screen */
|
/* loading plaque over black screen */
|
||||||
int w, h;
|
int w, h;
|
||||||
|
|
||||||
R_SetPalette(NULL);
|
if(i == 0){
|
||||||
scr_draw_loading = false;
|
R_SetPalette(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i == numframes - 1){
|
||||||
|
scr_draw_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
Draw_GetPicSize(&w, &h, "loading");
|
Draw_GetPicSize(&w, &h, "loading");
|
||||||
Draw_PicScaled((viddef.width - w * scale) / 2, (viddef.height - h * scale) / 2, "loading", scale);
|
Draw_PicScaled((viddef.width - w * scale) / 2, (viddef.height - h * scale) / 2, "loading", scale);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,18 @@ int gun_frame;
|
||||||
struct model_s *gun_model;
|
struct model_s *gun_model;
|
||||||
|
|
||||||
cvar_t *crosshair;
|
cvar_t *crosshair;
|
||||||
|
cvar_t *crosshair_3d;
|
||||||
|
cvar_t *crosshair_3d_glow;
|
||||||
|
cvar_t *crosshair_3d_color;
|
||||||
|
|
||||||
cvar_t *crosshair_scale;
|
cvar_t *crosshair_scale;
|
||||||
cvar_t *cl_testparticles;
|
cvar_t *cl_testparticles;
|
||||||
cvar_t *cl_testentities;
|
cvar_t *cl_testentities;
|
||||||
cvar_t *cl_testlights;
|
cvar_t *cl_testlights;
|
||||||
cvar_t *cl_testblend;
|
cvar_t *cl_testblend;
|
||||||
|
cvar_t *crosshair_3d_glow_r;
|
||||||
|
cvar_t *crosshair_3d_glow_g;
|
||||||
|
cvar_t *crosshair_3d_glow_b;
|
||||||
|
|
||||||
cvar_t *cl_stats;
|
cvar_t *cl_stats;
|
||||||
|
|
||||||
|
@ -53,6 +60,8 @@ lightstyle_t r_lightstyles[MAX_LIGHTSTYLES];
|
||||||
char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
|
char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
|
||||||
int num_cl_weaponmodels;
|
int num_cl_weaponmodels;
|
||||||
|
|
||||||
|
void V_Render3dCrosshair(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Specifies the model that will be used as the world
|
* Specifies the model that will be used as the world
|
||||||
*/
|
*/
|
||||||
|
@ -494,6 +503,9 @@ V_RenderView(float stereo_separation)
|
||||||
v_forward, etc. */
|
v_forward, etc. */
|
||||||
CL_AddEntities();
|
CL_AddEntities();
|
||||||
|
|
||||||
|
// before changing viewport we should trace the crosshair position
|
||||||
|
V_Render3dCrosshair();
|
||||||
|
|
||||||
if (cl_testparticles->value)
|
if (cl_testparticles->value)
|
||||||
{
|
{
|
||||||
V_TestParticles();
|
V_TestParticles();
|
||||||
|
@ -519,6 +531,7 @@ V_RenderView(float stereo_separation)
|
||||||
|
|
||||||
/* offset vieworg appropriately if
|
/* offset vieworg appropriately if
|
||||||
we're doing stereo separation */
|
we're doing stereo separation */
|
||||||
|
|
||||||
if (stereo_separation != 0)
|
if (stereo_separation != 0)
|
||||||
{
|
{
|
||||||
vec3_t tmp;
|
vec3_t tmp;
|
||||||
|
@ -572,6 +585,18 @@ V_RenderView(float stereo_separation)
|
||||||
qsort(cl.refdef.entities, cl.refdef.num_entities,
|
qsort(cl.refdef.entities, cl.refdef.num_entities,
|
||||||
sizeof(cl.refdef.entities[0]), (int (*)(const void *, const void *))
|
sizeof(cl.refdef.entities[0]), (int (*)(const void *, const void *))
|
||||||
entitycmpfnc);
|
entitycmpfnc);
|
||||||
|
} else if (cl.frame.valid && cl_paused->value && cl_stereo->value) {
|
||||||
|
// We need to adjust the refdef in stereo mode when paused.
|
||||||
|
vec3_t tmp;
|
||||||
|
CL_CalcViewValues();
|
||||||
|
VectorScale( cl.v_right, stereo_separation, tmp );
|
||||||
|
VectorAdd( cl.refdef.vieworg, tmp, cl.refdef.vieworg );
|
||||||
|
|
||||||
|
cl.refdef.vieworg[0] += 1.0/16;
|
||||||
|
cl.refdef.vieworg[1] += 1.0/16;
|
||||||
|
cl.refdef.vieworg[2] += 1.0/16;
|
||||||
|
|
||||||
|
cl.refdef.time = cl.time*0.001;
|
||||||
}
|
}
|
||||||
|
|
||||||
cl.refdef.x = scr_vrect.x;
|
cl.refdef.x = scr_vrect.x;
|
||||||
|
@ -602,6 +627,53 @@ V_RenderView(float stereo_separation)
|
||||||
SCR_DrawCrosshair();
|
SCR_DrawCrosshair();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
V_Render3dCrosshair(void)
|
||||||
|
{
|
||||||
|
trace_t crosshair_trace;
|
||||||
|
vec3_t end;
|
||||||
|
vec_t *crosshair_pos;
|
||||||
|
|
||||||
|
crosshair_3d = Cvar_Get("crosshair_3d", "0", CVAR_ARCHIVE);
|
||||||
|
crosshair_3d_glow = Cvar_Get("crosshair_3d_glow", "0", CVAR_ARCHIVE);
|
||||||
|
|
||||||
|
|
||||||
|
if(crosshair_3d->value || crosshair_3d_glow->value){
|
||||||
|
VectorMA(cl.refdef.vieworg,8192,cl.v_forward,end);
|
||||||
|
crosshair_trace = CL_PMTrace(cl.refdef.vieworg, vec3_origin, vec3_origin, end);
|
||||||
|
|
||||||
|
if(crosshair_3d_glow->value){
|
||||||
|
crosshair_3d_glow_r = Cvar_Get("crosshair_3d_glow_r", "5", CVAR_ARCHIVE);
|
||||||
|
crosshair_3d_glow_g = Cvar_Get("crosshair_3d_glow_g", "1", CVAR_ARCHIVE);
|
||||||
|
crosshair_3d_glow_b = Cvar_Get("crosshair_3d_glow_b", "4", CVAR_ARCHIVE);
|
||||||
|
|
||||||
|
V_AddLight(
|
||||||
|
crosshair_trace.endpos,
|
||||||
|
crosshair_3d_glow->value,
|
||||||
|
crosshair_3d_glow_r->value,
|
||||||
|
crosshair_3d_glow_g->value,
|
||||||
|
crosshair_3d_glow_b->value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(crosshair_3d->value){
|
||||||
|
entity_t crosshair_ent = {0};
|
||||||
|
|
||||||
|
crosshair_ent.origin[0] = crosshair_trace.endpos[0];
|
||||||
|
crosshair_ent.origin[1] = crosshair_trace.endpos[1];
|
||||||
|
crosshair_ent.origin[2] = crosshair_trace.endpos[2];
|
||||||
|
|
||||||
|
crosshair_ent.model = R_RegisterModel("models/crosshair/tris.md2");
|
||||||
|
//crosshair_ent.skin = R_RegisterSkin("models/crosshair/skin.pcx");
|
||||||
|
|
||||||
|
AngleVectors2(crosshair_trace.plane.normal, crosshair_ent.angles);
|
||||||
|
crosshair_ent.flags = RF_DEPTHHACK | RF_FULLBRIGHT | RF_NOSHADOW;
|
||||||
|
|
||||||
|
V_AddEntity(&crosshair_ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
V_Viewpos_f(void)
|
V_Viewpos_f(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -248,6 +248,7 @@ extern client_static_t cls;
|
||||||
|
|
||||||
/* cvars */
|
/* cvars */
|
||||||
extern cvar_t *cl_stereo_separation;
|
extern cvar_t *cl_stereo_separation;
|
||||||
|
extern cvar_t *cl_stereo_convergence;
|
||||||
extern cvar_t *cl_stereo;
|
extern cvar_t *cl_stereo;
|
||||||
extern cvar_t *cl_gun;
|
extern cvar_t *cl_gun;
|
||||||
extern cvar_t *cl_add_blend;
|
extern cvar_t *cl_add_blend;
|
||||||
|
@ -506,5 +507,6 @@ void CL_KeyInventory (int key);
|
||||||
void CL_DrawInventory (void);
|
void CL_DrawInventory (void);
|
||||||
|
|
||||||
void CL_PredictMovement (void);
|
void CL_PredictMovement (void);
|
||||||
|
trace_t CL_PMTrace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -117,6 +117,23 @@ typedef enum
|
||||||
it_sky
|
it_sky
|
||||||
} imagetype_t;
|
} imagetype_t;
|
||||||
|
|
||||||
|
enum stereo_modes {
|
||||||
|
STEREO_MODE_NONE,
|
||||||
|
STEREO_MODE_OPENGL,
|
||||||
|
STEREO_MODE_ANAGLYPH,
|
||||||
|
STEREO_MODE_ROW_INTERLEAVED,
|
||||||
|
STEREO_MODE_COLUMN_INTERLEAVED,
|
||||||
|
STEREO_MODE_PIXEL_INTERLEAVED,
|
||||||
|
STEREO_SPLIT_HORIZONTAL,
|
||||||
|
STEREO_SPLIT_VERTICAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum opengl_special_buffer_modes {
|
||||||
|
OPENGL_SPECIAL_BUFFER_MODE_NONE,
|
||||||
|
OPENGL_SPECIAL_BUFFER_MODE_STEREO,
|
||||||
|
OPENGL_SPECIAL_BUFFER_MODE_STENCIL,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct image_s
|
typedef struct image_s
|
||||||
{
|
{
|
||||||
char name[MAX_QPATH]; /* game path, including extension */
|
char name[MAX_QPATH]; /* game path, including extension */
|
||||||
|
@ -382,7 +399,7 @@ typedef struct
|
||||||
int currenttmu;
|
int currenttmu;
|
||||||
|
|
||||||
float camera_separation;
|
float camera_separation;
|
||||||
qboolean stereo_enabled;
|
enum stereo_modes stereo_mode;
|
||||||
|
|
||||||
qboolean hwgamma;
|
qboolean hwgamma;
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,11 @@ cvar_t *gl_msaa_samples;
|
||||||
cvar_t *vid_fullscreen;
|
cvar_t *vid_fullscreen;
|
||||||
cvar_t *vid_gamma;
|
cvar_t *vid_gamma;
|
||||||
|
|
||||||
|
cvar_t *cl_stereo;
|
||||||
|
cvar_t *cl_stereo_separation;
|
||||||
|
cvar_t *cl_stereo_anaglyph_colors;
|
||||||
|
cvar_t *cl_stereo_convergence;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the box is completely outside the frustom
|
* Returns true if the box is completely outside the frustom
|
||||||
*/
|
*/
|
||||||
|
@ -467,7 +472,10 @@ R_DrawParticles2(int num_particles, const particle_t particles[],
|
||||||
void
|
void
|
||||||
R_DrawParticles(void)
|
R_DrawParticles(void)
|
||||||
{
|
{
|
||||||
if (gl_ext_pointparameters->value && qglPointParameterfEXT)
|
qboolean stereo_split_tb = ((gl_state.stereo_mode == STEREO_SPLIT_VERTICAL) && gl_state.camera_separation);
|
||||||
|
qboolean stereo_split_lr = ((gl_state.stereo_mode == STEREO_SPLIT_HORIZONTAL) && gl_state.camera_separation);
|
||||||
|
|
||||||
|
if (gl_ext_pointparameters->value && qglPointParameterfEXT && !(stereo_split_tb || stereo_split_lr))
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned char color[4];
|
unsigned char color[4];
|
||||||
|
@ -678,8 +686,8 @@ R_MYgluPerspective(GLdouble fovy, GLdouble aspect,
|
||||||
xmin = ymin * aspect;
|
xmin = ymin * aspect;
|
||||||
xmax = ymax * aspect;
|
xmax = ymax * aspect;
|
||||||
|
|
||||||
xmin += -(2 * gl_state.camera_separation) / zNear;
|
xmin += - cl_stereo_convergence->value * (2 * gl_state.camera_separation) / zNear;
|
||||||
xmax += -(2 * gl_state.camera_separation) / zNear;
|
xmax += - cl_stereo_convergence->value * (2 * gl_state.camera_separation) / zNear;
|
||||||
|
|
||||||
glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
|
glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
|
||||||
}
|
}
|
||||||
|
@ -700,6 +708,20 @@ R_SetupGL(void)
|
||||||
w = x2 - x;
|
w = x2 - x;
|
||||||
h = y - y2;
|
h = y - y2;
|
||||||
|
|
||||||
|
qboolean drawing_left_eye = gl_state.camera_separation < 0;
|
||||||
|
qboolean stereo_split_tb = ((gl_state.stereo_mode == STEREO_SPLIT_VERTICAL) && gl_state.camera_separation);
|
||||||
|
qboolean stereo_split_lr = ((gl_state.stereo_mode == STEREO_SPLIT_HORIZONTAL) && gl_state.camera_separation);
|
||||||
|
|
||||||
|
if(stereo_split_lr) {
|
||||||
|
w = w / 2;
|
||||||
|
x = drawing_left_eye ? (x / 2) : (x + vid.width) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stereo_split_tb) {
|
||||||
|
h = h / 2;
|
||||||
|
y2 = drawing_left_eye ? (y2 + vid.height) / 2 : (y2 / 2);
|
||||||
|
}
|
||||||
|
|
||||||
glViewport(x, y2, w, h);
|
glViewport(x, y2, w, h);
|
||||||
|
|
||||||
/* set up projection matrix */
|
/* set up projection matrix */
|
||||||
|
@ -749,13 +771,20 @@ R_SetupGL(void)
|
||||||
void
|
void
|
||||||
R_Clear(void)
|
R_Clear(void)
|
||||||
{
|
{
|
||||||
|
// Check whether the stencil buffer needs clearing, and do so if need be.
|
||||||
|
GLbitfield stencilFlags = 0;
|
||||||
|
if (gl_state.stereo_mode >= STEREO_MODE_ROW_INTERLEAVED && gl_state.stereo_mode <= STEREO_MODE_PIXEL_INTERLEAVED) {
|
||||||
|
glClearStencil(0);
|
||||||
|
stencilFlags |= GL_STENCIL_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
if (gl_ztrick->value)
|
if (gl_ztrick->value)
|
||||||
{
|
{
|
||||||
static int trickframe;
|
static int trickframe;
|
||||||
|
|
||||||
if (gl_clear->value)
|
if (gl_clear->value)
|
||||||
{
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | stencilFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
trickframe++;
|
trickframe++;
|
||||||
|
@ -777,11 +806,11 @@ R_Clear(void)
|
||||||
{
|
{
|
||||||
if (gl_clear->value)
|
if (gl_clear->value)
|
||||||
{
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | stencilFlags | GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT | stencilFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
gldepthmin = 0;
|
gldepthmin = 0;
|
||||||
|
@ -823,6 +852,113 @@ R_Flash(void)
|
||||||
void
|
void
|
||||||
R_RenderView(refdef_t *fd)
|
R_RenderView(refdef_t *fd)
|
||||||
{
|
{
|
||||||
|
if ((gl_state.stereo_mode != STEREO_MODE_NONE) && gl_state.camera_separation) {
|
||||||
|
|
||||||
|
qboolean drawing_left_eye = gl_state.camera_separation < 0;
|
||||||
|
switch (gl_state.stereo_mode) {
|
||||||
|
case STEREO_MODE_ANAGLYPH:
|
||||||
|
{
|
||||||
|
|
||||||
|
// Work out the colour for each eye.
|
||||||
|
int anaglyph_colours[] = { 0x4, 0x3 }; // Left = red, right = cyan.
|
||||||
|
|
||||||
|
if (strlen(cl_stereo_anaglyph_colors->string) == 2) {
|
||||||
|
int eye, colour, missing_bits;
|
||||||
|
// Decode the colour name from its character.
|
||||||
|
for (eye = 0; eye < 2; ++eye) {
|
||||||
|
colour = 0;
|
||||||
|
switch (toupper(cl_stereo_anaglyph_colors->string[eye])) {
|
||||||
|
case 'B': ++colour; // 001 Blue
|
||||||
|
case 'G': ++colour; // 010 Green
|
||||||
|
case 'C': ++colour; // 011 Cyan
|
||||||
|
case 'R': ++colour; // 100 Red
|
||||||
|
case 'M': ++colour; // 101 Magenta
|
||||||
|
case 'Y': ++colour; // 110 Yellow
|
||||||
|
anaglyph_colours[eye] = colour;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fill in any missing bits.
|
||||||
|
missing_bits = ~(anaglyph_colours[0] | anaglyph_colours[1]) & 0x3;
|
||||||
|
for (eye = 0; eye < 2; ++eye) {
|
||||||
|
anaglyph_colours[eye] |= missing_bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the current colour.
|
||||||
|
glColorMask(
|
||||||
|
!!(anaglyph_colours[drawing_left_eye] & 0x4),
|
||||||
|
!!(anaglyph_colours[drawing_left_eye] & 0x2),
|
||||||
|
!!(anaglyph_colours[drawing_left_eye] & 0x1),
|
||||||
|
GL_TRUE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STEREO_MODE_ROW_INTERLEAVED:
|
||||||
|
case STEREO_MODE_COLUMN_INTERLEAVED:
|
||||||
|
case STEREO_MODE_PIXEL_INTERLEAVED:
|
||||||
|
{
|
||||||
|
qboolean flip_eyes = true;
|
||||||
|
int client_x, client_y;
|
||||||
|
|
||||||
|
//GLimp_GetClientAreaOffset(&client_x, &client_y);
|
||||||
|
client_x = 0;
|
||||||
|
client_y = 0;
|
||||||
|
|
||||||
|
R_SetGL2D();
|
||||||
|
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
glStencilMask(GL_TRUE);
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
|
||||||
|
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
|
||||||
|
glStencilFunc(GL_NEVER, 0, 1);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
{
|
||||||
|
glVertex2i(0, 0);
|
||||||
|
glVertex2i(vid.width, 0);
|
||||||
|
glVertex2i(vid.width, vid.height);
|
||||||
|
glVertex2i(0, vid.height);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glStencilOp(GL_INVERT, GL_KEEP, GL_KEEP);
|
||||||
|
glStencilFunc(GL_NEVER, 1, 1);
|
||||||
|
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
{
|
||||||
|
if (gl_state.stereo_mode == STEREO_MODE_ROW_INTERLEAVED || gl_state.stereo_mode == STEREO_MODE_PIXEL_INTERLEAVED) {
|
||||||
|
int y;
|
||||||
|
for (y = 0; y <= vid.height; y += 2) {
|
||||||
|
glVertex2f(0, y - 0.5f);
|
||||||
|
glVertex2f(vid.width, y - 0.5f);
|
||||||
|
}
|
||||||
|
flip_eyes ^= (client_y & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gl_state.stereo_mode == STEREO_MODE_COLUMN_INTERLEAVED || gl_state.stereo_mode == STEREO_MODE_PIXEL_INTERLEAVED) {
|
||||||
|
int x;
|
||||||
|
for (x = 0; x <= vid.width; x += 2) {
|
||||||
|
glVertex2f(x - 0.5f, 0);
|
||||||
|
glVertex2f(x - 0.5f, vid.height);
|
||||||
|
}
|
||||||
|
flip_eyes ^= (client_x & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glStencilMask(GL_FALSE);
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
|
||||||
|
glStencilFunc(GL_EQUAL, drawing_left_eye ^ flip_eyes, 1);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (gl_norefresh->value)
|
if (gl_norefresh->value)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -874,13 +1010,44 @@ R_RenderView(refdef_t *fd)
|
||||||
c_brush_polys, c_alias_polys, c_visible_textures,
|
c_brush_polys, c_alias_polys, c_visible_textures,
|
||||||
c_visible_lightmaps);
|
c_visible_lightmaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (gl_state.stereo_mode) {
|
||||||
|
case STEREO_MODE_ANAGLYPH:
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
break;
|
||||||
|
case STEREO_MODE_ROW_INTERLEAVED:
|
||||||
|
case STEREO_MODE_COLUMN_INTERLEAVED:
|
||||||
|
case STEREO_MODE_PIXEL_INTERLEAVED:
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
R_SetGL2D(void)
|
R_SetGL2D(void)
|
||||||
{
|
{
|
||||||
|
int x, w, y, h;
|
||||||
/* set 2D virtual screen size */
|
/* set 2D virtual screen size */
|
||||||
glViewport(0, 0, vid.width, vid.height);
|
qboolean drawing_left_eye = gl_state.camera_separation < 0;
|
||||||
|
qboolean stereo_split_tb = ((gl_state.stereo_mode == STEREO_SPLIT_VERTICAL) && gl_state.camera_separation);
|
||||||
|
qboolean stereo_split_lr = ((gl_state.stereo_mode == STEREO_SPLIT_HORIZONTAL) && gl_state.camera_separation);
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
w = vid.width;
|
||||||
|
y = 0;
|
||||||
|
h = vid.height;
|
||||||
|
|
||||||
|
if(stereo_split_lr) {
|
||||||
|
w = w / 2;
|
||||||
|
x = drawing_left_eye ? 0 : w;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stereo_split_tb) {
|
||||||
|
h = h / 2;
|
||||||
|
y = drawing_left_eye ? h : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glViewport(x, y, w, h);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glOrtho(0, vid.width, vid.height, 0, -99999, 99999);
|
glOrtho(0, vid.width, vid.height, 0, -99999, 99999);
|
||||||
|
@ -893,6 +1060,23 @@ R_SetGL2D(void)
|
||||||
glColor4f(1, 1, 1, 1);
|
glColor4f(1, 1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum opengl_special_buffer_modes GL_GetSpecialBufferModeForStereoMode(enum stereo_modes stereo_mode) {
|
||||||
|
switch (stereo_mode) {
|
||||||
|
case STEREO_MODE_NONE:
|
||||||
|
case STEREO_SPLIT_HORIZONTAL:
|
||||||
|
case STEREO_SPLIT_VERTICAL:
|
||||||
|
case STEREO_MODE_ANAGLYPH:
|
||||||
|
return OPENGL_SPECIAL_BUFFER_MODE_NONE;
|
||||||
|
case STEREO_MODE_OPENGL:
|
||||||
|
return OPENGL_SPECIAL_BUFFER_MODE_STEREO;
|
||||||
|
case STEREO_MODE_ROW_INTERLEAVED:
|
||||||
|
case STEREO_MODE_COLUMN_INTERLEAVED:
|
||||||
|
case STEREO_MODE_PIXEL_INTERLEAVED:
|
||||||
|
return OPENGL_SPECIAL_BUFFER_MODE_STENCIL;
|
||||||
|
}
|
||||||
|
return OPENGL_SPECIAL_BUFFER_MODE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
R_SetLightLevel(void)
|
R_SetLightLevel(void)
|
||||||
{
|
{
|
||||||
|
@ -1018,6 +1202,12 @@ R_Register(void)
|
||||||
|
|
||||||
gl_retexturing = Cvar_Get("gl_retexturing", "1", CVAR_ARCHIVE);
|
gl_retexturing = Cvar_Get("gl_retexturing", "1", CVAR_ARCHIVE);
|
||||||
|
|
||||||
|
|
||||||
|
cl_stereo = Cvar_Get( "cl_stereo", "0", CVAR_ARCHIVE );
|
||||||
|
cl_stereo_separation = Cvar_Get( "cl_stereo_separation", "-0.4", CVAR_ARCHIVE );
|
||||||
|
cl_stereo_anaglyph_colors = Cvar_Get( "cl_stereo_anaglyph_colors", "rc", CVAR_ARCHIVE );
|
||||||
|
cl_stereo_convergence = Cvar_Get( "cl_stereo_convergence", "1", CVAR_ARCHIVE );
|
||||||
|
|
||||||
Cmd_AddCommand("imagelist", R_ImageList_f);
|
Cmd_AddCommand("imagelist", R_ImageList_f);
|
||||||
Cmd_AddCommand("screenshot", R_ScreenShot);
|
Cmd_AddCommand("screenshot", R_ScreenShot);
|
||||||
Cmd_AddCommand("modellist", Mod_Modellist_f);
|
Cmd_AddCommand("modellist", Mod_Modellist_f);
|
||||||
|
@ -1128,6 +1318,7 @@ R_Init(void *hinstance, void *hWnd)
|
||||||
|
|
||||||
/* set our "safe" mode */
|
/* set our "safe" mode */
|
||||||
gl_state.prev_mode = 4;
|
gl_state.prev_mode = 4;
|
||||||
|
gl_state.stereo_mode = cl_stereo->value;
|
||||||
|
|
||||||
/* create the window and set up the context */
|
/* create the window and set up the context */
|
||||||
if (!R_SetMode())
|
if (!R_SetMode())
|
||||||
|
@ -1344,6 +1535,21 @@ R_BeginFrame(float camera_separation)
|
||||||
vid_fullscreen->modified = true;
|
vid_fullscreen->modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// force a vid_restart if cl_stereo has been modified.
|
||||||
|
if ( gl_state.stereo_mode != cl_stereo->value ) {
|
||||||
|
// If we've gone from one mode to another with the same special buffer requirements there's no need to restart.
|
||||||
|
if ( GL_GetSpecialBufferModeForStereoMode( gl_state.stereo_mode ) == GL_GetSpecialBufferModeForStereoMode( cl_stereo->value ) ) {
|
||||||
|
gl_state.stereo_mode = cl_stereo->value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VID_Printf(PRINT_ALL, "stereo supermode changed, restarting video!\n");
|
||||||
|
cvar_t *ref;
|
||||||
|
ref = Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
|
||||||
|
ref->modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (vid_gamma->modified)
|
if (vid_gamma->modified)
|
||||||
{
|
{
|
||||||
vid_gamma->modified = false;
|
vid_gamma->modified = false;
|
||||||
|
@ -1355,7 +1561,28 @@ R_BeginFrame(float camera_separation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go into 2D mode */
|
/* go into 2D mode */
|
||||||
glViewport(0, 0, vid.width, vid.height);
|
|
||||||
|
int x, w, y, h;
|
||||||
|
qboolean drawing_left_eye = gl_state.camera_separation < 0;
|
||||||
|
qboolean stereo_split_tb = ((gl_state.stereo_mode == STEREO_SPLIT_VERTICAL) && gl_state.camera_separation);
|
||||||
|
qboolean stereo_split_lr = ((gl_state.stereo_mode == STEREO_SPLIT_HORIZONTAL) && gl_state.camera_separation);
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
w = vid.width;
|
||||||
|
y = 0;
|
||||||
|
h = vid.height;
|
||||||
|
|
||||||
|
if(stereo_split_lr) {
|
||||||
|
w = w / 2;
|
||||||
|
x = drawing_left_eye ? 0 : w;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stereo_split_tb) {
|
||||||
|
h = h / 2;
|
||||||
|
y = drawing_left_eye ? h : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glViewport(x, y, w, h);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glOrtho(0, vid.width, vid.height, 0, -99999, 99999);
|
glOrtho(0, vid.width, vid.height, 0, -99999, 99999);
|
||||||
|
@ -1372,7 +1599,7 @@ R_BeginFrame(float camera_separation)
|
||||||
{
|
{
|
||||||
gl_drawbuffer->modified = false;
|
gl_drawbuffer->modified = false;
|
||||||
|
|
||||||
if ((gl_state.camera_separation == 0) || !gl_state.stereo_enabled)
|
if ((gl_state.camera_separation == 0) || gl_state.stereo_mode != STEREO_MODE_OPENGL)
|
||||||
{
|
{
|
||||||
if (Q_stricmp(gl_drawbuffer->string, "GL_FRONT") == 0)
|
if (Q_stricmp(gl_drawbuffer->string, "GL_FRONT") == 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue