/** * @brief A follow-up to GatherSampleLight, simply trace along the sun normal, adding sunlight */ static void GatherSampleSunlight (const vec3_t pos, const vec3_t normal, float* sample, float* direction, float scale, int* headhint) { vec3_t delta; float dot, light; if (!sun_intensity) return; dot = DotProduct(sun_normal, normal); if (dot <= 0.001) return; /* wrong direction */ /* don't use only 512 (which would be the 8 level max unit) but a * higher value - because the light angle is not fixed at 90 degree */ VectorMA(pos, 8192, sun_normal, delta); if (TR_TestLineSingleTile(pos, delta, headhint)) return; /* occluded */ light = sun_intensity * dot; if (light > 255) light = 255; light *= scale; /* add some light to it */ VectorMA(sample, light, sun_color, sample); /* and accumulate the direction */ VectorMix(normal, sun_normal, light / sun_intensity, delta); VectorMA(direction, light * scale, delta, direction); }
Blob Scrypt(const ConstBuf& password, const ConstBuf& salt, int n, int r, int p, size_t dkLen) { HmacPseudoRandomFunction<SHA256> prf; const size_t mfLen = r*128; Blob bb = PBKDF2(prf, password, salt, 1, p*mfLen); AlignedMem am((n+1)*r*128, 128); uint32_t *v = (uint32_t*)am.get(); SalsaBlockPtr tmp = (SalsaBlockPtr)alloca(r*128); for (int i=0; i<p; ++i) { SalsaBlockPtr x = (SalsaBlockPtr)(bb.data()+i*mfLen); for (int i=0; i<n; ++i) { memcpy(&v[i * 32 * r], x, 2*r * sizeof(x[0])); VectorMix(Salsa20Core, x, tmp, r, 8); } for (int i=0; i<n; ++i) { int j = 32*r * (x[2 * r - 1][0] & (n - 1)); VectorXor(x[0], &v[j], 2*r*16); VectorMix(Salsa20Core, x, tmp, r, 8); } } return PBKDF2(prf, password, bb, 1, dkLen); }
/* * S_LoopSample */ void S_LoopSample(const vec3_t org, s_sample_t *sample) { s_channel_t *ch; vec3_t delta; int i; if (!sample || !sample->chunk) return; ch = NULL; for (i = 0; i < MAX_CHANNELS; i++) { // find existing loop sound if (s_env.channels[i].ent_num != -1) continue; if (s_env.channels[i].sample == sample) { VectorSubtract(s_env.channels[i].org, org, delta); if (VectorLength(delta) < 512.0) { ch = &s_env.channels[i]; break; } } } if (ch) { // update existing loop sample ch->count++; VectorMix(ch->org, org, 1.0 / ch->count, ch->org); } else { // or allocate a new one if ((i = S_AllocChannel()) == -1) return; ch = &s_env.channels[i]; VectorCopy(org, ch->org); ch->ent_num = -1; ch->count = 1; ch->atten = ATTN_IDLE; ch->sample = sample; Mix_PlayChannel(i, ch->sample->chunk, 0); } S_SpatializeChannel(ch); }
/** * @brief Adds a loop sample for e.g. ambient sounds */ void S_LoopSample (const vec3_t org, s_sample_t* sample, float relVolume, float attenuation) { s_channel_t* ch; int i; if (!sample || !sample->chunk) return; ch = nullptr; for (i = 0; i < MAX_CHANNELS; i++){ /* find existing loop sound */ if (s_env.channels[i].sample == sample) { vec3_t delta; VectorSubtract(s_env.channels[i].org, org, delta); if (VectorLength(delta) < 255.0) { ch = &s_env.channels[i]; break; } } } if (ch) { /* update existing loop sample */ ch->count++; VectorMix(ch->org, org, 1.0 / ch->count, ch->org); } else { /* or allocate a new one */ float volume; if ((i = S_AllocChannel()) == -1) return; ch = &s_env.channels[i]; sample->lastPlayed = CL_Milliseconds(); VectorCopy(org, ch->org); ch->count = 1; ch->atten = attenuation; ch->sample = sample; volume = snd_volume->value * relVolume * MIX_MAX_VOLUME; Mix_VolumeChunk(ch->sample->chunk, volume); Mix_PlayChannel(i, ch->sample->chunk, 0); } S_SpatializeChannel(ch); }
/* * @brief Resolves the surface bounding box and lightmap texture coordinates. */ static void R_SetupBspSurface(r_bsp_model_t *bsp, r_bsp_surface_t *surf) { vec2_t st_mins, st_maxs; uint16_t i, j; ClearBounds(surf->mins, surf->maxs); st_mins[0] = st_mins[1] = 999999.0; st_maxs[0] = st_maxs[1] = -999999.0; const r_bsp_texinfo_t *tex = surf->texinfo; for (i = 0; i < surf->num_edges; i++) { const int32_t e = bsp->surface_edges[surf->first_edge + i]; const r_bsp_vertex_t *v; if (e >= 0) v = &bsp->vertexes[bsp->edges[e].v[0]]; else v = &bsp->vertexes[bsp->edges[-e].v[1]]; AddPointToBounds(v->position, surf->mins, surf->maxs); // calculate mins, maxs for (j = 0; j < 2; j++) { // calculate st_mins, st_maxs const vec_t val = DotProduct(v->position, tex->vecs[j]) + tex->vecs[j][3]; if (val < st_mins[j]) st_mins[j] = val; if (val > st_maxs[j]) st_maxs[j] = val; } } VectorMix(surf->mins, surf->maxs, 0.5, surf->center); // calculate the center // bump the texture coordinate vectors to ensure we don't split samples for (i = 0; i < 2; i++) { const int32_t bmins = floor(st_mins[i] / bsp->lightmaps->scale); const int32_t bmaxs = ceil(st_maxs[i] / bsp->lightmaps->scale); surf->st_mins[i] = bmins * bsp->lightmaps->scale; surf->st_maxs[i] = bmaxs * bsp->lightmaps->scale; surf->st_center[i] = (surf->st_maxs[i] + surf->st_mins[i]) / 2.0; surf->st_extents[i] = surf->st_maxs[i] - surf->st_mins[i]; } }
/** * @brief Adds the specified static light source after first ensuring that it * can not be merged with any known sources. */ static void R_AddBspLight(r_bsp_model_t *bsp, vec3_t origin, vec3_t color, vec_t radius) { if (radius <= 0.0) { Com_Debug(DEBUG_RENDERER, "Bad radius: %f\n", radius); return; } if (r_lighting->value) { // scale by r_lighting->value, if enabled radius *= r_lighting->value; } r_bsp_light_t *bl = NULL; GSList *e = r_bsp_light_state.lights; while (e) { vec3_t delta; bl = (r_bsp_light_t *) e->data; VectorSubtract(origin, bl->light.origin, delta); if (VectorLength(delta) <= BSP_LIGHT_MERGE_THRESHOLD) { // merge them break; } bl = NULL; e = e->next; } if (!bl) { // or allocate a new one bl = Mem_LinkMalloc(sizeof(*bl), bsp); r_bsp_light_state.lights = g_slist_prepend(r_bsp_light_state.lights, bl); VectorCopy(origin, bl->light.origin); bl->leaf = R_LeafForPoint(bl->light.origin, bsp); } bl->count++; bl->light.radius = ((bl->light.radius * (bl->count - 1)) + radius) / bl->count; VectorMix(bl->light.color, color, 1.0 / bl->count, bl->light.color); bl->debug.type = PARTICLE_CORONA; bl->debug.color[3] = 1.0; bl->debug.blend = GL_ONE; }
/* * R_AddBspLight * * Adds the specified static light source to the world model, after first * ensuring that it can not be merged with any known sources. */ static void R_AddBspLight(vec3_t org, float radius, vec3_t color) { r_bsp_light_t *l; vec3_t delta; int i; if (radius <= 0.0) { Com_Debug("R_AddBspLight: Bad radius: %f\n", radius); return; } l = r_load_model->bsp_lights; for (i = 0; i < r_load_model->num_bsp_lights; i++, l++) { VectorSubtract(org, l->origin, delta); if (VectorLength(delta) <= 32.0) // merge them break; } if (i == r_load_model->num_bsp_lights) { // or allocate a new one l = (r_bsp_light_t *) R_HunkAlloc(sizeof(*l)); if (!r_load_model->bsp_lights) // first source r_load_model->bsp_lights = l; VectorCopy(org, l->origin); l->leaf = R_LeafForPoint(l->origin, r_load_model); r_load_model->num_bsp_lights++; } l->count++; l->radius = ((l->radius * (l->count - 1)) + radius) / l->count; VectorMix(l->color, color, 1.0 / l->count, l->color); }
/** * @param[out] sample The sample color * @param[in] normal The light direction (normal vector) * @param[in] pos The point in the world that receives the light * @param[in] scale is the normalizer for multisampling * @param[in,out] headhints An array of theads for each light to optimize the tracing */ static void GatherSampleLight (vec3_t pos, const vec3_t normal, float* sample, float* direction, float scale, int* headhints) { light_t* l; vec3_t delta; int* headhint; for (l = lights[config.compile_for_day], headhint = headhints; l; l = l->next, headhint++) { float light = 0.0; float dot2; /* Com_Printf("Looking with next hint.\n"); */ VectorSubtract(l->origin, pos, delta); float dist = VectorNormalize(delta); float dot = DotProduct(delta, normal); if (dot <= 0.001) continue; /* behind sample surface */ switch (l->type) { case emit_point: /* linear falloff */ light = (l->intensity - dist) * dot; break; case emit_surface: /* exponential falloff */ light = (l->intensity / (dist * dist)) * dot; break; case emit_spotlight: /* linear falloff with cone */ dot2 = -DotProduct(delta, l->normal); if (dot2 > l->stopdot) { /* inside the cone */ light = (l->intensity - dist) * dot; } else { /* outside the cone */ light = (l->intensity * (dot2 / l->stopdot) - dist) * dot; } break; default: Sys_Error("Bad l->type"); } if (light <= 0.5) /* almost no light */ continue; if (TR_TestLineSingleTile(pos, l->origin, headhint)) continue; /* occluded */ if (light > 255) light = 255; /* add some light to it */ VectorMA(sample, light * scale, l->color, sample); /* and add some direction */ VectorMix(normal, delta, 2.0 * light / l->intensity, delta); VectorMA(direction, light * scale, delta, direction); } /* Com_Printf("Looking with last hint.\n"); */ GatherSampleSunlight(pos, normal, sample, direction, scale, headhint); }
/** * @brief Add the indirect lighting on top of the direct * lighting and save into final map format * @sa BuildFacelights */ void FinalLightFace (unsigned int facenum) { int j, k; vec3_t dir, intensity; byte* dest; dBspSurface_t* f = &curTile->faces[facenum]; facelight_t *fl = &facelight[config.compile_for_day][facenum]; /* none-lit texture */ if (curTile->texinfo[f->texinfo].surfaceFlags & SURF_WARP) return; ThreadLock(); f->lightofs[config.compile_for_day] = curTile->lightdatasize[config.compile_for_day]; curTile->lightdatasize[config.compile_for_day] += fl->numsamples * 3; /* account for light direction data as well */ curTile->lightdatasize[config.compile_for_day] += fl->numsamples * 3; if (curTile->lightdatasize[config.compile_for_day] > MAX_MAP_LIGHTING) Sys_Error("MAX_MAP_LIGHTING (%i exceeded %i) - try to reduce the brush size (%s)", curTile->lightdatasize[config.compile_for_day], MAX_MAP_LIGHTING, curTile->texinfo[f->texinfo].texture); ThreadUnlock(); /* write it out */ dest = &curTile->lightdata[config.compile_for_day][f->lightofs[config.compile_for_day]]; for (j = 0; j < fl->numsamples; j++) { vec3_t temp; /* start with raw sample data */ VectorCopy(fl->samples[j], temp); /* convert to float */ VectorScale(temp, 1.0 / 255.0, temp); /* add an ambient term if desired */ VectorAdd(temp, sun_ambient_color, temp); /* apply global scale factor */ VectorScale(temp, config.brightness, temp); float max = 0.0; /* find the brightest component */ for (k = 0; k < 3; k++) { /* enforcing positive values */ if (temp[k] < 0.0) temp[k] = 0.0; if (temp[k] > max) max = temp[k]; } if (max > 255.0) /* clamp without changing hue */ VectorScale(temp, 255.0 / max, temp); for (k = 0; k < 3; k++) { /* apply contrast */ temp[k] -= 0.5; /* normalize to -0.5 through 0.5 */ temp[k] *= config.contrast; /* scale */ temp[k] += 0.5; if (temp[k] > 1.0) /* clamp */ temp[k] = 1.0; else if (temp[k] < 0) temp[k] = 0; } /* apply saturation */ float d = DotProduct(temp, luminosity); VectorSet(intensity, d, d, d); VectorMix(intensity, temp, config.saturation, temp); for (k = 0; k < 3; k++) { temp[k] *= 255.0; /* back to byte */ if (temp[k] > 255.0) /* clamp */ temp[k] = 255.0; else if (temp[k] < 0.0) temp[k] = 0.0; *dest++ = (byte)temp[k]; } /* also write the directional data */ VectorCopy(fl->directions[j], dir); for (k = 0; k < 3; k++) *dest++ = (byte)((dir[k] + 1.0f) * 127.0f); } }