• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Telanor

GPU particles

39 posts in this topic

@Telanor: Two concerns: Grant your ParticleVertex a proper StructLayout (like in the original code), otherwise Marshal.SizeOf may go wrong. Also: Why is GPUParticles a static class ?


Yea I noticed I missed the StructLayout after I posted that. I've since added it, it didn't make any difference though. GPUParticles is a static class because I was planning on running all the particles from that class.
0

Share this post


Link to post
Share on other sites

The info is in the MSDN doc, you're just misreading the compiler error. Admittedly, setting up SO in the effect file is a little cryptic.
 


parameter count mismatch (ConstructGSWithSO)

There are up to four streams from your geometry shader you can select from, not just three. You're missing a NULL.

Also, if I get the sample right, it uses one output stream only, so you can omit the (optional) buffer index altogether (an index of >3 e.g. doesn't make sense anyway, you only got 4 output streams).

This should work (at least it compiles)

GeometryShader gsStreamOut = ConstructGSWithSO( pGSComp, "SV_POSITION.xyz;NORMAL.xyz;COLOR.xyzw;TEXCOORD0.xy;TEXCOORD1.x;TEXCOORD2.xy;",NULL,NULL,NULL,-1);
Note the -1 at the end. This is actually D3D11_SO_NO_RASTERIZED_STREAM, since you don't need rasterization for the particle update. Not sure this will work, try 0 first instead (PixelShader is NULL anyway).

 

I have  search disable rasterization you  said  that is  SetPixelShader(NULL) in  shader.Second make both the  depthState  and  StencilState disable!  I  want  konw  is the right way to realize you  said  like this?

Now  I have  success with  your help..  I am very  thanks  to you!  you  are  great...But  I doubt  is  the right  way to do like this

173985025201307252228022158823211327_000

Edited by GuoLei
0

Share this post


Link to post
Share on other sites

 

@Telanor: Two concerns: Grant your ParticleVertex a proper StructLayout (like in the original code), otherwise Marshal.SizeOf may go wrong. Also: Why is GPUParticles a static class ?


Yea I noticed I missed the StructLayout after I posted that. I've since added it, it didn't make any difference though. GPUParticles is a static class because I was planning on running all the particles from that class.

 

I  has  success  I will  give  the  code  to  you   maybe the  elapsedTime  you  are  wrong  

using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Runtime.InteropServices;
using Buffer = SharpDX.Direct3D11.Buffer;
using MapFlags = SharpDX.Direct3D11.MapFlags;
using MoonLight.Graphics;
using MoonLight.Vertex;
using MoonLight.Scene;
using MoonLight.Dispose;
using MoonLight.Time;

namespace MoonLight.Graphics.Particle
{
   

    public  class ParticleSystem:IMovableObj, IRenderableObj, IDisposable
    {

        BasicScene m_BasicScene;

        string m_Name;
        public string Name
        {
            get { return m_Name; }
        }

        SceneNode m_ParentSceneNode;

        public SceneNode ParentSceneNode
        {
            get { return m_ParentSceneNode; }
            set { m_ParentSceneNode = value; }
        }

       
        private const int MaxParticles = 1024 * 16;
        private const int MaxNew = 128;

        public const uint Flag_Constrained = 1;
        public const uint Flag_Fast_Fade = 2;

        private  Buffer m_SpawnBuffer;
        private  Buffer m_DrawFromBuffer;
        private  Buffer M_StreamToBuffer;

        private  EffectPass m_UpdatePass;
        private  EffectPass m_RenderPass;
        private  InputLayout m_InputLayout;
        ShaderResourceView m_ParticleTextureView;
        Effect m_Effect;

        private  VertexParticle[] m_NewParticles;
        private  int m_NumNew=0;
      

        private Random m_Random = new Random();
        private float m_Elapsed;


        public ParticleSystem(BasicScene basicScene, string name, Effect effect, Texture2D particleTexture2D)
        {
            this.m_Name = name;
            m_BasicScene = basicScene;
            m_NewParticles = new VertexParticle[MaxNew];

            m_SpawnBuffer = new Buffer(m_BasicScene.WPFRenderHost.Device, new BufferDescription(VertexParticle.SizeInBytes * MaxNew, ResourceUsage.Dynamic, BindFlags.VertexBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0));
            m_DrawFromBuffer = new Buffer(m_BasicScene.WPFRenderHost.Device, new BufferDescription(VertexParticle.SizeInBytes * MaxParticles, ResourceUsage.Default, BindFlags.VertexBuffer | BindFlags.StreamOutput, CpuAccessFlags.None, ResourceOptionFlags.None, 0));
            M_StreamToBuffer = new Buffer(m_BasicScene.WPFRenderHost.Device, new BufferDescription(VertexParticle.SizeInBytes * MaxParticles, ResourceUsage.Default, BindFlags.VertexBuffer | BindFlags.StreamOutput, CpuAccessFlags.None, ResourceOptionFlags.None, 0));

            m_UpdatePass = effect.GetTechniqueByName("UpdateTeq").GetPassByIndex(0);
            m_RenderPass = effect.GetTechniqueByName("RenderTeq").GetPassByIndex(0);

            m_InputLayout = new InputLayout(m_BasicScene.WPFRenderHost.Device, m_UpdatePass.Description.Signature, VertexParticle.VertexDeclaration);
            m_Effect = effect;
            m_ParticleTextureView = new ShaderResourceView(m_BasicScene.WPFRenderHost.Device, particleTexture2D);

        
        
        }


        public void Spawn(Vector3 position, Vector3 velocity, Color color, float sizeStart, float sizeEnd, float lifetime, bool constrained, bool fastFade)
        {
            // discard particle if buffer is full 
            if (m_NumNew >= MaxNew)
                return;

            // create particle struct 
            var v = new VertexParticle(position, velocity, color.ToVector4(), new Vector2(0, lifetime), 0, new Vector2(sizeStart, sizeEnd));

            // set the particle's flags 
            if (constrained) 
                v.Flags |= Flag_Constrained;
            if (fastFade) 
                v.Flags |= Flag_Fast_Fade;

            // append to buffer 
            m_NewParticles[m_NumNew++] = v;
        }


        public void AddToRenderQneue(RenderQueue renderQneue)
        {
            renderQneue.AddRenderableObj(this);
        }

        private Vector3 RandomDirection(Vector3 direction, float max)
        {
            float r1 = ((float)m_Random.NextDouble() * 2 - 1) * max;
            float r2 = ((float)m_Random.NextDouble() * 2 - 1) * max;
            float r3 = ((float)m_Random.NextDouble() * 2 - 1) * max;

            Quaternion q = Quaternion.RotationYawPitchRoll(r1, r2, r3);
            return Vector3.Transform(direction, q);
        }

        public void Draw(RenderTimer renderTimer)
        {
            if (m_BasicScene.SceneManager.RenderType == RenderType.Normal)
            {
                for (int i = 0; i < 128; i++)
                {
                    Vector3 position = Vector3.Zero;
                    Vector3 velocity = RandomDirection(Vector3.UnitY, MathUtil.TwoPi) * (float)m_Random.NextDouble(1.0, 4.0);
                    Color color = new Color((float)m_Random.NextDouble(), (float)m_Random.NextDouble(), (float)m_Random.NextDouble());
                    float startSize = 0.02f;
                    float endSize = 0.2f;
                    float lifetime = 2f;

                    Spawn(Vector3.Zero, velocity, color, startSize, endSize, lifetime, false, false);
                }
                m_Elapsed += ((float)renderTimer.IntervalMillseconds) / 1000;

                Advance();
                Render();
            }
        }
        void Advance()
        {
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.OutputMerger.SetDepthStencilState(m_BasicScene.WPFRenderHost.DeviceStates.NoneDepthStencilState);
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.InputAssembler.InputLayout = m_InputLayout;
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.PointList;
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(m_DrawFromBuffer, VertexParticle.SizeInBytes, 0));
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.StreamOutput.SetTarget(M_StreamToBuffer, 0);

            m_UpdatePass.Apply(m_BasicScene.WPFRenderHost.Device.ImmediateContext);

            // Update particles on the gpu 
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.DrawAuto();

            // See if we have any newly-spawned particles waiting 
            if (m_NumNew > 0)
            {
                // Copy new particles to vertex buffer and draw them to append them to stream output target 
                DataStream stream;
                m_BasicScene.WPFRenderHost.Device.ImmediateContext.MapSubresource(m_SpawnBuffer, MapMode.WriteDiscard, MapFlags.None, out stream);
                stream.WriteRange(m_NewParticles);
                m_BasicScene.WPFRenderHost.Device.ImmediateContext.UnmapSubresource(m_SpawnBuffer, 0);
                m_BasicScene.WPFRenderHost.Device.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.PointList;
                m_BasicScene.WPFRenderHost.Device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(m_SpawnBuffer, VertexParticle.SizeInBytes, 0));
                m_BasicScene.WPFRenderHost.Device.ImmediateContext.Draw(m_NumNew, 0);
                m_NumNew = 0;
            }

            m_BasicScene.WPFRenderHost.Device.ImmediateContext.StreamOutput.SetTargets(null);

            // Swap vertex buffers 
            Utilities.Swap(ref m_DrawFromBuffer, ref M_StreamToBuffer);
        }

        void Render()
        {
            // Since we just swapped the vertex buffers, particleDrawFrom contains the current state 
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.OutputMerger.SetBlendState(m_BasicScene.WPFRenderHost.DeviceStates.AdditiveState);
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.OutputMerger.SetDepthStencilState(m_BasicScene.WPFRenderHost.DeviceStates.NoneDepthState);
            Vector3 cameraForward = m_BasicScene.SceneManager.Camera.Direction;
            Matrix lookAtMatrix = Matrix.Billboard(Vector3.Zero, m_BasicScene.SceneManager.Camera.Position, Vector3.UnitY, cameraForward);
            m_Effect.GetVariableByName("_view").AsMatrix().SetMatrix(m_BasicScene.SceneManager.Camera.View);
            m_Effect.GetVariableByName("_proj").AsMatrix().SetMatrix(m_BasicScene.SceneManager.Camera.Projection);
            m_Effect.GetVariableByName("_lookAtMatrix").AsMatrix().SetMatrix(lookAtMatrix);
            m_Effect.GetVariableByName("_elapsedSeconds").AsScalar().Set(m_Elapsed);
            m_Effect.GetVariableByName("_camDir").AsVector().Set(cameraForward);
            m_Effect.GetVariableByName("_gravity").AsVector().Set(9.81f);
            m_Effect.GetVariableByName("_texture").AsShaderResource().SetResource(m_ParticleTextureView);
            this.m_Elapsed = 0;


            m_BasicScene.WPFRenderHost.Device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(m_DrawFromBuffer, VertexParticle.SizeInBytes, 0));
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.InputAssembler.InputLayout = m_InputLayout;
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.PointList;
            m_RenderPass.Apply(m_BasicScene.WPFRenderHost.Device.ImmediateContext);
            m_BasicScene.WPFRenderHost.Device.ImmediateContext.DrawAuto();

            m_BasicScene.WPFRenderHost.Device.ImmediateContext.GeometryShader.Set(null);
        }

        public void Dispose()
        {
            Disposer.RemoveAndDispose(ref m_SpawnBuffer);
            Disposer.RemoveAndDispose(ref m_DrawFromBuffer);
            Disposer.RemoveAndDispose(ref M_StreamToBuffer);
            Disposer.RemoveAndDispose(ref m_ParticleTextureView);
            Disposer.RemoveAndDispose(ref m_InputLayout);
        }
    }
}
0

