XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
// Normal-map optionsZW carry actual Core focal length/distance;
// densityExtentZW carry its near/far. PSInspectSky uses a separate debug b0.
cbuffer Camera : register(b0) { float4 viewport; float4 options; float4 centreScale; float4 panOrigin; float4 densityExtent; }
// Recovered shared gHDRScalingWrite is RGB-only. y selects unassociated
// original source output; an unbound buffer keeps the explicit old SDR
// adapter available to isolated legacy probes, never an inferred exposure.
cbuffer OriginalSourceOutput:register(b8) {float4 originalSourceOutput;}
float SceneStorageWrite() {return originalSourceOutput.y>.5?originalSourceOutput.x:1;}
// Original DistantMilkyWay source-space pass. Material runtime scalar binding
// and the game's shared output transform remain independently unclosed.
cbuffer MilkyWayCamera:register(b3) {
    float4 mwEyeFocal;float4 mwRightWidth;float4 mwUpHeight;float4 mwForwardNear;float4 mwMaterial;float4 mwOutput;
}
Texture2D<float4> originalMilkyWayAtlas:register(t9);
Texture2D<float4> originalMilkyWayColour:register(t10);
Texture2D<float4> originalMilkyWayHeight:register(t11);
struct Star { float2 position:POSITION; float2 radiusKind:RADIUS; float4 colour:COLOR; float4 appearance:APPEARANCE; };
struct Pixel { float4 position:SV_POSITION; float2 uv:TEXCOORD; float4 colour:COLOR; float kind:KIND; float4 appearance:TEXCOORD1; };
float4 Screen(float2 p) { return float4(p.x/viewport.x*2-1,1-p.y/viewport.y*2,0,1); }
Pixel VSStar(Star s,uint vertex:SV_VertexID) {
    const float2 corners[6]={float2(-1,-1),float2(-1,1),float2(1,-1),float2(1,-1),float2(-1,1),float2(1,1)};
    Pixel p; p.uv=corners[vertex]*s.radiusKind.x;p.position=Screen(s.position+p.uv);p.colour=s.colour;
    // Original VS BackgroundStars: physical gamma1, classified gamma2.2.
    // The CPU passes original float RGB without SDR palette clamping.
    if(s.appearance.z<.5)p.colour.rgb=pow(max(0,p.colour.rgb),2.2);
    p.kind=s.radiusKind.y;p.appearance=s.appearance;return p;
}
Texture2DArray<float4> originalStarSprites:register(t7);
SamplerState linearSampler:register(s0);
struct MilkyWaySprite {float4 worldAlpha:POSITION;float4 shape:SHAPE;float4 atlas:ATLAS;float4 layer:LAYER;};
struct MilkyWayPixel {float4 position:SV_POSITION;float2 uv:TEXCOORD;float4 colour:COLOR;};
MilkyWayPixel VSMilkyWay(MilkyWaySprite s,uint vertex:SV_VertexID) {
    // Exact original six UV/corner float4s, independent from star pixels.
    const float4 quad[6]={float4(0,1,-1,-1),float4(0,0,-1,1),float4(1,0,1,1),float4(1,0,1,1),float4(1,1,1,-1),float4(0,1,-1,-1)};
    float4 q=quad[vertex];MilkyWayPixel p;
    float3 towardsEye=mwEyeFocal.xyz-s.worldAlpha.xyz;float distance=length(towardsEye);
    float fade=saturate((distance-s.shape.z)/(s.layer.x+.001))*saturate((s.shape.w-distance)/(s.layer.x+.001));
    float height=smoothstep(mwMaterial.w,mwMaterial.z,abs(40955-mwEyeFocal.y))*step(.1,s.layer.y);
    p.colour.a=fade*s.worldAlpha.w*(1+height*mwMaterial.y);
    p.uv=(q.xy+s.atlas.xy)/s.atlas.zw;
    if(p.colour.a<.001) {p.position=float4(-2,-2,0,1);p.colour=0;return p;}
    towardsEye/=max(distance,1e-20);
    float3 basisRight=normalize(cross(mwUpHeight.xyz,towardsEye));float3 basisUp=cross(towardsEye,basisRight);
    float sine,cosine;sincos(s.shape.x,sine,cosine);
    float3 right=cosine*basisRight-sine*basisUp,up=cosine*basisUp+sine*basisRight;
    float3 world=s.worldAlpha.xyz+(right*q.z+up*q.w)*s.shape.y;
    float3 relative=world-mwEyeFocal.xyz;float depth=dot(relative,mwForwardNear.xyz);
    // Background has its own source fade out to300000ly. It is not clipped
    // to the local stellar-stream query volume. Final game projection is a
    // separate stage; the current actual camera's focal length is supplied.
    p.position=float4(dot(relative,mwRightWidth.xyz)*mwEyeFocal.w/(mwRightWidth.w*.5),
        dot(relative,mwUpHeight.xyz)*mwEyeFocal.w/(mwUpHeight.w*.5),mwForwardNear.w,depth);
    float3 rgb=originalMilkyWayColour.SampleLevel(linearSampler,float2(s.worldAlpha.x*.00001,1-s.worldAlpha.z*.00001),0).rgb;
    float2 heightUv=float2(length(s.worldAlpha.xz-50000)*.00002,max(0,1-abs(40955-s.worldAlpha.y)*.000024));
    float3 y=originalMilkyWayHeight.SampleLevel(linearSampler,heightUv,0).rgb;
    float3 combined=(rgb*rgb+y)*.5;p.colour.rgb=combined*combined;return p;
}
float4 PSMilkyWay(MilkyWayPixel p):SV_TARGET {
    float4 source=originalMilkyWayAtlas.Sample(linearSampler,p.uv)*p.colour;
    return float4(source.rgb*mwOutput.w,min(source.a,mwMaterial.x));
}
float4 PSStar(Pixel p):SV_TARGET {
    float r=length(p.uv),edge=max(fwidth(r)*.65,.45),size=max(1e-20,p.appearance.x);
    float morphology=p.appearance.y,realistic=p.appearance.z;
    float core=1-smoothstep(max(0,size-edge),size+edge,r);
    float a=core;float3 colour=p.colour.rgb;
    if(realistic>.5&&realistic<1.5) {
        float corona=exp(-r*r/(size*size*4.5))*p.appearance.w;
        float2 axis=abs(p.uv);float rays=(exp(-axis.x*3.2/size-axis.y/(size*2.3))+exp(-axis.y*3.2/size-axis.x/(size*2.3)))*.085;
        a=saturate(core+corona+rays)*saturate(size*2);
        float limb=sqrt(saturate(1-r*r/(size*size)));
        colour=lerp(colour,float3(1,1,.98),core*(.28+.45*limb))*(.77+.23*limb);
        // L/T/Y dwarfs retain a faint red/violet photosphere with little bloom.
        if(morphology>.5&&morphology<1.5)colour=p.colour.rgb*(.68+.32*limb);
        if(morphology>2.5&&morphology<3.5) {
            float2 jet=float2(p.uv.x*.94+p.uv.y*.342,-p.uv.x*.342+p.uv.y*.94);
            float beam=exp(-abs(jet.x)*5/size)*exp(-abs(jet.y)/(size*3.2))*.21;
            a=saturate(a+beam);colour=lerp(colour,float3(.62,.85,1),beam);
        }
        if(morphology>3.5) {
            float rim=exp(-pow((r-size*1.8)/max(.45,size*.27),2))*.5;
            float shadow=1-smoothstep(size,size+edge,r);
            a=saturate(shadow*.98+rim);colour=lerp(float3(.24,.3,.41),float3(.004,.005,.008),shadow);
        }
    }
    else {
        // Original VS/PS BackgroundStars, matching the actual52-byte Galaxy
        // producer: maskRGB weights(1,1), bias-1, power1.2 and internal glow.
        // Actual original unit quad and half(styleSize) are projected using
        // Focal/Z. HDR Write is applied only at the final RGB store below.
        float2 uv=p.uv/(size*2)+.5;
        float3 mask=originalStarSprites.SampleBias(linearSampler,float3(uv,morphology),-1).rgb;
        float light=pow(max(0,mask.r+mask.g+mask.b),1.2);
        //3AB44E0 overrides the named pInternalGlowParamsX/Y/Z from config180.
        //Main's original ctor initializes its alternate-glow flag to false.
        float radial=2.75-r/(size*.17)+1;
        float gain=radial*light*1.903+light*(1-saturate(1.903));
        colour=clamp(gain*p.colour.rgb,0,100);
        // Kept only for the explicit legacy SDR adapter below. Original PS
        // emits the instance alpha, without gain/coverage multiplication.
        a=saturate(gain);
    }
    float3 result;
    if(originalSourceOutput.y>.5) {
        result=colour;
        if(realistic<.5||realistic>1.5)a=1;
    }
    else if(realistic<.5||realistic>1.5)result=colour*p.colour.a;
    else result=colour*(a*p.colour.a);
    a*=p.colour.a;
    // Selection is a navigation glyph around the same star, never a larger sun.
    if(p.kind>=1.5) {
        float stellarCore=(realistic<.5||realistic>1.5)?size*.25:size;
        float markerRadius=max(p.kind>2.5?11:9.5,stellarCore+3);
        float marker=(1-smoothstep(.45,.45+edge,abs(r-markerRadius)))*.9;
        float pinY=p.uv.y+markerRadius+2;
        float pinWidth=clamp(-pinY/10,0,1)*4.2;
        float pointer=(1-smoothstep(max(0,pinWidth-.45),pinWidth+.45,abs(p.uv.x)))*step(-10,pinY)*step(pinY,0);
        // The current location uses the original map UI arrow above the GPU
        // star. Keep its ring here without a second procedural arrow.
        if(p.kind<2.5)marker=max(marker,pointer);
        float3 markerColour=p.kind>2.5?float3(.06,.87,.91):float3(1,.47,.08);
        result=result*(1-marker)+markerColour*marker;a=a*(1-marker)+marker;
    }
    return float4(result*SceneStorageWrite(),a);
}
struct Line {float2 position:POSITION;float2 path:TEXCOORD;float4 colour:COLOR;};
Pixel VSLine(Line s) {Pixel p;p.position=Screen(s.position);p.uv=s.path;p.colour=s.colour;p.kind=0;p.appearance=0;return p;}
float4 PSLine(Pixel p):SV_TARGET {if(p.uv.y>.5&&frac(p.uv.x/13)>.58)discard;return float4(p.colour.rgb*p.colour.a,p.colour.a);}
TextureCube<float4> gameSky:register(t0);
Pixel VSSky(uint id:SV_VertexID) {Pixel p;float2 uv=float2((id<<1)&2,id&2);p.position=float4(uv*float2(2,-2)+float2(-1,1),1,1);p.uv=uv;p.colour=0;p.kind=0;p.appearance=0;return p;}
float4 PSSky(Pixel p):SV_TARGET {
    float focal=options.z;
    float3 v=normalize(float3((p.uv.x-.5)*viewport.x/focal,(.5-p.uv.y)*viewport.y/focal,1));
    float cy=cos(viewport.z),sy=sin(viewport.z),cp=cos(viewport.w),sp=sin(viewport.w);
    float3 right=float3(cy,0,-sy),up=float3(sy*sp,cp,cy*sp),forward=float3(sy*cp,-sp,cy*cp);
    float3 ray=right*v.x+up*v.y+forward*v.z;
    float3 rgb=gameSky.SampleLevel(linearSampler,ray,0).rgb;
    rgb=max(rgb,0)/(1+max(rgb,0));return float4(pow(rgb,1.0/2.2)*.5,1);
}
float4 PSInspectSky(Pixel p):SV_TARGET {
    float u=p.uv.x*2-1,v=1-p.uv.y*2;float3 ray;
    switch((uint)options.z){case 0:ray=float3(1,v,-u);break;case 1:ray=float3(-1,v,u);break;
        case 2:ray=float3(u,1,-v);break;case 3:ray=float3(u,-1,v);break;case 4:ray=float3(u,v,1);break;default:ray=float3(-u,v,-1);break;}
    float3 rgb=max(gameSky.SampleLevel(linearSampler,ray,0).rgb,0);return float4(pow(rgb/(1+rgb),1.0/2.2),1);
}
Texture2D<float> densityMap:register(t1);
Pixel VSOverview(uint id:SV_VertexID) {
    const float2 uv[6]={float2(0,0),float2(0,1),float2(1,0),float2(1,0),float2(0,1),float2(1,1)};
    Pixel p;p.uv=uv[id];float2 plane=p.uv*densityExtent.xy-panOrigin.zw;
    float3 relative=float3(plane.x,0,plane.y)-centreScale.xyz;
    float cy=cos(viewport.z),sy=sin(viewport.z),cp=cos(viewport.w),sp=sin(viewport.w);
    float3 up=float3(sy*sp,cp,cy*sp),forward=float3(sy*cp,-sp,cy*cp),right=float3(cy,0,-sy);
    float3 focus=centreScale.xyz-right*panOrigin.x/centreScale.w+up*panOrigin.y/centreScale.w;
    relative=float3(plane.x,0,plane.y)-focus;
    float focal=options.z,depth=options.w+dot(relative,forward);
    p.position=float4(dot(relative,right)*focal*2/viewport.x,dot(relative,up)*focal*2/viewport.y,densityExtent.z,depth);
    p.colour=0;p.kind=0;p.appearance=0;return p;
}
float4 PSOverview(Pixel p):SV_TARGET {
    float value=densityMap.SampleLevel(linearSampler,p.uv,0);
    float intensity=saturate(log2(1+value*65535)/15);
    float fade=1-smoothstep(.025,.18,centreScale.w);
    // Density is diffuse unresolved galactic light. It carries no individual
    // stellar positions and must never synthesize point stars to fill a view.
    float opacity=intensity*.3*fade;
    float3 colour=lerp(float3(.14,.28,.46),float3(.72,.82,.9),intensity*intensity);
    // Tool overview adapter into the shared scene-storage target; this is
    // not evidence that the original overview shader used this calculation.
    return float4(colour*opacity*SceneStorageWrite(),opacity);
}

