]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
Fix PRVM_ValueString and PRVM_UglyValueString to check for out of bounds
[xonotic/darkplaces.git] / r_shadow.c
index 527a0bef559537e634a6e79237f16c7adc37df63..b866f8c01083928be426e7c83cc095de5a0ad5a5 100644 (file)
@@ -230,7 +230,7 @@ cvar_t r_shadow_bouncegrid_static_quality = { CVAR_SAVE, "r_shadow_bouncegrid_st
 cvar_t r_shadow_bouncegrid_static_spacing = {CVAR_SAVE, "r_shadow_bouncegrid_static_spacing", "64", "unit size of bouncegrid pixel when in static mode"};
 cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "0", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
 cvar_t r_coronas_occlusionsizescale = {CVAR_SAVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksum the proportion of hidden pixels controls corona intensity"};
-cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "0", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility) - bad performance (synchronous rendering) - worse on multi-gpu!"};
+cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "0", "fades coronas according to visibility"};
 cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
 cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"};
 cvar_t r_editlights_cursordistance = {0, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
@@ -563,20 +563,22 @@ static void r_shadow_shutdown(void)
 static void r_shadow_newmap(void)
 {
        r_shadow_bouncegrid_state.highpixels = NULL;
-       if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
-       if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
-       if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
-       if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
-       if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL;
+       if (r_shadow_bouncegrid_state.blurpixels[0]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; }
+       if (r_shadow_bouncegrid_state.blurpixels[1]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; }
+       if (r_shadow_bouncegrid_state.u8pixels) { Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; }
+       if (r_shadow_bouncegrid_state.fp16pixels) { Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; }
+       if (r_shadow_bouncegrid_state.splatpaths) { Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL; }
+
        r_shadow_bouncegrid_state.maxsplatpaths = 0;
-       if (r_shadow_bouncegrid_state.texture)    R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL;
-       if (r_shadow_lightcorona)                 R_SkinFrame_MarkUsed(r_shadow_lightcorona);
-       if (r_editlights_sprcursor)               R_SkinFrame_MarkUsed(r_editlights_sprcursor);
-       if (r_editlights_sprlight)                R_SkinFrame_MarkUsed(r_editlights_sprlight);
-       if (r_editlights_sprnoshadowlight)        R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight);
-       if (r_editlights_sprcubemaplight)         R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight);
-       if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight);
-       if (r_editlights_sprselection)            R_SkinFrame_MarkUsed(r_editlights_sprselection);
+
+       if (r_shadow_bouncegrid_state.texture)    { R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL; }
+       if (r_shadow_lightcorona)                 { R_SkinFrame_MarkUsed(r_shadow_lightcorona); }
+       if (r_editlights_sprcursor)               { R_SkinFrame_MarkUsed(r_editlights_sprcursor); }
+       if (r_editlights_sprlight)                { R_SkinFrame_MarkUsed(r_editlights_sprlight); }
+       if (r_editlights_sprnoshadowlight)        { R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight); }
+       if (r_editlights_sprcubemaplight)         { R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight); }
+       if (r_editlights_sprcubemapnoshadowlight) { R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight); }
+       if (r_editlights_sprselection)            { R_SkinFrame_MarkUsed(r_editlights_sprselection); }
        if (strncmp(cl.worldname, r_shadow_mapname, sizeof(r_shadow_mapname)))
                R_Shadow_EditLights_Reload_f();
 }
@@ -1973,13 +1975,16 @@ static void R_Shadow_BounceGrid_UpdateSpacing(void)
        numpixels = r_shadow_bouncegrid_state.pixelsperband*r_shadow_bouncegrid_state.pixelbands;
        if (r_shadow_bouncegrid_state.numpixels != numpixels)
        {
-               if (r_shadow_bouncegrid_state.texture) R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL;
+               if (r_shadow_bouncegrid_state.texture) { R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL; }
+
                r_shadow_bouncegrid_state.highpixels = NULL;
-               if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
-               if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
-               if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
-               if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
-               if (r_shadow_bouncegrid_state.splatpaths) Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL;
+
+               if (r_shadow_bouncegrid_state.blurpixels[0]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; }
+               if (r_shadow_bouncegrid_state.blurpixels[1]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; }
+               if (r_shadow_bouncegrid_state.u8pixels) { Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; }
+               if (r_shadow_bouncegrid_state.fp16pixels) { Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; }
+               if (r_shadow_bouncegrid_state.splatpaths) { Mem_Free(r_shadow_bouncegrid_state.splatpaths); r_shadow_bouncegrid_state.splatpaths = NULL; }
+
                r_shadow_bouncegrid_state.maxsplatpaths = 0;
                r_shadow_bouncegrid_state.numpixels = numpixels;
        }
@@ -2923,7 +2928,7 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures
        VectorMultiply(specularcolor, rsurface.rtlight->currentcolor, specularcolor);
        if (VectorLength2(ambientcolor) + VectorLength2(diffusecolor) + VectorLength2(specularcolor) < (1.0f / 1048576.0f))
                return;