Share this post


Link to post
Share on other sites

I have search disable rasterization you said that is SetPixelShader(NULL) in shader.Second make both the depthState and StencilState disable! I want konw is the right way to realize you said like this?
Now I have success with your help.. I am very thanks to you! you are great...But I doubt is the right way to do like this

You're welcome. Looks like the sample, so yeah, I think it's fine. Not sure if I understand your question (you might try google translate - no offense intended). Disabling depth write is ok. To correctly occlude particles you need to draw your other stuff first and the draw the particles with depth test only.

@Telanor:
I just have a gut feeling here. I suspect sort of a race condition or something with the static initialization. Does the sample work at all ? Could you try a non-static version ? I'm shooting in the dark: Do you have more - useful - information about that crash ? Call stack ? D3D debug log ?
0

Share this post


Link to post
Share on other sites
Yea the sample works perfectly fine, even in the VS graphics debugger. I tried switching to a non-static version and it still has the same problem. I'd love to provide you with any information I can but I'm not sure there's much to be had. Let me explain in more detail what's going on:

When I run the game normally, after the world loads up, I press a key to spawn 50k particles around me, the code runs, but I see absolutely nothing. Maybe their position is wrong, maybe they're too small, I don't know. So I try to run the VS graphics debugger, start up the game again, spawn the particles, press print screen and then it halts. If I leave the directx debug layer off, it just gives me a generic "External component threw an error" message.

Next I go turn on the debug layer and start it up again (without the graphics debugger). It runs without errors again. Starting it up with the graphics debugger, it now halts before I even have a chance to spawn any particles. It stops on the StreamOutput.SetTarget line in the `Advance` method, giving that warning about the query thing. I've tried making it so draw calls called before any particles have spawned don't run any code, but that still causes the same error once I do spawn the particles.

This is the CPU callstack, I can't imagine it'll be of much help:

[attachment=16994:callstack.png]

I can't get the GPU callstack that the graphics debugger lists since it crashes before I can take a snapshot. I'm not sure where I'd get a D3D debug log from. If you can tell me how to I'll post that up as well.
0

Share this post


Link to post
Share on other sites

Yeah call stack is useless indeed. But the explanations might help. So the thing runs you just can't debug it with the graphics debugger. (Lapse on my part, you did mention it already, I just didn't understand it fails with the debugger only). Welcome to the club: If memory serves, I could never debug  StreamOut  with PIX either.

 

That leaves only one thing: Debug yourself. Setup a staging buffer, use context.CopyResource to copy the stream out buffer to the stage after the update and context.Map the stage to read it back. Then inspect it or log it. To make it easier modify the system to use only one particle (one that never dies e.g.). Or draw a small mesh you know that draws at said position. That should cover the update part. It's a bit involved, but that's about what I can come up with (other than using a different tool that hopefully works).

 

You said you use CPU-particles now, so I assume you can draw them. Do you use the drawing technique from the sample (meaning: a quad expansion geometry shader) or something else ?

0

Share this post


Link to post
Share on other sites

 

I have search disable rasterization you said that is SetPixelShader(NULL) in shader.Second make both the depthState and StencilState disable! I want konw is the right way to realize you said like this?
Now I have success with your help.. I am very thanks to you! you are great...But I doubt is the right way to do like this

You're welcome. Looks like the sample, so yeah, I think it's fine. Not sure if I understand your question (you might try google translate - no offense intended). Disabling depth write is ok. To correctly occlude particles you need to draw your other stuff first and the draw the particles with depth test only.

@Telanor:
I just have a gut feeling here. I suspect sort of a race condition or something with the static initialization. Does the sample work at all ? Could you try a non-static version ? I'm shooting in the dark: Do you have more - useful - information about that crash ? Call stack ? D3D debug log ?

 

Oh!  you understand me!biggrin.png  ....you are friendly!!..Is  that  you say  draw  other stuff first  and   draw the particles  depth Test with  only  read and  not  write ?   I have been doing this for a long time?  Is that right? 

1

Share this post


Link to post
Share on other sites

Yeah call stack is useless indeed. But the explanations might help. So the thing runs you just can't debug it with the graphics debugger. (Lapse on my part, you did mention it already, I just didn't understand it fails with the debugger only). Welcome to the club: If memory serves, I could never debug  StreamOut  with PIX either.
 
That leaves only one thing: Debug yourself. Setup a staging buffer, use context.CopyResource to copy the stream out buffer to the stage after the update and context.Map the stage to read it back. Then inspect it or log it. To make it easier modify the system to use only one particle (one that never dies e.g.). Or draw a small mesh you know that draws at said position. That should cover the update part. It's a bit involved, but that's about what I can come up with (other than using a different tool that hopefully works).
 
You said you use CPU-particles now, so I assume you can draw them. Do you use the drawing technique from the sample (meaning: a quad expansion geometry shader) or something else ?


Well its not that I can't debug the streamout, I can't debug anything in my entire project because the particle system just kills the debugger. Of course I can disable it for debugging other systems, but I just wanted to point out that its not specifically when inspecting the particle system, the entire snapshot fails. More importantly, the debugger actually works just fine when run on the sample. I will give the manual debugging idea a try, but there's a lot of things that could be wrong that will be hard to spot without a proper debugger.

And yes, my CPU particles draw just fine. I'm not using any of the code/shaders from them for this though, I'm using the same drawing code/shader from the sample.

I've compared my code with what GuoLei posted and its pretty much identical, especially the part that's crashing for me, so I'm really not sure what's wrong with it. As a random though, I wonder if this has anything to do with the fact that my project is using DX11.1? Also here is my shader code, though I doubt the issue is coming from there:

//
// Particle effect using geometry shader and stream out
// 2013 Christoph Romstoeck (lwm)
//

Texture2D<float4> Texture;

SamplerState linearSampler
{
	AddressU = CLAMP;
	AddressV = CLAMP;
	Filter = MIN_MAG_MIP_LINEAR;
};

#define FLAG_CONSTRAINED 1
#define FLAG_FAST_FADE 2

cbuffer EveryFrame : register(b0)
{
	float4x4	View;
	float4x4	Projection;
	float4x4	LookAt;
	float3	CamDir;
	float	Time;
	float3	Gravity;
};

struct ParticleVertex
{
	float3 Position : POSITION;
	float3 Velocity : NORMAL;
	float4 Color : COLOR;
	float2 TimerLifetime : TEXCOORD0;
	uint Flags : TEXCOORD1;
	float2 SizeStartEnd : TEXCOORD2;
};

struct ParticleVertexGsUpdateOut
{
	float4 Position : SV_POSITION;
	float3 Velocity : NORMAL;
	float4 Color : COLOR;
	float2 TimerLifetime : TEXCOORD0;
	uint Flags : TEXCOORD1;
	float2 SizeStartEnd : TEXCOORD2;
};

struct ParticleVertexGsOut
{
	float4 Position : SV_POSITION;
	float4 Color : COLOR;
	float2 TexCoord : TEXCOORD0;
	float4 PositionVS : TEXCOORD1;
};

// ===

// Vertex shader has no work to do.
// Simply pass vertex on to the next stage.
ParticleVertex VS_Passthrough(ParticleVertex v)
{
	return v;
}

// Geometry shader to update one particle.
[maxvertexcount(1)]
void GS_Update(point ParticleVertex vertex[1], inout PointStream<ParticleVertexGsUpdateOut> stream) {

	ParticleVertex input = vertex[0];	

	// Calculate new age of the particle.
	float newTimer = input.TimerLifetime.x + Time;

	// If the particle is older than its lifetime, don't do anything.
	if(newTimer > input.TimerLifetime.y)
		return;

	// Calculate new position by adding the particle's velocity.
	float3 newPosition = input.Position + input.Velocity * Time;

	// Calculate new velocity by adding the world's gravity.
	float3 newVelocity = input.Velocity + Gravity * Time;

	ParticleVertexGsUpdateOut output;
	output.Position = float4(newPosition, 1);
	output.Velocity = newVelocity;
	output.Color = input.Color;
	output.TimerLifetime.x = newTimer;
	output.TimerLifetime.y = input.TimerLifetime.y;
	output.Flags = input.Flags;
	output.SizeStartEnd = input.SizeStartEnd;

	// Append updated particle to output stream.
	stream.Append(output);
}

GeometryShader pGSComp = CompileShader(gs_4_0, GS_Update());
GeometryShader pGSwSO = ConstructGSWithSO(pGSComp, "SV_POSITION.xyz; NORMAL.xyz; COLOR.xyzw; TEXCOORD0.xy; TEXCOORD1.x; TEXCOORD2.xy");

technique11 UpdateTeq
{
	pass Pass1
	{
		SetVertexShader(CompileShader(vs_4_0, VS_Passthrough()));
		SetGeometryShader(pGSwSO);
		SetPixelShader(NULL);
	}
}

// ===============================================

// Geometry shader to expand the vertex into a quad.
[maxvertexcount(4)]
void GS_Render(point ParticleVertex inputArray[1], inout TriangleStream<ParticleVertexGsOut> stream)
{

	ParticleVertex input = inputArray[0];	

	// Calculate the particles age in [0..1]
	float age = input.TimerLifetime.x / input.TimerLifetime.y;

	ParticleVertexGsOut v;

	// Determine the particle's color based on its age.
	v.Color = input.Color;
	bool fastFade = (input.Flags & FLAG_FAST_FADE) > 0;
	if (fastFade)
		v.Color.a *= (-(256 * 256) * pow(age - 0.5f, 16) + 1);
	else
		v.Color.a *= (-4 * (age - 0.5f) * (age - 0.5f) + 1);

	// Calculate the particle's current size
	float2 size = lerp(input.SizeStartEnd.x, input.SizeStartEnd.y, age);	

	// Check if one of the quad's axes should be constrained to the particle's velocity.
	bool constrained = (input.Flags & FLAG_CONSTRAINED) > 0;
	float3 right, up;

	if(constrained)
	{
		right = normalize(input.Velocity);
		up = cross(CamDir, right) * size.y;
		right *= size.x;
	}
	else
	{
		float2 xr = float4(size.x, 0, 0, 1);
		float2 yr = float4(0, size.y, 0, 1);

		right = mul(xr, LookAt).xyz;
		up = mul(yr, LookAt).xyz;
	}

	// Create and append four vertices to form a quad.
	float4 positionWS = float4(input.Position + right + up, 1.f);
	v.PositionVS = mul(positionWS, View);
	v.Position = mul(v.PositionVS, Projection);
	v.TexCoord = float2(1, 1);
	stream.Append(v);

	positionWS = float4(input.Position - right + up, 1.f);
	v.PositionVS = mul(positionWS, View);
	v.Position = mul(v.PositionVS, Projection);
	v.TexCoord = float2(0, 1);
	stream.Append(v);

	positionWS = float4(input.Position + right - up, 1.f);
	v.PositionVS = mul(positionWS, View);
	v.Position = mul(v.PositionVS, Projection);
	v.TexCoord = float2(1, 0);
	stream.Append(v);

	positionWS = float4(input.Position - right - up, 1.f);
	v.PositionVS = mul(positionWS, View);
	v.Position = mul(v.PositionVS, Projection);
	v.TexCoord = float2(0, 0);
	stream.Append(v);

	stream.RestartStrip();
}

// Simple pixel shader to render the particles.
float4 PS_Render(ParticleVertexGsOut input) : SV_Target
{
	float4 tex = Texture.Sample(linearSampler, input.TexCoord);

	return tex * input.Color;
}

technique11 RenderTeq
{
	pass Pass1
	{
		SetVertexShader(CompileShader(vs_4_0, VS_Passthrough()));
		SetGeometryShader(CompileShader(gs_4_0, GS_Render()));
		SetPixelShader(CompileShader(ps_4_0, PS_Render()));
	}
}

0

Share this post


Link to post
Share on other sites

@Guo-Leo: Well, yes, more or less. The sample uses additive blending, that's about the simplest one with respect to depth. E.g. for alpha-blended partcicles one needs them to draw them back to front (farthest first), so you have to sort them according to distance. There's also so-called soft particles (google it). I recently stumbled upon this blog post which is a quite interesting read.

 

