@@ -362,8 +362,8 @@ var primLodFrac
362362 equations . CreateColor ( environmentAlpha ) ,
363363 GenericColorMux . G_CCMUX_PRIM_LOD_FRAC
364364 => primLodFrac . Wrap ( ) ,
365- GenericColorMux . G_CCMUX_SCALE => color1 ,
366- GenericColorMux . G_CCMUX_K5 => color1 ,
365+ GenericColorMux . G_CCMUX_SCALE => color1 ,
366+ GenericColorMux . G_CCMUX_K5 => color1 ,
367367 _ => throw new ArgumentOutOfRangeException (
368368 nameof ( colorMux ) ,
369369 colorMux ,
@@ -433,82 +433,10 @@ var primLodFrac
433433 equations . CreateScalarOutput ( FixedFunctionSource . OUTPUT_ALPHA ,
434434 combinedAlpha ) ;
435435
436- // TODO: Handle shade case by writing lighting to alpha
437-
438- // Shamelessly stolen from:
439- // https://github.com/magcius/noclip.website/blob/main/src/zelview/f3dzex.ts#L135
440-
441- BlenderPm srcColor , dstColor ;
442- BlenderA srcFactor ;
443- BlenderB dstFactor ;
444-
445- var doBlend = true ;
446- if ( rdp . ForceBlending ) {
447- if ( cycleParams1 != null ) {
448- srcColor = rdp . P1 ;
449- srcFactor = rdp . A1 ;
450- dstColor = rdp . M1 ;
451- dstFactor = rdp . B1 ;
452- } else {
453- srcColor = rdp . P0 ;
454- srcFactor = rdp . A0 ;
455- dstColor = rdp . M0 ;
456- dstFactor = rdp . B0 ;
457- }
458- } else {
459- doBlend = cycleParams1 != null ;
460- srcColor = rdp . P0 ;
461- srcFactor = rdp . A0 ;
462- dstColor = rdp . M0 ;
463- dstFactor = rdp . B0 ;
464- }
436+ ApplyBlendMode_ ( n64Hardware , finMaterial ) ;
465437
466438 // TODO: I'm not sure if alpha compare is ever used on the N64
467439 finMaterial . DisableAlphaCompare ( ) ;
468- if ( ! doBlend ) {
469- finMaterial . SetBlending ( BlendEquation . ADD ,
470- BlendFactor . ONE ,
471- BlendFactor . ZERO ,
472- LogicOp . UNDEFINED ) ;
473- }
474-
475- if ( srcFactor == BlenderA . G_BL_0 &&
476- dstFactor == BlenderB . G_BL_1 ) {
477- finMaterial . SetBlending ( BlendEquation . ADD ,
478- BlendFactor . ONE ,
479- BlendFactor . ZERO ,
480- LogicOp . UNDEFINED ) ;
481- } else if (
482- srcColor == dstColor &&
483- srcFactor == BlenderA . G_BL_A_IN &&
484- dstFactor == BlenderB . G_BL_1MA ) {
485- finMaterial . SetBlending ( BlendEquation . ADD ,
486- BlendFactor . SRC_ALPHA ,
487- BlendFactor . ONE_MINUS_SRC_ALPHA ,
488- LogicOp . UNDEFINED ) ;
489- } else {
490- BlendFactor blendSrcFactor ;
491- if ( srcFactor == BlenderA . G_BL_0 ) {
492- blendSrcFactor = BlendFactor . ZERO ;
493- } else if
494- ( rdp is {
495- UseCoverageForAlpha : true ,
496- MultiplyCoverageWithAlpha : false
497- } ) {
498- // this is technically "coverage", admitting blending on edges
499- blendSrcFactor = BlendFactor . ONE ;
500- } else {
501- blendSrcFactor = BlendFactor . SRC_ALPHA ;
502- }
503-
504- var blendDstFactor =
505- TranslateBlendParamB_ ( dstFactor , blendSrcFactor ) ;
506-
507- finMaterial . SetBlending ( BlendEquation . ADD ,
508- blendSrcFactor ,
509- blendDstFactor ,
510- LogicOp . UNDEFINED ) ;
511- }
512440
513441 // Shamelessly stolen from:
514442 // https://github.com/magcius/noclip.website/blob/main/src/zelview/f3dzex.ts#L109
@@ -529,6 +457,60 @@ var primLodFrac
529457 } ) ;
530458 }
531459
460+ private static void ApplyBlendMode_ (
461+ IN64Hardware n64Hardware ,
462+ IMaterial finMaterial ) {
463+ // TODO: What does "FORCE_BL" do?
464+ // TODO: Is it possible to support two-cycle blending, maybe via a shader?
465+ // TODO: Figure out how to better support this
466+
467+ // HACK: Just kind of tries to see if we should do additive blending.
468+ // I have no idea how to properly implement this.
469+
470+ var rdp = n64Hardware . Rdp ;
471+
472+ var doAdditiveBlending
473+ = ShouldDoAdditiveBlendingFor_ ( rdp . P0 , rdp . A0 , rdp . M0 , rdp . B0 ) ;
474+ if ( rdp . CycleType is CycleType . TWO_CYCLE ) {
475+ doAdditiveBlending
476+ |= ShouldDoAdditiveBlendingFor_ ( rdp . P1 , rdp . A1 , rdp . M1 , rdp . B1 ) ;
477+ }
478+
479+ var useCoverageInsteadOfAlpha = rdp is {
480+ UseCoverageForAlpha : true ,
481+ MultiplyCoverageWithAlpha : false
482+ } ;
483+
484+ if ( doAdditiveBlending && ! useCoverageInsteadOfAlpha ) {
485+ finMaterial . SetBlending (
486+ BlendEquation . ADD ,
487+ BlendFactor . SRC_ALPHA ,
488+ BlendFactor . ONE_MINUS_SRC_ALPHA ,
489+ LogicOp . UNDEFINED ) ;
490+ } else {
491+ finMaterial . SetBlending (
492+ BlendEquation . ADD ,
493+ BlendFactor . ONE ,
494+ BlendFactor . ZERO ,
495+ LogicOp . UNDEFINED ) ;
496+ }
497+ }
498+
499+ private static bool ShouldDoAdditiveBlendingFor_ (
500+ BlenderPm p ,
501+ BlenderA a ,
502+ BlenderPm m ,
503+ BlenderB b ) {
504+ if ( p is BlenderPm . G_BL_CLR_IN &&
505+ m is BlenderPm . G_BL_CLR_MEM &&
506+ a is BlenderA . G_BL_A_IN &&
507+ b is BlenderB . G_BL_1MA or BlenderB . G_BL_A_MEM ) {
508+ return true ;
509+ }
510+
511+ return false ;
512+ }
513+
532514 public ModelImpl < Normal1Color2UvVertexImpl > Model { get ; }
533515
534516 public IMesh StartNewMesh ( string name ) {
@@ -843,22 +825,6 @@ private IReadOnlyMaterial GetOrCreateMaterial_() {
843825 return this . cachedMaterial_ ;
844826 }
845827
846- private static BlendFactor TranslateBlendParamB_ (
847- BlenderB paramB ,
848- BlendFactor srcParam ) {
849- return paramB switch {
850- BlenderB . G_BL_1MA => srcParam switch {
851- BlendFactor . SRC_ALPHA => BlendFactor . ONE_MINUS_SRC_ALPHA ,
852- BlendFactor . ONE => BlendFactor . ZERO ,
853- _ => BlendFactor . ONE
854- } ,
855- BlenderB . G_BL_A_MEM => BlendFactor . DST_ALPHA ,
856- BlenderB . G_BL_1 => BlendFactor . ONE ,
857- BlenderB . G_BL_0 => BlendFactor . ZERO ,
858- _ => throw new ArgumentOutOfRangeException ( nameof ( paramB ) , paramB , null )
859- } ;
860- }
861-
862828 public Color OverrideVertexColor {
863829 get => this . vertices_ . OverrideVertexColor ;
864830 set => this . vertices_ . OverrideVertexColor = value ;
0 commit comments