X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=28806317dba62ddf78b7cdda947a11ea96a0baa3;hb=d217d6b9ba9012bc374ac0d44d48422b7b13b755;hp=e348e3e9427b4229ed84b7b51bf90f563cec5a16;hpb=8b26f70d09928dacff04bd9d77fa5bfbe204b50a;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index e348e3e9..28806317 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -156,10 +156,6 @@ cvar_t gl_skyclip = {CF_CLIENT, "gl_skyclip", "4608", "nehahra farclip distance cvar_t r_texture_dds_load = {CF_CLIENT | CF_ARCHIVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"}; cvar_t r_texture_dds_save = {CF_CLIENT | CF_ARCHIVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"}; -cvar_t r_textureunits = {CF_CLIENT, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"}; -static cvar_t gl_combine = {CF_CLIENT | CF_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"}; -static cvar_t r_glsl = {CF_CLIENT | CF_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"}; - cvar_t r_usedepthtextures = {CF_CLIENT | CF_ARCHIVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"}; cvar_t r_viewfbo = {CF_CLIENT | CF_ARCHIVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"}; cvar_t r_rendertarget_debug = {CF_CLIENT, "r_rendertarget_debug", "-1", "replaces the view with the contents of the specified render target (by number - note that these can fluctuate depending on scene)"}; @@ -191,6 +187,7 @@ cvar_t r_glsl_postprocess_uservec2_enable = {CF_CLIENT | CF_ARCHIVE, "r_glsl_pos cvar_t r_glsl_postprocess_uservec3_enable = {CF_CLIENT | CF_ARCHIVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"}; cvar_t r_glsl_postprocess_uservec4_enable = {CF_CLIENT | CF_ARCHIVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"}; cvar_t r_colorfringe = {CF_CLIENT | CF_ARCHIVE, "r_colorfringe", "0", "Chromatic aberration. Values higher than 0.025 will noticeably distort the image"}; +cvar_t r_fxaa = {CF_CLIENT | CF_ARCHIVE, "r_fxaa", "0", "fast approximate anti aliasing"}; cvar_t r_water = {CF_CLIENT | CF_ARCHIVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"}; cvar_t r_water_cameraentitiesonly = {CF_CLIENT | CF_ARCHIVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"}; @@ -247,6 +244,7 @@ cvar_t r_glsl_saturation_redcompensate = {CF_CLIENT | CF_ARCHIVE, "r_glsl_satura cvar_t r_glsl_vertextextureblend_usebothalphas = {CF_CLIENT | CF_ARCHIVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."}; +// FIXME: This cvar would grow to a ridiculous size after several launches and clean exits when used during surface sorting. cvar_t r_framedatasize = {CF_CLIENT | CF_ARCHIVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"}; cvar_t r_buffermegs[R_BUFFERDATA_COUNT] = { @@ -847,9 +845,10 @@ enum SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math) SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines) - SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing + SHADERSTATICPARM_FXAA = 13, ///< fast approximate anti aliasing + SHADERSTATICPARM_COLORFRINGE = 14 ///< colorfringe (chromatic aberration) }; -#define SHADERSTATICPARMS_COUNT 14 +#define SHADERSTATICPARMS_COUNT 15 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT]; static int shaderstaticparms_count = 0; @@ -898,6 +897,8 @@ qbool R_CompileShader_CheckStaticParms(void) R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING); if (r_celoutlines.integer) R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES); + if (r_colorfringe.value) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_COLORFRINGE); return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0; } @@ -926,6 +927,7 @@ static void R_CompileShader_AddStaticParms(unsigned int mode, uint64_t permutati R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING"); R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES"); R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_COLORFRINGE, "USECOLORFRINGE"); } /// information about each possible shader permutation @@ -3066,9 +3068,6 @@ static void gl_main_start(void) { case RENDERPATH_GL32: case RENDERPATH_GLES2: - Cvar_SetValueQuick(&r_textureunits, MAX_TEXTUREUNITS); - Cvar_SetValueQuick(&gl_combine, 1); - Cvar_SetValueQuick(&r_glsl, 1); r_loadnormalmap = true; r_loadgloss = true; r_loadfog = false; @@ -3193,7 +3192,7 @@ static void gl_main_shutdown(void) r_texture_numcubemaps = 0; //r_texture_fogintensity = NULL; memset(&r_fb, 0, sizeof(r_fb)); - R_GLSL_Restart_f(&cmd_client); + R_GLSL_Restart_f(cmd_local); r_glsl_permutation = NULL; memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash)); @@ -3330,8 +3329,6 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_transparent_sortarraysize); Cvar_RegisterVariable(&r_texture_dds_load); Cvar_RegisterVariable(&r_texture_dds_save); - Cvar_RegisterVariable(&r_textureunits); - Cvar_RegisterVariable(&gl_combine); Cvar_RegisterVariable(&r_usedepthtextures); Cvar_RegisterVariable(&r_viewfbo); Cvar_RegisterVariable(&r_rendertarget_debug); @@ -3342,7 +3339,6 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize); Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax); Cvar_RegisterVariable(&r_viewscale_fpsscaling_target); - Cvar_RegisterVariable(&r_glsl); Cvar_RegisterVariable(&r_glsl_deluxemapping); Cvar_RegisterVariable(&r_glsl_offsetmapping); Cvar_RegisterVariable(&r_glsl_offsetmapping_steps); @@ -3363,6 +3359,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable); Cvar_RegisterVariable(&r_celshading); Cvar_RegisterVariable(&r_celoutlines); + Cvar_RegisterVariable(&r_fxaa); Cvar_RegisterVariable(&r_water); Cvar_RegisterVariable(&r_water_cameraentitiesonly); @@ -3442,107 +3439,48 @@ void Render_Init(void) R_Particles_Init(); R_Explosion_Init(); R_LightningBeams_Init(); + CL_MeshEntities_Init(); Mod_RenderInit(); } -int R_CullBox(const vec3_t mins, const vec3_t maxs) +static void R_GetCornerOfBox(vec3_t out, const vec3_t mins, const vec3_t maxs, int signbits) { - int i; - mplane_t *p; - if (r_trippy.integer) - return false; - for (i = 0;i < r_refdef.view.numfrustumplanes;i++) - { - p = r_refdef.view.frustum + i; - switch(p->signbits) - { - default: - case 0: - if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) - return true; - break; - case 1: - if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) - return true; - break; - case 2: - if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) - return true; - break; - case 3: - if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) - return true; - break; - case 4: - if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) - return true; - break; - case 5: - if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) - return true; - break; - case 6: - if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) - return true; - break; - case 7: - if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) - return true; - break; - } - } - return false; + out[0] = ((signbits & 1) ? mins : maxs)[0]; + out[1] = ((signbits & 2) ? mins : maxs)[1]; + out[2] = ((signbits & 4) ? mins : maxs)[2]; } -int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes) +static qbool _R_CullBox(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes, int ignore) { int i; const mplane_t *p; + vec3_t corner; if (r_trippy.integer) return false; for (i = 0;i < numplanes;i++) { + if(i == ignore) + continue; p = planes + i; - switch(p->signbits) - { - default: - case 0: - if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) - return true; - break; - case 1: - if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) - return true; - break; - case 2: - if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) - return true; - break; - case 3: - if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) - return true; - break; - case 4: - if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) - return true; - break; - case 5: - if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) - return true; - break; - case 6: - if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) - return true; - break; - case 7: - if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) - return true; - break; - } + R_GetCornerOfBox(corner, mins, maxs, p->signbits); + if (DotProduct(p->normal, corner) < p->dist) + return true; } return false; } +qbool R_CullFrustum(const vec3_t mins, const vec3_t maxs) +{ + // skip nearclip plane, it often culls portals when you are very close, and is almost never useful + return _R_CullBox(mins, maxs, r_refdef.view.numfrustumplanes, r_refdef.view.frustum, 4); +} + +qbool R_CullBox(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes) +{ + // nothing to ignore + return _R_CullBox(mins, maxs, numplanes, planes, -1); +} + //================================================================================== // LadyHavoc: this stores temporary data used within the same frame @@ -4014,13 +3952,13 @@ qbool R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t en if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs)) return true; + VectorCopy(eye, start); // try specific positions in the box first - note that these can be cached if (r_cullentities_trace_entityocclusion.integer) { for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++) { trace_t trace; - VectorCopy(eye, start); end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0]; end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1]; end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2]; @@ -4031,8 +3969,13 @@ qbool R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t en return true; } } - else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs)) - return true; + else + { + // try center + VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end); + if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs)) + return true; + } // try various random positions for (j = 0; j < numsamples; j++) @@ -4084,7 +4027,7 @@ static void R_View_UpdateEntityVisible (void) continue; } if (!(ent->flags & renderimask)) - if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) + if (!R_CullFrustum(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs)) r_refdef.viewcache.entityvisible[i] = true; } @@ -4096,7 +4039,7 @@ static void R_View_UpdateEntityVisible (void) { ent = r_refdef.scene.entities[i]; if (!(ent->flags & renderimask)) - if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) + if (!R_CullFrustum(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) r_refdef.viewcache.entityvisible[i] = true; } } @@ -5546,6 +5489,11 @@ void R_UpdateVariables(void) if (r_refdef.scene.worldmodel) { r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale; + + // Apply the default lightstyle to the lightmap even on q3bsp + if (cl.worldmodel && cl.worldmodel->type == mod_brushq3) { + r_refdef.scene.lightmapintensity *= r_refdef.scene.rtlightstylevalue[0]; + } } if (r_showsurfaces.integer) { @@ -5688,7 +5636,7 @@ void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, i rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity if(R_CompileShader_CheckStaticParms()) - R_GLSL_Restart_f(&cmd_client); + R_GLSL_Restart_f(cmd_local); if (!r_drawentities.integer) r_refdef.scene.numentities = 0; @@ -6179,7 +6127,7 @@ static void R_DrawEntityBBoxes(prvm_prog_t *prog) for (i = 0; i < prog->num_edicts; i++) { edict = PRVM_EDICT_NUM(i); - if (edict->priv.server->free) + if (edict->free) continue; // exclude the following for now, as they don't live in world coordinate space and can't be solid: if (PRVM_gameedictedict(edict, tag_entity) != 0) @@ -9315,11 +9263,8 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor model_t *model; const msurface_t *surface; const msurface_t *surfaces; - const int *surfacelist; const texture_t *texture; int numtriangles; - int numsurfacelist; - int surfacelistindex; int surfaceindex; int triangleindex; float localorigin[3]; @@ -9412,8 +9357,6 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor #endif dynamic = model->surfmesh.isanimated; - numsurfacelist = model->nummodelsurfaces; - surfacelist = model->sortedmodelsurfaces; surfaces = model->data_surfaces; bih = NULL; @@ -9449,9 +9392,8 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor } else { - for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++) + for (surfaceindex = model->submodelsurfaces_start;surfaceindex < model->submodelsurfaces_end;surfaceindex++) { - surfaceindex = surfacelist[surfacelistindex]; surface = surfaces + surfaceindex; // check cull box first because it rejects more than any other check if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs)) @@ -9777,7 +9719,7 @@ static void R_DrawModelDecals(void) static void R_DrawDebugModel(void) { entity_render_t *ent = rsurface.entity; - int i, j, flagsmask; + int j, flagsmask; const msurface_t *surface; model_t *model = ent->model; @@ -9793,10 +9735,11 @@ static void R_DrawDebugModel(void) GL_DepthMask(false); GL_DepthRange(0, 1); GL_BlendFunc(GL_ONE, GL_ONE); - for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++) { if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) continue; + surface = model->data_surfaces + j; rsurface.texture = R_GetCurrentTexture(surface->texture); if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) { @@ -9836,7 +9779,7 @@ static void R_DrawDebugModel(void) GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value); for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++) { - if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs)) + if (cullbox && R_CullFrustum(bihleaf->mins, bihleaf->maxs)) continue; switch (bihleaf->type) { @@ -9887,10 +9830,11 @@ static void R_DrawDebugModel(void) GL_DepthMask(true); } qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR - for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++) { if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) continue; + surface = model->data_surfaces + j; rsurface.texture = R_GetCurrentTexture(surface->texture); if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) { @@ -9925,10 +9869,11 @@ static void R_DrawDebugModel(void) GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); } - for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++) { if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) continue; + surface = model->data_surfaces + j; rsurface.texture = R_GetCurrentTexture(surface->texture); if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) { @@ -10034,7 +9979,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep } // check if this is an empty model - if (model->nummodelsurfaces == 0) + if (model->submodelsurfaces_start >= model->submodelsurfaces_end) return; rsurface.lightmaptexture = NULL; @@ -10048,9 +9993,9 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep if (ent == r_refdef.scene.worldentity) { // for the world entity, check surfacevisible - for (i = 0;i < model->nummodelsurfaces;i++) + for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++) { - j = model->sortedmodelsurfaces[i]; + j = model->modelsurfaces_sorted[i]; if (r_refdef.viewcache.world_surfacevisible[j]) r_surfacelist[numsurfacelist++] = surfaces + j; } @@ -10064,15 +10009,15 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep } else if (ui) { - // for ui we have to preserve the order of surfaces (not using sortedmodelsurfaces) - for (i = 0; i < model->nummodelsurfaces; i++) - r_surfacelist[numsurfacelist++] = surfaces + model->firstmodelsurface + i; + // for ui we have to preserve the order of surfaces (not using modelsurfaces_sorted) + for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++) + r_surfacelist[numsurfacelist++] = surfaces + i; } else { // add all surfaces - for (i = 0; i < model->nummodelsurfaces; i++) - r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i]; + for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++) + r_surfacelist[numsurfacelist++] = surfaces + model->modelsurfaces_sorted[i]; } /*