开发者

Apply pixel shader to video with DirectX

I need to apply a pixel shader to this code (the fullscreen quad). I have the FX file. What is the procedure? (EDIT finalized: code is working)

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();
                c开发者_JAVA技巧apturedVideoTexture.Dispose();
                renderTarget.Dispose();

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

            }

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

            return 0;

        }

This is the final effect achieved: Sepia on the VMR9 video:

Apply pixel shader to video with DirectX

Now what remains is code the anaglyph shaders for 3D content :)


Create your texture from the video frame and then LockRect it and copy the data in. You now have the data in a D3D9 Texture.

Loading a pixel shader is easy. Use D3DXCreateEffectFromFile.

Rendering a quad with a texture on it can easily be learnt by looking at any tutorial on the internet. Try this one:

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

If you set it up right the effect will automatically be applied to the quad.

Edit: From looking at your code it appears you don't set the world, view or projection matrices. Nor do you set your viewport.

Firstly you should set them all the matrices to identity. This means that the vertices you pass in will shift through the pipeline without any changes. You then need to bear in mind that the "projection" space runs from -1 to 1 (left to right bottom to top).

Therefore your need to define your quad as follows:

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

You then need to set your viewport as follows (This is a C++ Viewport set as i haven't really used C# much):

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

At this point I would expect to see the whole texture on screen.

Btw Im also not entirely sure what you are doing in the SetTextureStageState ... Are you just saying "Select Arg1". Are you passing in the equivalent of D3DTA_TEXTURE to COLOR ARG 1?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