X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=r_shadow.c;h=12da8519697f9a36a7c57870b689fbd4ea6e45a9;hp=66ceaa7ae02eaa434130625eca350f3a6fadbdfb;hb=73a9c0b93b725962fb628075d9457dc36fac9401;hpb=67a5b8dba9431970132086fe1d77e5526d71b23e diff --git a/r_shadow.c b/r_shadow.c index 66ceaa7a..12da8519 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -168,7 +168,7 @@ cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0 cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"}; cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"}; cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"}; -cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"}; +cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1"}; cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.25"}; cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1"}; cvar_t r_shadow_lightattenuationpower = {0, "r_shadow_lightattenuationpower", "0.5"}; @@ -176,12 +176,12 @@ cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "1 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1"}; cvar_t r_shadow_portallight = {0, "r_shadow_portallight", "1"}; cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "1000000"}; -cvar_t r_shadow_realtime_dlight = {0, "r_shadow_realtime_dlight", "1"}; -cvar_t r_shadow_realtime_dlight_shadows = {0, "r_shadow_realtime_dlight_shadows", "0"}; -cvar_t r_shadow_realtime_world = {0, "r_shadow_realtime_world", "0"}; -cvar_t r_shadow_realtime_world_dlightshadows = {0, "r_shadow_realtime_world_dlightshadows", "1"}; -cvar_t r_shadow_realtime_world_lightmaps = {0, "r_shadow_realtime_world_lightmaps", "0"}; -cvar_t r_shadow_realtime_world_shadows = {0, "r_shadow_realtime_world_shadows", "1"}; +cvar_t r_shadow_realtime_dlight = {CVAR_SAVE, "r_shadow_realtime_dlight", "1"}; +cvar_t r_shadow_realtime_dlight_shadows = {CVAR_SAVE, "r_shadow_realtime_dlight_shadows", "0"}; +cvar_t r_shadow_realtime_world = {CVAR_SAVE, "r_shadow_realtime_world", "0"}; +cvar_t r_shadow_realtime_world_dlightshadows = {CVAR_SAVE, "r_shadow_realtime_world_dlightshadows", "1"}; +cvar_t r_shadow_realtime_world_lightmaps = {CVAR_SAVE, "r_shadow_realtime_world_lightmaps", "0"}; +cvar_t r_shadow_realtime_world_shadows = {CVAR_SAVE, "r_shadow_realtime_world_shadows", "1"}; cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"}; cvar_t r_shadow_shadow_polygonfactor = {0, "r_shadow_shadow_polygonfactor", "0"}; cvar_t r_shadow_shadow_polygonoffset = {0, "r_shadow_shadow_polygonoffset", "1"}; @@ -503,8 +503,9 @@ void R_Shadow_PrepareShadowMark(int numtris) int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, float projectdistance, int numshadowmarktris, const int *shadowmarktris) { int i, j, tris = 0, vr[3], t, outvertices = 0; - const int *e, *n; float f, temp[3]; + const int *e, *n; + const float *v; if (maxvertexupdate < innumvertices) { @@ -525,10 +526,12 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int * memset(vertexremap, 0, maxvertexupdate * sizeof(int)); } + for (i = 0;i < numshadowmarktris;i++) + shadowmark[shadowmarktris[i]] = shadowmarkcount; + for (i = 0;i < numshadowmarktris;i++) { t = shadowmarktris[i]; - shadowmark[t] = shadowmarkcount; e = inelement3i + t * 3; // make sure the vertices are created for (j = 0;j < 3;j++) @@ -537,14 +540,24 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int * { vertexupdate[e[j]] = vertexupdatenum; vertexremap[e[j]] = outvertices; - VectorSubtract(invertex3f + e[j] * 3, projectorigin, temp); + v = invertex3f + e[j] * 3; + // project one copy of the vertex to the sphere radius of the light + // (FIXME: would projecting it to the light box be better?) + VectorSubtract(v, projectorigin, temp); f = projectdistance / VectorLength(temp); - VectorCopy(invertex3f + e[j] * 3, outvertex3f); + VectorCopy(v, outvertex3f); VectorMA(projectorigin, f, temp, (outvertex3f + 3)); outvertex3f += 6; outvertices += 2; } } + } + + for (i = 0;i < numshadowmarktris;i++) + { + t = shadowmarktris[i]; + e = inelement3i + t * 3; + n = inneighbor3i + t * 3; // output the front and back triangles outelement3i[0] = vertexremap[e[0]]; outelement3i[1] = vertexremap[e[1]]; @@ -554,13 +567,6 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int * outelement3i[5] = vertexremap[e[0]] + 1; outelement3i += 6; tris += 2; - } - - for (i = 0;i < numshadowmarktris;i++) - { - t = shadowmarktris[i]; - e = inelement3i + t * 3; - n = inneighbor3i + t * 3; // output the sides (facing outward from this triangle) if (shadowmark[n[0]] != shadowmarkcount) { @@ -624,39 +630,41 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, R_Shadow_RenderVolume(outverts, tris, varray_vertex3f2, shadowelements); } -void R_Shadow_VolumeFromBox(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, const vec3_t mins, const vec3_t maxs) +void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, vec3_t lightmins, vec3_t lightmaxs, vec3_t surfacemins, vec3_t surfacemaxs) { - int i; + int t, tend; + const int *e; const float *v[3]; - - // check which triangles are facing the , and then output - // triangle elements and vertices... by clever use of elements we - // can construct the whole shadow from the unprojected vertices and - // the projected vertices - - // identify lit faces within the bounding box - R_Shadow_PrepareShadowMark(numtris); - for (i = 0;i < numtris;i++) + if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs)) + return; + tend = firsttriangle + numtris; + if (surfacemins[0] >= lightmins[0] && surfacemaxs[0] <= lightmaxs[0] + && surfacemins[1] >= lightmins[1] && surfacemaxs[1] <= lightmaxs[1] + && surfacemins[2] >= lightmins[2] && surfacemaxs[2] <= lightmaxs[2]) { - v[0] = invertex3f + elements[i*3+0] * 3; - v[1] = invertex3f + elements[i*3+1] * 3; - v[2] = invertex3f + elements[i*3+2] * 3; - if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]) && maxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && mins[0] < max(v[0][0], max(v[1][0], v[2][0])) && maxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && mins[1] < max(v[0][1], max(v[1][1], v[2][1])) && maxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && mins[2] < max(v[0][2], max(v[1][2], v[2][2]))) - shadowmarklist[numshadowmark++] = i; + // surface box entirely inside light box, no box cull + for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3) + if (PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3)) + shadowmarklist[numshadowmark++] = t; + } + else + { + // surface box not entirely inside light box, cull each triangle + for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3) + { + v[0] = invertex3f + e[0] * 3; + v[1] = invertex3f + e[1] * 3; + v[2] = invertex3f + e[2] * 3; + if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]) + && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) + && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) + && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) + && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) + && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) + && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2]))) + shadowmarklist[numshadowmark++] = t; + } } - R_Shadow_VolumeFromList(numverts, numtris, invertex3f, elements, neighbors, projectorigin, projectdistance, numshadowmark, shadowmarklist); -} - -void R_Shadow_VolumeFromSphere(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, float radius) -{ - vec3_t mins, maxs; - mins[0] = projectorigin[0] - radius; - mins[1] = projectorigin[1] - radius; - mins[2] = projectorigin[2] - radius; - maxs[0] = projectorigin[0] + radius; - maxs[1] = projectorigin[1] + radius; - maxs[2] = projectorigin[2] + radius; - R_Shadow_VolumeFromBox(numverts, numtris, invertex3f, elements, neighbors, projectorigin, projectdistance, mins, maxs); } void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *vertex3f, const int *element3i) @@ -1290,6 +1298,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements bumptexture = r_shadow_blankbumptexture; if (!glosstexture) glosstexture = r_shadow_blankglosstexture; + // FIXME: support EF_NODEPTHTEST GL_DepthMask(false); GL_DepthTest(true); if (gl_dot3arb && gl_texturecubemap && gl_combine.integer && gl_stencil) @@ -2020,7 +2029,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) int i, shadow; entity_render_t *ent; float f; - vec3_t relativelightorigin, relativeeyeorigin, lightcolor; + vec3_t relativelightorigin, relativeeyeorigin, lightcolor, lightcolor2; rtexture_t *cubemaptexture; matrix4x4_t matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz; int numclusters, numsurfaces; @@ -2103,23 +2112,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) } */ -#if 1 - shadow = rtlight->shadow && (rtlight->isstatic ? r_shadow_realtime_world_shadows.integer : (r_shadow_realtime_world.integer ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer)); -#else - shadow = false; - if (rtlight->shadow) - { - if (rtlight->isstatic) - shadow = r_shadow_realtime_world_shadows.integer; - else - { - if (r_shadow_realtime_world.integer) - shadow = r_shadow_realtime_world_dlightshadows.integer; - else - shadow = r_shadow_realtime_dlight_shadows.integer; - } - } -#endif + shadow = rtlight->shadow && (rtlight->isstatic ? r_rtworldshadows : r_rtdlightshadows); if (shadow && (gl_stencil || visiblevolumes)) { @@ -2187,7 +2180,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) R_Shadow_Stage_Light(shadow && gl_stencil); ent = &cl_entities[0].render; - if (ent->model && ent->model->DrawLight) + if (ent->model && ent->model->DrawLight && (ent->flags & RENDER_LIGHT)) { Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin); Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin); @@ -2208,14 +2201,17 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - if (ent->visframe == r_framecount && BoxesOverlap(ent->mins, ent->maxs, cullmins, cullmaxs) && ent->model && ent->model->DrawLight && (ent->flags & RENDER_LIGHT)) + // can't draw transparent entity lighting here because + // 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); Matrix4x4_Transform(&ent->inversematrix, rtlight->shadoworigin, relativelightorigin); Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin); Matrix4x4_Concat(&matrix_modeltolight, &rtlight->matrix_worldtolight, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &rtlight->matrix_worldtoattenuationxyz, &ent->matrix); Matrix4x4_Concat(&matrix_modeltoattenuationz, &rtlight->matrix_worldtoattenuationz, &ent->matrix); - ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, ent->model->nummodelsurfaces, ent->model->surfacelist); + ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rtlight->radius, lightcolor2, &matrix_modeltolight, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz, cubemaptexture, ent->model->nummodelsurfaces, ent->model->surfacelist); } } } @@ -2244,7 +2240,7 @@ void R_ShadowVolumeLighting(int visiblevolumes) } else R_Shadow_Stage_Begin(); - if (r_shadow_realtime_world.integer) + if (r_rtworld) { if (r_shadow_debuglight.integer >= 0) { @@ -2256,7 +2252,7 @@ void R_ShadowVolumeLighting(int visiblevolumes) for (lnum = 0, light = r_shadow_worldlightchain;light;lnum++, light = light->next) R_DrawRTLight(&light->rtlight, visiblevolumes); } - if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) + if (r_rtdlight) for (lnum = 0, light = r_dlight;lnum < r_numdlights;lnum++, light++) R_DrawRTLight(&light->rtlight, visiblevolumes); @@ -2387,21 +2383,25 @@ void R_Shadow_FreeCubemaps(void) R_FreeTexturePool(&r_shadow_filters_texturepool); } -void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname) +dlight_t *R_Shadow_NewWorldLight(void) { dlight_t *light; - - if (radius < 15 || DotProduct(color, color) < 0.03) - { - Con_Print("R_Shadow_NewWorldLight: refusing to create a light too small/dim\n"); - return; - } - light = Mem_Alloc(r_shadow_mempool, sizeof(dlight_t)); + light->next = r_shadow_worldlightchain; + r_shadow_worldlightchain = light; + return light; +} + +void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname) +{ VectorCopy(origin, light->origin); - VectorCopy(angles, light->angles); - VectorCopy(color, light->color); - light->radius = radius; + light->angles[0] = angles[0] - 360 * floor(angles[0] / 360); + light->angles[1] = angles[1] - 360 * floor(angles[1] / 360); + light->angles[2] = angles[2] - 360 * floor(angles[2] / 360); + light->color[0] = max(color[0], 0); + light->color[1] = max(color[1], 0); + light->color[2] = max(color[2], 0); + light->radius = max(radius, 0); light->style = style; if (light->style < 0 || light->style >= MAX_LIGHTSTYLES) { @@ -2410,11 +2410,10 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra } light->shadow = shadowenable; light->corona = corona; - if (cubemapname && cubemapname[0] && strlen(cubemapname) < sizeof(light->cubemapname)) - strcpy(light->cubemapname, cubemapname); + if (!cubemapname) + cubemapname = ""; + strlcpy(light->cubemapname, cubemapname, strlen(light->cubemapname)); Matrix4x4_CreateFromQuakeEntity(&light->matrix, light->origin[0], light->origin[1], light->origin[2], light->angles[0], light->angles[1], light->angles[2], 1); - light->next = r_shadow_worldlightchain; - r_shadow_worldlightchain = light; R_RTLight_UpdateFromDLight(&light->rtlight, light, true); } @@ -2479,8 +2478,8 @@ void R_Shadow_DrawLightSprites(void) lighttextures[i] = pic->tex; } - for (light = r_shadow_worldlightchain;light;light = light->next) - R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSpriteCallback, light, ((int) light) % 5); + for (i = 0, light = r_shadow_worldlightchain;light;i++, light = light->next) + R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSpriteCallback, light, i % 5); R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursorCallback, NULL, 0); } @@ -2570,7 +2569,7 @@ void R_Shadow_LoadWorldLights(void) } VectorScale(color, r_editlights_rtlightscolorscale.value, color); radius *= r_editlights_rtlightssizescale.value; - R_Shadow_NewWorldLight(origin, angles, color, radius, corona, style, shadow, cubemapname); + R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, corona, style, shadow, cubemapname); s++; n++; } @@ -2600,7 +2599,10 @@ void R_Shadow_SaveWorldLights(void) buf = NULL; for (light = r_shadow_worldlightchain;light;light = light->next) { - sprintf(line, "%s%f %f %f %f %f %f %f %d %s %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style, light->cubemapname[0] ? light->cubemapname : "\"\"", light->corona, light->angles[0], light->angles[1], light->angles[2]); + if (light->cubemapname[0] || light->corona || light->angles[0] || light->angles[1] || light->angles[2]) + sprintf(line, "%s%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style, light->cubemapname, light->corona, light->angles[0], light->angles[1], light->angles[2]); + else + sprintf(line, "%s%f %f %f %f %f %f %f %d\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style); if (bufchars + (int) strlen(line) > bufmaxchars) { bufmaxchars = bufchars + strlen(line) + 2048; @@ -2660,7 +2662,7 @@ void R_Shadow_LoadLightsFile(void) radius = sqrt(DotProduct(color, color) / (falloff * falloff * 8192.0f * 8192.0f)); radius = bound(15, radius, 4096); VectorScale(color, (2.0f / (8388608.0f)), color); - R_Shadow_NewWorldLight(origin, vec3_origin, color, radius, 0, style, true, NULL); + R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, vec3_origin, color, radius, 0, style, true, NULL); s++; n++; } @@ -2877,7 +2879,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void) } VectorAdd(origin, originhack, origin); if (radius >= 1) - R_Shadow_NewWorldLight(origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va("cubemaps/%i", skin) : NULL); + R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va("cubemaps/%i", skin) : NULL); } } @@ -2968,7 +2970,7 @@ void R_Shadow_EditLights_Spawn_f(void) return; } color[0] = color[1] = color[2] = 1; - R_Shadow_NewWorldLight(r_editlights_cursorlocation, vec3_origin, color, 200, 0, 0, true, NULL); + R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), r_editlights_cursorlocation, vec3_origin, color, 200, 0, 0, true, NULL); } void R_Shadow_EditLights_Edit_f(void) @@ -3185,9 +3187,7 @@ void R_Shadow_EditLights_Edit_f(void) Con_Printf("Cubemap: %s\n", r_shadow_selectedlight->cubemapname); return; } - R_Shadow_FreeWorldLight(r_shadow_selectedlight); - r_shadow_selectedlight = NULL; - R_Shadow_NewWorldLight(origin, angles, color, radius, corona, style, shadows, cubemapname); + R_Shadow_UpdateWorldLight(r_shadow_selectedlight, origin, angles, color, radius, corona, style, shadows, cubemapname); } void R_Shadow_EditLights_EditAll_f(void) @@ -3241,9 +3241,7 @@ void R_Shadow_EditLights_ToggleShadow_f(void) Con_Print("No selected light.\n"); return; } - R_Shadow_NewWorldLight(r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname); - R_Shadow_FreeWorldLight(r_shadow_selectedlight); - r_shadow_selectedlight = NULL; + R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname); } void R_Shadow_EditLights_ToggleCorona_f(void) @@ -3258,9 +3256,7 @@ void R_Shadow_EditLights_ToggleCorona_f(void) Con_Print("No selected light.\n"); return; } - R_Shadow_NewWorldLight(r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname); - R_Shadow_FreeWorldLight(r_shadow_selectedlight); - r_shadow_selectedlight = NULL; + R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname); } void R_Shadow_EditLights_Remove_f(void) @@ -3352,8 +3348,6 @@ void R_Shadow_EditLights_CopyInfo_f(void) void R_Shadow_EditLights_PasteInfo_f(void) { - vec3_t origin; - VectorCopy(r_shadow_selectedlight->origin, origin); if (!r_editlights.integer) { Con_Print("Cannot paste light info when not in editing mode. Set r_editlights to 1.\n"); @@ -3364,9 +3358,7 @@ void R_Shadow_EditLights_PasteInfo_f(void) Con_Print("No selected light.\n"); return; } - R_Shadow_FreeWorldLight(r_shadow_selectedlight); - r_shadow_selectedlight = NULL; - R_Shadow_NewWorldLight(origin, r_shadow_bufferlight.angles, r_shadow_bufferlight.color, r_shadow_bufferlight.radius, r_shadow_bufferlight.corona, r_shadow_bufferlight.style, r_shadow_bufferlight.shadow, r_shadow_bufferlight.cubemapname); + R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_bufferlight.angles, r_shadow_bufferlight.color, r_shadow_bufferlight.radius, r_shadow_bufferlight.corona, r_shadow_bufferlight.style, r_shadow_bufferlight.shadow, r_shadow_bufferlight.cubemapname); } void R_Shadow_EditLights_Init(void)