}
#endif
+extern cvar_t r_transparent_alphatocoverage;
static void GL_Backend_ResetState(void)
{
qglColorMask(1, 1, 1, 1);CHECKGLERROR
qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
- qglDisable(GL_ALPHA_TEST);CHECKGLERROR
+ qglDisable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
qglDisable(GL_BLEND);CHECKGLERROR
qglCullFace(gl_state.cullface);CHECKGLERROR
CHECKGLERROR
if (gl_state.alphatest)
{
- qglEnable(GL_ALPHA_TEST);CHECKGLERROR
+ qglEnable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
}
else
{
- qglDisable(GL_ALPHA_TEST);CHECKGLERROR
+ qglDisable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
}
break;
case RENDERPATH_D3D9:
cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
+cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
permutation |= SHADERPERMUTATION_ALPHAKILL;
+ // Alpha to Coverage
+ // fixme: move to gl_backend
+ if (vid_multisampling.integer && r_transparent_alphatocoverage.integer)
+ {
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
+ {
+ qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
+ }
+ else
+ {
+ qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
+ }
+ }
if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
if (rsurfacepass == RSURFPASS_BACKGROUND)
Cvar_RegisterVariable(&r_nearclip);
Cvar_RegisterVariable(&r_deformvertexes);
Cvar_RegisterVariable(&r_transparent);
+ Cvar_RegisterVariable(&r_transparent_alphatocoverage);
Cvar_RegisterVariable(&r_showoverdraw);
Cvar_RegisterVariable(&r_showbboxes);
Cvar_RegisterVariable(&r_showsurfaces);
//GL_ARB_texture_gather
+//GL_ARB_multisample
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+extern void (GLAPIENTRY *qglSampleCoverageARB)(GLclampf value, GLboolean invert);
+
+extern void (GLAPIENTRY *qglPointSize)(GLfloat size);
+
#define DEBUGGL
#ifdef DEBUGGL
qboolean ext_texture_edge_clamp;
qboolean ext_texture_filter_anisotropic;
qboolean ext_texture_srgb;
+ qboolean arb_multisample;
}
viddef_support_t;
extern cvar_t vid_height;
extern cvar_t vid_bitsperpixel;
extern cvar_t vid_samples;
+extern cvar_t vid_multisampling;
extern cvar_t vid_refreshrate;
extern cvar_t vid_userefreshrate;
extern cvar_t vid_vsync;
SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples);
}
+
#if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
if (vid_vsync.integer)
SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
vid_usingmouse = false;
vid_usinghidecursor = false;
+ // enable multisampling
+ if (mode->samples > 1 && vid_multisampling.integer)
+ {
+ if (vid.support.arb_multisample)
+ qglEnable(GL_MULTISAMPLE_ARB);
+ else
+ {
+ Cvar_SetValueQuick(&vid_multisampling, 0);
+ qglDisable(GL_MULTISAMPLE_ARB);
+ }
+ }
+ else
+ qglDisable(GL_MULTISAMPLE_ARB);
+ CHECKGLERROR
+
#if SETVIDEOMODE
SDL_WM_GrabInput(SDL_GRAB_OFF);
#endif
cvar_t vid_height = {CVAR_SAVE, "vid_height", "480", "resolution"};
cvar_t vid_bitsperpixel = {CVAR_SAVE, "vid_bitsperpixel", "32", "how many bits per pixel to render at (32 or 16, 32 is recommended)"};
cvar_t vid_samples = {CVAR_SAVE, "vid_samples", "1", "how many anti-aliasing samples per pixel to request from the graphics driver (4 is recommended, 1 is faster)"};
+cvar_t vid_multisampling = {CVAR_SAVE, "vid_multisampling", "0", "Make use of GL_AGB_MULTISAMPLING for advaced anti-aliasing techniques such as Alpha-To-Coverage, not yet finished"};
cvar_t vid_refreshrate = {CVAR_SAVE, "vid_refreshrate", "60", "refresh rate to use, in hz (higher values flicker less, if supported by your monitor)"};
cvar_t vid_userefreshrate = {CVAR_SAVE, "vid_userefreshrate", "0", "set this to 1 to make vid_refreshrate used, or to 0 to let the engine choose a sane default"};
cvar_t vid_stereobuffer = {CVAR_SAVE, "vid_stereobuffer", "0", "enables 'quad-buffered' stereo rendering for stereo shutterglasses, HMD (head mounted display) devices, or polarized stereo LCDs, if supported by your drivers"};
void (GLAPIENTRY *qglGetQueryObjectivARB)(GLuint qid, GLenum pname, GLint *params);
void (GLAPIENTRY *qglGetQueryObjectuivARB)(GLuint qid, GLenum pname, GLuint *params);
+void (GLAPIENTRY *qglSampleCoverageARB)(GLclampf value, GLboolean invert);
+
#if _MSC_VER >= 1400
#define sscanf sscanf_s
#endif
{NULL, NULL}
};
+static dllfunction_t multisamplefuncs[] =
+{
+ {"glSampleCoverageARB", (void **) &qglSampleCoverageARB},
+ {NULL, NULL}
+};
+
void VID_ClearExtensions(void)
{
// VorteX: reset extensions info cvar, it got filled by GL_CheckExtension
vid.support.ext_texture_edge_clamp = GL_CheckExtension("GL_EXT_texture_edge_clamp", NULL, "-noedgeclamp", false) || GL_CheckExtension("GL_SGIS_texture_edge_clamp", NULL, "-noedgeclamp", false);
vid.support.ext_texture_filter_anisotropic = GL_CheckExtension("GL_EXT_texture_filter_anisotropic", NULL, "-noanisotropy", false);
vid.support.ext_texture_srgb = GL_CheckExtension("GL_EXT_texture_sRGB", NULL, "-nosrgb", false);
+ vid.support.arb_multisample = GL_CheckExtension("GL_ARB_multisample", multisamplefuncs, "-nomultisample", false);
+
// COMMANDLINEOPTION: GL: -noshaders disables use of OpenGL 2.0 shaders (which allow pixel shader effects, can improve per pixel lighting performance and capabilities)
// COMMANDLINEOPTION: GL: -noanisotropy disables GL_EXT_texture_filter_anisotropic (allows higher quality texturing)
// COMMANDLINEOPTION: GL: -noblendminmax disables GL_EXT_blend_minmax
// COMMANDLINEOPTION: GL: -notexturenonpoweroftwo disables GL_ARB_texture_non_power_of_two (which saves video memory if it is supported, but crashes on some buggy drivers)
// COMMANDLINEOPTION: GL: -novbo disables GL_ARB_vertex_buffer_object (which accelerates rendering)
// COMMANDLINEOPTION: GL: -nosrgb disables GL_EXT_texture_sRGB (which is used for higher quality non-linear texture gamma)
+// COMMANDLINEOPTION: GL: -nomultisample disables GL_ARB_multisample
if (vid.support.arb_draw_buffers)
qglGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, (GLint*)&vid.maxdrawbuffers);
Cvar_RegisterVariable(&vid_height);
Cvar_RegisterVariable(&vid_bitsperpixel);
Cvar_RegisterVariable(&vid_samples);
+ Cvar_RegisterVariable(&vid_multisampling);
Cvar_RegisterVariable(&vid_refreshrate);
Cvar_RegisterVariable(&vid_userefreshrate);
Cvar_RegisterVariable(&vid_stereobuffer);