//----------------------------------------------------------------------------- // Trace from a vertex to each direct light source, accumulating its contribution. //----------------------------------------------------------------------------- void ComputeDirectLightingAtPoint( Vector &position, Vector &normal, Vector &outColor, int iThread, int static_prop_id_to_skip=-1) { sampleLightOutput_t sampleOutput; outColor.Init(); // Iterate over all direct lights and accumulate their contribution int cluster = ClusterFromPoint( position ); for ( directlight_t *dl = activelights; dl != NULL; dl = dl->next ) { if ( dl->light.style ) { // skip lights with style continue; } // is this lights cluster visible? if ( !PVSCheck( dl->pvs, cluster ) ) continue; // push the vertex towards the light to avoid surface acne Vector adjusted_pos = position; Vector fudge=dl->light.origin-position; VectorNormalize( fudge ); fudge *= 1.0; adjusted_pos += fudge; if ( !GatherSampleLight( sampleOutput, dl, -1, adjusted_pos, &normal, 1, iThread, true, static_prop_id_to_skip ) ) continue; VectorMA( outColor, sampleOutput.falloff * sampleOutput.dot[0], dl->light.intensity, outColor ); } }
//----------------------------------------------------------------------------- // Computes max direct lighting for a single detal prop //----------------------------------------------------------------------------- static void ComputeMaxDirectLighting( DetailObjectLump_t& prop, Vector* maxcolor, int iThread ) { // The max direct lighting must be along the direction to one // of the static lights.... Vector origin, normal; ComputeWorldCenter( prop, origin, normal ); if ( !origin.IsValid() || !normal.IsValid() ) { static bool s_Warned = false; if ( !s_Warned ) { Warning("WARNING: Bogus detail props encountered!\n" ); s_Warned = true; } // fill with debug color for ( int i = 0; i < MAX_LIGHTSTYLES; ++i) { maxcolor[i].Init(1,0,0); } return; } int cluster = ClusterFromPoint(origin); Vector delta; CUtlVector< directlight_t* > lights; CUtlVector< Vector > directions; directlight_t* dl; for (dl = activelights; dl != 0; dl = dl->next) { // skyambient doesn't affect dlights.. if (dl->light.type == emit_skyambient) continue; // is this lights cluster visible? if ( PVSCheck( dl->pvs, cluster ) ) { lights.AddToTail(dl); VectorSubtract( dl->light.origin, origin, delta ); VectorNormalize( delta ); directions.AddToTail( delta ); } } // Find the max illumination int i; for ( i = 0; i < MAX_LIGHTSTYLES; ++i) { maxcolor[i].Init(0,0,0); } // NOTE: See version 10 for a method where we choose a normal based on whichever // one produces the maximum possible illumination. This appeared to work better on // e3_town, so I'm trying it now; hopefully it'll be good for all cases. int j; for ( j = 0; j < lights.Count(); ++j) { dl = lights[j]; sampleLightOutput_t out; if ( GatherSampleLight( out, dl, -1, origin, &normal, 1, iThread ) ) { // The first sample is for non-bumped lighting. // The other sample are for bumpmapping. VectorMA( maxcolor[dl->light.style], out.falloff * out.dot[0], dl->light.intensity, maxcolor[dl->light.style] ); } } }
/** * @brief * @sa FinalLightFace */ void BuildFacelights (unsigned int facenum) { dBspSurface_t* face; dBspPlane_t* plane; dBspTexinfo_t* tex; float* center; float* sdir, *tdir; vec3_t normal, binormal; vec4_t tangent; lightinfo_t li; float scale; int i, j, numsamples; facelight_t* fl; int* headhints; const int grid_type = config.soft ? 1 : 0; if (facenum >= MAX_MAP_FACES) { Com_Printf("MAX_MAP_FACES hit\n"); return; } face = &curTile->faces[facenum]; plane = &curTile->planes[face->planenum]; tex = &curTile->texinfo[face->texinfo]; if (tex->surfaceFlags & SURF_WARP) return; /* non-lit texture */ sdir = tex->vecs[0]; tdir = tex->vecs[1]; /* lighting -extra antialiasing */ if (config.extrasamples) numsamples = config.soft ? SOFT_SAMPLES : MAX_SAMPLES; else numsamples = 1; OBJZERO(li); scale = 1.0 / numsamples; /* each sample contributes this much */ li.face = face; li.facedist = plane->dist; VectorCopy(plane->normal, li.facenormal); /* negate the normal and dist */ if (face->side) { VectorNegate(li.facenormal, li.facenormal); li.facedist = -li.facedist; } /* get the origin offset for rotating bmodels */ VectorCopy(face_offset[facenum], li.modelorg); /* calculate lightmap texture mins and maxs */ CalcLightinfoExtents(&li); /* and the lightmap texture vectors */ CalcLightinfoVectors(&li); /* now generate all of the sample points */ CalcPoints(&li, 0, 0); fl = &facelight[config.compile_for_day][facenum]; fl->numsamples = li.numsurfpt; fl->samples = Mem_AllocTypeN(vec3_t, fl->numsamples); fl->directions = Mem_AllocTypeN(vec3_t, fl->numsamples); center = face_extents[facenum].center; /* center of the face */ /* Also setup the hints. Each hint is specific to each light source, including sunlight. */ headhints = Mem_AllocTypeN(int, (numlights[config.compile_for_day] + 1)); /* calculate light for each sample */ for (i = 0; i < fl->numsamples; i++) { float* const sample = fl->samples[i]; /* accumulate lighting here */ float* const direction = fl->directions[i]; /* accumulate direction here */ if (tex->surfaceFlags & SURF_PHONG) /* interpolated normal */ SampleNormal(&li, li.surfpt[i], normal); else /* or just plane normal */ VectorCopy(li.facenormal, normal); for (j = 0; j < numsamples; j++) { /* with antialiasing */ vec3_t pos; /* add offset for supersampling */ VectorMA(li.surfpt[i], sampleofs[grid_type][j][0] * li.step, li.textoworld[0], pos); VectorMA(pos, sampleofs[grid_type][j][1] * li.step, li.textoworld[1], pos); NudgeSamplePosition(pos, normal, center, pos); GatherSampleLight(pos, normal, sample, direction, scale, headhints); } if (VectorNotEmpty(direction)) { vec3_t dir; /* normalize it */ VectorNormalize(direction); /* finalize the lighting direction for the sample */ TangentVectors(normal, sdir, tdir, tangent, binormal); dir[0] = DotProduct(direction, tangent); dir[1] = DotProduct(direction, binormal); dir[2] = DotProduct(direction, normal); VectorCopy(dir, direction); } } /* Free the hints. */ Mem_Free(headhints); for (i = 0; i < fl->numsamples; i++) { /* pad them */ float* const direction = fl->directions[i]; if (VectorEmpty(direction)) VectorSet(direction, 0.0, 0.0, 1.0); } /* free the sample positions for the face */ Mem_Free(li.surfpt); }