From: havoc Date: Sun, 26 Sep 2004 12:46:40 +0000 (+0000) Subject: added r_rtworld, r_rtworldshadows, r_rtdlight, r_rtdlightshadows, and r_lightmapinten... X-Git-Tag: xonotic-v0.1.0preview~5566 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=ea4fc545e8444f579d88d8f096b054dcd7bc482f;ds=sidebyside added r_rtworld, r_rtworldshadows, r_rtdlight, r_rtdlightshadows, and r_lightmapintensity cvars to greatly clean up the handling of the various rtlight/normal rendering modes ifixed lighting problems on transparent alias models in r_shadow_realtime_world mode with r_shadow_realtime_world_lightmaps < 1 (note: still does not use the rtlights entities, just bsp model light queries like lightmap mode uses) cleaned up handling regarding RENDER_LIGHT, RENDER_SHADOW, EF_ADDITIVE, alpha, r_fullbright, RENDER_EXTERIORMODEL, and model->flags (now the EF_ADDITIVE and EF_FULLBRIGHT flags were moved to model->flags2) tag children now inherit RENDER_EXTERIORMODEL from their parent so you can simply attach an external weapon model to the player model and it will appear/disappear according to chase_active appropriately git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4540 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_input.c b/cl_input.c index aba9852b..9908c917 100644 --- a/cl_input.c +++ b/cl_input.c @@ -424,33 +424,8 @@ void CL_SendMove(usercmd_t *cmd) MSG_WriteByte (&buf, in_impulse); in_impulse = 0; - if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3) - { - // LordHavoc: should we ack this on receipt instead? would waste net bandwidth though - if (cl.entitydatabase) - { - i = EntityFrame_MostRecentlyRecievedFrameNum(cl.entitydatabase); - if (i > 0) - { - MSG_WriteByte(&buf, clc_ackentities); - MSG_WriteLong(&buf, i); - } - } - } - else if (cl.protocol == PROTOCOL_DARKPLACES4) - { - if (cl.entitydatabase4) - { - i = cl.latestframenum; - if (cl_nodelta.integer) - i = -1; - if (developer_networkentities.integer >= 1) - Con_Printf("send clc_ackentities %i\n", i); - MSG_WriteByte(&buf, clc_ackentities); - MSG_WriteLong(&buf, i); - } - } - else if (cl.protocol == PROTOCOL_DARKPLACES5) + // FIXME: should ack latest 3 frames perhaps? + if (cl.latestframenum > 0) { i = cl.latestframenum; if (cl_nodelta.integer) diff --git a/cl_main.c b/cl_main.c index ddc51144..88151231 100644 --- a/cl_main.c +++ b/cl_main.c @@ -513,6 +513,17 @@ void CL_LinkNetworkEntity(entity_t *e) // skip inactive entities and world if (!e->state_current.active || e == cl_entities) return; + e->render.alpha = e->state_current.alpha * (1.0f / 255.0f); // FIXME: interpolate? + e->render.scale = e->state_current.scale * (1.0f / 16.0f); // FIXME: interpolate? + e->render.flags = e->state_current.flags; + e->render.effects = e->state_current.effects; + if (e->state_current.flags & RENDER_COLORMAPPED) + e->render.colormap = e->state_current.colormap; + else if (cl.scores != NULL && e->state_current.colormap) + e->render.colormap = cl.scores[e->state_current.colormap - 1].colors; // color it + else + e->render.colormap = -1; // no special coloring + e->render.skinnum = e->state_current.skin; if (e->render.flags & RENDER_VIEWMODEL) { if (!r_drawviewmodel.integer || chase_active.integer || envmap) @@ -535,6 +546,8 @@ void CL_LinkNetworkEntity(entity_t *e) CL_LinkNetworkEntity(t); // make relative to the entity matrix = &t->render.matrix; + // some properties of the tag entity carry over + e->render.flags |= t->render.flags & RENDER_EXTERIORMODEL; // if a valid tagindex is used, make it relative to that tag instead // FIXME: use a model function to get tag info (need to handle skeletal) if (e->state_current.tagentity && e->state_current.tagindex >= 1 && (model = t->render.model) && e->state_current.tagindex <= t->render.model->alias.aliasnum_tags) @@ -555,19 +568,6 @@ void CL_LinkNetworkEntity(entity_t *e) matrix = &tempmatrix; } } - e->render.alpha = e->state_current.alpha * (1.0f / 255.0f); // FIXME: interpolate? - e->render.scale = e->state_current.scale * (1.0f / 16.0f); // FIXME: interpolate? - e->render.flags = e->state_current.flags; - if (e - cl_entities == cl.viewentity) - e->render.flags |= RENDER_EXTERIORMODEL; - e->render.effects = e->state_current.effects; - if (e->state_current.flags & RENDER_COLORMAPPED) - e->render.colormap = e->state_current.colormap; - else if (cl.scores != NULL && e->state_current.colormap) - e->render.colormap = cl.scores[e->state_current.colormap - 1].colors; // color it - else - e->render.colormap = -1; // no special coloring - e->render.skinnum = e->state_current.skin; // set up the render matrix if (e->state_previous.active && e->state_current.modelindex == e->state_previous.modelindex) { @@ -636,6 +636,9 @@ void CL_LinkNetworkEntity(entity_t *e) if (cl_itembobheight.value) origin[2] += (cos(cl.time * cl_itembobspeed.value * (2.0 * M_PI)) + 1.0) * 0.5 * cl_itembobheight.value; } + // transfer certain model flags to effects + if (e->render.model->flags2 & EF_FULLBRIGHT) + e->render.effects |= EF_FULLBRIGHT; } R_LerpAnimation(&e->render); @@ -843,23 +846,28 @@ void CL_LinkNetworkEntity(entity_t *e) CL_RocketTrail(e->persistent.trail_origin, origin, trailtype, e->state_current.glowcolor, e); } VectorCopy(origin, e->persistent.trail_origin); - // note: the cl.viewentity and intermission check is to hide player - // shadow during intermission and during the Nehahra movie and - // Nehahra cinematics - if (!(e->render.effects & (EF_NOSHADOW | EF_ADDITIVE)) - && (e->render.alpha == 1) - && !(e->render.flags & RENDER_VIEWMODEL) - && ((e - cl_entities) != cl.viewentity || (!cl.intermission && cl.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer))) - e->render.flags |= RENDER_SHADOW; - if (!(e->render.effects & EF_FULLBRIGHT)) + // tenebrae's sprites are all additive mode (weird) + if (gamemode == GAME_TENEBRAE && e->render.model && e->render.model->type == mod_sprite) + e->render.effects |= EF_ADDITIVE; + // player model is only shown with chase_active on + if (e - cl_entities == cl.viewentity) + e->render.flags |= RENDER_EXTERIORMODEL; + // transparent stuff can't be lit during the opaque stage + if (e->render.effects & (EF_ADDITIVE) || e->render.alpha < 1) + e->render.flags |= RENDER_TRANSPARENT; + // either fullbright or lit + if (!(e->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer) e->render.flags |= RENDER_LIGHT; + // hide player shadow during intermission or nehahra movie + if (!(e->render.effects & EF_NOSHADOW) + && !(e->render.flags & (RENDER_VIEWMODEL | RENDER_TRANSPARENT)) + && (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cl.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer))) + e->render.flags |= RENDER_SHADOW; // as soon as player is known we can call V_CalcRefDef if ((e - cl_entities) == cl.viewentity) V_CalcRefdef(); if (e->render.model && e->render.model->name[0] == '*' && e->render.model->TraceBox) cl_brushmodel_entities[cl_num_brushmodel_entities++] = &e->render; - if (gamemode == GAME_TENEBRAE && e->render.model && e->render.model->type == mod_sprite) - e->render.effects |= EF_ADDITIVE; // don't show entities with no modelindex (note: this still shows // entities which have a modelindex that resolved to a NULL model) if (e->render.model && !(e->render.effects & EF_NODRAW) && r_refdef.numentities < r_refdef.maxentities) @@ -1089,7 +1097,7 @@ void CL_RelinkBeams(void) return; //VectorCopy (org, ent->render.origin); ent->render.model = b->model; - ent->render.effects = EF_FULLBRIGHT; + //ent->render.effects = EF_FULLBRIGHT; //ent->render.angles[0] = pitch; //ent->render.angles[1] = yaw; //ent->render.angles[2] = rand()%360; diff --git a/gl_models.c b/gl_models.c index 8ba6f9f4..f05c9ef2 100644 --- a/gl_models.c +++ b/gl_models.c @@ -86,7 +86,7 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2) || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0) || ((layer->flags & ALIASLAYER_FOG) && !fogenabled) || (layer->flags & ALIASLAYER_SPECULAR) - || ((layer->flags & ALIASLAYER_DIFFUSE) && (r_shadow_realtime_world.integer && r_shadow_realtime_world_lightmaps.value <= 0 && r_ambient.integer <= 0 && r_fullbright.integer == 0 && !(ent->effects & EF_FULLBRIGHT)))) + || ((layer->flags & ALIASLAYER_DIFFUSE) && (ent->flags & RENDER_LIGHT) && r_lightmapintensity <= 0 && !(ent->flags & RENDER_TRANSPARENT) && r_ambient.integer <= 0)) continue; } if (!firstpass || (ent->effects & EF_ADDITIVE)) @@ -129,7 +129,7 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2) } else { - fullbright = !(layer->flags & ALIASLAYER_DIFFUSE) || r_fullbright.integer || (ent->effects & EF_FULLBRIGHT); + fullbright = !(layer->flags & ALIASLAYER_DIFFUSE) || !(ent->flags & RENDER_LIGHT); if (layer->flags & (ALIASLAYER_COLORMAP_PANTS | ALIASLAYER_COLORMAP_SHIRT)) { // 128-224 are backwards ranges @@ -144,26 +144,23 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2) } else tint[0] = tint[1] = tint[2] = 1; - if (r_shadow_realtime_world.integer && !fullbright) - VectorScale(tint, r_shadow_realtime_world_lightmaps.value, tint); + if (!fullbright && !(ent->flags & RENDER_TRANSPARENT)) + colorscale *= r_lightmapintensity; colorscale *= ifog; if (fullbright) GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha); - else + else if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha, false)) { - if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha, false)) + m.pointer_color = varray_color4f; + if (normal3f == NULL) { - m.pointer_color = varray_color4f; - if (normal3f == NULL) - { - normal3f = varray_normal3f; - Mod_BuildNormals(mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_element3i, normal3f); - } - R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, mesh->num_vertices, vertex3f, normal3f, varray_color4f); + normal3f = varray_normal3f; + Mod_BuildNormals(mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_element3i, normal3f); } - else - GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]); + R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, mesh->num_vertices, vertex3f, normal3f, varray_color4f); } + else + GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]); } R_Mesh_State(&m); GL_LockArrays(0, mesh->num_vertices); @@ -196,7 +193,7 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor aliasmesh_t *mesh; aliasskin_t *skin; float projectdistance, *vertex3f; - if (ent->effects & EF_ADDITIVE || ent->alpha < 1) + if (!(ent->flags & RENDER_SHADOW)) return; projectdistance = lightradius + ent->model->radius;// - sqrt(DotProduct(relativelightorigin, relativelightorigin)); if (projectdistance > 0.1) @@ -230,9 +227,6 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v aliaslayer_t *layer; aliasskin_t *skin; - if (ent->effects & (EF_ADDITIVE | EF_FULLBRIGHT) || ent->alpha < 1) - return; - R_Mesh_Matrix(&ent->matrix); fog = 0; @@ -256,6 +250,7 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v for (meshnum = 0, mesh = ent->model->alias.aliasdata_meshes;meshnum < ent->model->alias.aliasnum_meshes;meshnum++, mesh++) { skin = R_FetchAliasSkin(ent, mesh); + // FIXME: transparent skins need to be lit during the transparent render if (skin->flags & ALIASSKIN_TRANSPARENT) continue; if (ent->frameblend[0].frame == 0 && ent->frameblend[0].lerp == 1) diff --git a/gl_rmain.c b/gl_rmain.c index 79b6ab24..6816a436 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -37,7 +37,17 @@ int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels // true during envmap command capture qboolean envmap; +// maximum visible distance (recalculated from world box each frame) float r_farclip; +// brightness of world lightmaps and related lighting +// (often reduced when world rtlights are enabled) +float r_lightmapintensity; +// whether to draw world lights realtime, dlights realtime, and their shadows +qboolean r_rtworld; +qboolean r_rtworldshadows; +qboolean r_rtdlight; +qboolean r_rtdlightshadows; + // forces all rendering to draw triangle outlines int r_showtrispass; @@ -471,30 +481,6 @@ int R_DrawBrushModelsSky (void) return sky; } -/* -============= -R_DrawViewModel -============= -*/ -/* -void R_DrawViewModel (void) -{ - entity_render_t *ent; - - // FIXME: move these checks to client - if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model) - return; - - ent = &cl.viewent.render; - Mod_CheckLoaded(ent->model); - R_LerpAnimation(ent); - Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale); - Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix); - R_UpdateEntLights(ent); - ent->model->Draw(ent); -} -*/ - void R_DrawNoModel(entity_render_t *ent); void R_DrawModels(void) { @@ -585,11 +571,13 @@ void R_UpdateWorld(void) if (!r_refdef.entities/* || !cl.worldmodel*/) return; //Host_Error ("R_RenderView: NULL worldmodel"); + /* if (r_shadow_realtime_world.integer && !gl_stencil) { Con_Print("Realtime world lighting requires 32bit color; turning off r_shadow_realtime_world, please type vid_bitsperpixel 32;vid_restart and try again\n"); Cvar_SetValueQuick(&r_shadow_realtime_world, 0); } + */ // don't allow cheats in multiplayer if (!cl.islocalgame && cl.worldmodel) @@ -627,6 +615,11 @@ void R_RenderView(void) r_view_fov_y = bound(1, r_refdef.fov_y, 170); r_view_matrix = r_refdef.viewentitymatrix; GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); + r_rtworld = r_shadow_realtime_world.integer; + r_rtworldshadows = r_rtworld && r_shadow_realtime_world_shadows.integer; + r_rtdlight = r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer; + r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer); + r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1; // GL is weird because it's bottom to top, r_view_y is top to bottom qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height); @@ -670,7 +663,7 @@ void R_RenderScene(void) R_SetFrustum(); r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f; - if (gl_stencil && (r_shadow_realtime_world.integer || (r_shadow_realtime_dlight.integer && r_shadow_realtime_dlight_shadows.integer))) + if (gl_stencil && (r_rtworldshadows || r_rtdlightshadows)) GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f); else GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip); diff --git a/gl_rsurf.c b/gl_rsurf.c index 8ad9f9ff..06dd1dfb 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -810,7 +810,7 @@ static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata } turb = (surf->flags & SURF_DRAWTURB) && r_waterscroll.value; - fullbright = (ent->effects & EF_FULLBRIGHT) || (surf->flags & SURF_DRAWFULLBRIGHT) || !surf->samples; + fullbright = !(ent->flags & RENDER_LIGHT) || (surf->flags & SURF_DRAWFULLBRIGHT) || !surf->samples; base = fullbright ? 2.0f : r_ambient.value * (1.0f / 64.0f); if (surf->flags & SURF_DRAWTURB) base *= 0.5f; @@ -945,10 +945,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetailGlow(co m.tex[3] = R_GetTexture(texture->skin.glow); m.texcombinergb[3] = GL_ADD; } - if (r_shadow_realtime_world.integer) - GL_Color(r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, 1); - else - GL_Color(1, 1, 1, 1); + GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1); while((surf = *surfchain++) != NULL) { @@ -983,10 +980,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmapDetail(const m.texrgbscale[1] = 2; m.tex[2] = R_GetTexture(texture->skin.detail); m.texrgbscale[2] = 2; - if (r_shadow_realtime_world.integer) - GL_Color(r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, 1); - else - GL_Color(1, 1, 1, 1); + GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1); while((surf = *surfchain++) != NULL) { @@ -1018,10 +1012,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseCombine_TextureLightmap(const entity m.tex[0] = R_GetTexture(texture->skin.base); m.tex[1] = R_GetTexture((**surfchain).lightmaptexture); m.texrgbscale[1] = 2; - if (r_shadow_realtime_world.integer) - GL_Color(r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, 1); - else - GL_Color(1, 1, 1, 1); + GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1); while((surf = *surfchain++) != NULL) { if (surf->visframe == r_framecount) @@ -1048,10 +1039,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, GL_DepthTest(true); GL_BlendFunc(GL_ONE, GL_ZERO); m.tex[0] = R_GetTexture(texture->skin.base); - if (r_shadow_realtime_world.integer) - GL_Color(r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, 1); - else - GL_Color(1, 1, 1, 1); + GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1); while((surf = *surfchain++) != NULL) { if (surf->visframe == r_framecount) @@ -1230,10 +1218,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseLightmapOnly(const entity_render_t * GL_DepthMask(true); GL_DepthTest(true); m.tex[0] = R_GetTexture((**surfchain).lightmaptexture); - if (r_shadow_realtime_world.integer) - GL_Color(r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, 1); - else - GL_Color(1, 1, 1, 1); + GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1); while((surf = *surfchain++) != NULL) { if (surf->visframe == r_framecount) @@ -1286,7 +1271,7 @@ void R_UpdateLightmapInfo(entity_render_t *ent) model_t *model = ent->model; if (!model) return; - if (r_dynamic.integer && !r_shadow_realtime_dlight.integer) + if (r_dynamic.integer && !r_rtdlight) R_MarkLights(ent); for (i = 0;i < model->brushq1.light_styles;i++) { @@ -1378,7 +1363,7 @@ void R_DrawSurfaces(entity_render_t *ent, int flagsmask) } else { - if (ent->effects & EF_FULLBRIGHT || r_fullbright.integer) + if (!(ent->flags & RENDER_LIGHT)) { RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, surfchain); if (r_detailtextures.integer) @@ -1889,7 +1874,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t else if (ent != &cl_entities[0].render || surface->visframe == r_framecount) { t = surface->texinfo->texture->currentframe; - if (t->flags & SURF_LIGHTMAP && t->rendertype == SURFRENDER_OPAQUE) + if (t->flags & SURF_LIGHTMAP) R_Shadow_RenderLighting(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, t->skin.gloss, lightcubemap, LIGHTING_DIFFUSE | LIGHTING_SPECULAR); } } @@ -2055,10 +2040,7 @@ void R_Q3BSP_DrawFace_OpaqueWall_Pass_LightmapOnly(entity_render_t *ent, q3msurf GL_DepthTest(true); m.tex[0] = R_GetTexture(face->lightmaptexture); m.pointer_texcoord[0] = face->data_texcoordlightmap2f; - if (r_shadow_realtime_world.integer) - GL_Color(r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, r_shadow_realtime_world_lightmaps.value, 1); - else - GL_Color(1, 1, 1, 1); + GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1); m.pointer_vertex = face->data_vertex3f; R_Mesh_State(&m); GL_LockArrays(0, face->num_vertices); @@ -2099,9 +2081,7 @@ void R_Q3BSP_DrawFace_OpaqueWall_Pass_TextureVertex(entity_render_t *ent, q3msur GL_DepthTest(true); m.tex[0] = R_GetTexture(face->texture->skin.base); m.pointer_texcoord[0] = face->data_texcoordtexture2f; - mul = 2.0f; - if (r_shadow_realtime_world.integer && r_shadow_realtime_world_lightmaps.value != 1) - mul *= r_shadow_realtime_world_lightmaps.value; + mul = 2.0f * r_lightmapintensity; if (mul == 2 && gl_combine.integer) { m.texrgbscale[0] = 2; @@ -2136,9 +2116,7 @@ void R_Q3BSP_DrawFace_OpaqueWall_Pass_VertexOnly(entity_render_t *ent, q3msurfac GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); GL_DepthTest(true); - mul = 2.0f; - if (r_shadow_realtime_world.integer && r_shadow_realtime_world_lightmaps.value != 1) - mul *= r_shadow_realtime_world_lightmaps.value; + mul = 2.0f * r_lightmapintensity; if (mul == 1) m.pointer_color = face->data_color4f; else @@ -2178,6 +2156,8 @@ void R_Q3BSP_DrawFace_OpaqueWall_Pass_AddTextureAmbient(entity_render_t *ent, q3 void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int facenumber) { + int i; + float colorscale; const entity_render_t *ent = voident; q3msurface_t *face = ent->model->brushq3.data_faces + facenumber; rmeshstate_t m; @@ -2191,46 +2171,19 @@ void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int facenumber) GL_DepthTest(true); m.tex[0] = R_GetTexture(face->texture->skin.base); m.pointer_texcoord[0] = face->data_texcoordtexture2f; - // LordHavoc: quake3 was not able to do this; lit transparent surfaces + colorscale = r_lightmapintensity; if (gl_combine.integer) - { m.texrgbscale[0] = 2; - if (r_textureunits.integer >= 2) - { - m.tex[1] = R_GetTexture(face->lightmaptexture); - m.pointer_texcoord[1] = face->data_texcoordlightmap2f; - GL_Color(1, 1, 1, ent->alpha); - } - else - { - if (ent->alpha == 1) - m.pointer_color = face->data_color4f; - else - { - int i; - for (i = 0;i < face->num_vertices;i++) - { - varray_color4f[i*4+0] = face->data_color4f[i*4+0]; - varray_color4f[i*4+1] = face->data_color4f[i*4+1]; - varray_color4f[i*4+2] = face->data_color4f[i*4+2]; - varray_color4f[i*4+3] = face->data_color4f[i*4+3] * ent->alpha; - } - m.pointer_color = varray_color4f; - } - } - } else + colorscale *= 2.0f; + for (i = 0;i < face->num_vertices;i++) { - int i; - for (i = 0;i < face->num_vertices;i++) - { - varray_color4f[i*4+0] = face->data_color4f[i*4+0] * 2.0f; - varray_color4f[i*4+1] = face->data_color4f[i*4+1] * 2.0f; - varray_color4f[i*4+2] = face->data_color4f[i*4+2] * 2.0f; - varray_color4f[i*4+3] = face->data_color4f[i*4+3] * ent->alpha; - } - m.pointer_color = varray_color4f; + varray_color4f[i*4+0] = face->data_color4f[i*4+0] * colorscale; + varray_color4f[i*4+1] = face->data_color4f[i*4+1] * colorscale; + varray_color4f[i*4+2] = face->data_color4f[i*4+2] * colorscale; + varray_color4f[i*4+3] = face->data_color4f[i*4+3] * ent->alpha; } + m.pointer_color = varray_color4f; m.pointer_vertex = face->data_vertex3f; R_Mesh_State(&m); qglDisable(GL_CULL_FACE); @@ -2258,9 +2211,9 @@ void R_Q3BSP_DrawFace(entity_render_t *ent, q3msurface_t *face) return; } R_Mesh_Matrix(&ent->matrix); - if (r_shadow_realtime_world.integer && r_shadow_realtime_world_lightmaps.value <= 0) + if (r_lightmapintensity <= 0) R_Q3BSP_DrawFace_OpaqueWall_Pass_OpaqueGlow(ent, face); - else if ((ent->effects & EF_FULLBRIGHT) || r_fullbright.integer) + else if (!(ent->flags & RENDER_LIGHT)) { R_Q3BSP_DrawFace_OpaqueWall_Pass_Texture(ent, face); if (face->texture->skin.glow) diff --git a/model_shared.h b/model_shared.h index 701a6ed5..516cf45f 100644 --- a/model_shared.h +++ b/model_shared.h @@ -549,8 +549,6 @@ typedef struct model_s int flags; // engine calculated flags, ones that can not be set in the file int flags2; - // LordHavoc: if true (normally only for sprites) the model/sprite/bmodel is always rendered fullbright - int fullbright; // number of QC accessible frame(group)s in the model int numframes; // number of QC accessible skin(group)s in the model diff --git a/model_sprite.c b/model_sprite.c index 54150f8b..f6ef9f21 100644 --- a/model_sprite.c +++ b/model_sprite.c @@ -55,14 +55,14 @@ static void Mod_Sprite_SharedSetup(qbyte *datapointer, int version, int *palette Host_Error ("Mod_Sprite_SharedSetup: Invalid # of frames: %d\n", loadmodel->numframes); loadmodel->type = mod_sprite; - loadmodel->flags = EF_FULLBRIGHT; + loadmodel->flags2 = EF_FULLBRIGHT; // LordHavoc: hack to allow sprites to be non-fullbright for (i = 0;i < MAX_QPATH && loadmodel->name[i];i++) { if (loadmodel->name[i] == '!') { - loadmodel->flags &= ~EF_FULLBRIGHT; + loadmodel->flags2 &= ~EF_FULLBRIGHT; break; } } @@ -275,7 +275,7 @@ void Mod_IDSP_Load(model_t *mod, void *buffer) palette[i][2] = *in++; palette[i][3] = 255; } - loadmodel->flags |= EF_ADDITIVE; + loadmodel->flags2 |= EF_ADDITIVE; break; case SPRHL_INDEXALPHA: for (i = 0;i < 256;i++) diff --git a/protocol.c b/protocol.c index f897d219..0c966f8e 100644 --- a/protocol.c +++ b/protocol.c @@ -864,7 +864,7 @@ void EntityFrame_CL_ReadFrame(void) // read the frame header info f->time = cl.mtime[0]; number = MSG_ReadLong(); - f->framenum = MSG_ReadLong(); + cl.latestframenum = f->framenum = MSG_ReadLong(); f->eye[0] = MSG_ReadFloat(); f->eye[1] = MSG_ReadFloat(); f->eye[2] = MSG_ReadFloat(); @@ -1050,7 +1050,7 @@ void EntityFrame4_ResetDatabase(entityframe4_database_t *d) d->referenceentity[i] = defaultstate; } -int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum) +int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum, int servermode) { int i, j, found; entity_database4_commit_t *commit; @@ -1060,6 +1060,9 @@ int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum) d->referenceframenum = -1; for (i = 0;i < d->maxreferenceentities;i++) d->referenceentity[i] = defaultstate; + // if this is the server, remove commits + for (i = 0, commit = d->commit;i < MAX_ENTITY_HISTORY;i++, commit++) + commit->numentities = 0; found = true; } else if (d->referenceframenum == framenum) @@ -1120,7 +1123,7 @@ void EntityFrame4_CL_ReadFrame(void) // read the number of the frame this refers to referenceframenum = MSG_ReadLong(); // read the number of this frame - framenum = MSG_ReadLong(); + cl.latestframenum = framenum = MSG_ReadLong(); // read the start number enumber = (unsigned short) MSG_ReadShort(); if (developer_networkentities.integer >= 1) @@ -1131,7 +1134,7 @@ void EntityFrame4_CL_ReadFrame(void) Con_Printf(" %i", d->commit[i].framenum); Con_Print("\n"); } - if (!EntityFrame4_AckFrame(d, referenceframenum)) + if (!EntityFrame4_AckFrame(d, referenceframenum, false)) { Con_Print("EntityFrame4_CL_ReadFrame: reference frame invalid (VERY BAD ERROR), this update will be skipped\n"); skip = true; diff --git a/protocol.h b/protocol.h index e8fa52f4..db5687c8 100644 --- a/protocol.h +++ b/protocol.h @@ -323,8 +323,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define RENDER_EXTERIORMODEL 8 #define RENDER_LOWPRECISION 16 // send as low precision coordinates to save bandwidth #define RENDER_COLORMAPPED 32 -#define RENDER_SHADOW 64 // cast shadow -#define RENDER_LIGHT 128 // receive light +#define RENDER_SHADOW 65536 // cast shadow +#define RENDER_LIGHT 131072 // receive light +#define RENDER_TRANSPARENT 262144 // can't light during opaque stage // this is 80 bytes typedef struct @@ -607,7 +608,7 @@ void EntityFrame4_FreeDatabase(entityframe4_database_t *d); // reset a database (resets compression but does not reallocate anything) void EntityFrame4_ResetDatabase(entityframe4_database_t *d); // updates database to account for a frame-received acknowledgment -int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum); +int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum, int servermode); // writes a frame to the network stream void EntityFrame4_WriteFrame(sizebuf_t *msg, entityframe4_database_t *d, int numstates, const entity_state_t *states); // reads a frame from the network stream diff --git a/r_light.c b/r_light.c index d0c977d3..908b5aa6 100644 --- a/r_light.c +++ b/r_light.c @@ -135,7 +135,7 @@ void R_DrawCoronas(void) return; R_Mesh_Matrix(&r_identitymatrix); viewdist = DotProduct(r_vieworigin, r_viewforward); - if (r_shadow_realtime_world.integer) + if (r_rtworld) { for (lnum = 0, light = r_shadow_worldlightchain;light;light = light->next, lnum++) { @@ -372,13 +372,13 @@ int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, co ambient4f[0] = ambient4f[1] = ambient4f[2] = r_ambient.value * (2.0f / 128.0f); VectorClear(diffusecolor); VectorClear(diffusenormal); - if (r_fullbright.integer || (ent->effects & EF_FULLBRIGHT)) + if (!(ent->flags & RENDER_LIGHT)) { // highly rare VectorSet(ambient4f, 1, 1, 1); maxnearlights = 0; } - else if (r_shadow_realtime_world.integer && r_shadow_realtime_world_lightmaps.value <= 0) + else if (r_lightmapintensity <= 0 && !(ent->flags & RENDER_TRANSPARENT)) maxnearlights = 0; else { @@ -447,8 +447,9 @@ int R_LightModel(float *ambient4f, float *diffusecolor, float *diffusenormal, co nl->offset = sl->distbias; } } - if (!r_shadow_realtime_dlight.integer) + if (!r_rtdlight || (ent->flags & RENDER_TRANSPARENT)) { + // FIXME: this dlighting doesn't look like rtlights for (i = 0;i < r_numdlights;i++) { light = r_dlight + i; @@ -558,7 +559,7 @@ void R_LightModel_CalcVertexColors(const float *ambientcolor4f, const float *dif // pretty good lighting for (j = 0, nl = &nearlight[0];j < nearlights;j++, nl++) { - VectorSubtract(vertex3f, nl->origin, v); + VectorSubtract(nl->origin, vertex3f, v); // first eliminate negative lighting (back side) dot = DotProduct(normal3f, v); if (dot > 0) @@ -588,7 +589,7 @@ void R_UpdateEntLights(entity_render_t *ent) int i; const mlight_t *sl; vec3_t v; - if (r_shadow_realtime_world.integer && r_shadow_realtime_world_lightmaps.value <= 0) + if (r_lightmapintensity <= 0 && !(ent->flags & RENDER_TRANSPARENT)) return; VectorSubtract(ent->origin, ent->entlightsorigin, v); if (ent->entlightsframe != (r_framecount - 1) || (realtime > ent->entlightstime && DotProduct(v,v) >= 1.0f)) diff --git a/r_shadow.c b/r_shadow.c index 1126cb34..9ed419d5 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -2020,7 +2020,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 +2103,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)) { @@ -2208,14 +2192,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 +2231,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 +2243,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); diff --git a/r_sprites.c b/r_sprites.c index d215d494..906bcacb 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -91,7 +91,7 @@ void R_DrawSpriteModelCallback(const void *calldata1, int calldata2) R_Mesh_Matrix(&r_identitymatrix); - if ((ent->model->flags & EF_FULLBRIGHT) || (ent->effects & EF_FULLBRIGHT)) + if (!(ent->flags & RENDER_LIGHT)) color[0] = color[1] = color[2] = 1; else { @@ -118,7 +118,7 @@ void R_DrawSpriteModelCallback(const void *calldata1, int calldata2) if (ent->frameblend[i].lerp >= 0.01f) { frame = ent->model->sprite.sprdata_frames + ent->frameblend[i].frame; - R_DrawSpriteImage((ent->effects & EF_ADDITIVE) || (ent->model->flags & EF_ADDITIVE), frame, frame->texture, org, up, left, color[0] * ifog, color[1] * ifog, color[2] * ifog, ent->alpha * ent->frameblend[i].lerp); + R_DrawSpriteImage((ent->effects & EF_ADDITIVE), frame, frame->texture, org, up, left, color[0] * ifog, color[1] * ifog, color[2] * ifog, ent->alpha * ent->frameblend[i].lerp); if (fog * ent->frameblend[i].lerp >= 0.01f) R_DrawSpriteImage(true, frame, frame->fogtexture, org, up, left, fogcolor[0],fogcolor[1],fogcolor[2], fog * ent->alpha * ent->frameblend[i].lerp); } @@ -133,7 +133,7 @@ void R_DrawSpriteModelCallback(const void *calldata1, int calldata2) if (frame) { - R_DrawSpriteImage((ent->effects & EF_ADDITIVE) || (ent->model->flags & EF_ADDITIVE), frame, frame->texture, org, up, left, color[0] * ifog, color[1] * ifog, color[2] * ifog, ent->alpha); + R_DrawSpriteImage((ent->effects & EF_ADDITIVE), frame, frame->texture, org, up, left, color[0] * ifog, color[1] * ifog, color[2] * ifog, ent->alpha); if (fog * ent->frameblend[i].lerp >= 0.01f) R_DrawSpriteImage(true, frame, frame->fogtexture, org, up, left, fogcolor[0],fogcolor[1],fogcolor[2], fog * ent->alpha); } diff --git a/render.h b/render.h index 6a4fa824..b5f76e2d 100644 --- a/render.h +++ b/render.h @@ -83,6 +83,15 @@ extern int r_framecount; extern mplane_t frustum[4]; extern int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights; +// brightness of world lightmaps and related lighting +// (often reduced when world rtlights are enabled) +extern float r_lightmapintensity; +// whether to draw world lights realtime, dlights realtime, and their shadows +extern qboolean r_rtworld; +extern qboolean r_rtworldshadows; +extern qboolean r_rtdlight; +extern qboolean r_rtdlightshadows; + // forces all rendering to draw triangle outlines extern cvar_t r_showtris; extern int r_showtrispass; diff --git a/sv_user.c b/sv_user.c index 3eb4d0fd..147a5552 100644 --- a/sv_user.c +++ b/sv_user.c @@ -768,7 +768,7 @@ void SV_ReadClientMessage(void) if (host_client->entitydatabase) EntityFrame_AckFrame(host_client->entitydatabase, num); else if (host_client->entitydatabase4) - EntityFrame4_AckFrame(host_client->entitydatabase4, host_client->entitydatabase4->ackframenum); + EntityFrame4_AckFrame(host_client->entitydatabase4, host_client->entitydatabase4->ackframenum, true); else if (host_client->entitydatabase5) EntityFrame5_AckFrame(host_client->entitydatabase5, num, host_client - svs.clients + 1); break;