AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Eigener Firemonkey TEffect Shader

Ein Thema von CHackbart · begonnen am 23. Mai 2018 · letzter Beitrag vom 26. Mai 2018
 
CHackbart

Registriert seit: 22. Okt 2012
267 Beiträge
 
#1

Eigener Firemonkey TEffect Shader

  Alt 23. Mai 2018, 10:53
Hallo,

ich versuche gerade für ein Open Source Projekt einen Effektfilter zu schreiben und Delphi schmeisst da ein paar kleinere Steine in den Weg. Das kleinere Problem ist, die Anzeige unter Windows zu Testzwecken auf DX9 zu stellen. Dafür musste ich in FMX.Context.DX11 die RegisterContext Funktion deaktivieren. Da es nur zum Testen des Shaders ist, ist das okay. Leider gibt es keinen anderen Weg das zu realisieren, denn GlobalUseDXInDX9Mode ist dafür nicht angedacht.

Mit der Hilfe von Zudomon habe ich gestern einen Pixelshader für ps_2_a (DX9) erstellt.

Code:
sampler s0 : register(s0);
float4 p0 : register(c0);
float4 p1 : register(c1);

#define screen_size float2(p0[0],p0[1])
#define hardScan float(p0[2])
#define hardPix float(p0[3])
#define warp float2(p1[0], p1[1])

// Amount of shadow mask.
#define maskDark float (p1[2])
#define maskLight float (p1[3])

// sRGB to Linear.
// Assuing using sRGB typed textures this should not be needed.
float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow(abs((c+0.055)/1.055),2.4);}
float3 ToLinear(float3 c){return float3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));}

// Linear to sRGB.
// Assuing using sRGB typed textures this should not be needed.
float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(abs(c),0.41666)-0.055);}
float3 ToSrgb(float3 c){return float3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}

// Nearest emulated sample given floating point position and texel offset.
// Also zero's off screen.
float3 Fetch(float2 pos,float2 off){
  //pos=(floor(pos*screen_size+off)+float2(0.5,0.5))/screen_size;
  if (max(abs(pos.x-0.5), abs(pos.y-0.5)) > 0.5) { return float3(0.0, 0.0, 0.0);}
  return ToLinear(1.2 * tex2D(s0,pos).rgb);}

// Distance in emulated pixels to nearest texel.
float2 Dist(float2 pos){return -((pos-floor(pos))-float2(0.5, 0.5));}
// 1D Gaussian.
float Gaus(float pos,float scale){return exp2(scale*pos*pos);}

// 3-tap Gaussian filter along horz line.
// 3-tap Gaussian filter along horz line.
float3 Horz3(float2 pos,float off){
  float3 b=Fetch(pos,float2(-1.0,off));
  float3 c=Fetch(pos,float2( 0.0,off));
  float3 d=Fetch(pos,float2( 1.0,off));
  float dst=Dist(pos).x;
  // Convert distance to weight.
  float scale=hardPix;
  float wb=Gaus(dst-1.0,scale);
  float wc=Gaus(dst+0.0,scale);
  float wd=Gaus(dst+1.0,scale);
  // Return filtered sample.
  return (b*wb+c*wc+d*wd)/(wb+wc+wd);}

// 5-tap Gaussian filter along horz line.
float3 Horz5(float2 pos,float off){
  float3 a=Fetch(pos,float2(-2.0,off));
  float3 b=Fetch(pos,float2(-1.0,off));
  float3 c=Fetch(pos,float2( 0.0,off));
  float3 d=Fetch(pos,float2( 1.0,off));
  float3 e=Fetch(pos,float2( 2.0,off));
  float dst=Dist(pos).x;
  // Convert distance to weight.
  float scale=hardPix;
  float wa=Gaus(dst-2.0,scale);
  float wb=Gaus(dst-1.0,scale);
  float wc=Gaus(dst+0.0,scale);
  float wd=Gaus(dst+1.0,scale);
  float we=Gaus(dst+2.0,scale);
  // Return filtered sample.
  return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}


// Return scanline weight.
float Scan(float2 pos,float off){
  float dst=Dist(pos).y;
  return Gaus(dst+off,hardScan);}


// Allow nearest three lines to effect pixel.
float3 Tri(float2 pos){
  float3 a=Horz3(pos,-1.0);
  float3 b=Horz5(pos, 0.0);
  float3 c=Horz3(pos, 1.0);
  float wa=Scan(pos,-1.0);
  float wb=Scan(pos, 0.0);
  float wc=Scan(pos, 1.0);
  return a*wa+b*wb+c*wc;}


// Distortion of scanlines, and end of screen alpha.
float2 Warp(float2 pos){
  pos=pos*2.0-1.0;
  pos*=float2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
  return pos*0.5+0.5;}

// Shadow mask.
float3 Mask(float2 pos){
  pos.x+=pos.y*3.0;
  float3 mask=float3(maskDark,maskDark,maskDark);
  pos.x=frac(pos.x/6.0);
  if(pos.x<0.333)mask.r=maskLight;
  else if(pos.x<0.666)mask.g=maskLight;
  else mask.b=maskLight;
  return mask;
}

float4 main(float2 tex : TEXCOORD0) : COLOR
{
   float2 pos = tex*screen_size;
   tex = Warp(tex);
   float4 color;
   
   color.rgb = ToSrgb(Tri(tex)*Mask(pos));
   return float4(color.r, color.g, color.b, 1);
}
Dieser basiert auf Lottes GLSL CRT Pixelfilter und die Idee ist dabei eine CRT Anzeige zu simulieren. Das ganze funktioniert zumindest mit DX9 recht gut. Ich kann die Werte für den Shader übergeben und er stellt das ganze auch (siehe Anhang) korrektet dar.

Delphi-Quellcode:
procedure TCrtFilter.LoadShaders;
begin
  TFilterManager.FilterContext.SetShaders(FVertexShader, FShaders[FPass]);
  TFilterManager.FilterContext.SetShaderVariable('C0',
    [Vector3D(InputSize.Width, InputSize.Height, ValuesAsFloat['HardScan'],
    ValuesAsFloat['HardPix'])]);

  TFilterManager.FilterContext.SetShaderVariable('C1',
    [Vector3D(ValuesAsFloat['WarpX'], ValuesAsFloat['WarpY'],
  ValuesAsFloat['MaskDark'], ValuesAsFloat['MaskLight'])]);
end;

class function TCrtFilter.FilterAttr: TFilterRec;
begin
  Result := TFilterRec.Create('CrtFilter',
    'An effect that simulates a CRT Monitor.',
    [TFilterValueRec.Create('HardScan', 'Hardness of scanline.',
    TFilterValueType.Float, -12, -8, -16), TFilterValueRec.Create('HardPix',
    'Hardness of pixels in scanline.', TFilterValueType.Float, -3, -2, -4),
    TFilterValueRec.Create('WarpX', 'Display Warp horizontal.',
    TFilterValueType.Float, 1.0 / 40.0, 0, -1 / 8),
    TFilterValueRec.Create('WarpY', 'Display Warp vertical.',
    TFilterValueType.Float, 1.0 / 44.0, 0, -1 / 8),
    TFilterValueRec.Create('MaskDark', 'Amount of minimum darkness shadow.',
    TFilterValueType.Float, 0.5, -10, 10), TFilterValueRec.Create('MaskLight',
    'Amount of minimum lightness shadow.', TFilterValueType.Float, 1.5,
    -10, 10)]);
end;
Das Problem welches ich jetzt habe ist den DX9 Shader auf DX11 zu portieren. Hat das jemand schon einmal gemacht?
Angehängte Grafiken
Dateityp: jpg Screenshot 2018-05-23 um 11.45.32.jpg (158,5 KB, 35x aufgerufen)
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:25 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz