2012-12-08 103 views
1

我從ParticleGS DirectX10的樣品工作,在DirectX 11幾何着色器失真

建立幾何着色器基於粒子系統使用示例代碼,將其更改爲我喜歡的,我能畫一個四(這本質上是一個粒子不斷重新創建自己)。

這是我的shader代碼:

//Single particle stream-out shader which uses ping-pong buffers. 
//Based on DirectX sample ParticlesGS 

struct VSParticleIn 
{ 
    float3 pos    : POSITION;   
    float3 vel    : NORMAL;   
    float Timer   : TIMER;    
    uint Type    : TYPE;  //Only one type for the moment.   
}; 

struct VSParticleDrawOut 
{ 
    float3 pos : POSITION; 
    float4 color : COLOR0; 
    float radius : RADIUS; 
}; 

struct PSSceneIn 
{ 
    float4 pos : SV_Position; 
    float2 tex : TEXTURE0; 
    float4 color : COLOR0; 
}; 

cbuffer cbRenderParticle 
{ 
    float4x4 g_mWorldViewProj; 
    float4x4 g_mInvView; 
}; 

cbuffer cbAdvanceParticle 
{ 
    float g_fGlobalTime; 
    float g_fElapsedTime; 
    float4 g_vFrameGravity; 
    float g_fSecondsPerFirework = 1.0; 
}; 

cbuffer cbImmutable 
{ 
    float3 g_positions[4] = 
    { 
     float3(-1, 1, 0), 
     float3(1, 1, 0), 
     float3(-1, -1, 0), 
     float3(1, -1, 0), 
    }; 
    float2 g_texcoords[4] = 
    { 
     float2(0,1), 
     float2(1,1), 
     float2(0,0), 
     float2(1,0), 
    }; 
}; 

Texture2D g_txDiffuse; 
SamplerState g_samLinear 
{ 
    Filter = MIN_MAG_MIP_LINEAR; 
    AddressU = Clamp; 
    AddressV = Clamp; 
}; 

Texture1D g_txRandom; 
SamplerState g_samPoint 
{ 
    Filter = MIN_MAG_MIP_POINT; 
    AddressU = Wrap; 
}; 

RasterizerState mainState { 
    FillMode = Solid; 
    CullMode = None; 
    FrontCounterClockwise = false; 
}; 

BlendState AdditiveBlending 
{ 
    AlphaToCoverageEnable = FALSE; 
    BlendEnable[0] = TRUE; 
    SrcBlend = SRC_ALPHA; 
    DestBlend = ONE; 
    BlendOp = ADD; 
    SrcBlendAlpha = ZERO; 
    DestBlendAlpha = ZERO; 
    BlendOpAlpha = ADD; 
    RenderTargetWriteMask[0] = 0x0F; 
}; 

BlendState NoBlending 
{ 
    AlphaToCoverageEnable = FALSE; 
    BlendEnable[0] = FALSE; 
}; 

DepthStencilState DisableDepth 
{ 
    DepthEnable = FALSE; 
    DepthWriteMask = ZERO; 
}; 

DepthStencilState DSSLess 
{ 
    DepthEnable = TRUE; 
    DepthWriteMask = ALL; 
    StencilEnable = TRUE; 
    StencilReadMask = 0; 
    StencilWriteMask = 0; 

    FrontFaceStencilFunc = ALWAYS; 
    FrontFaceStencilDepthFail = INVERT; 
    FrontFaceStencilPass = KEEP; 
    FrontFaceStencilFail = KEEP; 

    BackFaceStencilFunc = ALWAYS; 
    BackFaceStencilDepthFail = INVERT; 
    BackFaceStencilPass = KEEP; 
    BackFaceStencilFail = KEEP; 

    DepthFunc = LESS; 
}; 

VSParticleDrawOut RenderSceneVS(VSParticleIn input) 
{ 
    VSParticleDrawOut output = (VSParticleDrawOut)0; 
    output.pos = input.pos; 
    output.radius = 3; 
    output.color = float4(1,1,1,1); 
    return output; 
} 

VSParticleIn PassthroughVS(VSParticleIn input) 
{ 
    return input; 
} 

float3 RandomDir(float fOffset) 
{ 
    float tCoord = (g_fGlobalTime + fOffset)/300.0; 
    return g_txRandom.SampleLevel(g_samPoint, tCoord, 0); 
} 


[maxvertexcount(128)] 
void AdvanceParticlesGS(point VSParticleIn input[1], inout PointStream<VSParticleIn> ParticleOutputStream) 
{ 
    //Just keeps emitting itself. 
    ParticleOutputStream.Append(input[0]); 
} 


[maxvertexcount(4)] 
void RenderSceneGS(point VSParticleDrawOut input[1], inout TriangleStream<PSSceneIn> SpriteStream) 
{ 
    PSSceneIn output; 

    for(int i=0; i<4; i++) 
    { 
     float3 position = g_positions[i]*input[0].radius; 
     //position = mul(position, g_mInvView) + input[0].pos; 
     output.pos = mul(float4(position,1.0), g_mWorldViewProj); 

     output.color = input[0].color; 
     output.tex = g_texcoords[i]; 
     SpriteStream.Append(output); 
    } 
    SpriteStream.RestartStrip(); 
} 

float4 RenderScenePS(PSSceneIn input) : SV_Target 
{ 
    return g_txDiffuse.Sample(g_samLinear, input.tex) * input.color; 
} 

technique10 RenderParticles 
{ 
    pass p0 
    { 
     SetVertexShader(CompileShader(vs_4_0, RenderSceneVS())); 
     SetGeometryShader(CompileShader(gs_4_0, RenderSceneGS())); 
     SetPixelShader(CompileShader(ps_4_0, RenderScenePS())); 

     SetBlendState(AdditiveBlending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF); 
     SetRasterizerState(mainState); 
     SetDepthStencilState(DSSLess, 0); 
    } 
} 


GeometryShader gsStreamOut = ConstructGSWithSO(CompileShader(gs_4_0, AdvanceParticlesGS()), "POSITION.xyz; NORMAL.xyz; TIMER.x; TYPE.x"); 
technique10 AdvanceParticles 
{ 
    pass p0 
    { 
     SetVertexShader(CompileShader(vs_4_0, PassthroughVS())); 
     SetGeometryShader(gsStreamOut); 
     SetPixelShader(NULL); 

     SetRasterizerState(mainState); 
     SetDepthStencilState(DisableDepth, 0); 
    } 
} 

不過,我注意到一個問題,這是類似於一個我曾經有過:呈現的形狀是扭曲。這是展示正在發生的事件的視頻。 http://youtu.be/6NY_hxjMfwY

現在,當我一起使用多個效果時,我曾經遇到過這個問題,當我意識到我需要爲其他效果明確設置幾何着色器爲空。我解決了這個問題,就像你在視頻中看到的一樣,因爲場景的其他部分正在正確繪製。請注意,雖然我在主渲染狀態下關閉了剔除,但某些方面正在以某種方式被剔除。

獨立運行時,着色器具有相同的行爲。其他着色器似乎不會干擾它。

我的問題是,什麼可能會導致quad的失真?我驗證了我的轉換矩陣,他們似乎是正確的。 什麼可能是失真的原因?或者什麼是常見原因?

+1

您的着色器代碼會很有趣,特別是幾何和頂點着色器。如果它的代碼太多,你可以將其發佈到pastebin並將其鏈接到此處。 – Gnietschow

+0

你走了,鏈接在問題的頂部! –

+1

你的代碼看起來很好。你確定你將正確的矩陣傳遞給着色器嗎? –

回答

0

我終於有了解決辦法! 問題在於RenderSceneGS幾何着色器。 矩陣應該在其他命令,這是

output.pos = mul(g_mWorldViewProj, float4(position,1.0)); 

我發現這種奇怪的,因爲這個訂單相比,在頂點着色器矩陣乘法實際上顛倒相乘。我被告知這是由於矩陣如何存儲在內存中的,但是我沒有關於這個問題的性質的更多信息。