]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
fixed up a number of nudging bugs in Collision_TraceLineTriangleFloat
[xonotic/darkplaces.git] / r_shadow.c
index f495c7189b2213cbe4d45551e7ca7968278e7a2b..c447789acd0a02fc37adc589532b62c1a20c8986 100644 (file)
@@ -199,10 +199,6 @@ cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsi
 cvar_t r_editlights_rtlightssizescale = {CVAR_SAVE, "r_editlights_rtlightssizescale", "0.7"};
 cvar_t r_editlights_rtlightscolorscale = {CVAR_SAVE, "r_editlights_rtlightscolorscale", "2"};
 
-int c_rt_lights, c_rt_clears, c_rt_scissored;
-int c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris;
-int c_rtcached_shadowmeshes, c_rtcached_shadowtris;
-
 float r_shadow_attenpower, r_shadow_attenscale;
 
 rtlight_t *r_shadow_compilingrtlight;
@@ -226,6 +222,10 @@ cubemapinfo_t;
 static int numcubemaps;
 static cubemapinfo_t cubemaps[MAX_CUBEMAPS];
 
+GLhandleARB r_shadow_program_light_diffusegloss = 0;
+GLhandleARB r_shadow_program_light_diffuse = 0;
+GLhandleARB r_shadow_program_light_gloss = 0;
+
 void R_Shadow_UncompileWorldLights(void);
 void R_Shadow_ClearWorldLights(void);
 void R_Shadow_SaveWorldLights(void);
@@ -237,6 +237,16 @@ void R_Shadow_ValidateCvars(void);
 static void R_Shadow_MakeTextures(void);
 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, dlight_t *light);
 
+// beginnings of GL_ARB_shaders support, not done yet
+GLhandleARB GL_Backend_LoadProgram(const char *vertexshaderfilename, const char *fragmentshaderfilename)
+{
+       return 0;
+}
+
+void GL_Backend_FreeProgram(GLhandleARB prog)
+{
+}
+
 void r_shadow_start(void)
 {
        // allocate vertex processing arrays
@@ -268,11 +278,23 @@ void r_shadow_start(void)
        r_shadow_buffer_numsurfacepvsbytes = 0;
        r_shadow_buffer_surfacepvs = NULL;
        r_shadow_buffer_surfacelist = NULL;
+       if (gl_support_fragment_shader)
+       {
+               r_shadow_program_light_diffusegloss = GL_Backend_LoadProgram("glsl/diffusegloss.vert", "glsl/diffusegloss.frag");
+               r_shadow_program_light_diffuse = GL_Backend_LoadProgram("glsl/diffuse.vert", "glsl/diffuse.frag");
+               r_shadow_program_light_gloss = GL_Backend_LoadProgram("glsl/gloss.vert", "glsl/gloss.frag");
+       }
 }
 
 void r_shadow_shutdown(void)
 {
        R_Shadow_UncompileWorldLights();
+       GL_Backend_FreeProgram(r_shadow_program_light_diffusegloss);
+       r_shadow_program_light_diffusegloss = 0;
+       GL_Backend_FreeProgram(r_shadow_program_light_diffuse);
+       r_shadow_program_light_diffuse = 0;
+       GL_Backend_FreeProgram(r_shadow_program_light_gloss);
+       r_shadow_program_light_gloss = 0;
        numcubemaps = 0;
        r_shadow_normalcubetexture = NULL;
        r_shadow_attenuation2dtexture = NULL;
@@ -856,10 +878,6 @@ void R_Shadow_Stage_Begin(void)
        qglEnable(GL_CULL_FACE);
        GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
        r_shadowstage = SHADOWSTAGE_NONE;
-
-       c_rt_lights = c_rt_clears = c_rt_scissored = 0;
-       c_rt_shadowmeshes = c_rt_shadowtris = c_rt_lightmeshes = c_rt_lighttris = 0;
-       c_rtcached_shadowmeshes = c_rtcached_shadowtris = 0;
 }
 
 void R_Shadow_Stage_ShadowVolumes(void)
@@ -1507,15 +1525,15 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        VectorScale(lightcolor, colorscale, color2);
+                       GL_LockArrays(0, numverts);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
                                GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-                               GL_LockArrays(0, numverts);
                                R_Mesh_Draw(numverts, numtriangles, elements);
-                               GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
                        }
+                       GL_LockArrays(0, 0);
                }
                if (diffusescale)
                {
@@ -1783,15 +1801,15 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        VectorScale(lightcolor, colorscale, color2);
+                       GL_LockArrays(0, numverts);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
                                GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-                               GL_LockArrays(0, numverts);
                                R_Mesh_Draw(numverts, numtriangles, elements);
-                               GL_LockArrays(0, 0);
                                c_rt_lightmeshes++;
                                c_rt_lighttris += numtriangles;
                        }
+                       GL_LockArrays(0, 0);
                }
                if (specularscale && (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture)))
                {
@@ -2008,20 +2026,20 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
 #endif
                                        }
                                }
+                               R_Mesh_State(&m);
+                               GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
+                               GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
+                               VectorScale(lightcolor, colorscale, color2);
+                               GL_LockArrays(0, numverts);
+                               for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
+                               {
+                                       GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
+                                       R_Mesh_Draw(numverts, numtriangles, elements);
+                                       c_rt_lightmeshes++;
+                                       c_rt_lighttris += numtriangles;
+                               }
+                               GL_LockArrays(0, 0);
                        }
-                       R_Mesh_State(&m);
-                       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
-                       GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
-                       VectorScale(lightcolor, colorscale, color2);
-                       GL_LockArrays(0, numverts);
-                       for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
-                       {
-                               GL_Color(bound(0, color2[0], 1), bound(0, color2[1], 1), bound(0, color2[2], 1), 1);
-                               R_Mesh_Draw(numverts, numtriangles, elements);
-                               c_rt_lightmeshes++;
-                               c_rt_lighttris += numtriangles;
-                       }
-                       GL_LockArrays(0, 0);
                }
        }
        else
@@ -2058,6 +2076,10 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
 #endif
                                }
                        }
+                       if (r_textureunits.integer >= 3)
+                               m.pointer_color = NULL;
+                       else
+                               m.pointer_color = varray_color4f;
                        R_Mesh_State(&m);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
@@ -2065,20 +2087,11 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                color[1] = bound(0, color2[1], 1);
                                color[2] = bound(0, color2[2], 1);
                                if (r_textureunits.integer >= 3)
-                               {
                                        GL_Color(color[0], color[1], color[2], 1);
-                                       m.pointer_color = NULL;
-                               }
                                else if (r_textureunits.integer >= 2)
-                               {
                                        R_Shadow_VertexNoShadingWithZAttenuation(numverts, vertex3f, color, matrix_modeltolight);
-                                       m.pointer_color = varray_color4f;
-                               }
                                else
-                               {
                                        R_Shadow_VertexNoShadingWithXYZAttenuation(numverts, vertex3f, color, matrix_modeltolight);
-                                       m.pointer_color = varray_color4f;
-                               }
                                GL_LockArrays(0, numverts);
                                R_Mesh_Draw(numverts, numtriangles, elements);
                                GL_LockArrays(0, 0);
@@ -2185,7 +2198,7 @@ void R_RTLight_UpdateFromDLight(rtlight_t *rtlight, const dlight_t *light, int i
 
        rtlight->lightmap_cullradius = bound(0, rtlight->radius, 2048.0f);
        rtlight->lightmap_cullradius2 = rtlight->lightmap_cullradius * rtlight->lightmap_cullradius;
-       VectorScale(rtlight->color, rtlight->radius * d_lightstylevalue[rtlight->style] * 0.125f, rtlight->lightmap_light);
+       VectorScale(rtlight->color, rtlight->radius * (rtlight->style >= 0 ? d_lightstylevalue[rtlight->style] : 128) * 0.125f, rtlight->lightmap_light);
        rtlight->lightmap_subtract = 1.0f / rtlight->lightmap_cullradius2;
 }
 
@@ -2334,7 +2347,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
        cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
        cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
        cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
-       if (d_lightstylevalue[rtlight->style] <= 0)
+       if (rtlight->style >= 0 && d_lightstylevalue[rtlight->style] <= 0)
                return;
        numclusters = 0;
        clusterlist = NULL;
@@ -2351,16 +2364,16 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                VectorCopy(rtlight->cullmins, cullmins);
                VectorCopy(rtlight->cullmaxs, cullmaxs);
        }
-       else if (cl.worldmodel && cl.worldmodel->GetLightInfo)
+       else if (r_refdef.worldmodel && r_refdef.worldmodel->GetLightInfo)
        {
                // dynamic light, world available and can receive realtime lighting
                // if the light box is offscreen, skip it right away
                if (R_CullBox(cullmins, cullmaxs))
                        return;
                // calculate lit surfaces and clusters
-               R_Shadow_EnlargeClusterBuffer(cl.worldmodel->brush.num_pvsclusters);
-               R_Shadow_EnlargeSurfaceBuffer(cl.worldmodel->nummodelsurfaces); 
-               cl.worldmodel->GetLightInfo(&cl_entities[0].render, rtlight->shadoworigin, rtlight->radius, cullmins, cullmaxs, r_shadow_buffer_clusterlist, r_shadow_buffer_clusterpvs, &numclusters, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces);
+               R_Shadow_EnlargeClusterBuffer(r_refdef.worldmodel->brush.num_pvsclusters);
+               R_Shadow_EnlargeSurfaceBuffer(r_refdef.worldmodel->nummodelsurfaces); 
+               r_refdef.worldmodel->GetLightInfo(&cl_entities[0].render, rtlight->shadoworigin, rtlight->radius, cullmins, cullmaxs, r_shadow_buffer_clusterlist, r_shadow_buffer_clusterpvs, &numclusters, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces);
                clusterlist = r_shadow_buffer_clusterlist;
                clusterpvs = r_shadow_buffer_clusterpvs;
                surfacelist = r_shadow_buffer_surfacelist;
@@ -2381,7 +2394,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
        if (R_Shadow_ScissorForBBox(cullmins, cullmaxs))
                return;
 
-       f = d_lightstylevalue[rtlight->style] * (1.0f / 256.0f);
+       f = (rtlight->style >= 0 ? d_lightstylevalue[rtlight->style] : 128) * (1.0f / 256.0f);
        VectorScale(rtlight->color, f, lightcolor);
        /*
        if (rtlight->selected)
@@ -2440,7 +2453,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                                {
                                        if (!BoxesOverlap(ent->mins, ent->maxs, cullmins, cullmaxs))
                                                continue;
-                                       if (cl.worldmodel != NULL && cl.worldmodel->brush.BoxTouchingPVS != NULL && !cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, clusterpvs, ent->mins, ent->maxs))
+                                       if (r_refdef.worldmodel != NULL && r_refdef.worldmodel->brush.BoxTouchingPVS != NULL && !r_refdef.worldmodel->brush.BoxTouchingPVS(r_refdef.worldmodel, clusterpvs, ent->mins, ent->maxs))
                                                continue;
                                }
                                if (!(ent->flags & RENDER_SHADOW) || !ent->model || !ent->model->DrawShadowVolume)
@@ -2461,6 +2474,9 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                ent = &cl_entities[0].render;
                if (ent->model && ent->model->DrawLight && (ent->flags & RENDER_LIGHT))
                {
+                       lightcolor2[0] = lightcolor[0] * ent->colormod[0] * ent->alpha;
+                       lightcolor2[1] = lightcolor[1] * ent->colormod[1] * ent->alpha;
+                       lightcolor2[2] = lightcolor[2] * ent->colormod[2] * ent->alpha;
                        Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin);
                        Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
                        Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix);
@@ -2470,10 +2486,10 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                        {
                                R_Mesh_Matrix(&ent->matrix);
                                for (mesh = rtlight->static_meshchain_light;mesh;mesh = mesh->next)
-                                       R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, relativeeyeorigin, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, mesh->map_diffuse, mesh->map_normal, mesh->map_specular, cubemaptexture, rtlight->ambientscale, rtlight->diffusescale, rtlight->specularscale);
+                                       R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->vertex3f, mesh->svector3f, mesh->tvector3f, mesh->normal3f, mesh->texcoord2f, relativelightorigin, relativeeyeorigin, lightcolor2, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, mesh->map_diffuse, mesh->map_normal, mesh->map_specular, cubemaptexture, rtlight->ambientscale, rtlight->diffusescale, rtlight->specularscale);
                        }
                        else
-                               ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, rtlight->ambientscale, rtlight->diffusescale, rtlight->specularscale, numsurfaces, surfacelist);
+                               ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor2, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, rtlight->ambientscale, rtlight->diffusescale, rtlight->specularscale, numsurfaces, surfacelist);
                }
                if (r_drawentities.integer)
                {
@@ -2484,7 +2500,9 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes)
                                // transparent meshes are deferred for later
                                if (ent->visframe == r_framecount && BoxesOverlap(ent->mins, ent->maxs, cullmins, cullmaxs) && ent->model && ent->model->DrawLight && (ent->flags & (RENDER_LIGHT | RENDER_TRANSPARENT)) == RENDER_LIGHT)
                                {
-                                       VectorScale(lightcolor, ent->alpha, lightcolor2);
+                                       lightcolor2[0] = lightcolor[0] * ent->colormod[0] * ent->alpha;
+                                       lightcolor2[1] = lightcolor[1] * ent->colormod[1] * ent->alpha;
+                                       lightcolor2[2] = lightcolor[2] * ent->colormod[2] * ent->alpha;
                                        Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin);
                                        Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
                                        Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix);
@@ -2503,7 +2521,7 @@ void R_ShadowVolumeLighting(int visiblevolumes)
        dlight_t *light;
        rmeshstate_t m;
 
-       if (cl.worldmodel && strncmp(cl.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname)))
+       if (r_refdef.worldmodel && strncmp(r_refdef.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname)))
                R_Shadow_EditLights_Reload_f();
 
        if (visiblevolumes)
@@ -2794,12 +2812,12 @@ void R_Shadow_LoadWorldLights(void)
        int n, a, style, shadow, flags;
        char name[MAX_QPATH], cubemapname[MAX_QPATH], *lightsstring, *s, *t;
        float origin[3], radius, color[3], angles[3], corona, coronasizescale, ambientscale, diffusescale, specularscale;
-       if (cl.worldmodel == NULL)
+       if (r_refdef.worldmodel == NULL)
        {
                Con_Print("No map loaded.\n");
                return;
        }
-       FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
+       FS_StripExtension (r_refdef.worldmodel->name, name, sizeof (name));
        strlcat (name, ".rtlights", sizeof (name));
        lightsstring = FS_LoadFile(name, tempmempool, false);
        if (lightsstring)
@@ -2881,12 +2899,12 @@ void R_Shadow_SaveWorldLights(void)
        char line[1024];
        if (!r_shadow_worldlightchain)
                return;
-       if (cl.worldmodel == NULL)
+       if (r_refdef.worldmodel == NULL)
        {
                Con_Print("No map loaded.\n");
                return;
        }
-       FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
+       FS_StripExtension (r_refdef.worldmodel->name, name, sizeof (name));
        strlcat (name, ".rtlights", sizeof (name));
        bufchars = bufmaxchars = 0;
        buf = NULL;
@@ -2927,12 +2945,12 @@ void R_Shadow_LoadLightsFile(void)
        int n, a, style;
        char name[MAX_QPATH], *lightsstring, *s, *t;
        float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
-       if (cl.worldmodel == NULL)
+       if (r_refdef.worldmodel == NULL)
        {
                Con_Print("No map loaded.\n");
                return;
        }
-       FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
+       FS_StripExtension (r_refdef.worldmodel->name, name, sizeof (name));
        strlcat (name, ".lights", sizeof (name));
        lightsstring = FS_LoadFile(name, tempmempool, false);
        if (lightsstring)
@@ -2978,18 +2996,18 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
        float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
        char key[256], value[1024];
 
-       if (cl.worldmodel == NULL)
+       if (r_refdef.worldmodel == NULL)
        {
                Con_Print("No map loaded.\n");
                return;
        }
        // try to load a .ent file first
-       FS_StripExtension (cl.worldmodel->name, key, sizeof (key));
+       FS_StripExtension (r_refdef.worldmodel->name, key, sizeof (key));
        strlcat (key, ".ent", sizeof (key));
        data = entfiledata = FS_LoadFile(key, tempmempool, true);
        // and if that is not found, fall back to the bsp file entity string
        if (!data)
-               data = cl.worldmodel->brush.entities;
+               data = r_refdef.worldmodel->brush.entities;
        if (!data)
                return;
        for (entnum = 0;COM_ParseToken(&data, false) && com_token[0] == '{';entnum++)
@@ -3129,7 +3147,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                        }
                        else if (!strcmp("style", key))
                                style = atoi(value);
-                       else if (cl.worldmodel->type == mod_brushq3)
+                       else if (r_refdef.worldmodel->type == mod_brushq3)
                        {
                                if (!strcmp("scale", key))
                                        lightscale = atof(value);
@@ -3228,9 +3246,9 @@ void R_Shadow_EditLights_Clear_f(void)
 
 void R_Shadow_EditLights_Reload_f(void)
 {
-       if (!cl.worldmodel)
+       if (!r_refdef.worldmodel)
                return;
-       strlcpy(r_shadow_mapname, cl.worldmodel->name, sizeof(r_shadow_mapname));
+       strlcpy(r_shadow_mapname, r_refdef.worldmodel->name, sizeof(r_shadow_mapname));
        R_Shadow_ClearWorldLights();
        R_Shadow_LoadWorldLights();
        if (r_shadow_worldlightchain == NULL)
@@ -3243,7 +3261,7 @@ void R_Shadow_EditLights_Reload_f(void)
 
 void R_Shadow_EditLights_Save_f(void)
 {
-       if (!cl.worldmodel)
+       if (!r_refdef.worldmodel)
                return;
        R_Shadow_SaveWorldLights();
 }