Применение пиксельного шейдера к текстуре внутри спрайта с помощью 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
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));
                }
            }

         }
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));
                }
            }

         }

Я знаю, что мне чего-то не хватает, но все примеры, с которыми я сталкивался, касаются рендеринга каркасов и тому подобного — я рендерю изображения из родной библиотеки, и все, что у меня есть, это пиксельный буфер.

Пожалуйста, будьте осторожны, так как все эти вещи DirectX для меня очень новы.


person Marcus Davies    schedule 04.06.2016    source источник
comment
Какого черта кто-то будет использовать DX9 в 2016 году?   -  person Felix K.    schedule 13.07.2016
comment
Это для эмулятора Sega Genesis (проект самообучения) 1. Мне было проще, 2. Обратная совместимость. Я сделал проводник d3d11, но простота использования с D3D9 перевесила преимущества использования чего-либо более современного.   -  person Marcus Davies    schedule 17.07.2016


Ответы (2)


Вы не установили переменные униформы / шейдера, поэтому не стоит ожидать какого-либо разумного результата. Думаю, я ожидал бы, что uIntensity будет равен 0, поэтому вы должны получить экстремальные строки развертки, но я предполагаю, что он также может быть 1.0 (в этом случае вы его не увидите). Опять же, если ваше окно уменьшено на 50% после применения строк развертки. , вы можете не увидеть строки сканирования.

Короче говоря, не тестируйте такой простой пиксельный шейдер. Протестируйте с помощью пиксельного шейдера, который возвращает float4(1,0,0,1);.

person zeromus    schedule 04.07.2016
comment
Спасибо. К сожалению, предоставление ожидаемых параметров по-прежнему ошеломляет меня (я никогда не имел дело с шейдерами - когда-либо). Вместо этого я использовал фреймворк - ReShade, который дал мне мгновенные результаты. - person Marcus Davies; 13.07.2016

Я не смог осуществить свою мечту по поддержке шейдеров в моем проекте (эмулятор Sega Genesis)

Вместо этого я использовал фреймворк под названием ReShade, по сути, он позволяет выходу из приложения с поддержкой DirectX перехватывать его рендеринг модифицированным драйвером (d3d9.dll), этот хук позволяет загружать предварительно скомпилированные шейдеры с использованием варианта HLSL.

вы просто помещаете драйвер в каталог приложений, тогда все вызовы DirectX управляются этим драйвером.

У меня сразу были результаты.

Веб-сайт Resahde

person Marcus Davies    schedule 13.07.2016