From: havoc Date: Mon, 9 Apr 2018 04:39:19 +0000 (+0000) Subject: UNMERGE! Refactored R_UpdateEntityLighting to CL_UpdateEntityShading, which sets... X-Git-Tag: xonotic-v0.8.5~17 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=cb77c846dbc2485d351d5d6db390b8d7a75cdae9;p=xonotic%2Fdarkplaces.git UNMERGE! Refactored R_UpdateEntityLighting to CL_UpdateEntityShading, which sets fields like ent->render_modellight_ambient. Added texture->render_modellight_ambient and similar fields which concretely define how the material is to be rendered, so all of the various tweaks and modifiers are no longer buried in R_SetupShader_Surface which has now been refactored heavily. Removed R_LightPoint as it's really not necessary - this change will make lit particles a little bit slower as R_CompleteLightPoint is a slightly more expensive function. Refactored R_CompleteLightPoint to have more consistent code, changed the final color math so that it passes q1bsp/q2bsp lighting through unmodified. Changed shading of tag_entity attachments - they now use the root entity's origin for shading, this fixes r_shadows where the shadows could go in different directions on CSQC entities (r_shadows code already contained a hack to work around this problem for network entities). Renamed r_refdef.lightmapintensity and ambient to r_refdef.scene.lightmapintensity and ambientintensity. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12376 d7cf8633-e32d-0410-b094-e92efae38249 ::stable-branch::unmerge=4e1f3f76d5fe7befe20034a730630c314d45956b --- diff --git a/cl_main.c b/cl_main.c index 8753a5eb..d5707029 100644 --- a/cl_main.c +++ b/cl_main.c @@ -2406,14 +2406,14 @@ void CL_MeshEntities_Init(void) ent->state_current.active = true; ent->render.model = cl_meshentitymodels + i; ent->render.alpha = 1; - ent->render.flags = RENDER_SHADOW | RENDER_LIGHT | RENDER_CUSTOMIZEDMODELLIGHT; + ent->render.flags = RENDER_SHADOW | RENDER_LIGHT; ent->render.framegroupblend[0].lerp = 1; ent->render.frameblend[0].lerp = 1; VectorSet(ent->render.colormod, 1, 1, 1); VectorSet(ent->render.glowmod, 1, 1, 1); - VectorSet(ent->render.custommodellight_ambient, 1, 1, 1); - VectorSet(ent->render.custommodellight_diffuse, 0, 0, 0); - VectorSet(ent->render.custommodellight_lightdir, 0, 0, 1); + VectorSet(ent->render.modellight_ambient, 1, 1, 1); + VectorSet(ent->render.modellight_diffuse, 0, 0, 0); + VectorSet(ent->render.modellight_lightdir, 0, 0, 1); Matrix4x4_CreateIdentity(&ent->render.matrix); CL_UpdateRenderEntity(&ent->render); } @@ -2451,221 +2451,6 @@ void CL_MeshEntities_Shutdown(void) { } -extern cvar_t r_overheadsprites_pushback; -extern cvar_t r_fullbright_directed_pitch_relative; -extern cvar_t r_fullbright_directed_pitch; -extern cvar_t r_fullbright_directed_ambient; -extern cvar_t r_fullbright_directed_diffuse; -extern cvar_t r_fullbright_directed; -extern cvar_t r_equalize_entities_minambient; -extern cvar_t r_equalize_entities_to; -extern cvar_t r_equalize_entities_by; -extern cvar_t r_hdr_glowintensity; - -static void CL_UpdateEntityShading_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal) -{ - vec3_t angles; - - VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value); - VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value); - - // Use cl.viewangles and not r_refdef.view.forward here so it is the - // same for all stereo views, and to better handle pitches outside - // [-90, 90] (in_pitch_* cvars allow that). - VectorCopy(cl.viewangles, angles); - if (r_fullbright_directed_pitch_relative.integer) { - angles[PITCH] += r_fullbright_directed_pitch.value; - } - else { - angles[PITCH] = r_fullbright_directed_pitch.value; - } - AngleVectors(angles, worldspacenormal, NULL, NULL); - VectorNegate(worldspacenormal, worldspacenormal); -} - -static void CL_UpdateEntityShading_Entity(entity_render_t *ent) -{ - float shadingorigin[3], f, fa, fd, fdd, a[3], c[3], dir[3]; - int q; - - for (q = 0; q < 3; q++) - a[q] = c[q] = dir[q] = 0; - - ent->render_modellight_forced = false; - ent->render_rtlight_disabled = false; - - // pick an appropriate value for render_modellight_origin - if this is an - // attachment we want to use the parent's render_modellight_origin so that - // shading is the same (also important for r_shadows to cast shadows in the - // same direction) - if (VectorLength2(ent->custommodellight_origin)) - { - // CSQC entities always provide this (via CL_GetTagMatrix) - for (q = 0; q < 3; q++) - shadingorigin[q] = ent->custommodellight_origin[q]; - } - else if (ent->entitynumber > 0 && ent->entitynumber < cl.num_entities) - { - // network entity - follow attachment chain back to a root entity, - int entnum = ent->entitynumber, recursion; - for (recursion = 32; recursion > 0; --recursion) - { - int parentnum = cl.entities[entnum].state_current.tagentity; - if (parentnum < 1 || parentnum >= cl.num_entities || !cl.entities_active[parentnum]) - break; - entnum = parentnum; - } - // grab the root entity's origin - Matrix4x4_OriginFromMatrix(&cl.entities[entnum].render.matrix, shadingorigin); - } - else - { - // not a CSQC entity (which sets custommodellight_origin), not a network - // entity - so it's probably not attached to anything - Matrix4x4_OriginFromMatrix(&ent->matrix, shadingorigin); - } - - if (!(ent->flags & RENDER_LIGHT) || r_fullbright.integer) - { - // intentionally EF_FULLBRIGHT entity - // the only type that is not scaled by r_refdef.scene.lightmapintensity - // CSQC can still provide its own customized modellight values - ent->render_rtlight_disabled = true; - ent->render_modellight_forced = true; - if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT) - { - // custom colors provided by CSQC - for (q = 0; q < 3; q++) - { - a[q] = ent->custommodellight_ambient[q]; - c[q] = ent->custommodellight_diffuse[q]; - dir[q] = ent->custommodellight_lightdir[q]; - } - } - else if (r_fullbright_directed.integer) - CL_UpdateEntityShading_GetDirectedFullbright(a, c, dir); - else - for (q = 0; q < 3; q++) - a[q] = 1; - } - else - { - // fetch the lighting from the worldmodel data - - // CSQC can provide its own customized modellight values - if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT) - { - ent->render_modellight_forced = true; - for (q = 0; q < 3; q++) - { - a[q] = ent->custommodellight_ambient[q]; - c[q] = ent->custommodellight_diffuse[q]; - dir[q] = ent->custommodellight_lightdir[q]; - } - } - else if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT)) - { - if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites - shadingorigin[2] = shadingorigin[2] + r_overheadsprites_pushback.value; - R_CompleteLightPoint(a, c, dir, shadingorigin, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity); - ent->render_modellight_forced = true; - ent->render_rtlight_disabled = true; - } - else if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint) - R_CompleteLightPoint(a, c, dir, shadingorigin, LP_LIGHTMAP, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity); - else if (r_fullbright_directed.integer) - CL_UpdateEntityShading_GetDirectedFullbright(a, c, dir); - else - R_CompleteLightPoint(a, c, dir, shadingorigin, LP_LIGHTMAP, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity); - - if (ent->flags & RENDER_EQUALIZE) - { - // first fix up ambient lighting... - if (r_equalize_entities_minambient.value > 0) - { - fd = 0.299f * ent->render_modellight_diffuse[0] + 0.587f * ent->render_modellight_diffuse[1] + 0.114f * ent->render_modellight_diffuse[2]; - if (fd > 0) - { - fa = (0.299f * ent->render_modellight_ambient[0] + 0.587f * ent->render_modellight_ambient[1] + 0.114f * ent->render_modellight_ambient[2]); - if (fa < r_equalize_entities_minambient.value * fd) - { - // solve: - // fa'/fd' = minambient - // fa'+0.25*fd' = fa+0.25*fd - // ... - // fa' = fd' * minambient - // fd'*(0.25+minambient) = fa+0.25*fd - // ... - // fd' = (fa+0.25*fd) * 1 / (0.25+minambient) - // fa' = (fa+0.25*fd) * minambient / (0.25+minambient) - // ... - fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value); - f = fdd / fd; // f>0 because all this is additive; f<1 because fdd 0 && r_equalize_entities_by.value != 0) - { - fa = 0.299f * a[0] + 0.587f * a[1] + 0.114f * a[2]; - fd = 0.299f * c[0] + 0.587f * c[1] + 0.114f * c[2]; - f = fa + 0.25 * fd; - if (f > 0) - { - // adjust brightness and saturation to target - float l2 = r_equalize_entities_by.value, l1 = 1 - l2; - for (q = 0; q < 3; q++) - { - a[q] = l1 * a[q] + l2 * (fa / f); - c[q] = l1 * c[q] + l2 * (fd / f); - } - } - } - } - } - - for (q = 0; q < 3; q++) - { - ent->render_fullbright[q] = ent->colormod[q]; - ent->render_glowmod[q] = ent->glowmod[q] * r_hdr_glowintensity.value; - ent->render_modellight_ambient[q] = a[q] * ent->colormod[q]; - ent->render_modellight_diffuse[q] = c[q] * ent->colormod[q]; - ent->render_modellight_specular[q] = c[q]; - ent->render_modellight_lightdir[q] = dir[q]; - ent->render_lightmap_ambient[q] = ent->colormod[q] * r_refdef.scene.ambientintensity; - ent->render_lightmap_diffuse[q] = ent->colormod[q] * r_refdef.scene.lightmapintensity; - ent->render_lightmap_specular[q] = r_refdef.scene.lightmapintensity; - ent->render_rtlight_diffuse[q] = ent->colormod[q]; - ent->render_rtlight_specular[q] = 1; - } - - // these flags disable code paths, make sure it's obvious if they're ignored by storing 0 1 2 - if (ent->render_modellight_forced) - for (q = 0; q < 3; q++) - ent->render_lightmap_ambient[q] = ent->render_lightmap_diffuse[q] = ent->render_lightmap_specular[q] = q; - if (ent->render_rtlight_disabled) - for (q = 0; q < 3; q++) - ent->render_rtlight_diffuse[q] = ent->render_rtlight_specular[q] = q; - - if (VectorLength2(ent->render_modellight_lightdir) == 0) - VectorSet(ent->render_modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here - VectorNormalize(ent->render_modellight_lightdir); -} - - -void CL_UpdateEntityShading(void) -{ - int i; - CL_UpdateEntityShading_Entity(r_refdef.scene.worldentity); - for (i = 0; i < r_refdef.scene.numentities; i++) - CL_UpdateEntityShading_Entity(r_refdef.scene.entities[i]); -} - /* =========== CL_Shutdown diff --git a/cl_particles.c b/cl_particles.c index 9d64080b..5e873998 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -2723,14 +2723,10 @@ static void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const // note: lighting is not cheap! if (particletype[p->typeindex].lighting) { - float a[3], c[3], dir[3]; vecorg[0] = p->org[0]; vecorg[1] = p->org[1]; vecorg[2] = p->org[2]; - R_CompleteLightPoint(a, c, dir, vecorg, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity); - c4f[0] = p->color[0] * colormultiplier[0] * (a[0] + 0.25f * c[0]); - c4f[1] = p->color[1] * colormultiplier[1] * (a[1] + 0.25f * c[1]); - c4f[2] = p->color[2] * colormultiplier[2] * (a[2] + 0.25f * c[2]); + R_LightPoint(c4f, vecorg, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); } // mix in the fog color if (r_refdef.fogenabled) diff --git a/cl_screen.c b/cl_screen.c index abde7491..a2bbf496 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -1894,7 +1894,6 @@ static void R_Envmap_f (void) buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 4); buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3); - CL_UpdateEntityShading(); for (j = 0;j < 12;j++) { dpsnprintf(filename, sizeof(filename), "env/%s%s.tga", basename, envmapinfo[j].name); @@ -2187,10 +2186,7 @@ static void SCR_DrawScreen (void) if (cl.csqc_loaded) CL_VM_UpdateView(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime)); else - { - CL_UpdateEntityShading(); R_RenderView(); - } } if (!r_stereo_sidebyside.integer && !r_stereo_horizontal.integer && !r_stereo_vertical.integer) diff --git a/client.h b/client.h index 6be9d5a5..5486b1bf 100644 --- a/client.h +++ b/client.h @@ -573,37 +573,10 @@ typedef struct entity_render_s int animcache_skeletaltransform3x4offset; int animcache_skeletaltransform3x4size; - // CL_UpdateEntityShading reads these fields - // used only if RENDER_CUSTOMIZEDMODELLIGHT is set - vec3_t custommodellight_ambient; - vec3_t custommodellight_diffuse; - vec3_t custommodellight_lightdir; - // CSQC entities get their shading from the root of their attachment chain - float custommodellight_origin[3]; - - // derived lighting parameters (CL_UpdateEntityShading) - - // used by MATERIALFLAG_FULLBRIGHT which is MATERIALFLAG_MODELLIGHT with - // this as ambient color, along with MATERIALFLAG_NORTLIGHT - float render_fullbright[3]; - // color tint for the base pass glow textures if any - float render_glowmod[3]; - // MATERIALFLAG_MODELLIGHT uses these parameters - float render_modellight_ambient[3]; - float render_modellight_diffuse[3]; - float render_modellight_lightdir[3]; - float render_modellight_specular[3]; - // lightmap rendering (not MATERIALFLAG_MODELLIGHT) - float render_lightmap_ambient[3]; - float render_lightmap_diffuse[3]; - float render_lightmap_specular[3]; - // rtlights use these colors for the materials on this entity - float render_rtlight_diffuse[3]; - float render_rtlight_specular[3]; - // ignore lightmap and use lightgrid on this entity (e.g. FULLBRIGHT) - qboolean render_modellight_forced; - // do not process per pixel lights on this entity at all (like MATERIALFLAG_NORTLIGHT) - qboolean render_rtlight_disabled; + // current lighting from map (updated ONLY by client code, not renderer) + vec3_t modellight_ambient; + vec3_t modellight_diffuse; // q3bsp + vec3_t modellight_lightdir; // q3bsp // storage of decals on this entity // (note: if allowdecals is set, be sure to call R_DecalSystem_Reset on removal!) @@ -1913,12 +1886,7 @@ typedef struct r_refdef_scene_s { // controls intensity lightmap layers unsigned short lightstylevalue[MAX_LIGHTSTYLES]; // 8.8 fraction of base light value - // adds brightness to the whole scene, separate from lightmapintensity - // see CL_UpdateEntityShading - float ambientintensity; - // brightness of lightmap and modellight lighting on materials - // see CL_UpdateEntityShading - float lightmapintensity; + float ambient; qboolean rtworld; qboolean rtworldshadows; @@ -1988,6 +1956,9 @@ typedef struct r_refdef_s // true during envmap command capture qboolean envmap; + // brightness of world lightmaps and related lighting + // (often reduced when world rtlights are enabled) + float lightmapintensity; // whether to draw world lights realtime, dlights realtime, and their shadows float polygonfactor; float polygonoffset; @@ -2061,7 +2032,6 @@ extern const char *cl_meshentitynames[NUM_MESHENTITIES]; #define CL_Mesh_UI() (&cl_meshentitymodels[MESH_UI]) void CL_MeshEntities_AddToScene(void); void CL_MeshEntities_Reset(void); -void CL_UpdateEntityShading(void); void CL_NewFrameReceived(int num); void CL_ParseEntityLump(char *entitystring); diff --git a/clvm_cmds.c b/clvm_cmds.c index 54848d8e..10fee13a 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -696,12 +696,17 @@ static void VM_CL_getlight (prvm_prog_t *prog) { vec3_t ambientcolor, diffusecolor, diffusenormal; vec3_t p; - int flags = prog->argc >= 2 ? PRVM_G_FLOAT(OFS_PARM1) : LP_LIGHTMAP; VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getlight); VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p); - R_CompleteLightPoint(ambientcolor, diffusecolor, diffusenormal, p, flags, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity); + VectorClear(ambientcolor); + VectorClear(diffusecolor); + VectorClear(diffusenormal); + if (prog->argc >= 2) + R_CompleteLightPoint(ambientcolor, diffusecolor, diffusenormal, p, PRVM_G_FLOAT(OFS_PARM1)); + else if (cl.worldmodel && cl.worldmodel->brush.LightPoint) + cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal); VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN)); if (PRVM_clientglobalvector(getlight_ambient)) VectorCopy(ambientcolor, PRVM_clientglobalvector(getlight_ambient)); @@ -2448,7 +2453,7 @@ static int CL_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int extern cvar_t cl_bob; extern cvar_t cl_bobcycle; extern cvar_t cl_bobup; -int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex, prvm_vec_t *shadingorigin) +int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex) { int ret; int attachloop; @@ -2521,16 +2526,6 @@ int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4)); } */ - - // return the origin of the view - if (shadingorigin) - Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, shadingorigin); - } - else - { - // return the origin of the root entity in the chain - if (shadingorigin) - Matrix4x4_OriginFromMatrix(out, shadingorigin); } return 0; } @@ -2587,7 +2582,7 @@ static void VM_CL_gettaginfo (prvm_prog_t *prog) e = PRVM_G_EDICT(OFS_PARM0); tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); - returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex, NULL); + returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex); Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin); VectorCopy(forward, PRVM_clientglobalvector(v_forward)); VectorScale(left, -1, PRVM_clientglobalvector(v_right)); @@ -3235,7 +3230,7 @@ static void VM_CL_GetEntity (prvm_prog_t *prog) VectorAdd(cl.entities[entnum].render.maxs, org, PRVM_G_VECTOR(OFS_RETURN)); break; case 16: // light - VectorMA(cl.entities[entnum].render.render_modellight_ambient, 0.5, cl.entities[entnum].render.render_modellight_diffuse, PRVM_G_VECTOR(OFS_RETURN)); + VectorMA(cl.entities[entnum].render.modellight_ambient, 0.5, cl.entities[entnum].render.modellight_diffuse, PRVM_G_VECTOR(OFS_RETURN)); break; default: PRVM_G_FLOAT(OFS_RETURN) = 0; @@ -3271,7 +3266,6 @@ static void VM_CL_R_RenderScene (prvm_prog_t *prog) // we need to update any RENDER_VIEWMODEL entities at this point because // csqc supplies its own view matrix CL_UpdateViewEntities(); - CL_UpdateEntityShading(); // now draw stuff! R_RenderView(); @@ -4256,7 +4250,7 @@ static void VM_CL_V_CalcRefdef(prvm_prog_t *prog) flags = PRVM_G_FLOAT(OFS_PARM1); // use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad) - CL_GetTagMatrix(prog, &entrendermatrix, ent, 0, NULL); + CL_GetTagMatrix(prog, &entrendermatrix, ent, 0); VectorCopy(cl.csqc_viewangles, clviewangles); teleported = (flags & REFDEFFLAG_TELEPORTED) != 0; diff --git a/csprogs.c b/csprogs.c index 8d54fc0f..5f73c6ec 100644 --- a/csprogs.c +++ b/csprogs.c @@ -346,9 +346,8 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum) if (!VectorLength2(entrender->glowmod)) VectorSet(entrender->glowmod, 1, 1, 1); - // LadyHavoc: use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad) - // this also sets the custommodellight_origin for us - CL_GetTagMatrix(prog, &entrender->matrix, ed, 0, entrender->custommodellight_origin); + // LordHavoc: use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad) + CL_GetTagMatrix(prog, &entrender->matrix, ed, 0); // set up the animation data VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed); @@ -364,9 +363,9 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum) // model light if (renderflags & RF_MODELLIGHT) { - if (PRVM_clientedictvector(ed, modellight_ambient)) VectorCopy(PRVM_clientedictvector(ed, modellight_ambient), entrender->custommodellight_ambient); else VectorClear(entrender->custommodellight_ambient); - if (PRVM_clientedictvector(ed, modellight_diffuse)) VectorCopy(PRVM_clientedictvector(ed, modellight_diffuse), entrender->custommodellight_diffuse); else VectorClear(entrender->custommodellight_diffuse); - if (PRVM_clientedictvector(ed, modellight_dir)) VectorCopy(PRVM_clientedictvector(ed, modellight_dir), entrender->custommodellight_lightdir); else VectorClear(entrender->custommodellight_lightdir); + if (PRVM_clientedictvector(ed, modellight_ambient)) VectorCopy(PRVM_clientedictvector(ed, modellight_ambient), entrender->modellight_ambient); else VectorClear(entrender->modellight_ambient); + if (PRVM_clientedictvector(ed, modellight_diffuse)) VectorCopy(PRVM_clientedictvector(ed, modellight_diffuse), entrender->modellight_diffuse); else VectorClear(entrender->modellight_diffuse); + if (PRVM_clientedictvector(ed, modellight_dir)) VectorCopy(PRVM_clientedictvector(ed, modellight_dir), entrender->modellight_lightdir); else VectorClear(entrender->modellight_lightdir); entrender->flags |= RENDER_CUSTOMIZEDMODELLIGHT; } @@ -1190,13 +1189,15 @@ qboolean CL_VM_GetEntitySoundOrigin(int entnum, vec3_t out) CSQC_BEGIN; + // FIXME consider attachments here! + ed = PRVM_EDICT_NUM(entnum - MAX_EDICTS); if(!ed->priv.required->free) { mod = CL_GetModelFromEdict(ed); VectorCopy(PRVM_clientedictvector(ed, origin), out); - if(CL_GetTagMatrix(prog, &matrix, ed, 0, NULL) == 0) + if(CL_GetTagMatrix(prog, &matrix, ed, 0) == 0) Matrix4x4_OriginFromMatrix(&matrix, out); if (mod && mod->soundfromcenter) VectorMAMAM(1.0f, out, 0.5f, mod->normalmins, 0.5f, mod->normalmaxs, out); diff --git a/csprogs.h b/csprogs.h index 226cf96c..56761014 100644 --- a/csprogs.h +++ b/csprogs.h @@ -98,7 +98,7 @@ qboolean CL_VM_Parse_TempEntity(void); void CL_VM_Parse_StuffCmd(const char *msg); void CL_VM_Parse_CenterPrint(const char *msg); int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent); -int CL_GetTagMatrix(prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex, prvm_vec_t *shadingorigin); +int CL_GetTagMatrix(prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex); void CL_GetEntityMatrix(prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix); /* VMs exposing the polygon calls must call this on Init/Reset */ void VM_Polygons_Reset(prvm_prog_t *prog); diff --git a/gl_rmain.c b/gl_rmain.c index 4e35c2ed..ce44d68b 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -2212,7 +2212,7 @@ static int R_BlendFuncFlags(int src, int dst) return r; } -void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy) +void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy) { // select a permutation of the lighting shader appropriate to this // combination of texture, entity, light source, and fogging, only use the @@ -2221,27 +2221,28 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif dpuint64 permutation = 0; unsigned int mode = 0; int blendfuncflags; - texture_t *t = rsurface.texture; + static float dummy_colormod[3] = {1, 1, 1}; + float *colormod = rsurface.colormod; float m16f[16]; matrix4x4_t tempmatrix; r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane; if (r_trippy.integer && !notrippy) permutation |= SHADERPERMUTATION_TRIPPY; - if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) permutation |= SHADERPERMUTATION_ALPHAKILL; - if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE) permutation |= SHADERPERMUTATION_OCCLUDE; - if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1]) + if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1]) permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic if (rsurfacepass == RSURFPASS_BACKGROUND) { // distorted background - if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER) { mode = SHADERMODE_WATER; - if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX; - if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA)) + if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)) { // this is the right thing to do for wateralpha GL_BlendFunc(GL_ONE, GL_ZERO); @@ -2254,10 +2255,10 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } } - else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION) + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION) { mode = SHADERMODE_REFRACTION; - if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -2274,9 +2275,9 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif } else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY) { - if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f)) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { - switch(t->offsetmapping) + switch(rsurface.texture->offsetmapping) { case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; @@ -2284,7 +2285,7 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif case OFFSETMAPPING_OFF: break; } } - if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; // normalmap (deferred prepass), may use alpha test on diffuse mode = SHADERMODE_DEFERREDGEOMETRY; @@ -2295,9 +2296,9 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif } else if (rsurfacepass == RSURFPASS_RTLIGHT) { - if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f)) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { - switch(t->offsetmapping) + switch(rsurface.texture->offsetmapping) { case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; @@ -2305,21 +2306,21 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif case OFFSETMAPPING_OFF: break; } } - if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX; // light source mode = SHADERMODE_LIGHTSOURCE; if (rsurface.rtlight->currentcubemap != r_texture_whitecube) permutation |= SHADERPERMUTATION_CUBEFILTER; - if (VectorLength2(rtlightdiffuse) > 0) + if (diffusescale > 0) permutation |= SHADERPERMUTATION_DIFFUSE; - if (VectorLength2(rtlightspecular) > 0) + if (specularscale > 0) permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; if (r_refdef.fogenabled) permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE); - if (t->colormapping) + if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; if (r_shadow_usingshadowmap2d) { @@ -2330,18 +2331,69 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (r_shadow_shadowmap2ddepthbuffer) permutation |= SHADERPERMUTATION_DEPTHRGB; } - if (t->reflectmasktexture) + if (rsurface.texture->reflectmasktexture) permutation |= SHADERPERMUTATION_REFLECTCUBE; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE); if (vid.allowalphatocoverage) GL_AlphaToCoverage(false); } - else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT) + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) + { + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) + { + switch(rsurface.texture->offsetmapping) + { + case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; + case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_OFF: break; + } + } + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) + permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) + permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX; + // unshaded geometry (fullbright or ambient model lighting) + mode = SHADERMODE_FLATCOLOR; + ambientscale = diffusescale = specularscale = 0; + if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) + permutation |= SHADERPERMUTATION_GLOW; + if (r_refdef.fogenabled) + permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE); + if (rsurface.texture->colormapping) + permutation |= SHADERPERMUTATION_COLORMAPPING; + if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)) + { + permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; + permutation |= SHADERPERMUTATION_SHADOWMAP2D; + + if (r_shadow_shadowmap2ddepthbuffer) + permutation |= SHADERPERMUTATION_DEPTHRGB; + } + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) + permutation |= SHADERPERMUTATION_REFLECTION; + if (rsurface.texture->reflectmasktexture) + permutation |= SHADERPERMUTATION_REFLECTCUBE; + GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + // when using alphatocoverage, we don't need alphakill + if (vid.allowalphatocoverage) + { + if (r_transparent_alphatocoverage.integer) + { + GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + permutation &= ~SHADERPERMUTATION_ALPHAKILL; + } + else + GL_AlphaToCoverage(false); + } + } + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL) { - if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f)) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { - switch(t->offsetmapping) + switch(rsurface.texture->offsetmapping) { case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; @@ -2349,21 +2401,20 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif case OFFSETMAPPING_OFF: break; } } - if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX; // directional model lighting mode = SHADERMODE_LIGHTDIRECTION; - if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) + if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; - if (VectorLength2(t->render_modellight_diffuse)) - permutation |= SHADERPERMUTATION_DIFFUSE; - if (VectorLength2(t->render_modellight_specular) > 0) + permutation |= SHADERPERMUTATION_DIFFUSE; + if (specularscale > 0) permutation |= SHADERPERMUTATION_SPECULAR; if (r_refdef.fogenabled) permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE); - if (t->colormapping) + if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)) { @@ -2373,11 +2424,11 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (r_shadow_shadowmap2ddepthbuffer) permutation |= SHADERPERMUTATION_DEPTHRGB; } - if (t->currentmaterialflags & MATERIALFLAG_REFLECTION) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; - if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED)) + if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)) permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP; - if (t->reflectmasktexture) + if (rsurface.texture->reflectmasktexture) permutation |= SHADERPERMUTATION_REFLECTCUBE; if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld) { @@ -2385,14 +2436,72 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (r_shadow_bouncegrid_state.directional) permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL; } - GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2); - blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2); + GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); // when using alphatocoverage, we don't need alphakill if (vid.allowalphatocoverage) { if (r_transparent_alphatocoverage.integer) { - GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + permutation &= ~SHADERPERMUTATION_ALPHAKILL; + } + else + GL_AlphaToCoverage(false); + } + } + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) + { + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) + { + switch(rsurface.texture->offsetmapping) + { + case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; + case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_OFF: break; + } + } + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) + permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) + permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX; + // ambient model lighting + mode = SHADERMODE_LIGHTDIRECTION; + if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) + permutation |= SHADERPERMUTATION_GLOW; + if (r_refdef.fogenabled) + permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE); + if (rsurface.texture->colormapping) + permutation |= SHADERPERMUTATION_COLORMAPPING; + if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)) + { + permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; + permutation |= SHADERPERMUTATION_SHADOWMAP2D; + + if (r_shadow_shadowmap2ddepthbuffer) + permutation |= SHADERPERMUTATION_DEPTHRGB; + } + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) + permutation |= SHADERPERMUTATION_REFLECTION; + if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)) + permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP; + if (rsurface.texture->reflectmasktexture) + permutation |= SHADERPERMUTATION_REFLECTCUBE; + if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld) + { + permutation |= SHADERPERMUTATION_BOUNCEGRID; + if (r_shadow_bouncegrid_state.directional) + permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL; + } + GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + // when using alphatocoverage, we don't need alphakill + if (vid.allowalphatocoverage) + { + if (r_transparent_alphatocoverage.integer) + { + GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); permutation &= ~SHADERPERMUTATION_ALPHAKILL; } else @@ -2401,9 +2510,9 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif } else { - if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f)) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { - switch(t->offsetmapping) + switch(rsurface.texture->offsetmapping) { case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; @@ -2411,16 +2520,16 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif case OFFSETMAPPING_OFF: break; } } - if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; - if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX) permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX; // lightmapped wall - if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) + if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer) permutation |= SHADERPERMUTATION_GLOW; if (r_refdef.fogenabled) permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE); - if (t->colormapping) + if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)) { @@ -2430,18 +2539,18 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (r_shadow_shadowmap2ddepthbuffer) permutation |= SHADERPERMUTATION_DEPTHRGB; } - if (t->currentmaterialflags & MATERIALFLAG_REFLECTION) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; - if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED)) + if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)) permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP; - if (t->reflectmasktexture) + if (rsurface.texture->reflectmasktexture) permutation |= SHADERPERMUTATION_REFLECTCUBE; if (FAKELIGHT_ENABLED) { // fake lightmapping (q1bsp, q3bsp, fullbright map) mode = SHADERMODE_FAKELIGHT; permutation |= SHADERPERMUTATION_DIFFUSE; - if (VectorLength2(t->render_lightmap_specular) > 0) + if (specularscale > 0) permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; } else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping) @@ -2452,7 +2561,7 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif else mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE; permutation |= SHADERPERMUTATION_DIFFUSE; - if (VectorLength2(t->render_lightmap_specular) > 0) + if (specularscale > 0) permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; } else if (r_glsl_deluxemapping.integer >= 2) @@ -2463,7 +2572,7 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif else mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR; permutation |= SHADERPERMUTATION_DIFFUSE; - if (VectorLength2(t->render_lightmap_specular) > 0) + if (specularscale > 0) permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; } else if (rsurface.uselightmaptexture) @@ -2482,20 +2591,22 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (r_shadow_bouncegrid_state.directional) permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL; } - GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2); - blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2); + GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); // when using alphatocoverage, we don't need alphakill if (vid.allowalphatocoverage) { if (r_transparent_alphatocoverage.integer) { - GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); permutation &= ~SHADERPERMUTATION_ALPHAKILL; } else GL_AlphaToCoverage(false); } } + if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD)) + colormod = dummy_colormod; if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG)) permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE); if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA) @@ -2517,11 +2628,11 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif { if (mode == SHADERMODE_LIGHTDIRECTION) { - hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]); + hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]); } } - Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f); - Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f); + Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f); + Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f); Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f); hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]); @@ -2529,52 +2640,54 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (mode == SHADERMODE_LIGHTSOURCE) { hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]); - hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED - hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]); - hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]); - hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]); + hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale); // additive passes are only darkened by fog, not tinted hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0); - hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); + hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); } else { - hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]); - hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]); if (mode == SHADERMODE_FLATCOLOR) { - hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]); } else if (mode == SHADERMODE_LIGHTDIRECTION) { - hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]); - hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]); - hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]); - hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED - hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale); + hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]); + hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale); + hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]); + hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]); } else { - hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]); - hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]); - hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale); + hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale); + hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale); } // additive passes are only darkened by fog, not tinted if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0) hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0); else hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]); - hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor); + hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]); hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]); - hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha); - hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha); - hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin); - hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin); - hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]); + hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]); + hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin); + hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin); + hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); if (mode == SHADERMODE_WATER) - hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]); + hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); } if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO) { @@ -2586,15 +2699,15 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]); hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); } - hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]); - hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1)); + hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); + hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); - if (t->pantstexture) - hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]); + if (rsurface.texture->pantstexture) + hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]); else hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0); - if (t->shirttexture) - hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]); + if (rsurface.texture->shirttexture) + hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]); else hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0); hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]); @@ -2602,28 +2715,28 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip); hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade); hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps, - r_glsl_offsetmapping_scale.value*t->offsetscale, + r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer) ); hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality); - hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias); + hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias); hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height); - R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture ); - R_Mesh_TexBind(GL20TU_COLOR , t->basetexture ); - R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture ); - R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture ); - if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture ); - if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture ); - if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture ); - if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture ); - if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture ); - if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture ); - if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture ); - if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube); + R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture ); + R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture ); + R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture ); + R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture ); + if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture ); + if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture ); + if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture ); + if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture ); + if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture ); + if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture ); + if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture ); + if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube); if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture ); if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation ); R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white); @@ -2692,39 +2805,39 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif { if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);} if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]); - if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED - if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]); - if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]); - if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]); + if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]); + if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale); + if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale); + if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale); // additive passes are only darkened by fog, not tinted if (r_glsl_permutation->loc_FogColor >= 0) qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); } else { if (mode == SHADERMODE_FLATCOLOR) { - if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]); + if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]); } else if (mode == SHADERMODE_LIGHTDIRECTION) { - if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]); - if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]); - if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]); - if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]); - if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]); - if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED - if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]); + if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]); + if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]); + if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale); + if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]); + if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale); + if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]); + if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]); } else { - if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]); - if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]); - if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]); - if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]); - if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]); + if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]); + if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]); + if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale); + if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale); + if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale); } // additive passes are only darkened by fog, not tinted if (r_glsl_permutation->loc_FogColor >= 0) @@ -2734,18 +2847,18 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif else qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]); } - if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor); + if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]); if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]); - if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha); - if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha); - if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin); - if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); - if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]); - } - if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);} - if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);} + if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]); + if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]); + if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin); + if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin); + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); + if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); + } + if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);} + if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);} if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);} if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO) { @@ -2758,20 +2871,20 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); } - if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]); - if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1)); + if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); + if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); if (r_glsl_permutation->loc_Color_Pants >= 0) { - if (t->pantstexture) - qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]); + if (rsurface.texture->pantstexture) + qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]); else qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0); } if (r_glsl_permutation->loc_Color_Shirt >= 0) { - if (t->shirttexture) - qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]); + if (rsurface.texture->shirttexture) + qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]); else qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0); } @@ -2780,13 +2893,13 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip); if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade); if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, - r_glsl_offsetmapping_scale.value*t->offsetscale, + r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer) ); if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality); - if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias); + if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias); if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height); if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);} @@ -2795,18 +2908,18 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white ); if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white ); if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps ); - if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , t->nmaptexture ); - if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , t->basetexture ); - if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , t->glosstexture ); - if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , t->glowtexture ); - if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , t->backgroundnmaptexture ); - if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , t->backgroundbasetexture ); - if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , t->backgroundglosstexture ); - if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , t->backgroundglowtexture ); - if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , t->pantstexture ); - if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , t->shirttexture ); - if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , t->reflectmasktexture ); - if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube); + if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture ); + if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture ); + if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture ); + if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture ); + if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture ); + if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture ); + if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture ); + if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture ); + if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture ); + if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture ); + if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture ); + if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube); if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture ); if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation ); if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white); @@ -2850,54 +2963,56 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif { {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);} DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale); // additive passes are only darkened by fog, not tinted DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); } else { if (mode == SHADERMODE_FLATCOLOR) { - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]); } else if (mode == SHADERMODE_LIGHTDIRECTION) { - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]); } else { - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale); } - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]); // additive passes are only darkened by fog, not tinted if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0) DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0); else DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]); - DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor); + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]); - DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha); - DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); - DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]); - } - {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);} - {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);} + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]); + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); + DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); + } + {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);} + {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);} {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);} if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO) { @@ -2910,20 +3025,20 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]); } - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1)); + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); if (DPSOFTRAST_UNIFORM_Color_Pants >= 0) { - if (t->pantstexture) - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]); + if (rsurface.texture->pantstexture) + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]); else DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0); } if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0) { - if (t->shirttexture) - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]); + if (rsurface.texture->shirttexture) + DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]); else DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0); } @@ -2932,28 +3047,28 @@ void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdif DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip); DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, - r_glsl_offsetmapping_scale.value*t->offsetscale, + r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer) ); DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias); DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height); - R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture ); - R_Mesh_TexBind(GL20TU_COLOR , t->basetexture ); - R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture ); - R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture ); - if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture ); - if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture ); - if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture ); - if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture ); - if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture ); - if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture ); - if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture ); - if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube); + R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture ); + R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture ); + R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture ); + R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture ); + if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture ); + if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture ); + if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture ); + if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture ); + if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture ); + if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture ); + if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture ); + if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube); if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture ); if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation ); R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white); @@ -4996,6 +5111,171 @@ void R_AnimCache_CacheVisibleEntities(void) //================================================================================== +extern cvar_t r_overheadsprites_pushback; + +static void R_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal) +{ + vec3_t angles; + + VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value); + VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value); + + // Use cl.viewangles and not r_refdef.view.forward here so it is the + // same for all stereo views, and to better handle pitches outside + // [-90, 90] (in_pitch_* cvars allow that). + VectorCopy(cl.viewangles, angles); + if (r_fullbright_directed_pitch_relative.integer) { + angles[PITCH] += r_fullbright_directed_pitch.value; + } else { + angles[PITCH] = r_fullbright_directed_pitch.value; + } + AngleVectors(angles, worldspacenormal, NULL, NULL); + VectorNegate(worldspacenormal, worldspacenormal); +} + +static void R_View_UpdateEntityLighting (void) +{ + int i; + entity_render_t *ent; + vec3_t tempdiffusenormal, avg; + vec_t f, fa, fd, fdd; + qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled(); + + for (i = 0;i < r_refdef.scene.numentities;i++) + { + ent = r_refdef.scene.entities[i]; + + // skip unseen models + if ((!r_refdef.viewcache.entityvisible[i] && skipunseen)) + continue; + + // skip bsp models + if (ent->model && ent->model == cl.worldmodel) + { + // TODO: use modellight for r_ambient settings on world? + // The logic here currently matches RSurf_ActiveWorldEntity. + if (r_fullbright_directed.integer && (r_fullbright.integer || !ent->model || !ent->model->lit)) + { + R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); + Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir); + if(VectorLength2(ent->modellight_lightdir) == 0) + VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here + VectorNormalize(ent->modellight_lightdir); + } + else + { + VectorSet(ent->modellight_ambient, 0, 0, 0); + VectorSet(ent->modellight_diffuse, 0, 0, 0); + VectorSet(ent->modellight_lightdir, 0, 0, 1); + } + continue; + } + + if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT) + { + // aleady updated by CSQC + // TODO: force modellight on BSP models in this case? + VectorCopy(ent->modellight_lightdir, tempdiffusenormal); + } + else + { + // fetch the lighting from the worldmodel data + VectorClear(ent->modellight_ambient); + VectorClear(ent->modellight_diffuse); + VectorClear(tempdiffusenormal); + if (ent->flags & RENDER_LIGHT) + { + vec3_t org; + Matrix4x4_OriginFromMatrix(&ent->matrix, org); + + // complete lightning for lit sprites + // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)? + if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT)) + { + if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites + org[2] = org[2] + r_overheadsprites_pushback.value; + R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); + } + else if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint) + { + R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP); + } + else if (r_fullbright_directed.integer) + { + R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); + } + else + { + VectorSet(ent->modellight_ambient, 1, 1, 1); + } + + if(ent->flags & RENDER_EQUALIZE) + { + // first fix up ambient lighting... + if(r_equalize_entities_minambient.value > 0) + { + fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2]; + if(fd > 0) + { + fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]); + if(fa < r_equalize_entities_minambient.value * fd) + { + // solve: + // fa'/fd' = minambient + // fa'+0.25*fd' = fa+0.25*fd + // ... + // fa' = fd' * minambient + // fd'*(0.25+minambient) = fa+0.25*fd + // ... + // fd' = (fa+0.25*fd) * 1 / (0.25+minambient) + // fa' = (fa+0.25*fd) * minambient / (0.25+minambient) + // ... + fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value); + f = fdd / fd; // f>0 because all this is additive; f<1 because fddmodellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient); + VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse); + } + } + } + + if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0) + { + fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]; + fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2]; + f = fa + 0.25 * fd; + if(f > 0) + { + // adjust brightness and saturation to target + avg[0] = avg[1] = avg[2] = fa / f; + VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient); + avg[0] = avg[1] = avg[2] = fd / f; + VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse); + } + } + } + } + else + { + // EF_FULLBRIGHT entity. + if (r_fullbright_directed.integer) + { + R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal); + } + else + { + VectorSet(ent->modellight_ambient, 1, 1, 1); + } + } + } + + // move the light direction into modelspace coordinates for lighting code + Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir); + if(VectorLength2(ent->modellight_lightdir) == 0) + VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here + VectorNormalize(ent->modellight_lightdir); + } +} + qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs) { int i; @@ -5262,7 +5542,7 @@ void R_HDR_UpdateIrisAdaptation(const vec3_t point) p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value; p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value; p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value; - R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity); + R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); d = DotProduct(forward, diffusenormal); brightness += VectorLength(ambient); if (d > 0) @@ -5493,6 +5773,7 @@ static void R_View_UpdateWithScissor(const int *myscissor) R_View_SetFrustum(myscissor); R_View_WorldVisibility(r_refdef.view.useclipplane); R_View_UpdateEntityVisible(); + R_View_UpdateEntityLighting(); } static void R_View_Update(void) @@ -5501,6 +5782,7 @@ static void R_View_Update(void) R_View_SetFrustum(NULL); R_View_WorldVisibility(r_refdef.view.useclipplane); R_View_UpdateEntityVisible(); + R_View_UpdateEntityLighting(); } float viewscalefpsadjusted = 1.0f; @@ -6909,7 +7191,7 @@ void R_UpdateVariables(void) { R_Textures_Frame(); - r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f); + r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f); r_refdef.farclip = r_farclip_base.value; if (r_refdef.scene.worldmodel) @@ -6927,14 +7209,14 @@ void R_UpdateVariables(void) r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil; r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer; r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil; - r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; + r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; if (FAKELIGHT_ENABLED) { - r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value; + r_refdef.lightmapintensity *= r_fakelight_intensity.value; } else if (r_refdef.scene.worldmodel) { - r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale; + r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale; } if (r_showsurfaces.integer) { @@ -6942,7 +7224,7 @@ void R_UpdateVariables(void) r_refdef.scene.rtworldshadows = false; r_refdef.scene.rtdlight = false; r_refdef.scene.rtdlightshadows = false; - r_refdef.scene.lightmapintensity = 0; + r_refdef.lightmapintensity = 0; } r_gpuskeletal = false; @@ -7079,7 +7361,7 @@ void R_RenderView(void) if (r_timereport_active) R_TimeReport("start"); r_textureframe++; // used only by R_GetCurrentTexture - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity if(R_CompileShader_CheckStaticParms()) R_GLSL_Restart_f(); @@ -7329,7 +7611,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) if (r_refdef.scene.extraupdate) S_ExtraUpdate (); - if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0) + if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { R_ResetViewRendering3D(fbo, depthtexture, colortexture); R_Shadow_DrawModelShadows(); @@ -7350,7 +7632,7 @@ void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) if (r_refdef.scene.extraupdate) S_ExtraUpdate (); - if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0) + if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { R_ResetViewRendering3D(fbo, depthtexture, colortexture); R_Shadow_DrawModelShadows(); @@ -7508,7 +7790,7 @@ static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float c int i, edge; float *v, *c, f1, f2, edgemins[3], edgemaxs[3]; - RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false); + RSurf_ActiveWorldEntity(); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); @@ -7669,7 +7951,7 @@ static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); GL_DepthMask(false); } - else if (ent->alpha < 1) + else if (rsurface.colormod[3] < 1) { GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); @@ -7686,10 +7968,10 @@ static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const memcpy(color4f, nomodelcolor4f, sizeof(float[6*4])); for (i = 0, c = color4f;i < 6;i++, c += 4) { - c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale; - c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale; - c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale; - c[3] *= ent->alpha; + c[0] *= rsurface.colormod[0]; + c[1] *= rsurface.colormod[1]; + c[2] *= rsurface.colormod[2]; + c[3] *= rsurface.colormod[3]; } if (r_refdef.fogenabled) { @@ -8032,11 +8314,10 @@ static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname) texture_t *R_GetCurrentTexture(texture_t *t) { - int i, q; + int i; const entity_render_t *ent = rsurface.entity; dp_model_t *model = ent->model; // when calling this, ent must not be NULL q3shaderinfo_layer_tcmod_t *tcmod; - float specularscale = 0.0f; if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate) return t->currentframe; @@ -8100,115 +8381,27 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)]; t->currentmaterialflags = t->basematerialflags; - t->currentalpha = rsurface.entity->alpha * t->basealpha; + t->currentalpha = rsurface.colormod[3] * t->basealpha; if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer)) t->currentalpha *= r_wateralpha.value; if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later if(!r_fb.water.enabled || r_refdef.view.isoverlay) t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA); - - // decide on which type of lighting to use for this surface - if (rsurface.entity->render_modellight_forced) - t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT; - if (rsurface.entity->render_rtlight_disabled) - t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT; - if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD)) - { - // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale - t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT; - for (q = 0; q < 3; q++) - { - t->render_glowmod[q] = rsurface.entity->glowmod[q]; - t->render_modellight_lightdir[q] = q == 2; - t->render_modellight_ambient[q] = 1; - t->render_modellight_diffuse[q] = 0; - t->render_modellight_specular[q] = 0; - t->render_lightmap_ambient[q] = 0; - t->render_lightmap_diffuse[q] = 0; - t->render_lightmap_specular[q] = 0; - t->render_rtlight_diffuse[q] = 0; - t->render_rtlight_specular[q] = 0; - } - } - else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT)) - { - // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading - t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT; - for (q = 0; q < 3; q++) - { - t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale; - t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale; - t->render_modellight_lightdir[q] = q == 2; - t->render_modellight_diffuse[q] = 0; - t->render_modellight_specular[q] = 0; - t->render_lightmap_ambient[q] = 0; - t->render_lightmap_diffuse[q] = 0; - t->render_lightmap_specular[q] = 0; - t->render_rtlight_diffuse[q] = 0; - t->render_rtlight_specular[q] = 0; - } - } + if (!(rsurface.ent_flags & RENDER_LIGHT)) + t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; else if (FAKELIGHT_ENABLED) { // no modellight if using fakelight for the map - t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT); - for (q = 0; q < 3; q++) - { - t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale; - t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q]; - t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale; - t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale; - t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale; - t->render_lightmap_ambient[q] = 0; - t->render_lightmap_diffuse[q] = 0; - t->render_lightmap_specular[q] = 0; - t->render_rtlight_diffuse[q] = 0; - t->render_rtlight_specular[q] = 0; - } - } - else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL) - { - // ambient + single direction light (modellight) - t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT; - for (q = 0; q < 3; q++) - { - t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale; - t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q]; - t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale; - t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale; - t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale; - t->render_lightmap_ambient[q] = 0; - t->render_lightmap_diffuse[q] = 0; - t->render_lightmap_specular[q] = 0; - t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale; - t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale; - } } - else + else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) { - // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1 - for (q = 0; q < 3; q++) - { - t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale; - t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale; - t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale; - t->render_modellight_diffuse[q] = 0; - t->render_modellight_specular[q] = 0; - t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale; - t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale; - t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale; - t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale; - t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale; - } - } - - for (q = 0; q < 3; q++) - { - t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q]; - t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q]; + // pick a model lighting mode + if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f)) + t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL; + else + t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT; } - if (rsurface.ent_flags & RENDER_ADDITIVE) t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; else if (t->currentalpha < 1) @@ -8253,7 +8446,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++) R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags); - t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f); + t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f); if (t->currentskinframe->qpixels) R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping); t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base; @@ -8293,6 +8486,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) } t->specularpower = r_shadow_glossexponent.value; // TODO: store reference values for these in the texture? + t->specularscale = 0; if (r_shadow_gloss.integer > 0) { if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss)) @@ -8301,19 +8495,20 @@ texture_t *R_GetCurrentTexture(texture_t *t) { t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white; t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white; - specularscale = r_shadow_glossintensity.value; + t->specularscale = r_shadow_glossintensity.value; } } else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0) { t->glosstexture = r_texture_white; t->backgroundglosstexture = r_texture_white; - specularscale = r_shadow_gloss2intensity.value; + t->specularscale = r_shadow_gloss2intensity.value; t->specularpower = r_shadow_gloss2exponent.value; } } - specularscale *= t->specularscalemod; + t->specularscale *= t->specularscalemod; t->specularpower *= t->specularpowermod; + t->rtlightambient = 0; // lightmaps mode looks bad with dlights using actual texturing, so turn // off the colormap and glossmap, but leave the normalmap on as it still @@ -8334,20 +8529,12 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->backgroundnmaptexture = r_texture_blanknormalmap; t->backgroundglosstexture = r_texture_black; t->backgroundglowtexture = NULL; - specularscale = 0; - t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE)); - } - - if (specularscale != 1.0f) - { - for (q = 0; q < 3; q++) - { - t->render_modellight_specular[q] *= specularscale; - t->render_lightmap_specular[q] *= specularscale; - t->render_rtlight_specular[q] *= specularscale; - } + t->specularscale = 0; + t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE)); } + Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha); + VectorClear(t->dlightcolor); t->currentnumlayers = 0; if (t->currentmaterialflags & MATERIALFLAG_WALL) { @@ -8373,38 +8560,54 @@ texture_t *R_GetCurrentTexture(texture_t *t) blendfunc1 = GL_ONE; blendfunc2 = GL_ZERO; } + // don't colormod evilblend textures + if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)) + VectorSet(t->lightmapcolor, 1, 1, 1); depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED); - if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT) + if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) { - // basic lit geometry - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha); - // add pants/shirt if needed - if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha); - if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha); + // fullbright is not affected by r_refdef.lightmapintensity + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); } else { + vec3_t ambientcolor; + float colorscale; + // set the color tint used for lights affecting this surface + VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]); + colorscale = 2; + // q3bsp has no lightmap updates, so the lightstylevalue that + // would normally be baked into the lightmap must be + // applied to the color + // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright) + if (model->type == mod_brushq3) + colorscale *= r_refdef.scene.rtlightstylevalue[0]; + colorscale *= r_refdef.lightmapintensity; + VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor); + VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor); // basic lit geometry - R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha); + R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]); // add pants/shirt if needed - if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha); - if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha); + if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); + if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]); // now add ambient passes if needed - if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f)) + if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f)) { - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha); - if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha); - if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]); + if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]); + if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture) + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]); } } if (t->glowtexture != NULL && !gl_lightmaps.integer) - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]); if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD)) { // if this is opaque use alpha blend which will darken the earlier @@ -8418,7 +8621,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) // were darkened by fog already, and we should not add fog color // (because the background was not darkened, there is no fog color // that was lost behind it). - R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha); + R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]); } } @@ -8427,6 +8630,143 @@ texture_t *R_GetCurrentTexture(texture_t *t) rsurfacestate_t rsurface; +void RSurf_ActiveWorldEntity(void) +{ + dp_model_t *model = r_refdef.scene.worldmodel; + //if (rsurface.entity == r_refdef.scene.worldentity) + // return; + rsurface.entity = r_refdef.scene.worldentity; + rsurface.skeleton = NULL; + memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param)); + rsurface.ent_skinnum = 0; + rsurface.ent_qwskin = -1; + rsurface.ent_flags = r_refdef.scene.worldentity->flags; + rsurface.shadertime = r_refdef.scene.time; + rsurface.matrix = identitymatrix; + rsurface.inversematrix = identitymatrix; + rsurface.matrixscale = 1; + rsurface.inversematrixscale = 1; + R_EntityMatrix(&identitymatrix); + VectorCopy(r_refdef.view.origin, rsurface.localvieworigin); + Vector4Copy(r_refdef.fogplane, rsurface.fogplane); + rsurface.fograngerecip = r_refdef.fograngerecip; + rsurface.fogheightfade = r_refdef.fogheightfade; + rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist; + rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip; + if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit)) + { + R_GetDirectedFullbright(rsurface.modellight_ambient, rsurface.modellight_diffuse, rsurface.modellight_lightdir); + rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT; + } + else + { + VectorSet(rsurface.modellight_ambient, 0, 0, 0); + VectorSet(rsurface.modellight_diffuse, 0, 0, 0); + VectorSet(rsurface.modellight_lightdir, 0, 0, 1); + } + VectorSet(rsurface.colormap_pantscolor, 0, 0, 0); + VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0); + VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale); + rsurface.colormod[3] = 1; + VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value); + memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend)); + rsurface.frameblend[0].lerp = 1; + rsurface.ent_alttextures = false; + rsurface.basepolygonfactor = r_refdef.polygonfactor; + rsurface.basepolygonoffset = r_refdef.polygonoffset; + rsurface.entityskeletaltransform3x4 = NULL; + rsurface.entityskeletaltransform3x4buffer = NULL; + rsurface.entityskeletaltransform3x4offset = 0; + rsurface.entityskeletaltransform3x4size = 0;; + rsurface.entityskeletalnumtransforms = 0; + rsurface.modelvertex3f = model->surfmesh.data_vertex3f; + rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f; + rsurface.modelsvector3f = model->surfmesh.data_svector3f; + rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f; + rsurface.modeltvector3f = model->surfmesh.data_tvector3f; + rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f; + rsurface.modelnormal3f = model->surfmesh.data_normal3f; + rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f; + rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f; + rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f; + rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f; + rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f; + rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f; + rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f; + rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub; + rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub; + rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub; + rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub; + rsurface.modelelement3i = model->surfmesh.data_element3i; + rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer; + rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset; + rsurface.modelelement3s = model->surfmesh.data_element3s; + rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer; + rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset; + rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets; + rsurface.modelnumvertices = model->surfmesh.num_vertices; + rsurface.modelnumtriangles = model->surfmesh.num_triangles; + rsurface.modelsurfaces = model->data_surfaces; + rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh; + rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer; + rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f; + rsurface.modelgeneratedvertex = false; + rsurface.batchgeneratedvertex = false; + rsurface.batchfirstvertex = 0; + rsurface.batchnumvertices = 0; + rsurface.batchfirsttriangle = 0; + rsurface.batchnumtriangles = 0; + rsurface.batchvertex3f = NULL; + rsurface.batchvertex3f_vertexbuffer = NULL; + rsurface.batchvertex3f_bufferoffset = 0; + rsurface.batchsvector3f = NULL; + rsurface.batchsvector3f_vertexbuffer = NULL; + rsurface.batchsvector3f_bufferoffset = 0; + rsurface.batchtvector3f = NULL; + rsurface.batchtvector3f_vertexbuffer = NULL; + rsurface.batchtvector3f_bufferoffset = 0; + rsurface.batchnormal3f = NULL; + rsurface.batchnormal3f_vertexbuffer = NULL; + rsurface.batchnormal3f_bufferoffset = 0; + rsurface.batchlightmapcolor4f = NULL; + rsurface.batchlightmapcolor4f_vertexbuffer = NULL; + rsurface.batchlightmapcolor4f_bufferoffset = 0; + rsurface.batchtexcoordtexture2f = NULL; + rsurface.batchtexcoordtexture2f_vertexbuffer = NULL; + rsurface.batchtexcoordtexture2f_bufferoffset = 0; + rsurface.batchtexcoordlightmap2f = NULL; + rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL; + rsurface.batchtexcoordlightmap2f_bufferoffset = 0; + rsurface.batchskeletalindex4ub = NULL; + rsurface.batchskeletalindex4ub_vertexbuffer = NULL; + rsurface.batchskeletalindex4ub_bufferoffset = 0; + rsurface.batchskeletalweight4ub = NULL; + rsurface.batchskeletalweight4ub_vertexbuffer = NULL; + rsurface.batchskeletalweight4ub_bufferoffset = 0; + rsurface.batchvertexmesh = NULL; + rsurface.batchvertexmesh_vertexbuffer = NULL; + rsurface.batchvertexmesh_bufferoffset = 0; + rsurface.batchelement3i = NULL; + rsurface.batchelement3i_indexbuffer = NULL; + rsurface.batchelement3i_bufferoffset = 0; + rsurface.batchelement3s = NULL; + rsurface.batchelement3s_indexbuffer = NULL; + rsurface.batchelement3s_bufferoffset = 0; + rsurface.passcolor4f = NULL; + rsurface.passcolor4f_vertexbuffer = NULL; + rsurface.passcolor4f_bufferoffset = 0; + rsurface.forcecurrenttextureupdate = false; +} + void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass) { dp_model_t *model = ent->model; @@ -8439,7 +8779,9 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1; rsurface.ent_flags = ent->flags; if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit)) + { rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT; + } rsurface.shadertime = r_refdef.scene.time - ent->shadertime; rsurface.matrix = ent->matrix; rsurface.inversematrix = ent->inversematrix; @@ -8452,6 +8794,14 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale; rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale; rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip; + VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient); + VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse); + VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir); + VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor); + VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor); + VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod); + rsurface.colormod[3] = ent->alpha; + VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod); memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend)); rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0; rsurface.basepolygonfactor = r_refdef.polygonfactor; @@ -8694,6 +9044,13 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale; rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale; rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip; + VectorSet(rsurface.modellight_ambient, 0, 0, 0); + VectorSet(rsurface.modellight_diffuse, 0, 0, 0); + VectorSet(rsurface.modellight_lightdir, 0, 0, 1); + VectorSet(rsurface.colormap_pantscolor, 0, 0, 0); + VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0); + Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a); + VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value); memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend)); rsurface.frameblend[0].lerp = 1; rsurface.ent_alttextures = false; @@ -10314,9 +10671,9 @@ static void RSurf_DrawBatch_GL11_ApplyAmbient(void) rsurface.passcolor4f_bufferoffset = 0; for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4) { - c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0]; - c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1]; - c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2]; + c2[0] = c[0] + r_refdef.scene.ambient; + c2[1] = c[1] + r_refdef.scene.ambient; + c2[2] = c[2] + r_refdef.scene.ambient; c2[3] = c[3]; } } @@ -10380,7 +10737,7 @@ static void RSurf_DrawBatch_GL11_ClampColor(void) } } -static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity) +static void RSurf_DrawBatch_GL11_ApplyFakeLight(void) { int i; float f; @@ -10398,14 +10755,14 @@ static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity) f = -DotProduct(r_refdef.view.forward, n); f = max(0, f); f = f * 0.85 + 0.15; // work around so stuff won't get black - f *= fakelightintensity; + f *= r_refdef.lightmapintensity; Vector4Set(c, f, f, f, 1); } } static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) { - RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value); + RSurf_DrawBatch_GL11_ApplyFakeLight(); if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(); if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a); R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset); @@ -10413,7 +10770,7 @@ static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, q RSurf_DrawBatch(); } -static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor) +static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor) { int i; float f; @@ -10426,14 +10783,14 @@ static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, vec3_t lightdir; // TODO: optimize // model lighting - VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir); - f = 0.5f * lightmapintensity; - ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f; - ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f; - ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f; - diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f; - diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f; - diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f; + VectorCopy(rsurface.modellight_lightdir, lightdir); + f = 0.5f * r_refdef.lightmapintensity; + ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f; + ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f; + ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f; + diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f; + diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f; + diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f; alpha = *a; if (VectorLength2(diffusecolor) > 0) { @@ -10468,7 +10825,7 @@ static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog) { - RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor); + RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor); if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(); if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a); R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset); @@ -10621,7 +10978,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface { // render screenspace normalmap to texture GL_DepthMask(true); - R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false); RSurf_DrawBatch(); return; } @@ -10649,18 +11006,18 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface { // render water or distortion background GL_DepthMask(true); - R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false); RSurf_DrawBatch(); // blend surface on top GL_DepthMask(false); - R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false); RSurf_DrawBatch(); } else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)) { // render surface with reflection texture as input GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); - R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false); RSurf_DrawBatch(); } } @@ -10669,7 +11026,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface // render surface batch normally GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); - R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0); RSurf_DrawBatch(); } @@ -10680,7 +11037,7 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface qboolean applyfog; int layerindex; const texturelayer_t *layer; - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++) @@ -10787,7 +11144,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface qboolean applyfog; int layerindex; const texturelayer_t *layer; - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++) @@ -10892,15 +11249,14 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const int j; r_vertexgeneric_t *batchvertex; float c[4]; - texture_t *t = rsurface.texture; // R_Mesh_ResetTextureState(); R_SetupShader_Generic_NoTexture(false, false); - if(t && t->currentskinframe) + if(rsurface.texture && rsurface.texture->currentskinframe) { - memcpy(c, t->currentskinframe->avgcolor, sizeof(c)); - c[3] *= t->currentalpha; + memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c)); + c[3] *= rsurface.texture->currentalpha; } else { @@ -10910,11 +11266,11 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const c[3] = 1; } - if (t->pantstexture || t->shirttexture) + if (rsurface.texture->pantstexture || rsurface.texture->shirttexture) { - c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7); - c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7); - c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7); + c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7); + c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7); + c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7); } // brighten it up (as texture value 127 means "unlit") @@ -10922,27 +11278,27 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const c[1] *= 2 * r_refdef.view.colorscale; c[2] *= 2 * r_refdef.view.colorscale; - if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA) + if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA) c[3] *= r_wateralpha.value; - if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1) + if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1) { GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); } - else if(t->currentmaterialflags & MATERIALFLAG_ADD) + else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD) { GL_BlendFunc(GL_ONE, GL_ONE); GL_DepthMask(false); } - else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST) + else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) { GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead GL_DepthMask(false); } - else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) + else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) { - GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]); + GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]); GL_DepthMask(false); } else @@ -10955,20 +11311,32 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const { rsurface.passcolor4f = NULL; - if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT) + if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) + { + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); + + rsurface.passcolor4f = NULL; + rsurface.passcolor4f_vertexbuffer = 0; + rsurface.passcolor4f_bufferoffset = 0; + } + else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) { qboolean applycolor = true; float one = 1.0; RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); - RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor); + r_refdef.lightmapintensity = 1; + RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor); + r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all } else if (FAKELIGHT_ENABLED) { RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); - RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value); + r_refdef.lightmapintensity = r_fakelight_intensity.value; + RSurf_DrawBatch_GL11_ApplyFakeLight(); + r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all } else { @@ -10977,12 +11345,12 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const rsurface.passcolor4f = rsurface.batchlightmapcolor4f; rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer; rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset; - RSurf_DrawBatch_GL11_ApplyAmbient(); } if(!rsurface.passcolor4f) RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(); + RSurf_DrawBatch_GL11_ApplyAmbient(); RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]); if(r_refdef.fogenabled) RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(); @@ -11061,6 +11429,36 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const } } +static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass) +{ + CHECKGLERROR + RSurf_SetupDepthAndCulling(); + if (r_showsurfaces.integer) + { + R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth); + return; + } + switch (vid.renderpath) + { + case RENDERPATH_GL20: + case RENDERPATH_D3D9: + case RENDERPATH_D3D10: + case RENDERPATH_D3D11: + case RENDERPATH_SOFT: + case RENDERPATH_GLES2: + R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass); + break; + case RENDERPATH_GL13: + case RENDERPATH_GLES1: + R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth); + break; + case RENDERPATH_GL11: + R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth); + break; + } + CHECKGLERROR +} + static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass) { CHECKGLERROR @@ -11099,7 +11497,12 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const const msurface_t *surface; const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE]; - if (r_showsurfaces.integer && r_showsurfaces.integer != 3) + // if the model is static it doesn't matter what value we give for + // wantnormals and wanttangents, so this logic uses only rules applicable + // to a model, knowing that they are meaningless otherwise + if (ent == r_refdef.scene.worldentity) + RSurf_ActiveWorldEntity(); + else if (r_showsurfaces.integer && r_showsurfaces.integer != 3) RSurf_ActiveModelEntity(ent, false, false, false); else { @@ -11204,9 +11607,12 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const } } // render the range of surfaces - R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false); + if (ent == r_refdef.scene.worldentity) + R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false); + else + R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false); } - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist) @@ -11254,6 +11660,84 @@ static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msu RSurf_DrawBatch(); } +static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass) +{ + CHECKGLERROR + if (depthonly) + R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist); + else if (prepass) + { + if (!rsurface.texture->currentnumlayers) + return; + if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) + R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist); + else + R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass); + } + else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3)) + R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); + else if (!rsurface.texture->currentnumlayers) + return; + else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)))) + { + // in the deferred case, transparent surfaces were queued during prepass + if (!r_shadow_usingdeferredprepass) + R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist); + } + else + { + // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier + R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass); + } + CHECKGLERROR +} + +static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass) +{ + int i, j; + texture_t *texture; + R_FrameData_SetMark(); + // break the surface list down into batches by texture and use of lightmapping + for (i = 0;i < numsurfaces;i = j) + { + j = i + 1; + // texture is the base texture pointer, rsurface.texture is the + // current frame/skin the texture is directing us to use (for example + // if a model has 2 skins and it is on skin 1, then skin 0 tells us to + // use skin 1 instead) + texture = surfacelist[i]->texture; + rsurface.texture = R_GetCurrentTexture(texture); + if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)) + { + // if this texture is not the kind we want, skip ahead to the next one + for (;j < numsurfaces && texture == surfacelist[j]->texture;j++) + ; + continue; + } + if(FAKELIGHT_ENABLED || depthonly || prepass) + { + rsurface.lightmaptexture = NULL; + rsurface.deluxemaptexture = NULL; + rsurface.uselightmaptexture = false; + // simply scan ahead until we find a different texture or lightmap state + for (;j < numsurfaces && texture == surfacelist[j]->texture;j++) + ; + } + else + { + rsurface.lightmaptexture = surfacelist[i]->lightmaptexture; + rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture; + rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL; + // simply scan ahead until we find a different texture or lightmap state + for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++) + ; + } + // render the range of surfaces + R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass); + } + R_FrameData_ReturnToMark(); +} + static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass) { CHECKGLERROR @@ -11919,7 +12403,10 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) // if the model is static it doesn't matter what value we give for // wantnormals and wanttangents, so this logic uses only rules applicable // to a model, knowing that they are meaningless otherwise - RSurf_ActiveModelEntity(ent, false, false, false); + if (ent == r_refdef.scene.worldentity) + RSurf_ActiveWorldEntity(); + else + RSurf_ActiveModelEntity(ent, false, false, false); decalsystem->lastupdatetime = r_refdef.scene.time; @@ -12272,6 +12759,101 @@ static void R_DrawDebugModel(void) int r_maxsurfacelist = 0; const msurface_t **r_surfacelist = NULL; +void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass) +{ + int i, j, endj, flagsmask; + dp_model_t *model = r_refdef.scene.worldmodel; + msurface_t *surfaces; + unsigned char *update; + int numsurfacelist = 0; + if (model == NULL) + return; + + if (r_maxsurfacelist < model->num_surfaces) + { + r_maxsurfacelist = model->num_surfaces; + if (r_surfacelist) + Mem_Free((msurface_t**)r_surfacelist); + r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist)); + } + + RSurf_ActiveWorldEntity(); + + surfaces = model->data_surfaces; + update = model->brushq1.lightmapupdateflags; + + // update light styles on this submodel + if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) + { + model_brush_lightstyleinfo_t *style; + for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++) + { + if (style->value != r_refdef.scene.lightstylevalue[style->style]) + { + int *list = style->surfacelist; + style->value = r_refdef.scene.lightstylevalue[style->style]; + for (j = 0;j < style->numsurfaces;j++) + update[list[j]] = true; + } + } + } + + flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL; + + if (debug) + { + R_DrawDebugModel(); + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity + return; + } + + rsurface.lightmaptexture = NULL; + rsurface.deluxemaptexture = NULL; + rsurface.uselightmaptexture = false; + rsurface.texture = NULL; + rsurface.rtlight = NULL; + numsurfacelist = 0; + // add visible surfaces to draw list + for (i = 0;i < model->nummodelsurfaces;i++) + { + j = model->sortedmodelsurfaces[i]; + if (r_refdef.viewcache.world_surfacevisible[j]) + r_surfacelist[numsurfacelist++] = surfaces + j; + } + // update lightmaps if needed + if (model->brushq1.firstrender) + { + model->brushq1.firstrender = false; + for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++) + if (update[j]) + R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j); + } + else if (update) + { + for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++) + if (r_refdef.viewcache.world_surfacevisible[j]) + if (update[j]) + R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j); + } + // don't do anything if there were no surfaces + if (!numsurfacelist) + { + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity + return; + } + R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass); + + // add to stats if desired + if (r_speeds.integer && !skysurfaces && !depthonly) + { + r_refdef.stats[r_stat_world_surfaces] += numsurfacelist; + for (j = 0;j < numsurfacelist;j++) + r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles; + } + + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity +} + void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass) { int i, j, endj, flagsmask; @@ -12290,7 +12872,12 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist)); } - if (r_showsurfaces.integer && r_showsurfaces.integer != 3) + // if the model is static it doesn't matter what value we give for + // wantnormals and wanttangents, so this logic uses only rules applicable + // to a model, knowing that they are meaningless otherwise + if (ent == r_refdef.scene.worldentity) + RSurf_ActiveWorldEntity(); + else if (r_showsurfaces.integer && r_showsurfaces.integer != 3) RSurf_ActiveModelEntity(ent, false, false, false); else if (prepass) RSurf_ActiveModelEntity(ent, true, true, true); @@ -12337,7 +12924,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr update = model->brushq1.lightmapupdateflags; // update light styles - if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0) + if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { model_brush_lightstyleinfo_t *style; for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++) @@ -12357,7 +12944,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr if (debug) { R_DrawDebugModel(); - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity return; } @@ -12368,26 +12955,12 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr rsurface.rtlight = NULL; numsurfacelist = 0; // add visible surfaces to draw list - if (ent == r_refdef.scene.worldentity) - { - // for the world entity, check surfacevisible - for (i = 0;i < model->nummodelsurfaces;i++) - { - j = model->sortedmodelsurfaces[i]; - if (r_refdef.viewcache.world_surfacevisible[j]) - r_surfacelist[numsurfacelist++] = surfaces + j; - } - } - else - { - // add all surfaces - for (i = 0; i < model->nummodelsurfaces; i++) - r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i]; - } + for (i = 0;i < model->nummodelsurfaces;i++) + r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i]; // don't do anything if there were no surfaces if (!numsurfacelist) { - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity return; } // update lightmaps if needed @@ -12414,12 +12987,11 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles; } - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass) { - int q; static texture_t texture; static msurface_t surface; const msurface_t *surfacelist = &surface; @@ -12439,21 +13011,6 @@ void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, i // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS // JUST GREP FOR "specularscalemod = 1". - for (q = 0; q < 3; q++) - { - texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value; - texture.render_modellight_lightdir[q] = q == 2; - texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity; - texture.render_modellight_diffuse[q] = r_refdef.view.colorscale; - texture.render_modellight_specular[q] = r_refdef.view.colorscale; - texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity; - texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity; - texture.render_lightmap_specular[q] = r_refdef.view.colorscale; - texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale; - texture.render_rtlight_specular[q] = r_refdef.view.colorscale; - } - texture.currentalpha = 1.0f; - surface.texture = &texture; surface.num_triangles = numtriangles; surface.num_firsttriangle = firsttriangle; diff --git a/gl_rsurf.c b/gl_rsurf.c index 0bec0bde..0c9e85dc 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -583,7 +583,10 @@ void R_Q1BSP_DrawSky(entity_render_t *ent) { if (ent->model == NULL) return; - R_DrawModelSurfaces(ent, true, true, false, false, false); + if (ent == r_refdef.scene.worldentity) + R_DrawWorldSurfaces(true, true, false, false, false); + else + R_DrawModelSurfaces(ent, true, true, false, false, false); } void R_Q1BSP_DrawAddWaterPlanes(entity_render_t *ent) @@ -594,7 +597,10 @@ void R_Q1BSP_DrawAddWaterPlanes(entity_render_t *ent) if (model == NULL) return; - RSurf_ActiveModelEntity(ent, true, false, false); + if (ent == r_refdef.scene.worldentity) + RSurf_ActiveWorldEntity(); + else + RSurf_ActiveModelEntity(ent, true, false, false); surfaces = model->data_surfaces; flagsmask = MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA; @@ -623,7 +629,7 @@ void R_Q1BSP_DrawAddWaterPlanes(entity_render_t *ent) R_Water_AddWaterPlane(surfaces + j, n); } } - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } void R_Q1BSP_Draw(entity_render_t *ent) @@ -631,7 +637,10 @@ void R_Q1BSP_Draw(entity_render_t *ent) dp_model_t *model = ent->model; if (model == NULL) return; - R_DrawModelSurfaces(ent, false, true, false, false, false); + if (ent == r_refdef.scene.worldentity) + R_DrawWorldSurfaces(false, true, false, false, false); + else + R_DrawModelSurfaces(ent, false, true, false, false, false); } void R_Q1BSP_DrawDepth(entity_render_t *ent) @@ -645,7 +654,10 @@ void R_Q1BSP_DrawDepth(entity_render_t *ent) GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); // R_Mesh_ResetTextureState(); - R_DrawModelSurfaces(ent, false, false, true, false, false); + if (ent == r_refdef.scene.worldentity) + R_DrawWorldSurfaces(false, false, true, false, false); + else + R_DrawModelSurfaces(ent, false, false, true, false, false); GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); } @@ -653,7 +665,10 @@ void R_Q1BSP_DrawDebug(entity_render_t *ent) { if (ent->model == NULL) return; - R_DrawModelSurfaces(ent, false, false, false, true, false); + if (ent == r_refdef.scene.worldentity) + R_DrawWorldSurfaces(false, false, false, true, false); + else + R_DrawModelSurfaces(ent, false, false, false, true, false); } void R_Q1BSP_DrawPrepass(entity_render_t *ent) @@ -661,7 +676,10 @@ void R_Q1BSP_DrawPrepass(entity_render_t *ent) dp_model_t *model = ent->model; if (model == NULL) return; - R_DrawModelSurfaces(ent, false, true, false, false, true); + if (ent == r_refdef.scene.worldentity) + R_DrawWorldSurfaces(false, true, false, false, true); + else + R_DrawModelSurfaces(ent, false, true, false, false, true); } typedef struct r_q1bsp_getlightinfo_s @@ -1239,7 +1257,7 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa info.pvs = info.model->brush.GetPVS(info.model, info.relativelightorigin); else info.pvs = NULL; - RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false); + RSurf_ActiveWorldEntity(); if (!info.noocclusion && r_shadow_compilingrtlight && r_shadow_realtime_world_compileportalculling.integer && info.model->brush.data_portals) { @@ -1260,7 +1278,7 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa R_Q1BSP_CallRecursiveGetLightInfo(&info, !info.noocclusion && (r_shadow_compilingrtlight ? r_shadow_realtime_world_compilesvbsp.integer : r_shadow_realtime_dlight_svbspculling.integer) != 0); } - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity // limit combined leaf box to light boundaries outmins[0] = max(info.outmins[0] - 1, info.lightmins[0]); @@ -1500,7 +1518,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface ; // now figure out what to do with this particular range of surfaces // VorteX: added MATERIALFLAG_NORTLIGHT - if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NORTLIGHT)) != MATERIALFLAG_WALL) + if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NORTLIGHT)) != MATERIALFLAG_WALL) continue; if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))) continue; diff --git a/model_brush.h b/model_brush.h index 2eb38470..fb167321 100644 --- a/model_brush.h +++ b/model_brush.h @@ -115,13 +115,15 @@ mplane_t; #define MATERIALFLAG_REFLECTION 0x00100000 // use model lighting on this material (q1bsp lightmap sampling or q3bsp lightgrid, implies FULLBRIGHT is false) #define MATERIALFLAG_MODELLIGHT 0x00200000 +// add directional model lighting to this material (q3bsp lightgrid only) +#define MATERIALFLAG_MODELLIGHT_DIRECTIONAL 0x00400000 // causes RSurf_GetCurrentTexture to leave alone certain fields #define MATERIALFLAG_CUSTOMSURFACE 0x00800000 // causes MATERIALFLAG_BLENDED to render a depth pass before rendering, hiding backfaces and other hidden geometry #define MATERIALFLAG_TRANSDEPTH 0x01000000 // like refraction, but doesn't distort etc. #define MATERIALFLAG_CAMERA 0x02000000 -// disable rtlight on surface - does not disable other types of lighting (LIGHTMAP, MODELLIGHT) +// disable rtlight on surface, use R_LightPoint instead #define MATERIALFLAG_NORTLIGHT 0x04000000 // alphagen vertex #define MATERIALFLAG_ALPHAGEN_VERTEX 0x08000000 diff --git a/model_shared.h b/model_shared.h index f913e4bd..d2c765c5 100644 --- a/model_shared.h +++ b/model_shared.h @@ -614,29 +614,14 @@ typedef struct texture_s rtexture_t *backgroundnmaptexture; // normalmap (bumpmap for dot3) rtexture_t *backgroundglosstexture; // glossmap (for dot3) rtexture_t *backgroundglowtexture; // glow only (fullbrights) + float specularscale; float specularpower; - - // rendering parameters - updated by R_GetCurrentTexture using rsurface.render_* fields - // (almost) all map textures are lightmap (no MATERIALFLAG_MODELLIGHT set), - // (almost) all model textures are MATERIALFLAG_MODELLIGHT, - // MATERIALFLAG_FULLBRIGHT is rendered as a forced MATERIALFLAG_MODELLIGHT with rtlights disabled - float render_glowmod[3]; - // MATERIALFLAG_MODELLIGHT uses these parameters - float render_modellight_ambient[3]; - float render_modellight_diffuse[3]; - float render_modellight_lightdir[3]; - float render_modellight_specular[3]; - // lightmap rendering (not MATERIALFLAG_MODELLIGHT) - float render_lightmap_ambient[3]; - float render_lightmap_diffuse[3]; - float render_lightmap_specular[3]; - // rtlights use these colors for the materials on this entity - float render_rtlight_diffuse[3]; - float render_rtlight_specular[3]; - // tint applied on top of render_*_diffuse for pants layer - float render_colormap_pants[3]; - // tint applied on top of render_*_diffuse for shirt layer - float render_colormap_shirt[3]; + // color tint (colormod * currentalpha) used for rtlighting this material + float dlightcolor[3]; + // color tint (colormod * 2) used for lightmapped lighting on this material + // includes alpha as 4th component + // replaces role of gl_Color in GLSL shader + float lightmapcolor[4]; // from q3 shaders int customblendfunc[2]; diff --git a/mvm_cmds.c b/mvm_cmds.c index a310b0e7..ace22bfa 100644 --- a/mvm_cmds.c +++ b/mvm_cmds.c @@ -1624,8 +1624,7 @@ void MVM_init_cmd(prvm_prog_t *prog) scene->maxentities = MAX_EDICTS + 256 + 512; scene->entities = (entity_render_t **)Mem_Alloc(prog->progs_mempool, sizeof(entity_render_t *) * scene->maxentities); - // LadyHavoc: what is this for? - scene->ambientintensity = 32.0f; + scene->ambient = 32.0f; } void MVM_reset_cmd(prvm_prog_t *prog) diff --git a/r_shadow.c b/r_shadow.c index 44fd8f29..2d173461 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -3884,10 +3884,10 @@ static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, cons RSurf_DrawBatch(); } -static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3], const float specularcolor[3]) +static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale) { // ARB2 GLSL shader path (GFFX5200, Radeon 9500) - R_SetupShader_Surface(ambientcolor, diffusecolor, specularcolor, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false); + R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false); RSurf_DrawBatch(); } @@ -3980,26 +3980,29 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve } } -static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3]) +static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale) { // OpenGL 1.1 path (anything) float ambientcolorbase[3], diffusecolorbase[3]; float ambientcolorpants[3], diffusecolorpants[3]; float ambientcolorshirt[3], diffusecolorshirt[3]; - const float *surfacepants = rsurface.texture->render_colormap_pants; - const float *surfaceshirt = rsurface.texture->render_colormap_shirt; + const float *surfacecolor = rsurface.texture->dlightcolor; + const float *surfacepants = rsurface.colormap_pantscolor; + const float *surfaceshirt = rsurface.colormap_shirtcolor; rtexture_t *basetexture = rsurface.texture->basetexture; rtexture_t *pantstexture = rsurface.texture->pantstexture; rtexture_t *shirttexture = rsurface.texture->shirttexture; qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f); qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f); - VectorCopy(ambientcolor, ambientcolorbase); - VectorCopy(diffusecolor, diffusecolorbase); + ambientscale *= 2 * r_refdef.view.colorscale; + diffusescale *= 2 * r_refdef.view.colorscale; + ambientcolorbase[0] = lightcolor[0] * ambientscale * surfacecolor[0];ambientcolorbase[1] = lightcolor[1] * ambientscale * surfacecolor[1];ambientcolorbase[2] = lightcolor[2] * ambientscale * surfacecolor[2]; + diffusecolorbase[0] = lightcolor[0] * diffusescale * surfacecolor[0];diffusecolorbase[1] = lightcolor[1] * diffusescale * surfacecolor[1];diffusecolorbase[2] = lightcolor[2] * diffusescale * surfacecolor[2]; ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2]; diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2]; ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2]; diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2]; - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (VectorLength2(diffusecolor) > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); rsurface.passcolor4f = (float *)R_FrameData_Alloc((rsurface.batchfirstvertex + rsurface.batchnumvertices) * sizeof(float[4])); R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0); @@ -4049,28 +4052,25 @@ static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const m extern cvar_t gl_lightmaps; void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist) { + float ambientscale, diffusescale, specularscale; qboolean negated; - float ambientcolor[3], diffusecolor[3], specularcolor[3]; - VectorM(rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient, rsurface.texture->render_rtlight_diffuse, ambientcolor); - VectorM(rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient), rsurface.texture->render_rtlight_diffuse, diffusecolor); - VectorM(rsurface.rtlight->specularscale, rsurface.texture->render_rtlight_specular, specularcolor); + float lightcolor[3]; + VectorCopy(rsurface.rtlight->currentcolor, lightcolor); + ambientscale = rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient; + diffusescale = rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient); + specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale; if (!r_shadow_usenormalmap.integer) { - VectorMAM(1.0f, ambientcolor, 1.0f, diffusecolor, ambientcolor); - VectorClear(diffusecolor); - VectorClear(specularcolor); + ambientscale += 1.0f * diffusescale; + diffusescale = 0; + specularscale = 0; } - VectorMultiply(ambientcolor, rsurface.rtlight->currentcolor, ambientcolor); - VectorMultiply(diffusecolor, rsurface.rtlight->currentcolor, diffusecolor); - VectorMultiply(specularcolor, rsurface.rtlight->currentcolor, specularcolor); - if (VectorLength2(ambientcolor) + VectorLength2(diffusecolor) + VectorLength2(specularcolor) < (1.0f / 1048576.0f)) + if ((ambientscale + diffusescale) * VectorLength2(lightcolor) + specularscale * VectorLength2(lightcolor) < (1.0f / 1048576.0f)) return; - negated = (rsurface.rtlight->currentcolor[0] + rsurface.rtlight->currentcolor[1] + rsurface.rtlight->currentcolor[2] < 0) && vid.support.ext_blend_subtract; + negated = (lightcolor[0] + lightcolor[1] + lightcolor[2] < 0) && vid.support.ext_blend_subtract; if(negated) { - VectorNegate(ambientcolor, ambientcolor); - VectorNegate(diffusecolor, diffusecolor); - VectorNegate(specularcolor, specularcolor); + VectorNegate(lightcolor, lightcolor); GL_BlendEquationSubtract(true); } RSurf_SetupDepthAndCulling(); @@ -4081,13 +4081,13 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist); break; case R_SHADOW_RENDERMODE_LIGHT_GLSL: - R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, ambientcolor, diffusecolor, specularcolor); + R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale, specularscale); break; case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX: - R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, ambientcolor, diffusecolor); + R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale); break; default: Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode); @@ -4464,7 +4464,7 @@ static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist { shadowmesh_t *mesh; - RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false); + RSurf_ActiveWorldEntity(); if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer) { @@ -4484,7 +4484,7 @@ static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist else if (r_refdef.scene.worldentity->model) r_refdef.scene.worldmodel->DrawShadowMap(r_shadow_shadowmapside, r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, surfacesides, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs); - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs) @@ -4499,7 +4499,7 @@ static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacel if (r_refdef.scene.worldmodel->brush.shadowmesh ? !r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i : !r_refdef.scene.worldmodel->surfmesh.data_neighbor3i) return; - RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false); + RSurf_ActiveWorldEntity(); if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer) { @@ -4556,7 +4556,7 @@ static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacel r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs); } - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } static void R_Shadow_DrawEntityShadow(entity_render_t *ent) @@ -4582,7 +4582,7 @@ static void R_Shadow_DrawEntityShadow(entity_render_t *ent) ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs); break; } - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } void R_Shadow_SetupEntityLight(const entity_render_t *ent) @@ -4601,7 +4601,7 @@ static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const uns return; // set up properties for rendering light onto this entity - RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false); + RSurf_ActiveWorldEntity(); rsurface.entitytolight = rsurface.rtlight->matrix_worldtolight; Matrix4x4_Concat(&rsurface.entitytoattenuationxyz, &matrix_attenuationxyz, &rsurface.entitytolight); Matrix4x4_Concat(&rsurface.entitytoattenuationz, &matrix_attenuationz, &rsurface.entitytolight); @@ -4609,7 +4609,7 @@ static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const uns r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, lighttrispvs); - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } static void R_Shadow_DrawEntityLight(entity_render_t *ent) @@ -4622,7 +4622,7 @@ static void R_Shadow_DrawEntityLight(entity_render_t *ent) model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL); - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } static void R_Shadow_PrepareLight(rtlight_t *rtlight) @@ -5572,7 +5572,7 @@ void R_Shadow_PrepareModelShadows(void) r_shadow_nummodelshadows = 0; r_shadow_shadowmapatlas_modelshadows_size = 0; - if (!r_refdef.scene.numentities || r_refdef.scene.lightmapintensity <= 0.0f || r_shadows.integer <= 0) + if (!r_refdef.scene.numentities || r_refdef.lightmapintensity <= 0.0f || r_shadows.integer <= 0) return; switch (r_shadow_shadowmode) @@ -5740,7 +5740,7 @@ static void R_Shadow_DrawModelShadowMaps(void) relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2])); RSurf_ActiveModelEntity(ent, false, false, false); ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs); - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } #if 0 @@ -5837,14 +5837,45 @@ void R_Shadow_DrawModelShadows(void) Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection); else { - VectorNegate(ent->render_modellight_lightdir, tmp); - Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection); + if(ent->entitynumber != 0) + { + if(ent->entitynumber >= MAX_EDICTS) // csqc entity + { + // FIXME handle this + VectorNegate(ent->modellight_lightdir, relativelightdirection); + } + else + { + // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities) + int entnum, entnum2, recursion; + entnum = entnum2 = ent->entitynumber; + for(recursion = 32; recursion > 0; --recursion) + { + entnum2 = cl.entities[entnum].state_current.tagentity; + if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2]) + entnum = entnum2; + else + break; + } + if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain + { + VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection); + // transform into modelspace of OUR entity + Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp); + Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection); + } + else + VectorNegate(ent->modellight_lightdir, relativelightdirection); + } + } + else + VectorNegate(ent->modellight_lightdir, relativelightdirection); } VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin); RSurf_ActiveModelEntity(ent, false, false, false); ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs); - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } // not really the right mode, but this will disable any silly stencil features @@ -6079,7 +6110,7 @@ void R_Shadow_DrawCoronas(void) qglGenQueriesARB(r_maxqueries - i, r_queries + i); CHECKGLERROR } - RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false); + RSurf_ActiveWorldEntity(); GL_BlendFunc(GL_ONE, GL_ZERO); GL_CullFace(GL_NONE); GL_DepthMask(false); @@ -7543,48 +7574,141 @@ LIGHT SAMPLING ============================================================================= */ -void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const vec3_t p, const int flags, float lightmapintensity, float ambientintensity) +void R_LightPoint(float *color, const vec3_t p, const int flags) { - int i, numlights, flag, q; + int i, numlights, flag; + float f, relativepoint[3], dist, dist2, lightradius2; + vec3_t diffuse, n; + rtlight_t *light; + dlight_t *dlight; + + if (r_fullbright.integer) + { + VectorSet(color, 1, 1, 1); + return; + } + + VectorClear(color); + + if (flags & LP_LIGHTMAP) + { + if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint) + { + VectorClear(diffuse); + r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, color, diffuse, n); + VectorAdd(color, diffuse, color); + } + else + VectorSet(color, 1, 1, 1); + color[0] += r_refdef.scene.ambient; + color[1] += r_refdef.scene.ambient; + color[2] += r_refdef.scene.ambient; + } + + if (flags & LP_RTWORLD) + { + flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; + numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); + for (i = 0; i < numlights; i++) + { + dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i); + if (!dlight) + continue; + light = &dlight->rtlight; + if (!(light->flags & flag)) + continue; + // sample + lightradius2 = light->radius * light->radius; + VectorSubtract(light->shadoworigin, p, relativepoint); + dist2 = VectorLength2(relativepoint); + if (dist2 >= lightradius2) + continue; + dist = sqrt(dist2) / light->radius; + f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0; + if (f <= 0) + continue; + // todo: add to both ambient and diffuse + if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1) + VectorMA(color, f, light->currentcolor, color); + } + } + if (flags & LP_DYNLIGHT) + { + // sample dlights + for (i = 0;i < r_refdef.scene.numlights;i++) + { + light = r_refdef.scene.lights[i]; + // sample + lightradius2 = light->radius * light->radius; + VectorSubtract(light->shadoworigin, p, relativepoint); + dist2 = VectorLength2(relativepoint); + if (dist2 >= lightradius2) + continue; + dist = sqrt(dist2) / light->radius; + f = dist < 1 ? (r_shadow_lightintensityscale.value * ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist))) : 0; + if (f <= 0) + continue; + // todo: add to both ambient and diffuse + if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1) + VectorMA(color, f, light->color, color); + } + } +} + +void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const vec3_t p, const int flags) +{ + int i, numlights, flag; rtlight_t *light; dlight_t *dlight; float relativepoint[3]; float color[3]; + float dir[3]; float dist; float dist2; float intensity; - float sa[3], sx[3], sy[3], sz[3], sd[3]; + float sample[5*3]; float lightradius2; - // use first order spherical harmonics to combine directional lights - for (q = 0; q < 3; q++) - sa[q] = sx[q] = sy[q] = sz[q] = sd[q] = 0; + if (r_fullbright.integer) + { + VectorSet(ambient, 1, 1, 1); + VectorClear(diffuse); + VectorClear(lightdir); + return; + } - if (flags & LP_LIGHTMAP) + if (flags == LP_LIGHTMAP) { + VectorSet(ambient, r_refdef.scene.ambient, r_refdef.scene.ambient, r_refdef.scene.ambient); + VectorClear(diffuse); + VectorClear(lightdir); if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint) - { - float tempambient[3]; - for (q = 0; q < 3; q++) - tempambient[q] = color[q] = relativepoint[q] = 0; - r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, tempambient, color, relativepoint); - // calculate a weighted average light direction as well - intensity = VectorLength(color); - for (q = 0; q < 3; q++) - { - sa[q] += (0.5f * color[q] + tempambient[q]) * lightmapintensity; - sx[q] += (relativepoint[0] * color[q]) * lightmapintensity; - sy[q] += (relativepoint[1] * color[q]) * lightmapintensity; - sz[q] += (relativepoint[2] * color[q]) * lightmapintensity; - sd[q] += (intensity * relativepoint[q]) * lightmapintensity; - } - } + r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, ambient, diffuse, lightdir); else - { - // unlit map - fullbright but scaled by lightmapintensity - for (q = 0; q < 3; q++) - sa[q] += lightmapintensity; - } + VectorSet(ambient, 1, 1, 1); + return; + } + + memset(sample, 0, sizeof(sample)); + VectorSet(sample, r_refdef.scene.ambient, r_refdef.scene.ambient, r_refdef.scene.ambient); + + if ((flags & LP_LIGHTMAP) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint) + { + vec3_t tempambient; + VectorClear(tempambient); + VectorClear(color); + VectorClear(relativepoint); + r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, p, tempambient, color, relativepoint); + VectorScale(tempambient, r_refdef.lightmapintensity, tempambient); + VectorScale(color, r_refdef.lightmapintensity, color); + VectorAdd(sample, tempambient, sample); + VectorMA(sample , 0.5f , color, sample ); + VectorMA(sample + 3, relativepoint[0], color, sample + 3); + VectorMA(sample + 6, relativepoint[1], color, sample + 6); + VectorMA(sample + 9, relativepoint[2], color, sample + 9); + // calculate a weighted average light direction as well + intensity = VectorLength(color); + VectorMA(sample + 12, intensity, relativepoint, sample + 12); } if (flags & LP_RTWORLD) @@ -7611,18 +7735,17 @@ void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const continue; if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) continue; - for (q = 0; q < 3; q++) - color[q] = light->currentcolor[q] * intensity; - intensity = VectorLength(color); + // scale down intensity to add to both ambient and diffuse + //intensity *= 0.5f; VectorNormalize(relativepoint); - for (q = 0; q < 3; q++) - { - sa[q] += 0.5f * color[q]; - sx[q] += relativepoint[0] * color[q]; - sy[q] += relativepoint[1] * color[q]; - sz[q] += relativepoint[2] * color[q]; - sd[q] += intensity * relativepoint[q]; - } + VectorScale(light->currentcolor, intensity, color); + VectorMA(sample , 0.5f , color, sample ); + VectorMA(sample + 3, relativepoint[0], color, sample + 3); + VectorMA(sample + 6, relativepoint[1], color, sample + 6); + VectorMA(sample + 9, relativepoint[2], color, sample + 9); + // calculate a weighted average light direction as well + intensity *= VectorLength(color); + VectorMA(sample + 12, intensity, relativepoint, sample + 12); } // FIXME: sample bouncegrid too! } @@ -7645,30 +7768,30 @@ void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const continue; if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) continue; - for (q = 0; q < 3; q++) - color[q] = light->currentcolor[q] * intensity; - intensity = VectorLength(color); + // scale down intensity to add to both ambient and diffuse + //intensity *= 0.5f; VectorNormalize(relativepoint); - for (q = 0; q < 3; q++) - { - sa[q] += 0.5f * color[q]; - sx[q] += relativepoint[0] * color[q]; - sy[q] += relativepoint[1] * color[q]; - sz[q] += relativepoint[2] * color[q]; - sd[q] += intensity * relativepoint[q]; - } + VectorScale(light->currentcolor, intensity, color); + VectorMA(sample , 0.5f , color, sample ); + VectorMA(sample + 3, relativepoint[0], color, sample + 3); + VectorMA(sample + 6, relativepoint[1], color, sample + 6); + VectorMA(sample + 9, relativepoint[2], color, sample + 9); + // calculate a weighted average light direction as well + intensity *= VectorLength(color); + VectorMA(sample + 12, intensity, relativepoint, sample + 12); } } - // calculate the weighted-average light direction (bentnormal) - for (q = 0; q < 3; q++) - lightdir[q] = sd[q]; - VectorNormalize(lightdir); - for (q = 0; q < 3; q++) - { - // extract the diffuse color along the chosen direction and scale it - diffuse[q] = (lightdir[0] * sx[q] + lightdir[1] * sy[q] + lightdir[2] * sz[q]); - // subtract some of diffuse from ambient - ambient[q] = sa[q] + -0.333f * diffuse[q] + ambientintensity; - } + // calculate the direction we'll use to reduce the sample to a directional light source + VectorCopy(sample + 12, dir); + //VectorSet(dir, sample[3] + sample[4] + sample[5], sample[6] + sample[7] + sample[8], sample[9] + sample[10] + sample[11]); + VectorNormalize(dir); + // extract the diffuse color along the chosen direction and scale it + diffuse[0] = (dir[0]*sample[3] + dir[1]*sample[6] + dir[2]*sample[ 9] + sample[ 0]); + diffuse[1] = (dir[0]*sample[4] + dir[1]*sample[7] + dir[2]*sample[10] + sample[ 1]); + diffuse[2] = (dir[0]*sample[5] + dir[1]*sample[8] + dir[2]*sample[11] + sample[ 2]); + // subtract some of diffuse from ambient + VectorMA(sample, -0.333f, diffuse, ambient); + // store the normalized lightdir + VectorCopy(dir, lightdir); } diff --git a/r_shadow.h b/r_shadow.h index 809805eb..3346b77e 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -159,7 +159,8 @@ void R_Shadow_PrepareModelShadows(void); #define LP_LIGHTMAP 1 #define LP_RTWORLD 2 #define LP_DYNLIGHT 4 -void R_CompleteLightPoint(float *ambient, float *diffuse, float *lightdir, const vec3_t p, const int flags, float lightmapintensity, float ambientintensity); +void R_LightPoint(float *color, const vec3_t p, const int flags); +void R_CompleteLightPoint(float *ambientcolor, float *diffusecolor, float *diffusenormal, const vec3_t p, const int flags); void R_Shadow_DrawShadowMaps(void); void R_Shadow_DrawModelShadows(void); diff --git a/r_sprites.c b/r_sprites.c index d72bee10..a45a3e73 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -392,15 +392,9 @@ static void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, frame = model->sprite.sprdata_frames + ent->frameblend[i].subframe; texture = R_GetCurrentTexture(model->data_textures + ent->frameblend[i].subframe); - // sprites are fullbright by default, but if this one is not fullbright we - // need to combine the lighting into ambient as sprite lighting is not - // directional + // lit sprite by lightgrid if it is not fullbright, lit only ambient if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - { - VectorMAM(1.0f, texture->render_modellight_ambient, 0.25f, texture->render_modellight_diffuse, texture->render_modellight_ambient); - VectorClear(texture->render_modellight_diffuse); - VectorClear(texture->render_modellight_specular); - } + VectorAdd(ent->modellight_ambient, ent->modellight_diffuse, rsurface.modellight_ambient); // sprites dont use lightdirection // SPR_LABEL should not use depth test AT ALL if(model->sprite.sprnum_type == SPR_LABEL || model->sprite.sprnum_type == SPR_LABEL_SCALE) diff --git a/render.h b/render.h index 8f387103..52e3e705 100644 --- a/render.h +++ b/render.h @@ -127,7 +127,7 @@ extern cvar_t r_wateralpha; extern cvar_t r_dynamic; void R_UpdateVariables(void); // must call after setting up most of r_refdef, but before calling R_RenderView -void R_RenderView(void); // must set r_refdef and call R_UpdateVariables and CL_UpdateEntityShading first +void R_RenderView(void); // must set r_refdef and call R_UpdateVariables first void R_RenderView_UpdateViewVectors(void); // just updates r_refdef.view.{forward,left,up,origin,right,inverse_matrix} typedef enum r_refdef_scene_type_s { @@ -404,6 +404,18 @@ typedef struct rsurfacestate_s // animation blending state from entity frameblend_t frameblend[MAX_FRAMEBLENDS]; skeleton_t *skeleton; + // directional model shading state from entity + vec3_t modellight_ambient; + vec3_t modellight_diffuse; + vec3_t modellight_lightdir; + // colormapping state from entity (these are black if colormapping is off) + vec3_t colormap_pantscolor; + vec3_t colormap_shirtcolor; + // special coloring of ambient/diffuse textures (gloss not affected) + // colormod[3] is the alpha of the entity + float colormod[4]; + // special coloring of glow textures + float glowmod[3]; // view location in model space vec3_t localvieworigin; // polygon offset data for submodels @@ -442,8 +454,8 @@ typedef struct rsurfacestate_s float userwavefunc_param[Q3WAVEFUNC_USER_COUNT]; // pointer to an entity_render_t used only by R_GetCurrentTexture and - // RSurf_ActiveModelEntity as a unique id within each frame (see r_frame - // also) + // RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity as a unique id within + // each frame (see r_frame also) entity_render_t *entity; } rsurfacestate_t; @@ -452,6 +464,7 @@ extern rsurfacestate_t rsurface; void R_HDR_UpdateIrisAdaptation(const vec3_t point); +void RSurf_ActiveWorldEntity(void); void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass); void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents); void RSurf_SetupDepthAndCulling(void); @@ -498,7 +511,7 @@ rsurfacepass_t; void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha); void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy); void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal); -void R_SetupShader_Surface(const float ambientcolor[3], const float diffusecolor[3], const float specularcolor[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *waterplane, qboolean notrippy); +void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *waterplane, qboolean notrippy); void R_SetupShader_DeferredLight(const rtlight_t *rtlight); typedef struct r_waterstate_waterplane_s diff --git a/shader_glsl.h b/shader_glsl.h index 36542c53..a69dbbc5 100644 --- a/shader_glsl.h +++ b/shader_glsl.h @@ -1421,6 +1421,12 @@ "uniform sampler2D Texture_ReflectMask;\n", "uniform samplerCube Texture_ReflectCube;\n", "#endif\n", +"#ifdef MODE_LIGHTDIRECTION\n", +"uniform myhalf3 LightColor;\n", +"#endif\n", +"#ifdef MODE_LIGHTSOURCE\n", +"uniform myhalf3 LightColor;\n", +"#endif\n", "#ifdef USEBOUNCEGRID\n", "uniform sampler3D Texture_BounceGrid;\n", "uniform float BounceGridIntensity;\n", @@ -1522,6 +1528,7 @@ "#else\n", " color.rgb = diffusetex * Color_Ambient;\n", "#endif\n", +" color.rgb *= LightColor;\n", " color.rgb *= cast_myhalf(dp_texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n", "#if defined(USESHADOWMAP2D)\n", " color.rgb *= ShadowMapCompare(CubeVector);\n", @@ -1539,7 +1546,7 @@ " #ifdef USEDIFFUSE\n", " myhalf3 lightnormal = cast_myhalf3(normalize(LightVector));\n", " #endif\n", -" #define lightcolor 1\n", +" #define lightcolor LightColor\n", "#endif // MODE_LIGHTDIRECTION\n", "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " #define SHADING\n", @@ -1582,7 +1589,7 @@ "#ifdef MODE_FAKELIGHT\n", " #define SHADING\n", " myhalf3 lightnormal = cast_myhalf3(normalize(EyeVectorFogDepth.xyz));\n", -" #define lightcolor 1\n", +" myhalf3 lightcolor = cast_myhalf3(1.0);\n", "#endif // MODE_FAKELIGHT\n", "\n", "\n", diff --git a/shader_hlsl.h b/shader_hlsl.h index 57df52d0..9b3f04c3 100644 --- a/shader_hlsl.h +++ b/shader_hlsl.h @@ -1329,6 +1329,12 @@ "uniform sampler Texture_ReflectMask : register(s5),\n", "uniform samplerCUBE Texture_ReflectCube : register(s6),\n", "#endif\n", +"#ifdef MODE_LIGHTDIRECTION\n", +"uniform half3 LightColor : register(c21),\n", +"#endif\n", +"#ifdef MODE_LIGHTSOURCE\n", +"uniform half3 LightColor : register(c21),\n", +"#endif\n", "\n", "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n", "uniform sampler Texture_Attenuation : register(s9),\n", @@ -1445,6 +1451,7 @@ "#else\n", " color.rgb = diffusetex * Color_Ambient;\n", "#endif\n", +" color.rgb *= LightColor;\n", " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n", "#if defined(USESHADOWMAP2D)\n", " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n", @@ -1490,7 +1497,7 @@ " #ifdef USEDIFFUSE\n", " half3 lightnormal = half3(normalize(LightVector));\n", " #endif\n", -" #define lightcolor 1\n", +" #define lightcolor LightColor\n", "#endif // MODE_LIGHTDIRECTION\n", "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " #define SHADING\n", @@ -1529,7 +1536,7 @@ "#ifdef MODE_FAKELIGHT\n", " #define SHADING\n", " half3 lightnormal = half3(normalize(EyeVector));\n", -" #define lightcolor 1\n", +" half3 lightcolor = half3(1.0,1.0,1.0);\n", "#endif // MODE_FAKELIGHT\n", "\n", "\n",