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

3

我需要将一个像素着色器应用到这段代码(全屏四边形)。我有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视频上的棕褐色:
现在需要编写3D内容的立体眼镜着色器代码 :)

你说你需要帮助,但是你并没有提出任何问题。你期望有人为你编写函数吗? - Paul Groke
我需要帮助编写它,事实上我在DirectX方面完全是个新手。一个能够完成相同功能的示例也可以。或者是由其他人编写的函数,或者是原型代码... - Marino Šimić
这是一个非常难回答的问题。你尝试过写代码吗?这样你至少可以针对具体的问题提出问题。 - Goz
你能发布完整的dshow代码吗? - Softlion
1个回答

2
从视频帧中创建纹理,然后对其进行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?

我会尝试您的建议并进行跟进。 - Marino Šimić
设备.设置纹理级别状态(0, 纹理级别状态.颜色操作, 2); 设备.设置纹理级别状态(0, 纹理级别状态.颜色参数1, 2);应该等同于:设置纹理级别状态(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
设置纹理级别状态(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);我会尝试您的建议,看看是否有所改变。
- Marino Šimić
我删除了你指定的行并修改了视口,分配了矩阵,现在我在四边形上拥有全屏视频。现在我只需要应用像素着色器。+1 分给你,你离赏金非常接近:)) - Marino Šimić
没事了,我已经成功应用了着色器,谢谢奖金 :) - Marino Šimić

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接