mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-22 20:51:31 +00:00
first attempt at porting separation support
ported from stereo-quake http://www.benryves.com/products/stereoquake
This commit is contained in:
parent
1c3dce7be0
commit
0f8bda3c33
5 changed files with 259 additions and 11 deletions
|
@ -95,6 +95,11 @@ cvar_t *hand;
|
|||
cvar_t *gender;
|
||||
cvar_t *gender_auto;
|
||||
|
||||
|
||||
cvar_t *cl_stereo;
|
||||
cvar_t *cl_stereo_separation;
|
||||
cvar_t *cl_stereo_convergence;
|
||||
|
||||
cvar_t *cl_vwep;
|
||||
|
||||
client_static_t cls;
|
||||
|
@ -529,6 +534,10 @@ CL_InitLocal(void)
|
|||
cl_paused = Cvar_Get("paused", "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_address = Cvar_Get("rcon_address", "", 0);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ cvar_t *scr_graphscale;
|
|||
cvar_t *scr_graphshift;
|
||||
cvar_t *scr_drawall;
|
||||
|
||||
cvar_t *scr_scale;
|
||||
cvar_t *gl_hudscale; /* named for consistency with R1Q2 */
|
||||
cvar_t *gl_consolescale;
|
||||
cvar_t *gl_menuscale;
|
||||
|
@ -70,6 +71,34 @@ extern cvar_t *crosshair_scale;
|
|||
void SCR_TimeRefresh_f(void);
|
||||
void SCR_Loading_f(void);
|
||||
|
||||
int SCR_Scale ( void )
|
||||
{
|
||||
|
||||
int scale_x, scale_y, scale;
|
||||
|
||||
scale = scr_scale->value;
|
||||
if (scale == 1) {
|
||||
return scale;
|
||||
} else if (scale < 0) {
|
||||
scale = 0;
|
||||
}
|
||||
|
||||
scale_x = abs(viddef.width) / 320;
|
||||
scale_y = abs(viddef.height) / 240;
|
||||
|
||||
if (scale_x > scale_y) {
|
||||
scale_x = scale_y;
|
||||
}
|
||||
|
||||
if (scale == 0 || (scale_x > 0 && scale_x < scale))
|
||||
{
|
||||
scale = scale_x;
|
||||
}
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A new packet was just parsed
|
||||
*/
|
||||
|
@ -434,6 +463,7 @@ SCR_Init(void)
|
|||
scr_graphscale = Cvar_Get("graphscale", "1", 0);
|
||||
scr_graphshift = Cvar_Get("graphshift", "0", 0);
|
||||
scr_drawall = Cvar_Get("scr_drawall", "0", 0);
|
||||
scr_scale = Cvar_Get ("scr_scale", "0", CVAR_ARCHIVE);
|
||||
gl_hudscale = Cvar_Get("gl_hudscale", "-1", CVAR_ARCHIVE);
|
||||
gl_consolescale = Cvar_Get("gl_consolescale", "-1", CVAR_ARCHIVE);
|
||||
gl_menuscale = Cvar_Get("gl_menuscale", "-1", CVAR_ARCHIVE);
|
||||
|
@ -1441,9 +1471,18 @@ SCR_UpdateScreen(void)
|
|||
return; /* not initialized yet */
|
||||
}
|
||||
|
||||
separation[0] = 0;
|
||||
separation[1] = 0;
|
||||
numframes = 1;
|
||||
if ( cl_stereo->value )
|
||||
{
|
||||
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++)
|
||||
{
|
||||
|
|
|
@ -248,6 +248,7 @@ extern client_static_t cls;
|
|||
|
||||
/* cvars */
|
||||
extern cvar_t *cl_stereo_separation;
|
||||
extern cvar_t *cl_stereo_convergence;
|
||||
extern cvar_t *cl_stereo;
|
||||
extern cvar_t *cl_gun;
|
||||
extern cvar_t *cl_add_blend;
|
||||
|
@ -283,6 +284,8 @@ extern cvar_t *cl_vwep;
|
|||
extern cvar_t *horplus;
|
||||
extern cvar_t *cin_force43;
|
||||
|
||||
int SCR_Scale (void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int key; /* so entities can reuse same entry */
|
||||
|
@ -404,6 +407,8 @@ void CL_AddDLights (void);
|
|||
void CL_AddTEnts (void);
|
||||
void CL_AddLightStyles (void);
|
||||
|
||||
void CL_CalcViewValues (void);
|
||||
|
||||
void CL_PrepRefresh (void);
|
||||
void CL_RegisterSounds (void);
|
||||
|
||||
|
|
|
@ -117,6 +117,21 @@ typedef enum
|
|||
it_sky
|
||||
} 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,
|
||||
};
|
||||
|
||||
enum opengl_special_buffer_modes {
|
||||
OPENGL_SPECIAL_BUFFER_MODE_NONE,
|
||||
OPENGL_SPECIAL_BUFFER_MODE_STEREO,
|
||||
OPENGL_SPECIAL_BUFFER_MODE_STENCIL,
|
||||
};
|
||||
|
||||
typedef struct image_s
|
||||
{
|
||||
char name[MAX_QPATH]; /* game path, including extension */
|
||||
|
@ -382,7 +397,7 @@ typedef struct
|
|||
int currenttmu;
|
||||
|
||||
float camera_separation;
|
||||
qboolean stereo_enabled;
|
||||
enum stereo_modes stereo_mode;
|
||||
|
||||
qboolean hwgamma;
|
||||
|
||||
|
|
|
@ -142,6 +142,14 @@ cvar_t *gl_msaa_samples;
|
|||
cvar_t *vid_fullscreen;
|
||||
cvar_t *vid_gamma;
|
||||
|
||||
cvar_t *cl_stereo;
|
||||
cvar_t *cl_stereo_separation;
|
||||
cvar_t *cl_stereo_anaglyph_colors;
|
||||
cvar_t *cl_stereo_convergence;
|
||||
|
||||
cvar_t *scr_viewsize;
|
||||
|
||||
|
||||
/*
|
||||
* Returns true if the box is completely outside the frustom
|
||||
*/
|
||||
|
@ -412,6 +420,7 @@ R_DrawParticles2(int num_particles, const particle_t particles[],
|
|||
vec3_t up, right;
|
||||
float scale;
|
||||
byte color[4];
|
||||
float viewsize;
|
||||
|
||||
R_Bind(r_particletexture->texnum);
|
||||
glDepthMask(GL_FALSE); /* no z buffering */
|
||||
|
@ -422,6 +431,8 @@ R_DrawParticles2(int num_particles, const particle_t particles[],
|
|||
VectorScale(vup, 1.5, up);
|
||||
VectorScale(vright, 1.5, right);
|
||||
|
||||
viewsize = scr_viewsize->value * 0.01f;
|
||||
|
||||
for (p = particles, i = 0; i < num_particles; i++, p++)
|
||||
{
|
||||
/* hack a scale up to keep particles from disapearing */
|
||||
|
@ -438,6 +449,8 @@ R_DrawParticles2(int num_particles, const particle_t particles[],
|
|||
scale = 1 + scale * 0.004;
|
||||
}
|
||||
|
||||
scale *= viewsize;
|
||||
|
||||
*(int *)color = colortable[p->color];
|
||||
color[3] = p->alpha * 255;
|
||||
|
||||
|
@ -473,11 +486,14 @@ R_DrawParticles(void)
|
|||
unsigned char color[4];
|
||||
const particle_t *p;
|
||||
|
||||
float viewsize;
|
||||
viewsize = scr_viewsize->value * 0.01f;
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glPointSize(LittleFloat(gl_particle_size->value));
|
||||
glPointSize(LittleFloat(gl_particle_size->value * viewsize));
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
|
||||
|
@ -678,8 +694,8 @@ R_MYgluPerspective(GLdouble fovy, GLdouble aspect,
|
|||
xmin = ymin * aspect;
|
||||
xmax = ymax * aspect;
|
||||
|
||||
xmin += -(2 * gl_state.camera_separation) / zNear;
|
||||
xmax += -(2 * gl_state.camera_separation) / zNear;
|
||||
xmin += - cl_stereo_convergence->value * (2 * gl_state.camera_separation) / zNear;
|
||||
xmax += - cl_stereo_convergence->value * (2 * gl_state.camera_separation) / zNear;
|
||||
|
||||
glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
|
||||
}
|
||||
|
@ -749,13 +765,20 @@ R_SetupGL(void)
|
|||
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)
|
||||
{
|
||||
static int trickframe;
|
||||
|
||||
if (gl_clear->value)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClear(GL_COLOR_BUFFER_BIT | stencilFlags);
|
||||
}
|
||||
|
||||
trickframe++;
|
||||
|
@ -777,11 +800,11 @@ R_Clear(void)
|
|||
{
|
||||
if (gl_clear->value)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glClear(GL_COLOR_BUFFER_BIT | stencilFlags | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | stencilFlags);
|
||||
}
|
||||
|
||||
gldepthmin = 0;
|
||||
|
@ -823,6 +846,113 @@ R_Flash(void)
|
|||
void
|
||||
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 * cl_stereo_separation->value) < 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)
|
||||
{
|
||||
return;
|
||||
|
@ -874,6 +1004,17 @@ R_RenderView(refdef_t *fd)
|
|||
c_brush_polys, c_alias_polys, c_visible_textures,
|
||||
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
|
||||
|
@ -893,6 +1034,21 @@ R_SetGL2D(void)
|
|||
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_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
|
||||
R_SetLightLevel(void)
|
||||
{
|
||||
|
@ -1018,6 +1174,14 @@ R_Register(void)
|
|||
|
||||
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 );
|
||||
|
||||
scr_viewsize = Cvar_Get( "viewsize", "100", CVAR_ARCHIVE );
|
||||
|
||||
Cmd_AddCommand("imagelist", R_ImageList_f);
|
||||
Cmd_AddCommand("screenshot", R_ScreenShot);
|
||||
Cmd_AddCommand("modellist", Mod_Modellist_f);
|
||||
|
@ -1128,6 +1292,7 @@ R_Init(void *hinstance, void *hWnd)
|
|||
|
||||
/* set our "safe" mode */
|
||||
gl_state.prev_mode = 4;
|
||||
gl_state.stereo_mode = cl_stereo->value;
|
||||
|
||||
/* create the window and set up the context */
|
||||
if (!R_SetMode())
|
||||
|
@ -1344,6 +1509,21 @@ R_BeginFrame(float camera_separation)
|
|||
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)
|
||||
{
|
||||
vid_gamma->modified = false;
|
||||
|
@ -1372,7 +1552,7 @@ R_BeginFrame(float camera_separation)
|
|||
{
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue