使用 SlimDX Direct3D9 将像素着色器应用于精灵中的纹理
Applying a pixel Shader to a texture within a sprite with SlimDX Direct3D9
所以,我对使用 DirectX 进行开发还很陌生,我正在慢慢达到目标...但是!
我有这个实例化 Direct3D9 运行时,创建设备并加载像素着色器。 - 我可以确认像素着色器加载为 1) 它适用于不是我开发的其他应用程序。 2) 我可以破解并看到所有各种属性都可用,并且 3) 没有报告错误。
这是设置。
Direct3DInstance = new SlimDX.Direct3D9.Direct3D();
SlimDX.Direct3D9.PresentParameters PP = new SlimDX.Direct3D9.PresentParameters();
PP.Windowed = true;
PP.BackBufferHeight = PAN_Video.ClientSize.Height;
PP.BackBufferWidth = PAN_Video.ClientSize.Width;
PP.BackBufferCount = 0;
PP.BackBufferFormat = SlimDX.Direct3D9.Format.R5G6B5;
PP.PresentationInterval = SlimDX.Direct3D9.PresentInterval.Immediate;
PP.DeviceWindowHandle = PAN_Video.Handle;
Direct3DDevice = new SlimDX.Direct3D9.Device(Direct3DInstance, 0, SlimDX.Direct3D9.DeviceType.Hardware, PAN_Video.Handle, SlimDX.Direct3D9.CreateFlags.HardwareVertexProcessing, PP);
string error = null;
SlimDX.Direct3D9.ShaderBytecode SBC = SlimDX.Direct3D9.ShaderBytecode.Compile(File.ReadAllText(@"C:\Users\Marcus\Desktop\scanlines.txt"), null, null, "main", "ps_3_0", SlimDX.Direct3D9.ShaderFlags.UseLegacyD3DX9_31Dll, out error);
SlimDX.Direct3D9.PixelShader PS = new SlimDX.Direct3D9.PixelShader(Direct3DDevice, SBC);
Direct3DDevice.PixelShader = PS;
这是着色器 - 它不是我的,而是我用来测试的。
// hlslf output by Cg compiler
// cgc version 3.1.0013, build date Apr 18 2012
// command line args: -profile hlslf -po version=110
//vendor NVIDIA Corporation
//version 3.1.0.13
//profile hlslf
//program main_fragment
//semantic main_fragment.s_p : TEXUNIT0
//semantic uIntensity
//var sampler2D s_p : TEXUNIT0 : _s_p 0 : 2 : 1
//var float uIntensity : : _uIntensity : -1 : 1
//var float2 texcoord : $vin.TEXCOORD0 : TEXCOORD0 : 0 : 1
//var float2 wpos : $vin.WPOS : WPOS : 1 : 1
//var float4 main_fragment : $vout.COLOR : COLOR : -1 : 1
//default uIntensity = 100
#
pragma pack_matrix(row_major)
struct input
{
float2 _video_size;
float2 _texture_size;
float2 _output_size;
};
float _TMP1;
float _TMP0;
uniform float _uIntensity;
// main procedure, the original name was main_fragment
float4 main( in float2 _texcoord: TEXCOORD0, in float2 _wpos: VPOS, uniform sampler2D _s_p: TEXUNIT0): COLOR0
{
float4 _temp;
_temp = tex2D(_s_p, _texcoord);
_TMP0 = floor(_wpos.y / 2.00000000000000000E000 f);
_TMP1 = floor(_wpos.y);
if(_TMP0 != _TMP1 / 2.00000000000000000E000 f)
{ // if begin
_temp.xyz = _temp.xyz * _uIntensity;
} // end if
return _temp;
} // main end
那么,我以为加载着色器的那一刻它就会应用于所有渲染输出,但显然我错了。
以下是每 2-5 毫秒发生的情况 - 所有视频都渲染到屏幕上,所以所有 D3D 东西都在工作,但加载的像素着色器没有任何区别。
Interface.VideoInfo VI = Interface.EX_GetVideoBuffer();
Direct3DDevice.Clear(SlimDX.Direct3D9.ClearFlags.Target, Color.Black, 1.0f, 0);
using (System.Drawing.Bitmap WindowsBMP = new System.Drawing.Bitmap(VI.Width, VI.Height, VI.Stride, System.Drawing.Imaging.PixelFormat.Format16bppRgb565, VI.Buffer))
{
BitmapData WindowsBPMData = WindowsBMP.LockBits(new Rectangle(0, 0, VI.Width, VI.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
byte[] Data = new byte[WindowsBPMData.Stride * WindowsBPMData.Height];
Marshal.Copy(WindowsBPMData.Scan0, Data, 0, Data.Length);
WindowsBMP.UnlockBits(WindowsBPMData);
using (SlimDX.Direct3D9.Texture TEX = new SlimDX.Direct3D9.Texture(Direct3DDevice, WindowsBPMData.Width, WindowsBPMData.Height, 0, SlimDX.Direct3D9.Usage.None, SlimDX.Direct3D9.Format.A8R8G8B8, SlimDX.Direct3D9.Pool.Managed))
{
DataRectangle DR = TEX.LockRectangle(0, SlimDX.Direct3D9.LockFlags.Discard);
DR.Data.Position = 0;
DR.Data.Write(Data, 0, Data.Length);
DR.Data.Close();
TEX.UnlockRectangle(0);
using (SlimDX.Direct3D9.Sprite S = new SlimDX.Direct3D9.Sprite(Direct3DDevice))
{
Direct3DDevice.BeginScene();
S.Begin(SlimDX.Direct3D9.SpriteFlags.None);
S.Draw(TEX, Color.Transparent);
S.End();
Direct3DDevice.EndScene();
Direct3DDevice.Present(new Rectangle(0, 0, WindowsBPMData.Width, WindowsBPMData.Height), new Rectangle(0, 0, PAN_Video.Width, PAN_Video.Height));
}
}
}
我知道我遗漏了一些东西 - 但我遇到的所有示例都涉及渲染线框等 - 我正在渲染来自本机 Lib 的图像,而我所拥有的只是像素缓冲区。
请多多关照,因为 DirectX 的东西对我来说都是全新的。
您没有设置制服/着色器变量,因此您不应期待任何合理的输出。我想我希望 uIntensity 为 0,所以你应该得到极端的扫描线,但我想它也可能是 1.0(在这种情况下你不会看到它。)再一次,如果你的 window 缩小 50 % 应用扫描线后,您可能看不到扫描线。
总之,不要用这么简单的像素着色器来测试。使用 returns float4(1,0,0,1);.
的像素着色器进行测试
我无法实现在我的项目(Sega Genesis Emulator)中提供着色器支持的梦想
我改用了一个名为 ReShade 的框架,本质上它允许来自启用 DirectX 的应用程序的输出使其渲染被修改后的驱动程序拦截 (d3d9.dll),此挂钩允许使用各种加载预编译着色器HLSL.
您只需将驱动程序放在应用程序目录中,然后对 DirectX 的任何调用都由该驱动程序管理。
我立竿见影。
所以,我对使用 DirectX 进行开发还很陌生,我正在慢慢达到目标...但是!
我有这个实例化 Direct3D9 运行时,创建设备并加载像素着色器。 - 我可以确认像素着色器加载为 1) 它适用于不是我开发的其他应用程序。 2) 我可以破解并看到所有各种属性都可用,并且 3) 没有报告错误。
这是设置。
Direct3DInstance = new SlimDX.Direct3D9.Direct3D();
SlimDX.Direct3D9.PresentParameters PP = new SlimDX.Direct3D9.PresentParameters();
PP.Windowed = true;
PP.BackBufferHeight = PAN_Video.ClientSize.Height;
PP.BackBufferWidth = PAN_Video.ClientSize.Width;
PP.BackBufferCount = 0;
PP.BackBufferFormat = SlimDX.Direct3D9.Format.R5G6B5;
PP.PresentationInterval = SlimDX.Direct3D9.PresentInterval.Immediate;
PP.DeviceWindowHandle = PAN_Video.Handle;
Direct3DDevice = new SlimDX.Direct3D9.Device(Direct3DInstance, 0, SlimDX.Direct3D9.DeviceType.Hardware, PAN_Video.Handle, SlimDX.Direct3D9.CreateFlags.HardwareVertexProcessing, PP);
string error = null;
SlimDX.Direct3D9.ShaderBytecode SBC = SlimDX.Direct3D9.ShaderBytecode.Compile(File.ReadAllText(@"C:\Users\Marcus\Desktop\scanlines.txt"), null, null, "main", "ps_3_0", SlimDX.Direct3D9.ShaderFlags.UseLegacyD3DX9_31Dll, out error);
SlimDX.Direct3D9.PixelShader PS = new SlimDX.Direct3D9.PixelShader(Direct3DDevice, SBC);
Direct3DDevice.PixelShader = PS;
这是着色器 - 它不是我的,而是我用来测试的。
// hlslf output by Cg compiler
// cgc version 3.1.0013, build date Apr 18 2012
// command line args: -profile hlslf -po version=110
//vendor NVIDIA Corporation
//version 3.1.0.13
//profile hlslf
//program main_fragment
//semantic main_fragment.s_p : TEXUNIT0
//semantic uIntensity
//var sampler2D s_p : TEXUNIT0 : _s_p 0 : 2 : 1
//var float uIntensity : : _uIntensity : -1 : 1
//var float2 texcoord : $vin.TEXCOORD0 : TEXCOORD0 : 0 : 1
//var float2 wpos : $vin.WPOS : WPOS : 1 : 1
//var float4 main_fragment : $vout.COLOR : COLOR : -1 : 1
//default uIntensity = 100
#
pragma pack_matrix(row_major)
struct input
{
float2 _video_size;
float2 _texture_size;
float2 _output_size;
};
float _TMP1;
float _TMP0;
uniform float _uIntensity;
// main procedure, the original name was main_fragment
float4 main( in float2 _texcoord: TEXCOORD0, in float2 _wpos: VPOS, uniform sampler2D _s_p: TEXUNIT0): COLOR0
{
float4 _temp;
_temp = tex2D(_s_p, _texcoord);
_TMP0 = floor(_wpos.y / 2.00000000000000000E000 f);
_TMP1 = floor(_wpos.y);
if(_TMP0 != _TMP1 / 2.00000000000000000E000 f)
{ // if begin
_temp.xyz = _temp.xyz * _uIntensity;
} // end if
return _temp;
} // main end
那么,我以为加载着色器的那一刻它就会应用于所有渲染输出,但显然我错了。
以下是每 2-5 毫秒发生的情况 - 所有视频都渲染到屏幕上,所以所有 D3D 东西都在工作,但加载的像素着色器没有任何区别。
Interface.VideoInfo VI = Interface.EX_GetVideoBuffer();
Direct3DDevice.Clear(SlimDX.Direct3D9.ClearFlags.Target, Color.Black, 1.0f, 0);
using (System.Drawing.Bitmap WindowsBMP = new System.Drawing.Bitmap(VI.Width, VI.Height, VI.Stride, System.Drawing.Imaging.PixelFormat.Format16bppRgb565, VI.Buffer))
{
BitmapData WindowsBPMData = WindowsBMP.LockBits(new Rectangle(0, 0, VI.Width, VI.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
byte[] Data = new byte[WindowsBPMData.Stride * WindowsBPMData.Height];
Marshal.Copy(WindowsBPMData.Scan0, Data, 0, Data.Length);
WindowsBMP.UnlockBits(WindowsBPMData);
using (SlimDX.Direct3D9.Texture TEX = new SlimDX.Direct3D9.Texture(Direct3DDevice, WindowsBPMData.Width, WindowsBPMData.Height, 0, SlimDX.Direct3D9.Usage.None, SlimDX.Direct3D9.Format.A8R8G8B8, SlimDX.Direct3D9.Pool.Managed))
{
DataRectangle DR = TEX.LockRectangle(0, SlimDX.Direct3D9.LockFlags.Discard);
DR.Data.Position = 0;
DR.Data.Write(Data, 0, Data.Length);
DR.Data.Close();
TEX.UnlockRectangle(0);
using (SlimDX.Direct3D9.Sprite S = new SlimDX.Direct3D9.Sprite(Direct3DDevice))
{
Direct3DDevice.BeginScene();
S.Begin(SlimDX.Direct3D9.SpriteFlags.None);
S.Draw(TEX, Color.Transparent);
S.End();
Direct3DDevice.EndScene();
Direct3DDevice.Present(new Rectangle(0, 0, WindowsBPMData.Width, WindowsBPMData.Height), new Rectangle(0, 0, PAN_Video.Width, PAN_Video.Height));
}
}
}
我知道我遗漏了一些东西 - 但我遇到的所有示例都涉及渲染线框等 - 我正在渲染来自本机 Lib 的图像,而我所拥有的只是像素缓冲区。
请多多关照,因为 DirectX 的东西对我来说都是全新的。
您没有设置制服/着色器变量,因此您不应期待任何合理的输出。我想我希望 uIntensity 为 0,所以你应该得到极端的扫描线,但我想它也可能是 1.0(在这种情况下你不会看到它。)再一次,如果你的 window 缩小 50 % 应用扫描线后,您可能看不到扫描线。
总之,不要用这么简单的像素着色器来测试。使用 returns float4(1,0,0,1);.
的像素着色器进行测试我无法实现在我的项目(Sega Genesis Emulator)中提供着色器支持的梦想
我改用了一个名为 ReShade 的框架,本质上它允许来自启用 DirectX 的应用程序的输出使其渲染被修改后的驱动程序拦截 (d3d9.dll),此挂钩允许使用各种加载预编译着色器HLSL.
您只需将驱动程序放在应用程序目录中,然后对 DirectX 的任何调用都由该驱动程序管理。
我立竿见影。