| 571 | } |
| 572 | |
| 573 | void Object::DrawShadow(Shape* shadow, Vector3Par shadowPos, ClipFlags clipFlags, const FrameBase& frame) |
| 574 | { |
| 575 | // Phase 2 (modern-shadow-plan.md): IsShadow draws now route through |
| 576 | // the dedicated unlit VSShadow + PSShadow variants in 3D pass, |
| 577 | // bypassing the lit ambient+diffuse*NdotL formula entirely. No |
| 578 | // DisableSun bit needed — PrepareMeshTL re-enabling sun is harmless |
| 579 | // for the unlit shader. Screen-space IsShadow draws keep VSScreen |
| 580 | // (PSShadow is layout-agnostic). |
| 581 | int spec = IsOnSurface | IsShadow | IsAlphaFog; |
| 582 | |
| 583 | if (GEngine->GetTL() && EnableHWTLState && shadow->GetVertexBuffer() && !(spec & OnSurface)) |
| 584 | { |
| 585 | // T&L shadow drawing |
| 586 | // turn off all lights |
| 587 | GEngine->EnableSunLight(false); |
| 588 | // prepare matrices |
| 589 | const LightList noLights; |
| 590 | GEngine->PrepareMeshTL(noLights, frame.Transform(), render::SplitLegacy(spec)); |
| 591 | // set z-bias |
| 592 | GEngine->SetBias(0x10); |
| 593 | |
| 594 | if (shadow->NFaces() > 0 && shadow->NSections() > 0) |
| 595 | { |
| 596 | // set shadow material |
| 597 | TLMaterial shadowMat; |
| 598 | |
| 599 | if (spec & OnSurface) |
| 600 | { |
| 601 | // we may need to split the shape |
| 602 | } |
| 603 | float shadowFactor = GEngine->GetShadowFactor() * (1.0 / 256); |
| 604 | |
| 605 | shadowMat.diffuse = Color(0, 0, 0, shadowFactor); |
| 606 | shadowMat.ambient = Color(0, 0, 0, shadowFactor); |
| 607 | shadowMat.emmisive = HBlack; |
| 608 | shadowMat.forcedDiffuse = HBlack; |
| 609 | shadowMat.specFlags = 0; |
| 610 | LightList empty; |
| 611 | GEngine->SetMaterial(shadowMat, empty, render::LegacySpec{}); |
| 612 | |
| 613 | GEngine->BeginMeshTL(*shadow, spec); |
| 614 | // check first face properties |
| 615 | // note: we need alpha set-up properly |
| 616 | |
| 617 | int secBeg = -1; |
| 618 | int secEnd = -1; |
| 619 | Texture* secTexture = (Texture*)-1; |
| 620 | int secSpecial = -1; |
| 621 | |
| 622 | for (int i = 0; i < shadow->NSections(); i++) |
| 623 | { |
| 624 | const ShapeSection& sec = shadow->GetSection(i); |
| 625 | if (sec.properties.Special() & (IsHidden | IsHiddenProxy)) |
| 626 | { |
| 627 | continue; |
| 628 | } |
| 629 | |
| 630 | if (secBeg < 0) |
no test coverage detected