-       negated = (rsurface.rtlight->currentcolor[0] + rsurface.rtlight->currentcolor[1] + rsurface.rtlight->currentcolor[2] < 0) && vid.support.ext_blend_subtract;
+       negated = (rsurface.rtlight->currentcolor[0] + rsurface.rtlight->currentcolor[1] + rsurface.rtlight->currentcolor[2] < 0);
        if(negated)
        {
                VectorNegate(ambientcolor, ambientcolor);
@@ -4429,7 +4434,7 @@ static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequer
 {
        float zdist;
        vec3_t centerorigin;
-#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
+#ifndef USE_GLES2
        float vertex3f[12];
 #endif
        // if it's too close, skip it
@@ -4449,21 +4454,21 @@ static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequer
                {
                case RENDERPATH_GL32:
                case RENDERPATH_GLES2:
-#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
+#ifndef USE_GLES2
                        CHECKGLERROR
                        // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
-                       qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
+                       qglBeginQuery(GL_SAMPLES_PASSED, rtlight->corona_queryindex_allpixels);
                        GL_DepthFunc(GL_ALWAYS);
                        R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
                        R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
                        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
-                       qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
+                       qglEndQuery(GL_SAMPLES_PASSED);
                        GL_DepthFunc(GL_LEQUAL);
-                       qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
+                       qglBeginQuery(GL_SAMPLES_PASSED, rtlight->corona_queryindex_visiblepixels);
                        R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
                        R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
                        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
-                       qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
+                       qglEndQuery(GL_SAMPLES_PASSED);
                        CHECKGLERROR
 #endif
                        break;
@@ -4478,7 +4483,6 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
 {
        vec3_t color;
        unsigned int occlude = 0;
-       GLint allpixels = 0, visiblepixels = 0;
 
        // now we have to check the query result
        if (rtlight->corona_queryindex_visiblepixels)
@@ -4487,31 +4491,22 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                {
                case RENDERPATH_GL32:
                case RENDERPATH_GLES2:
-#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
-                       // See if we can use the GPU-side method to prevent implicit sync
-                       if (vid.support.arb_query_buffer_object) {
+#ifndef USE_GLES2
+                       // store the pixel counts into a uniform buffer for the shader to
+                       // use - we'll never know the results on the cpu without
+                       // synchronizing and we don't want that
 #define BUFFER_OFFSET(i)    ((GLint *)((unsigned char*)NULL + (i)))
-                               if (!r_shadow_occlusion_buf) {
-                                       qglGenBuffers(1, &r_shadow_occlusion_buf);
-                                       qglBindBuffer(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
-                                       qglBufferData(GL_QUERY_BUFFER_ARB, 8, NULL, GL_DYNAMIC_COPY);
-                               } else {
-                                       qglBindBuffer(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
-                               }
-                               qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(0));
-                               qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(4));
-                               qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf);
-                               occlude = MATERIALFLAG_OCCLUDE;
-                               cscale *= rtlight->corona_visibility;
-                               CHECKGLERROR
-                               break;
+                       if (!r_shadow_occlusion_buf) {
+                               qglGenBuffers(1, &r_shadow_occlusion_buf);
+                               qglBindBuffer(GL_QUERY_BUFFER, r_shadow_occlusion_buf);
+                               qglBufferData(GL_QUERY_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
+                       } else {
+                               qglBindBuffer(GL_QUERY_BUFFER, r_shadow_occlusion_buf);
                        }
-                       CHECKGLERROR
-                       qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
-                       qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
-                       if (visiblepixels < 1 || allpixels < 1)
-                               return;
-                       rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
+                       qglGetQueryObjectiv(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT, BUFFER_OFFSET(0));
+                       qglGetQueryObjectiv(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT, BUFFER_OFFSET(4));
+                       qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf);
+                       occlude = MATERIALFLAG_OCCLUDE;
                        cscale *= rtlight->corona_visibility;
                        CHECKGLERROR
                        break;
@@ -4529,7 +4524,7 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
        if (VectorLength(color) > (1.0f / 256.0f))
        {
                float vertex3f[12];
-               qboolean negated = (color[0] + color[1] + color[2] < 0) && vid.support.ext_blend_subtract;
+               qboolean negated = (color[0] + color[1] + color[2] < 0);
                if(negated)
                {
                        VectorNegate(color, color);
@@ -4560,16 +4555,14 @@ void R_Shadow_DrawCoronas(void)
 
        range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
 
-       // check occlusion of coronas
-       // use GL_ARB_occlusion_query if available
-       // otherwise use raytraces
+       // check occlusion of coronas, using occlusion queries or raytraces
        r_numqueries = 0;
        switch (vid.renderpath)
        {
        case RENDERPATH_GL32:
        case RENDERPATH_GLES2:
-               usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
-#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
+               usequery = r_coronas_occlusionquery.integer;
+#ifndef USE_GLES2
                if (usequery)
                {
                        GL_ColorMask(0,0,0,0);
@@ -4580,7 +4573,7 @@ void R_Shadow_DrawCoronas(void)
                                r_maxqueries = ((unsigned int)range + r_refdef.scene.numlights) * 4;
                                r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
                                CHECKGLERROR
-                               qglGenQueriesARB(r_maxqueries - i, r_queries + i);
+                               qglGenQueries(r_maxqueries - i, r_queries + i);
                                CHECKGLERROR
                        }
                        RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);