cbuffer GalacticZoneCamera:register(b2) {float4 zoneTransform;float4 zoneDimensions;float4 zoneSettings;}
Texture2D<uint> galacticZoneIds:register(t5);
Texture2D<float> galacticZoneBoundaries:register(t6);
uint ZoneId(int2 pixel) {
    if(any(pixel<0)||any(pixel>=(int2)zoneDimensions.xy))return 0;
    return galacticZoneIds.Load(int3(pixel,0));
}
float4 PSGalacticZones(Pixel p):SV_TARGET {
    float cy=cos(viewport.z),sy=sin(viewport.z),cp=cos(viewport.w),sp=sin(viewport.w);
    float3 right=float3(cy,0,-sy),up=float3(sy*sp,cp,cy*sp),forward=float3(sy*cp,-sp,cy*cp);
    float focal=options.z,distance=options.w;
    float3 focus=centreScale.xyz-right*panOrigin.x/centreScale.w+up*panOrigin.y/centreScale.w;
    float3 eye=focus-forward*distance;
    float2 screen=(p.uv*viewport.xy-viewport.xy*.5)/focal;
    float3 ray=forward+right*screen.x-up*screen.y;
    float safeY=abs(ray.y)<1e-6?(ray.y<0?-1e-6:1e-6):ray.y;
    float depth=-eye.y/safeY;
    float2 texel=((eye+ray*depth).xz+zoneTransform.zw)*zoneTransform.xy;
    float2 derivativeX=ddx(texel),derivativeY=ddy(texel);
    float2 texelWidth=max(float2(length(float2(derivativeX.x,derivativeY.x)),length(float2(derivativeX.y,derivativeY.y))),1e-5);
    float footprint=max(texelWidth.x,texelWidth.y);
    if(abs(ray.y)<1e-6||depth<densityExtent.z||depth>densityExtent.w||any(texel<0)||any(texel>=zoneDimensions.xy))discard;
    // Near view uses exact categorical ID edges with screen-space AA. At
    // distance the mip chain contains averaged coverage of those same edges;
    // it never invents regions or colours a whole region's interior.
    int2 pixel=(int2)floor(texel);float2 inside=frac(texel);uint id=ZoneId(pixel);
    float edgeDistance=10000;
    if(ZoneId(pixel+int2(-1,0))!=id)edgeDistance=min(edgeDistance,inside.x/texelWidth.x);
    if(ZoneId(pixel+int2(1,0))!=id)edgeDistance=min(edgeDistance,(1-inside.x)/texelWidth.x);
    if(ZoneId(pixel+int2(0,-1))!=id)edgeDistance=min(edgeDistance,inside.y/texelWidth.y);
    if(ZoneId(pixel+int2(0,1))!=id)edgeDistance=min(edgeDistance,(1-inside.y)/texelWidth.y);
    float precise=1-smoothstep(.15,zoneSettings.y,edgeDistance);
    float mip=max(0,log2(max(1,footprint)));
    float coverage=galacticZoneBoundaries.SampleLevel(linearSampler,texel/zoneDimensions.xy,mip);
    float distant=saturate(coverage*min(footprint,8)*.5);
    float edge=lerp(precise,distant,smoothstep(.65,1.35,footprint));
    float grazing=smoothstep(.015,.09,abs(ray.y)/length(ray));
    float lodFade=1-smoothstep(16,96,footprint);
    float alpha=edge*zoneSettings.x*grazing*lodFade;
    // Tool boundary adapter: only RGB uses shared scene-storage scale.
    return float4(float3(.23,.49,.54)*alpha*SceneStorageWrite(),alpha);
}

struct PowerContour {float4 centreRadius:POSITION;float4 linearColour:COLOR;};
Texture2D<float> originalTerritoryGlow:register(t8);
Pixel VSPowerContour(PowerContour source,uint vertex:SV_VertexID) {
    const float2 corners[6]={float2(-1,-1),float2(-1,1),float2(1,-1),float2(1,-1),float2(-1,1),float2(1,1)};
    Pixel p;p.uv=corners[vertex]*.5+.5;p.colour=source.linearColour;p.kind=0;p.appearance=0;
    float cy=cos(viewport.z),sy=sin(viewport.z),cp=cos(viewport.w),sp=sin(viewport.w);
    float3 right=float3(cy,0,-sy),up=float3(sy*sp,cp,cy*sp),forward=float3(sy*cp,-sp,cy*cp);
    float focal=options.z,cameraDistance=options.w;
    float3 focus=centreScale.xyz-right*panOrigin.x/centreScale.w+up*panOrigin.y/centreScale.w;
    float3 eye=focus-forward*cameraDistance;
    // Original GalaxyMapSimpleBillboard VS: camera-axis corner +/-1 times
    // the actual world radius. Outer Activities tangent geometry belongs to
    // a different primitive and must not alter Territory billboards.
    float3 world=source.centreRadius.xyz+(right*corners[vertex].x+up*corners[vertex].y)*source.centreRadius.w;
    float3 delta=world-eye;float depth=dot(delta,forward),near=densityExtent.z;
    p.position=float4(dot(delta,right)*focal*2/viewport.x,dot(delta,up)*focal*2/viewport.y,near,depth);
    return p;
}
float4 PSPowerContour(Pixel p):SV_TARGET {
    // Original PS: sample.r * instanceAlpha * linearRGB; output alpha0.
    // Source material disables emissive rescaling. Actual effect uses
    // One/InverseSourceAlpha/Add; alpha0 therefore preserves destination.
    return float4(originalTerritoryGlow.Sample(linearSampler,p.uv)*p.colour.a*p.colour.rgb*SceneStorageWrite(),0);
}

cbuffer NebulaCamera:register(b1) {float4 nebulaCentreHalf;float4 nebulaOrientation;float4 nebulaRect;float4 nebulaSettings;}
Texture3D<float4> nebulaVolume:register(t2);
Texture2D<float4> nebulaTransfer:register(t3);
Texture2D<float4> nebulaLayer:register(t4);
float3 InverseNebulaRotation(float3 v) {
    float3 q=-nebulaOrientation.xyz;
    return v+2*cross(q,cross(q,v)+nebulaOrientation.w*v);
}
Pixel VSNebula(uint id:SV_VertexID) {
    const float2 uv[6]={float2(0,0),float2(0,1),float2(1,0),float2(1,0),float2(0,1),float2(1,1)};
    Pixel p;float2 xy=lerp(nebulaRect.xy,nebulaRect.zw,uv[id]);p.uv=xy/viewport.xy;p.position=Screen(xy);p.colour=0;p.kind=0;p.appearance=0;return p;
}
float4 PSNebula(Pixel p):SV_TARGET {
    float cy=cos(viewport.z),sy=sin(viewport.z),cp=cos(viewport.w),sp=sin(viewport.w);
    float3 right=float3(cy,0,-sy),up=float3(sy*sp,cp,cy*sp),depth=float3(sy*cp,-sp,cy*cp);
    float focal=options.z;
    float2 xy=(p.uv*viewport.xy-viewport.xy*.5)/focal;
    float3 origin=InverseNebulaRotation(-nebulaCentreHalf.xyz)/nebulaCentreHalf.w;
    float3 direction=InverseNebulaRotation(normalize(depth+right*xy.x-up*xy.y));
    float3 safe=direction;safe.x=abs(safe.x)<1e-6?1e-6:safe.x;safe.y=abs(safe.y)<1e-6?1e-6:safe.y;safe.z=abs(safe.z)<1e-6?1e-6:safe.z;
    float3 a=(-1-origin)/safe,b=(1-origin)/safe;
    float3 lo=min(a,b),hi=max(a,b);float near=max(0,max(lo.x,max(lo.y,lo.z))),far=min(hi.x,min(hi.y,hi.z));
    if(near>=far)discard;
    uint samples=(uint)nebulaSettings.x;float step=(far-near)/samples;
    float4 result=0;
    [loop]for(uint i=0;i<samples;i++) {
        float3 uv=(origin+direction*(near+(i+.5)*step))*.5+.5;
        float4 voxel=nebulaVolume.SampleLevel(linearSampler,uv,0);
        float4 transfer=nebulaTransfer.SampleLevel(linearSampler,float2(voxel.a,.5),0);
        float alpha=1-exp(-voxel.a*max(0,transfer.a)*step*1.8);
        float3 colour=pow(saturate(voxel.rgb),1.0/2.2)*.65;
        colour=nebulaSettings.y>.5?float3(.008,.012,.019):colour;
        result.rgb+=(1-result.a)*colour*alpha;result.a+=(1-result.a)*alpha;
        if(result.a>.985)break;
    }
    return result;
}
float4 PSNebulaComposite(Pixel p):SV_TARGET {
    // Tool volumetric layer remains R8 and premultiplied; only its composite
    // RGB is adapted to the common floating point scene-storage scale.
    float4 source=nebulaLayer.SampleLevel(linearSampler,p.uv,0);
    return float4(source.rgb*SceneStorageWrite(),source.a);
}

