屏幕空间正方形在 PIX 中看起来扭曲

发布于 2024-12-02 01:19:20 字数 6627 浏览 2 评论 0原文

我有一个简单的函数,可以创建一个覆盖整个屏幕的正方形,我用它来应用后处理效果,但据我所知,它是导致无数错误的原因。

当我在 PIX 中运行代码时,我得到以下网格,但正方形应该是直的并覆盖屏幕,不是吗?

来自 PIX 捕获的网格信息

我的顶点着色器不进行任何转换,只是将位置信息传递给像素着色器。

创建正方形的函数如下:

private void InitializeGeometry()
    {
        meshes = new Dictionary<Vector3, Mesh>();
        //build array of vertices for one square
        ppVertex[] vertexes = new ppVertex[4];
        //vertexes[0].Position = new Vector3(-1f, -1f, 0.25f);

        vertexes[0].Position = new Vector3(-1, -1, 1f);
        vertexes[1].Position = new Vector3(-1, 1, 1f);
        vertexes[2].Position = new Vector3(1, -1, 1f);
        vertexes[3].Position = new Vector3(1, 1, 1f);

        vertexes[0].TexCoords = new Vector2(0, 0);
        vertexes[1].TexCoords = new Vector2(0, 1);
        vertexes[2].TexCoords = new Vector2(1, 0);
        vertexes[3].TexCoords = new Vector2(1, 1);

        //build index array for the vertices to build a quad from two triangles
        short[] indexes = { 0, 1, 2, 1, 3, 2 };

        //create the data stream to push the vertex data into the buffer
        DataStream vertices = new DataStream(Marshal.SizeOf(typeof(Vertex)) * 4, true, true);
        //load the data stream
        vertices.WriteRange(vertexes);
        //reset the data position
        vertices.Position = 0;

        //create the data stream to push the index data into the buffer
        DataStream indices = new DataStream(sizeof(short) * 6, true, true);
        //load the data stream
        indices.WriteRange(indexes);
        //reset the data position
        indices.Position = 0;

        //create the mesh object
        Mesh mesh = new Mesh();

        //create the description of the vertex buffer
        D3D.BufferDescription vbd = new BufferDescription();
        vbd.BindFlags = D3D.BindFlags.VertexBuffer;
        vbd.CpuAccessFlags = D3D.CpuAccessFlags.None;
        vbd.OptionFlags = ResourceOptionFlags.None;
        vbd.SizeInBytes = Marshal.SizeOf(typeof(Vertex)) * 4;
        vbd.Usage = ResourceUsage.Default;
        //create and assign the vertex buffer to the mesh, filling it with data
        mesh.VertexBuffer = new D3D.Buffer(device, vertices, vbd);

        //create the description of the index buffer
        D3D.BufferDescription ibd = new BufferDescription();
        ibd.BindFlags = D3D.BindFlags.IndexBuffer;
        ibd.CpuAccessFlags = D3D.CpuAccessFlags.None;
        ibd.OptionFlags = ResourceOptionFlags.None;
        ibd.SizeInBytes = sizeof(short) * 6;
        ibd.Usage = ResourceUsage.Default;
        //create and assign the index buffer to the mesh, filling it with data
        mesh.IndexBuffer = new D3D.Buffer(device, indices, ibd);

        //get vertex and index counts
        mesh.vertices = vertexes.GetLength(0);
        mesh.indices = indexes.Length;

        //close the data streams
        indices.Close();
        vertices.Close();

        meshes.Add(new Vector3(0), mesh);
    }

当我渲染正方形时:

private void DrawScene()
    {
        lock (meshes)
        {
            foreach (Mesh mesh in meshes.Values)
            {
                if (mesh.indices > 0)
                {
                    try
                    {
                        //if (camera.SphereInFrustum(mesh.BoundingSphere, sphereRadius))
                        //{
                            context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(mesh.VertexBuffer, Marshal.SizeOf(typeof(Vertex)), 0));
                            context.InputAssembler.SetIndexBuffer(mesh.IndexBuffer, Format.R16_UInt, 0);
                            context.DrawIndexed(mesh.indices, 0, 0);
                        //}
                    }
                    catch (Exception err)
                    {
                        MessageBox.Show(err.Message);
                    }
                }
            }
        }
    }

编辑:我添加了正在运行的顶点着色器

cbuffer EveryFrame : register(cb0)
{
    float3 diffuseColor : packoffset(c0);
    float3 lightdir : packoffset(c1);
};

cbuffer EveryMotion : register(cb1)
{
    float4x4 WorldViewProjection : packoffset(c0);
    float4x4 LightWorldViewProjection : packoffset(c4);
};

struct VS_IN
{
    float3 position : POSITION;
    float3 normal : NORMAL;
    float4 col : TEXCOORD;
};

struct PS_IN
{
    float4 position : SV_POSITION;
    float4 col : TEXCOORD;
    float3 normal : NORMAL;
};

PS_IN VS(VS_IN input)
{
    PS_IN output;
    output.position = float4(input.position,1);
    output.col = input.col;
    output.normal = input.normal;
    return output;
}

这是 PIX 的顶点输出。

PreVS:

preVS

PostVS:

postVS

这是当我选择调试顶点 0 时生成的反汇编 PIX,

//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
//
//
//
// Input signature:
//
// Name             Index   Mask Register SysValue Format   Used
// ---------------- ----- ------ -------- -------- ------ ------
// POSITION             0   xyz         0     NONE  float   xyz 
// NORMAL               0   xyz         1     NONE  float   xyz 
// TEXCOORD             0   xyzw        2     NONE  float       
//
//
// Output signature:
//
// Name             Index   Mask Register SysValue Format   Used
// ---------------- ----- ------ -------- -------- ------ ------
// SV_POSITION          0   xyzw        0      POS  float   xyzw
// TEXCOORD             0   xyzw        1     NONE  float   xyzw
// NORMAL               0   xyz         2     NONE  float   xyz 
//
vs_4_0
dcl_input v0.xyz
dcl_input v1.xyz
dcl_output_siv  o0.xyzw , position
dcl_output o1.xyzw
dcl_output o2.xyz
mov o0.xyz, v0.xyzx
mov o0.w, l(1.000000)
mov o1.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
mov o2.xyz, v1.xyzx
ret 
// Approximately 5 instruction slots used

我还添加了输入汇编器:

private void SetPPInputAssembler(Shader shader)
        {
            InputElement[] elements = new[] {
                new InputElement("POSITION",0,Format.R32G32B32_Float,0),
                new InputElement("NORMAL",0,Format.R32G32B32_Float,12,0),
                new InputElement("TEXCOORD",0,Format.R32G32_Float,24,0),
            };

            InputLayout layout = new InputLayout(device, shader.InputSignature, elements);

            context.InputAssembler.InputLayout = layout;
            context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
        }

I have a simple function that creates a square that covers the entire screen, I use it for applying post-processing effects, however as far as I can tell it has been the cause of countless errors.

When I run my code in PIX I get the following mesh, but the square should be straight and covering the screen, shouldn't it?

Mesh information from PIX capture

My vertex shader does no transformation and simply passes position information to the pixel shader.

The function that creates the square is as follows:

private void InitializeGeometry()
    {
        meshes = new Dictionary<Vector3, Mesh>();
        //build array of vertices for one square
        ppVertex[] vertexes = new ppVertex[4];
        //vertexes[0].Position = new Vector3(-1f, -1f, 0.25f);

        vertexes[0].Position = new Vector3(-1, -1, 1f);
        vertexes[1].Position = new Vector3(-1, 1, 1f);
        vertexes[2].Position = new Vector3(1, -1, 1f);
        vertexes[3].Position = new Vector3(1, 1, 1f);

        vertexes[0].TexCoords = new Vector2(0, 0);
        vertexes[1].TexCoords = new Vector2(0, 1);
        vertexes[2].TexCoords = new Vector2(1, 0);
        vertexes[3].TexCoords = new Vector2(1, 1);

        //build index array for the vertices to build a quad from two triangles
        short[] indexes = { 0, 1, 2, 1, 3, 2 };

        //create the data stream to push the vertex data into the buffer
        DataStream vertices = new DataStream(Marshal.SizeOf(typeof(Vertex)) * 4, true, true);
        //load the data stream
        vertices.WriteRange(vertexes);
        //reset the data position
        vertices.Position = 0;

        //create the data stream to push the index data into the buffer
        DataStream indices = new DataStream(sizeof(short) * 6, true, true);
        //load the data stream
        indices.WriteRange(indexes);
        //reset the data position
        indices.Position = 0;

        //create the mesh object
        Mesh mesh = new Mesh();

        //create the description of the vertex buffer
        D3D.BufferDescription vbd = new BufferDescription();
        vbd.BindFlags = D3D.BindFlags.VertexBuffer;
        vbd.CpuAccessFlags = D3D.CpuAccessFlags.None;
        vbd.OptionFlags = ResourceOptionFlags.None;
        vbd.SizeInBytes = Marshal.SizeOf(typeof(Vertex)) * 4;
        vbd.Usage = ResourceUsage.Default;
        //create and assign the vertex buffer to the mesh, filling it with data
        mesh.VertexBuffer = new D3D.Buffer(device, vertices, vbd);

        //create the description of the index buffer
        D3D.BufferDescription ibd = new BufferDescription();
        ibd.BindFlags = D3D.BindFlags.IndexBuffer;
        ibd.CpuAccessFlags = D3D.CpuAccessFlags.None;
        ibd.OptionFlags = ResourceOptionFlags.None;
        ibd.SizeInBytes = sizeof(short) * 6;
        ibd.Usage = ResourceUsage.Default;
        //create and assign the index buffer to the mesh, filling it with data
        mesh.IndexBuffer = new D3D.Buffer(device, indices, ibd);

        //get vertex and index counts
        mesh.vertices = vertexes.GetLength(0);
        mesh.indices = indexes.Length;

        //close the data streams
        indices.Close();
        vertices.Close();

        meshes.Add(new Vector3(0), mesh);
    }

and when I render the square:

private void DrawScene()
    {
        lock (meshes)
        {
            foreach (Mesh mesh in meshes.Values)
            {
                if (mesh.indices > 0)
                {
                    try
                    {
                        //if (camera.SphereInFrustum(mesh.BoundingSphere, sphereRadius))
                        //{
                            context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(mesh.VertexBuffer, Marshal.SizeOf(typeof(Vertex)), 0));
                            context.InputAssembler.SetIndexBuffer(mesh.IndexBuffer, Format.R16_UInt, 0);
                            context.DrawIndexed(mesh.indices, 0, 0);
                        //}
                    }
                    catch (Exception err)
                    {
                        MessageBox.Show(err.Message);
                    }
                }
            }
        }
    }

EDIT: I've added the vertex shader being run

cbuffer EveryFrame : register(cb0)
{
    float3 diffuseColor : packoffset(c0);
    float3 lightdir : packoffset(c1);
};

cbuffer EveryMotion : register(cb1)
{
    float4x4 WorldViewProjection : packoffset(c0);
    float4x4 LightWorldViewProjection : packoffset(c4);
};

struct VS_IN
{
    float3 position : POSITION;
    float3 normal : NORMAL;
    float4 col : TEXCOORD;
};

struct PS_IN
{
    float4 position : SV_POSITION;
    float4 col : TEXCOORD;
    float3 normal : NORMAL;
};

PS_IN VS(VS_IN input)
{
    PS_IN output;
    output.position = float4(input.position,1);
    output.col = input.col;
    output.normal = input.normal;
    return output;
}

Here's PIX's vertex output.

PreVS:

preVS

PostVS:

postVS

And here's the dissassembly PIX generated when I chose to debug vertex 0

//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
//
//
//
// Input signature:
//
// Name             Index   Mask Register SysValue Format   Used
// ---------------- ----- ------ -------- -------- ------ ------
// POSITION             0   xyz         0     NONE  float   xyz 
// NORMAL               0   xyz         1     NONE  float   xyz 
// TEXCOORD             0   xyzw        2     NONE  float       
//
//
// Output signature:
//
// Name             Index   Mask Register SysValue Format   Used
// ---------------- ----- ------ -------- -------- ------ ------
// SV_POSITION          0   xyzw        0      POS  float   xyzw
// TEXCOORD             0   xyzw        1     NONE  float   xyzw
// NORMAL               0   xyz         2     NONE  float   xyz 
//
vs_4_0
dcl_input v0.xyz
dcl_input v1.xyz
dcl_output_siv  o0.xyzw , position
dcl_output o1.xyzw
dcl_output o2.xyz
mov o0.xyz, v0.xyzx
mov o0.w, l(1.000000)
mov o1.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
mov o2.xyz, v1.xyzx
ret 
// Approximately 5 instruction slots used

I've also added the input assembler:

private void SetPPInputAssembler(Shader shader)
        {
            InputElement[] elements = new[] {
                new InputElement("POSITION",0,Format.R32G32B32_Float,0),
                new InputElement("NORMAL",0,Format.R32G32B32_Float,12,0),
                new InputElement("TEXCOORD",0,Format.R32G32_Float,24,0),
            };

            InputLayout layout = new InputLayout(device, shader.InputSignature, elements);

            context.InputAssembler.InputLayout = layout;
            context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

苏佲洛 2024-12-09 01:19:20

显然,您的顶点输入位置与您想要给出的值不匹配。

对于第一个顶点,值在纹理坐标的 z 坐标之前看起来不错。
您在程序 Vertex-struct 中定义了一个 Vector2D,但在 Vertexshader Vertex-struct 中定义了一个 Vector4D,事情就变得混乱了。

只需将 VS_IN 更改为:

struct VS_IN
{
    float3 position : POSITION;
    float3 normal : NORMAL;
    float2 col : TEXCOORD; // float2 instead of float4
};

我不确定您是否真的想要颜色或更确切地说是纹理坐标。如果您确实想要颜色 float4 是正确的,但是您必须更改

vertexes[0].TexCoords = new Vector2(0, 0);

vertexes[0].TexCoords = new Vector4(0, 0, 0, 0);

无论哪种方式,其中一个变量命名错误,可能是造成混乱的原因。

Obviously your vertex input positions don't match the values you want to give in.

For the first vertex the values look good until the z-coordinate of the texture coordinates.
You are defining a Vector2D in your program Vertex-struct, but a Vector4D in the Vertexshader Vertex-struct and things get mixed up.

just change VS_IN to this:

struct VS_IN
{
    float3 position : POSITION;
    float3 normal : NORMAL;
    float2 col : TEXCOORD; // float2 instead of float4
};

I'm not sure though if you really want to have colors or rather texcoords. If you really want to have colors float4 would be right, but then you had to change

vertexes[0].TexCoords = new Vector2(0, 0);

into

vertexes[0].TexCoords = new Vector4(0, 0, 0, 0);

Either way, one of those variables is misnamed and probably the reason for the confusion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文