@Telanor: I'm really sorry to tell you I'm out of clues or helpful suggestions. I'm still using VS 2010, vanilla D3D11 and PIX. Yesterday I heard from NightCreature about the inconveniences of the graphics debugger. Your suspicion about D3D11.1 might as well be true.

 

Looking at your shader I have one final thought though: This looks like you're using the D3DX effect system (technique11, not the SharpDX effect system). Is it ?. When I played with alternative tools, or sometimes even with PIX, I had troubles. I also wonder how well it behaves with the newer runtimes. Try using bare shaders for a change. Good luck.

0

Share this post


Link to post
Share on other sites
I may give that a try but I'm not so sure it'll help. I've been using the effects system for all my shaders so far with no problem. When I get a chance I'll set up the particle system in a separate project and switch between DX11 and 11.1 and see if that makes any difference. Thanks for trying though unbird, I appreciate it.
1

Share this post


Link to post
Share on other sites

@Guo-Leo: Well, yes, more or less. The sample uses additive blending, that's about the simplest one with respect to depth. E.g. for alpha-blended partcicles one needs them to draw them back to front (farthest first), so you have to sort them according to distance. There's also so-called soft particles (google it). I recently stumbled upon this blog post which is a quite interesting read.

 

@Telanor: I'm really sorry to tell you I'm out of clues or helpful suggestions. I'm still using VS 2010, vanilla D3D11 and PIX. Yesterday I heard from NightCreature about the inconveniences of the graphics debugger. Your suspicion about D3D11.1 might as well be true.

 

Looking at your shader I have one final thought though: This looks like you're using the D3DX effect system (technique11, not the SharpDX effect system). Is it ?. When I played with alternative tools, or sometimes even with PIX, I had troubles. I also wonder how well it behaves with the newer runtimes. Try using bare shaders for a change. Good luck.

Thank you for your guidance?  you  are  great!  Thank you Very  much!   I  will  go  on study with  your  guidance.

1

Share this post


Link to post
Share on other sites

I just want to make a clarification:


Also, on the topic of gpu particles, I've seen some systems that use directcompute instead. Am I correct in assuming that only works on feature level 11 and up?
No. GPU particles have been around for a while, they are viable on anything that is Shader Model 3.0 and later - google "Lutz Latta" and "Building a million particle system". More advanced hardware makes everything much more streamlined and eventually takes it to be viable on a meaningful installed base.
1

Share this post


Link to post
Share on other sites

Also, on the topic of gpu particles, I've seen some systems that use directcompute instead. Am I correct in assuming that only works on feature level 11 and up?


No, you can use compute shaders with feature level 10.x (cs_4_0) with a couple of restrictions. Also, so called Append/Consume buffers are restricted to shader model 5 which would be nice for particles (see the Hieroglyph engine particle sample).

Edit: Oh, well, that was actually an old question and has sort of been answered already. I really should stop doing this echoing thing wink.png Edited by unbird
0

Share this post


Link to post
Share on other sites
So I went and rebuilt the sample in a stand-alone project using plain sharpdx without the toolkit. It runs fine and the graphics debugger works. I tested with both DX11 and DX11.1, no problems. So I guess there's some kind of strange issue occurring elsewhere in my project which is somehow breaking the particle code. I guess the only thing I can do is turn off systems and see if it starts working.
0

Share this post


Link to post
Share on other sites
More updates:

While setting up the stand-alone project, I had to set the gravity/deltaTime to 0 because otherwise the particles randomly flew off the screen at insane speeds. Turns out I forgot the gravity parameter was a Vector3 and was passing just a float. For some reason, SharpDX has a Set(float dataRef) overload which was being called. So the particles now render correctly in my main project (yay!).

I also went through and commented out all the other draw calls but the VS debugger *still* crashes instantly on start up, so I really have no idea what its problem is. Nvida Nsight now supports DX11.1 and runs but says it can't find debug info for the shaders (it is there) so I can't debug with that either. I guess I'll just have to use the separate project if I ever need to debug the particles.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0