简体   繁体   English

使用DirectX将像素着色器应用于视频

[英]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. 我有FX文件。 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();
                capturedVideoTexture.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: 这是最终实现的效果:乌贼属关于VMR9视频:

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

Now what remains is code the anaglyph shaders for 3D content :) 现在剩下的就是3D内容的立体阴影着色器的代码:)

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. 从视频帧创建纹理,然后LockRect它并复制数据。现在您拥有D3D9纹理中的数据。

Loading a pixel shader is easy. 加载像素着色器很容易。 Use D3DXCreateEffectFromFile . 使用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 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). 然后你需要记住,“投影”空间从-1到1(从左到右从下到上)。

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): 然后,您需要按如下方式设置视口(这是一个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 );

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". 顺便说一句我也不完全确定你在SetTextureStageState中做了什么......你只是说“选择Arg1”。 Are you passing in the equivalent of D3DTA_TEXTURE to COLOR ARG 1? 你是否正在将D3DTA_TEXTURE传递给COLOR ARG 1?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM