Применить пиксельный шейдер к видео с помощью DirectX - PullRequest
3 голосов
/ 21 марта 2011

Мне нужно применить пиксельный шейдер к этому коду (полноэкранный квад). У меня есть файл FX. Какая процедура? (ПРАВКА завершена: код работает)

public int CompositeImage(IntPtr pD3DDevice, IntPtr pddsRenderTarget, AMMediaType pmtRenderTarget, long rtStart, long rtEnd, int dwClrBkGnd, VMR9VideoStreamInfo[] pVideoStreamInfo, int cStreams)
        {
            try
            {
                if (udevice != pD3DDevice)
                {
                    InitCompositionDevice(pD3DDevice);
                }

                // will be creating managed object from those so increment ref count
                Marshal.AddRef(pddsRenderTarget);
                Marshal.AddRef(pVideoStreamInfo[0].pddsVideoSurface);

                device.Clear(ClearFlags.Target, Color.Red, 1f, 0);
                device.BeginScene();

                // here the video frame will be stored
                Texture capturedVideoTexture = null;

                // this is the output surface
                Surface renderTarget = new Surface(pddsRenderTarget);

                // get the surface for the input video
                Surface videoSurface = new Surface(pVideoStreamInfo[0].pddsVideoSurface);

                // will use this rect for calculations
                Rectangle videoSurfaceRect = new Rectangle(0, 0, videoSurface.Description.Width, videoSurface.Description.Height);

                // create single layer texture from input video
                capturedVideoTexture = new Texture(device, videoSurfaceRect.Width, videoSurfaceRect.Height, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);

                // get its surface
                Surface textureSurface = capturedVideoTexture.GetSurfaceLevel(0);

                // will use this rect for calculations
                Rectangle textureSurfaceRect = new Rectangle(0, 0, textureSurface.Description.Width, textureSurface.Description.Height);

                // copy the whole video surface into the texture surface
                device.StretchRectangle(videoSurface, videoSurfaceRect, textureSurface, textureSurfaceRect, TextureFilter.Linear);

                // identity matreices for world projection and view
                device.Transform.World = Matrix.Identity;
                device.Transform.Projection = Matrix.Identity;
                device.Transform.View = Matrix.Identity;

                // setup viewport
                Viewport view = new Viewport();
                view.X = 0;
                view.Y = 0;
                view.Width = 1920;
                view.Height = 1080;
                view.MinZ = 0;
                view.MaxZ = 1;
                device.Viewport = view;

                // writing will go to output surface
                device.SetRenderTarget(0, renderTarget);

                // nothing fancy of a vertex shader
                device.VertexFormat = CustomVertex.PositionTextured.Format;

                // use the texture while rendering
                device.SetTexture(0, capturedVideoTexture);

                //Bind our Vertex Buffer
                device.SetStreamSource(0, vb, 0);

                // setup and apply shader
                ps.Begin(FX.None);
                ps.BeginPass(0);
                ps.SetValue("ScreenTexture", capturedVideoTexture);

                //Render from our Vertex Buffer
                device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);

                ps.EndPass();
                ps.End();

                device.EndScene();

                videoSurface.Dispose();
                textureSurface.Dispose();
                capturedVideoTexture.Dispose();
                renderTarget.Dispose();

                videoSurface = null;
                renderTarget = null;
                capturedVideoTexture = null;

            }

            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
            }

            return 0;

        }

Это конечный достигнутый эффект: сепия на видео VMR9:

http://img825.imageshack.us/img825/9207/sepiag.png

Теперь осталось написать код шейдеров анаглифов для 3D-контента:)

1 Ответ

2 голосов
/ 27 марта 2011

Создайте свою текстуру из видеокадра, а затем LockRect и скопируйте данные. Теперь у вас есть данные в текстуре D3D9.

Загрузка пиксельного шейдера проста. Используйте D3DXCreateEffectFromFile .

Визуализация квадрата с текстурой может быть легко изучена при просмотре любого учебника в Интернете. Попробуйте это:

http://www.drunkenhyena.com/cgi-bin/view_cpp_article.pl?chapter=2;article=30

Если вы установите его правильно, эффект будет автоматически применен к квадру.

Редактировать: При просмотре вашего кода выясняется, что вы не устанавливаете мир, вид или матрицы проекций. Также вы не устанавливаете свой видовой экран.

Во-первых, вы должны установить для них все матрицы на единицу. Это означает, что вершины, которые вы проходите, будут перемещаться по конвейеру без каких-либо изменений. Затем вам необходимо помнить, что пространство «проекции» изменяется от -1 до 1 (слева направо, снизу вверх).

Поэтому вам нужно определить ваш квад:

ver[0] = new CustomVertex.PositionTextured(-1, 1, 0, 0, 0);
ver[1] = new CustomVertex.PositionTextured(1, 1, 0, 1, 0);
ver[2] = new CustomVertex.PositionTextured(-1, -1, 0, 0, 1);
ver[3] = new CustomVertex.PositionTextured(1, 1, 0, 1, 0);
ver[4] = new CustomVertex.PositionTextured(1, -1, 0, 1, 1);
ver[5] = new CustomVertex.PositionTextured(-1, -1, 0, 0, 1);

Затем вам нужно установить свой видовой экран следующим образом (это набор видимости C ++, так как я не особо использовал C #):

D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = 1920;
vp.Height = 1080;
vp.MinZ   = 0.0f;
vp.MaxZ   = 1.0f;
pDevice->SetViewport( &vp );

В этот момент я ожидаю увидеть всю текстуру на экране.

Кстати, я также не совсем уверен, что вы делаете в SetTextureStageState ... Вы просто говорите "Выберите Arg1". Вы передаете эквивалент D3DTA_TEXTURE в COLOR ARG 1?

...