// Original StarMapLine: six shared quad vertices,64B records and a BC7
// eight-row pattern atlas. Width is a half-precision world half-width.
cbuffer OriginalGridCamera:register(b4) {
    float4 gridEyeFocal,gridRightWidth,gridUpHeight,gridForwardNear,gridProjection,gridFade;
}
Texture2D<float4> originalGridDiffuse:register(t12);
struct OriginalGridLine {
    float3 from:POSITION0;float3 to:POSITION1;float4 shape:SHAPE;
    float4 colour:COLOR;float4 pattern:PATTERN;
};
struct OriginalGridPixel {
    float4 position:SV_POSITION;float3 world:TEXCOORD0;float2 uv:TEXCOORD1;float4 colour:COLOR;
};
OriginalGridPixel VSOriginalGrid(OriginalGridLine source,uint vertex:SV_VertexID) {
    const float4 quad[6]={float4(0,1,-1,-1),float4(0,0,-1,1),float4(1,0,1,1),
        float4(1,0,1,1),float4(1,1,1,-1),float4(0,1,-1,-1)};
    const float endpoint[6]={1,1,2,2,2,1};
    float3 direction=normalize(source.to-source.from),towardsEye=normalize(gridEyeFocal.xyz-source.from);
    // The original swizzled multiply/subtract is cross(view,line), including
    // its orientation relative to the diffuse atlas's vertical coordinate.
    float3 side=normalize(cross(towardsEye,direction));
    float3 centre=endpoint[vertex]>1.5?source.to:source.from;
    OriginalGridPixel p;p.world=centre+side*(quad[vertex].w*source.shape.z);
    p.uv=float2(endpoint[vertex]>1.5?length(source.to-source.from)*source.pattern.z+source.pattern.w:source.pattern.w,
        (quad[vertex].y+source.pattern.x)/source.pattern.y);p.colour=source.colour;
    float3 delta=p.world-gridEyeFocal.xyz;float depth=dot(delta,gridForwardNear.xyz);
    float near=gridForwardNear.w;
    p.position=float4(dot(delta,gridRightWidth.xyz)*gridEyeFocal.w*2/gridRightWidth.w,
        dot(delta,gridUpHeight.xyz)*gridEyeFocal.w*2/gridUpHeight.w,near,depth);
    return p;
}
float4 PSOriginalGrid(OriginalGridPixel p):SV_TARGET {
    float distance=length(p.world-gridEyeFocal.xyz),blend=saturate(length(gridEyeFocal.xyz)*.04);
    float radius=lerp(gridFade.x,gridFade.y,blend),range=lerp(gridFade.z,gridFade.w,blend);
    float fade=saturate((distance-radius*range)/(radius-radius*range));
    float alpha=fade*originalGridDiffuse.Sample(linearSampler,p.uv).a*p.colour.a;
    // Actual StarMapLine PS writes RGB*gHDRScalingWrite and independent
    // alpha; its actual effect uses SrcAlpha/One/Add for both channels.
    return float4(p.colour.rgb*gridProjection.y*SceneStorageWrite(),alpha);
}