void ParticleSparkUpdate() { ARX_PROFILE_FUNC(); if(g_sparkParticlesCount == 0) { return; } const GameInstant now = g_gameTime.now(); RenderMaterial sparkMaterial; sparkMaterial.setBlendType(RenderMaterial::Additive); for(size_t i = 0; i < g_sparkParticlesMax; i++) { SparkParticle & spark = g_sparkParticles[i]; if(spark.m_duration == 0) { continue; } long framediff = spark.timcreation + spark.m_duration - toMsi(now); long framediff2 = toMsi(now) - spark.timcreation; if(framediff2 < 0) { continue; } if(framediff <= 0) { spark.m_duration = 0; g_sparkParticlesCount--; continue; } float val = (spark.m_duration - framediff) * 0.01f; Vec3f in = spark.m_pos + spark.move * val; Vec3f tailDirection = glm::normalize(-spark.move); TexturedVertex tv[3]; tv[0].color = spark.rgb; tv[1].color = Color::gray(0.4f).toRGBA(); tv[2].color = Color::black.toRGBA(); worldToClipSpace(in, tv[0]); if(tv[0].w < 0 || tv[0].p.z > g_camera->cdepth * fZFogEnd * tv[0].w) { continue; } Vec3f temp1 = in + Vec3f(Random::getf(0.f, 0.5f), 0.8f, Random::getf(0.f, 0.5f)); Vec3f temp2 = in + tailDirection * spark.m_tailLength; worldToClipSpace(temp1, tv[1]); worldToClipSpace(temp2, tv[2]); g_renderBatcher.add(sparkMaterial, tv); } }
static void ComputeLight2DPos(EERIE_LIGHT * _pL) { Vec4f p = worldToClipSpace(_pL->pos); if(p.w <= 0.f) { return; } Vec3f pos2d = Vec3f(p) / p.w; if(pos2d.z > 0.f && pos2d.z < 1000.f) { float siz = 50; float fMaxdist = player.m_telekinesis ? 850 : 300; float t = siz * (1.0f - 1.0f * p.w / fMaxdist) + 10; _pL->m_screenRect = Rectf(pos2d.x - t, pos2d.y - t, pos2d.x + t, pos2d.y + t); } }
bool Label::updateScreenTransform(const glm::mat4& _mvp, const glm::vec2& _screenSize, bool _testVisibility) { glm::vec2 screenPosition; float rot = 0; glm::vec2 ap1, ap2; switch (m_type) { case Type::debug: case Type::point: { glm::vec4 v1 = worldToClipSpace(_mvp, glm::vec4(m_transform.modelPosition1, 0.0, 1.0)); if (_testVisibility && (v1.w <= 0)) { return false; } screenPosition = clipToScreenSpace(v1, _screenSize); ap1 = ap2 = screenPosition; break; } case Type::line: { // project label position from mercator world space to clip coordinates glm::vec4 v1 = worldToClipSpace(_mvp, glm::vec4(m_transform.modelPosition1, 0.0, 1.0)); glm::vec4 v2 = worldToClipSpace(_mvp, glm::vec4(m_transform.modelPosition2, 0.0, 1.0)); // check whether the label is behind the camera using the perspective division factor if (_testVisibility && (v1.w <= 0 || v2.w <= 0)) { return false; } // project to screen space glm::vec2 p1 = clipToScreenSpace(v1, _screenSize); glm::vec2 p2 = clipToScreenSpace(v2, _screenSize); rot = angleBetweenPoints(p1, p2) + M_PI_2; if (rot > M_PI_2 || rot < -M_PI_2) { // un-readable labels rot += M_PI; } else { std::swap(p1, p2); } float length = glm::length(p2 - p1); float exceedHeuristic = 30; // default heuristic : 30% if (_testVisibility && (m_dim.x > length)) { float exceed = (1 - (length / m_dim.x)) * 100; if (exceed > exceedHeuristic) { return false; } } ap1 = p1; ap2 = p2; break; } } align(screenPosition, ap1, ap2); // update screen position glm::vec2 offset = m_options.offset; if (m_transform.state.rotation != 0.f) { offset = glm::rotate(offset, m_transform.state.rotation); } glm::vec2 newScreenPos = screenPosition + offset; if (newScreenPos != m_transform.state.screenPos) { m_transform.state.screenPos = newScreenPos; m_dirty = true; } // update screen rotation if (m_transform.state.rotation != rot) { m_transform.state.rotation = rot; m_dirty = true; } return true; }
glm::vec2 worldToScreenSpace(const glm::mat4& _mvp, const glm::vec4& _worldPosition, const glm::vec2& _screenSize) { return clipToScreenSpace(worldToClipSpace(_mvp, _worldPosition), _screenSize); }
void updateLightFlares() { RaycastDebugClear(); ARX_PROFILE_FUNC(); Entity * pTableIO[256]; size_t nNbInTableIO = 0; float temp_increase = toMs(g_platformTime.lastFrameDuration()) * 0.004f; const Vec3f camPos = g_camera->m_pos; bool bComputeIO = false; Vec4f zFar = g_preparedCamera.m_viewToScreen * Vec4f(0.f, 0.f, g_camera->cdepth * fZFogEnd, 1.f); float fZFar = zFar.z / zFar.w; for(size_t i = 0; i < g_culledDynamicLightsCount; i++) { EERIE_LIGHT * el = g_culledDynamicLights[i]; if(!ACTIVEBKG->isInActiveTile(el->pos)) { el->m_isVisible = false; continue; } if(el->extras & EXTRAS_FLARE) { Vec3f lv = el->pos; Vec4f p = worldToClipSpace(lv); Vec3f pos2d = Vec3f(p) / p.w; el->m_flareFader -= temp_increase; if(p.w > 0.f && pos2d.x > 0.f && pos2d.x < g_size.width() && pos2d.y > (cinematicBorder.CINEMA_DECAL * g_sizeRatio.y) && pos2d.y < (g_size.height() - (cinematicBorder.CINEMA_DECAL * g_sizeRatio.y))) { Vec3f vector = lv - camPos; lv -= vector * (50.f / glm::length(vector)); Vec3f ee3dlv = lv; Vec2s ees2dlv(checked_range_cast<short>(pos2d.x), checked_range_cast<short>(pos2d.y)); if(!bComputeIO) { GetFirstInterAtPos(ees2dlv, 2, &ee3dlv, pTableIO, &nNbInTableIO); bComputeIO = true; } if( pos2d.z > fZFar || RaycastLightFlare(camPos, el->pos) || GetFirstInterAtPos(ees2dlv, 3, &ee3dlv, pTableIO, &nNbInTableIO) ) { el->m_flareFader -= temp_increase * 2.f; } else { el->m_flareFader += temp_increase * 2.f; } } el->m_flareFader = glm::clamp(el->m_flareFader, 0.f, .8f); } } }