int depthtest;
int depthfunc;
int scissortest;
- int alphatest;
- int alphafunc;
- float alphavalue;
int viewport[4];
int scissor[4];
float depthrange[2];
command->mode = mode;
}
-DEFCOMMAND(15, AlphaTest, int enable;)
-static void DPSOFTRAST_Interpret_AlphaTest(DPSOFTRAST_State_Thread *thread, DPSOFTRAST_Command_AlphaTest *command)
-{
- thread->alphatest = command->enable;
-}
-void DPSOFTRAST_AlphaTest(int enable)
-{
- DPSOFTRAST_Command_AlphaTest *command = DPSOFTRAST_ALLOCATECOMMAND(AlphaTest);
- command->enable = enable;
-}
-
-DEFCOMMAND(16, AlphaFunc, int func; float ref;)
-static void DPSOFTRAST_Interpret_AlphaFunc(DPSOFTRAST_State_Thread *thread, DPSOFTRAST_Command_AlphaFunc *command)
-{
- thread->alphafunc = command->func;
- thread->alphavalue = command->ref;
-}
-void DPSOFTRAST_AlphaFunc(int func, float ref)
-{
- DPSOFTRAST_Command_AlphaFunc *command = DPSOFTRAST_ALLOCATECOMMAND(AlphaFunc);
- command->func = func;
- command->ref = ref;
-}
-
void DPSOFTRAST_Color4f(float r, float g, float b, float a)
{
dpsoftrast.color[0] = r;
pixel += (span->y * dpsoftrast.fb_width + span->x) * 4;
pixeli += span->y * dpsoftrast.fb_width + span->x;
// handle alphatest now (this affects depth writes too)
- if (thread->alphatest)
+ if (thread->shader_permutation & SHADERPERMUTATION_ALPHAKILL)
for (x = startx;x < endx;x++)
if (in4ub[x*4+3] < 128)
pixelmask[x] = false;
unsigned char buffer_FragColorbgra8[DPSOFTRAST_DRAW_MAXSPANLENGTH*4];
DPSOFTRAST_Draw_Span_Begin(thread, triangle, span, buffer_z);
DPSOFTRAST_Draw_Span_Texture2DVaryingBGRA8(thread, triangle, span, buffer_texture_colorbgra8, GL20TU_COLOR, 2, buffer_z);
- if (thread->alphatest || thread->fb_blendmode != DPSOFTRAST_BLENDMODE_OPAQUE)
+ if ((thread->shader_permutation & SHADERPERMUTATION_ALPHAKILL) || thread->fb_blendmode != DPSOFTRAST_BLENDMODE_OPAQUE)
pixel = buffer_FragColorbgra8;
Color_Ambientm = _mm_shuffle_epi32(_mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(&thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Ambient*4]), _mm_set1_ps(256.0f))), _MM_SHUFFLE(3, 0, 1, 2));
Color_Ambientm = _mm_and_si128(Color_Ambientm, _mm_setr_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0));
int arrayindex = DPSOFTRAST_ARRAY_COLOR;
DPSOFTRAST_Draw_Span_Begin(thread, triangle, span, buffer_z);
DPSOFTRAST_Draw_Span_Texture2DVaryingBGRA8(thread, triangle, span, buffer_texture_colorbgra8, GL20TU_COLOR, 2, buffer_z);
- if (thread->alphatest || thread->fb_blendmode != DPSOFTRAST_BLENDMODE_OPAQUE)
+ if ((thread->shader_permutation & SHADERPERMUTATION_ALPHAKILL) || thread->fb_blendmode != DPSOFTRAST_BLENDMODE_OPAQUE)
pixel = buffer_FragColorbgra8;
Color_Ambientm = _mm_shuffle_epi32(_mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(&thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Ambient*4]), _mm_set1_ps(256.0f))), _MM_SHUFFLE(3, 0, 1, 2));
Color_Ambientm = _mm_and_si128(Color_Ambientm, _mm_setr_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0));
DPSOFTRAST_Draw_Span_Begin(thread, triangle, span, buffer_z);
DPSOFTRAST_Draw_Span_Texture2DVaryingBGRA8(thread, triangle, span, buffer_texture_colorbgra8, GL20TU_COLOR, DPSOFTRAST_ARRAY_TEXCOORD0, buffer_z);
DPSOFTRAST_Draw_Span_Texture2DVaryingBGRA8(thread, triangle, span, buffer_texture_lightmapbgra8, GL20TU_LIGHTMAP, DPSOFTRAST_ARRAY_TEXCOORD4, buffer_z);
- if (thread->alphatest || thread->fb_blendmode != DPSOFTRAST_BLENDMODE_OPAQUE)
+ if ((thread->shader_permutation & SHADERPERMUTATION_ALPHAKILL) || thread->fb_blendmode != DPSOFTRAST_BLENDMODE_OPAQUE)
pixel = buffer_FragColorbgra8;
Color_Ambientm = _mm_shuffle_epi32(_mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(&thread->uniform4f[DPSOFTRAST_UNIFORM_Color_Ambient*4]), _mm_set1_ps(256.0f))), _MM_SHUFFLE(3, 0, 1, 2));
Color_Ambientm = _mm_and_si128(Color_Ambientm, _mm_setr_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0));
INTERPCOMMAND(DepthRange)
INTERPCOMMAND(PolygonOffset)
INTERPCOMMAND(CullFace)
- INTERPCOMMAND(AlphaTest)
- INTERPCOMMAND(AlphaFunc)
INTERPCOMMAND(SetTexture)
INTERPCOMMAND(SetShader)
INTERPCOMMAND(Uniform4f)
thread->depthtest = true;
thread->depthfunc = GL_LEQUAL;
thread->scissortest = false;
- thread->alphatest = false;
- thread->alphafunc = GL_GREATER;
- thread->alphavalue = 0.5f;
thread->viewport[0] = 0;
thread->viewport[1] = 0;
thread->viewport[2] = dpsoftrast.fb_width;
void DPSOFTRAST_DepthRange(float range0, float range1);
void DPSOFTRAST_PolygonOffset(float alongnormal, float intoview);
void DPSOFTRAST_CullFace(int mode);
-void DPSOFTRAST_AlphaTest(int enable);
-void DPSOFTRAST_AlphaFunc(int alphafunc, float alphavalue);
void DPSOFTRAST_Color4f(float r, float g, float b, float a);
void DPSOFTRAST_GetPixelsBGRA(int blockx, int blocky, int blockwidth, int blockheight, unsigned char *outpixels);
void DPSOFTRAST_CopyRectangleToTexture(int index, int mip, int tx, int ty, int sx, int sy, int width, int height);
int alphatest;
int alphafunc;
float alphafuncvalue;
+ qboolean alphatocoverage;
int scissortest;
unsigned int unit;
unsigned int clientunit;
gl_state.alphatest = false;
gl_state.alphafunc = GL_GEQUAL;
gl_state.alphafuncvalue = 0.5f;
+ gl_state.alphatocoverage = false;
gl_state.blendfunc1 = GL_ONE;
gl_state.blendfunc2 = GL_ZERO;
gl_state.blend = false;
#ifdef SUPPORTD3D
{
IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
- IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
- IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
- IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
qglColorMask(1, 1, 1, 1);CHECKGLERROR
qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
- qglDisable((r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
+ qglDisable(GL_ALPHA_TEST);CHECKGLERROR
qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
qglDisable(GL_BLEND);CHECKGLERROR
qglCullFace(gl_state.cullface);CHECKGLERROR
break;
case RENDERPATH_SOFT:
DPSOFTRAST_ColorMask(1,1,1,1);
- DPSOFTRAST_AlphaTest(gl_state.alphatest);
DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
DPSOFTRAST_CullFace(gl_state.cullface);
DPSOFTRAST_DepthFunc(gl_state.depthfunc);
qglEnable(GL_DEPTH_TEST);CHECKGLERROR
qglDepthMask(gl_state.depthmask);CHECKGLERROR
qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
- // if (vid.renderpath == RENDERPATH_GL20)
- // {
- // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
- // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
- // }
if (vid.support.arb_vertex_buffer_object)
{
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
case RENDERPATH_GLES1:
case RENDERPATH_GL20:
case RENDERPATH_GLES2:
- if (vid.support.arb_multisample)
+ if (vid.support.arb_multisample && vid.mode.samples > 1)
{
if (state)
qglEnable(GL_MULTISAMPLE_ARB);
CHECKGLERROR
if (gl_state.alphatest)
{
- qglEnable((r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
+ qglEnable(GL_ALPHA_TEST);CHECKGLERROR
}
else
{
- qglDisable((r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
+ qglDisable(GL_ALPHA_TEST);CHECKGLERROR
}
break;
case RENDERPATH_D3D9:
-#ifdef SUPPORTD3D
-// IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
-#endif
- break;
case RENDERPATH_D3D10:
- break;
case RENDERPATH_D3D11:
+ case RENDERPATH_SOFT:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES2:
break;
+ }
+ }
+}
+
+void GL_AlphaToCoverage(qboolean state)
+{
+ if (gl_state.alphatocoverage != state)
+ {
+ gl_state.alphatocoverage = state;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ case RENDERPATH_D3D9:
+ case RENDERPATH_D3D10:
+ case RENDERPATH_D3D11:
case RENDERPATH_SOFT:
- DPSOFTRAST_AlphaTest(gl_state.alphatest);
break;
case RENDERPATH_GL20:
- case RENDERPATH_GLES2:
- if (vid_multisampling.integer)
+ // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
+ if (vid.support.arb_multisample && vid.mode.samples > 1)
{
- if (gl_state.alphatest && r_transparent_alphatocoverage.integer)
- qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
- else
- qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
CHECKGLERROR
+ if (gl_state.alphatocoverage)
+ {
+ qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
+ qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR
+ }
+ else
+ {
+ qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
+ qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
+ }
}
break;
}
void GL_PolygonOffset(float planeoffset, float depthoffset);
void GL_CullFace(int state);
void GL_AlphaTest(int state);
+void GL_AlphaToCoverage(qboolean state);
void GL_MultiSampling(qboolean state);
void GL_ColorMask(int r, int g, int b, int a);
void GL_Color(float cr, float cg, float cb, float ca);
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_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces when using vid_samples 2 or higher"};
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)"};
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
if (!second)
texturemode = GL_MODULATE;
+ GL_AlphaToCoverage(false);
switch (vid.renderpath)
{
case RENDERPATH_D3D9:
unsigned int permutation = 0;
if (r_trippy.integer && !notrippy)
permutation |= SHADERPERMUTATION_TRIPPY;
+ GL_AlphaToCoverage(false);
switch (vid.renderpath)
{
case RENDERPATH_D3D9:
permutation |= SHADERPERMUTATION_TRIPPY;
if (r_trippy.integer)
permutation |= SHADERPERMUTATION_TRIPPY;
+ GL_AlphaToCoverage(false);
switch (vid.renderpath)
{
case RENDERPATH_D3D9:
GL_BlendFunc(GL_ONE, GL_ZERO);
blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
}
+ GL_AlphaToCoverage(false);
}
else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
{
mode = SHADERMODE_DEFERREDGEOMETRY;
GL_BlendFunc(GL_ONE, GL_ZERO);
blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
+ GL_AlphaToCoverage(false);
}
else if (rsurfacepass == RSURFPASS_RTLIGHT)
{
permutation |= SHADERPERMUTATION_REFLECTCUBE;
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
+ GL_AlphaToCoverage(false);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
permutation |= SHADERPERMUTATION_REFLECTCUBE;
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
{
}
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
{
}
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
}
else
{
}
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
}
if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
colormod = dummy_colormod;
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
}
+ GL_AlphaToCoverage(false);
Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
// render surface batch normally
GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
- GL_AlphaTest(true);
RSurf_DrawBatch();
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
- GL_AlphaTest(false);
}
static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
{
// ARB2 GLSL shader path (GFFX5200, Radeon 9500)
R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false);
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
- {
- GL_DepthFunc(GL_EQUAL);
- GL_AlphaTest(true);
- }
RSurf_DrawBatch();
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
- {
- GL_DepthFunc(GL_LEQUAL);
- GL_AlphaTest(false);
- }
}
static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numvertices, int numtriangles, const int *element3i, vec3_t diffusecolor2, vec3_t ambientcolor2)
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;
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"};
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);
{
viddef_mode_t mode;
-#if 0
- // LordHavoc: FIXME: VorteX broke vid_restart with this, it is a mystery why it would ever work, commented out
- // multisampling should set at least 2 samples
- if (vid.support.arb_multisample)
- {
- GL_MultiSampling(false);
- if (vid_multisampling.integer)
- samples = max(2, samples);
- }
-#endif
-
memset(&mode, 0, sizeof(mode));
mode.fullscreen = fullscreen != 0;
mode.width = width;
Cvar_SetValueQuick(&vid_refreshrate, vid.mode.refreshrate);
Cvar_SetValueQuick(&vid_stereobuffer, vid.mode.stereobuffer);
- // activate multisampling
- if (vid_multisampling.integer)
- GL_MultiSampling(true);
+ // LordHavoc: disabled this code because multisampling is on by default if the framebuffer is multisampled
+// // activate multisampling
+// if (vid.mode.samples > 1)
+// GL_MultiSampling(true);
return true;
}