Quantcast
Channel: Community | MonoGame - Latest topics
Viewing all articles
Browse latest Browse all 6821

GL instanced shader problem.

$
0
0

@willmotil wrote:

Im using vs2017 on win7 i have created the same project for the crossplatform template gl and windows dx

So i have a example Instanced DX shader that i have trimmed down to simplify it so i can understand it better. this works under the Dx 4_0 profile with hi def set under the windows template.

However

The same shader under GL 3_0 on hi-def, while it does show a window and it doesn't error or crash ect... Nothing is drawn all i get is a black screen.

Im at a loss as to why ?...

Here is the shader followed by the full code you need a texture to run the example.

,,, the shader ,,

#if OPENGL
//#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0
#define PS_SHADERMODEL ps_4_0
#endif

static const float PI = 3.14159265359;
static const float EIGHT_PI = 25.1327412287;


float Life;
float TotalTime;
//int MaxNumOfParticles;
//float2 RadiusRange;

matrix WorldViewProjection;

Texture2D ParticleTexture : register(t0);
sampler TexSampler : register(s0);

//__________________________________________________________
//__________________________________________________________

struct VSVertexInputSimple
{
    float4 Position : SV_POSITION;
    float2 TexCoord : TEXCOORD0;
    //uint InstanceId : SV_InstanceId;
};

struct VSInstanceInputSimple
{
    float3 RandomIntervals : POSITION1;
    float ParticleTime : BLENDWEIGHT0;
};

struct VSOutputSimple
{
    float4 Position : SV_POSITION;
    float2 TexCoord : TEXCOORD0;
    float4 Color : COLOR0;
};

VSOutputSimple MainVSSimple(in VSVertexInputSimple vertexInput, VSInstanceInputSimple instanceInput)
{
    //VSOutput output = (VSOutput)0;
    VSOutputSimple output; //= (VSOutput)0;

    float3 randomIntervals = instanceInput.RandomIntervals;
    float particleTime = instanceInput.ParticleTime;

    float timeFraction = fmod((particleTime + TotalTime) / (float)Life, 1.0f);

    output.Position = vertexInput.Position;
    output.Position.xy += randomIntervals;
    output.Position.y += timeFraction * 100;
    output.Position.z = 0;//vertexInput.InstanceId * 10 / (float)MaxNumOfParticles;
    output.Position = mul(output.Position, WorldViewProjection);

    // Set colour of particle using the other two passed-in random intervals 
    float4 endColor = lerp(float4(0.0, 0.5, 1.0, 0.8), float4(1.0, 1.0, 1.0, 0.8), randomIntervals.y);
    float4 startColor = lerp(float4(1.0, 0.0, 0.0, 0.8), float4(0.3, 0.0, 1.0, 1.0), randomIntervals.z);

    output.Color = lerp(startColor, endColor, timeFraction);
    output.Color *= (-4 * pow(timeFraction - 0.5, 2) + 1);

    output.TexCoord = vertexInput.TexCoord;

    return output;
}

float4 MainPSSimple(VSOutputSimple input) : COLOR0
{
    return input.Color * ParticleTexture.Sample(TexSampler, input.TexCoord);
}

technique ParticleDrawingSimple
{
    pass P0
    {
        VertexShader = compile VS_SHADERMODEL MainVSSimple();
        PixelShader = compile PS_SHADERMODEL MainPSSimple();
    }
};

,,, the code ,, All the classes and structs have been placed in one cs file for simplicity...

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Runtime.InteropServices;

namespace Game1
{
    [StructLayout(LayoutKind.Sequential)]
    public struct InstanceData : IVertexType
    {
        public static readonly VertexDeclaration VertexDeclaration;

        public Vector3 RandomIntervals;
        public float Time;

        VertexDeclaration IVertexType.VertexDeclaration
        {
            get { return VertexDeclaration; }
        }

        static InstanceData()
        {
            var elements = new VertexElement[]
                {
                    new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
                    new VertexElement(12, VertexElementFormat.Single, VertexElementUsage.BlendWeight, 0)
                };
            VertexDeclaration = new VertexDeclaration(elements);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct VertexData : IVertexType
    {
        public static readonly VertexDeclaration VertexDeclaration;

        public Vector3 Position;
        public Vector2 TexCoords;

        VertexDeclaration IVertexType.VertexDeclaration
        {
            get { return VertexDeclaration; }
        }

        static VertexData()
        {
            var elements = new VertexElement[]
                {
                    new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
                    new VertexElement(12, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
                };
            VertexDeclaration = new VertexDeclaration(elements);
        }
    }

    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        ParticleSystem02 particleSystem;
        Matrix worldViewProj;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.GraphicsProfile = GraphicsProfile.HiDef;
            graphics.PreferMultiSampling = false;
            Window.AllowUserResizing = true;
            // Set the default resolution to be 1024x768
            graphics.PreferredBackBufferWidth = 1024;
            graphics.PreferredBackBufferHeight = 768;
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();

            // Setup the worldViewProj matrix
            float width = GraphicsDevice.PresentationParameters.BackBufferWidth;
            float height = GraphicsDevice.PresentationParameters.BackBufferHeight;
            float aspect = width / height;

            // Create our camera that's looking straight at the center
            Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 5.0f), Vector3.Zero, Vector3.Up);

            // Create a projection matrix so that the world dimensions have the same aspect ratio as our window size
            Matrix projMatrix = Matrix.CreateOrthographic(aspect * 300, 300, 0.1f, 10000);

            worldViewProj = viewMatrix * projMatrix;
        }

        protected override void LoadContent()
        {
            Effect particlesEffect = Content.Load<Effect>("ParticleFx02");
            Texture2D particleTexture = Content.Load<Texture2D>("particle");

            particleSystem = new ParticleSystem02(particlesEffect)
            {
                ParticleSize = new Vector2(3.0f, 3.0f),
                ParticleTexture = particleTexture,
                Life = 20.0f,
                EmitRate = 12500,
                Radius = 180.0f,
                RadiusDeviation = new Vector2(40.0f, 100.0f),
            };

            particleSystem.RefreshParticleSystemBuffers(GraphicsDevice);

        }

        protected override void UnloadContent()
        {
            Content.Unload();
        }

        protected override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            particleSystem.UpdateParticleTime((float)gameTime.ElapsedGameTime.TotalSeconds);

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
        }

        protected override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.Black, 1.0f, 0);
            GraphicsDevice.BlendState = BlendState.Additive;
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            particleSystem.DrawParticles(ref worldViewProj, GraphicsDevice);
        }
    }
    class ParticleSystem02
    {
        // Vertex data
        VertexBuffer vertexBuffer;
        IndexBuffer indexBuffer;
        VertexBufferBinding vertexBufferBinding;

        // Instance data
        int numInstancesToDraw;
        InstanceData[] instanceData;
        VertexBuffer instanceBuffer;
        VertexBufferBinding instanceBufferBinding;

        Effect particlesEffect;

        Vector2 radiusRange;

        float totalTime = 0;

        #region Properties
        public Vector2 ParticleSize { get; set; }
        public Texture2D ParticleTexture { get; set; }
        public float Life { get; set; }
        public uint EmitRate { get; set; }
        public float Radius { get; set; }
        public Vector2 RadiusDeviation { get; set; }

        public int MaxVisibleParticles
        {
            get; private set;
        }

        #endregion Properties

        #region Initilisation
        public ParticleSystem02(Effect effect)
        {
            particlesEffect = effect;
        }

        public void RefreshParticleSystemBuffers(GraphicsDevice graphicsDevice)
        {
            // Create a single quad centered at the origin
            float halfWidth = ParticleSize.X / 2;
            float halfHeight = ParticleSize.Y / 2;

            VertexData[] vertices = new VertexData[4];
            vertices[0].Position = new Vector3(-halfWidth, -halfHeight, 0);
            vertices[1].Position = new Vector3(halfWidth, -halfHeight, 0);
            vertices[2].Position = new Vector3(-halfWidth, halfHeight, 0);
            vertices[3].Position = new Vector3(halfWidth, halfHeight, 0);

            vertices[0].TexCoords = new Vector2(0.0f, 0.0f);
            vertices[1].TexCoords = new Vector2(1.0f, 0.0f);
            vertices[2].TexCoords = new Vector2(0.0f, 1.0f);
            vertices[3].TexCoords = new Vector2(1.0f, 1.0f);

            vertexBuffer = new VertexBuffer(graphicsDevice, VertexData.VertexDeclaration, 4, BufferUsage.WriteOnly);
            vertexBuffer.SetData(vertices);

            vertexBufferBinding = new VertexBufferBinding(vertexBuffer);

            int[] indices = new int[6];
            indices[0] = 1;
            indices[1] = 0;
            indices[2] = 2;
            indices[3] = 3;
            indices[4] = 1;
            indices[5] = 2;

            indexBuffer = new IndexBuffer(graphicsDevice, typeof(int), 6, BufferUsage.WriteOnly);
            indexBuffer.SetData(indices);

            MaxVisibleParticles = (int)Math.Max(Math.Ceiling(Life * EmitRate), 1);

            instanceData = new InstanceData[MaxVisibleParticles];
            instanceBuffer = new VertexBuffer(graphicsDevice, InstanceData.VertexDeclaration, MaxVisibleParticles, BufferUsage.WriteOnly);
            instanceBufferBinding = new VertexBufferBinding(instanceBuffer, 0, 1);

            Random rnd = new Random();

            // Initialise our instance buffer
            for (int i = 0; i < MaxVisibleParticles; ++i)
            {
                // instance data float time
                instanceData[i].Time = -(i + 1) / (float)EmitRate;
                // instance data float position
                instanceData[i].RandomIntervals = new Vector3
                    (
                    (rnd.Next(0, 300) - 150),
                    -.001f,
                    rnd.Next(0, MaxVisibleParticles + 1) / (float)MaxVisibleParticles
                    );
            }

            instanceBuffer.SetData(instanceData);

            radiusRange = new Vector2(Radius + RadiusDeviation.X, Radius + RadiusDeviation.Y);
        }

        #endregion Initilisation

        public void UpdateParticleTime(float seconds)
        {
            // Potentially, you could adjust the number of 
            // particles rendered based on the time
            // However, here we're simply using the maximal number
            numInstancesToDraw = MaxVisibleParticles;

            // Update the total running time
            totalTime += seconds;
        }

        public void DrawParticles(ref Matrix worldViewProj, GraphicsDevice graphicsDevice)
        {
            particlesEffect.CurrentTechnique = particlesEffect.Techniques["ParticleDrawingSimple"];
            // Initialise our shader constants
            particlesEffect.Parameters["WorldViewProjection"].SetValue(worldViewProj);
            particlesEffect.Parameters["Life"].SetValue(Life);
            //particlesEffect.Parameters["RadiusRange"].SetValue(radiusRange);
            //particlesEffect.Parameters["MaxNumOfParticles"].SetValue(MaxVisibleParticles);
            particlesEffect.Parameters["TotalTime"].SetValue((float)totalTime);
            particlesEffect.CurrentTechnique.Passes[0].Apply();

            // Set textures and buffers
            graphicsDevice.Textures[0] = ParticleTexture;
            graphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;
            graphicsDevice.SetVertexBuffers(vertexBufferBinding, instanceBufferBinding);
            graphicsDevice.Indices = indexBuffer;

            graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 6, 0, 2, numInstancesToDraw);
        }
    }
}

Posts: 4

Participants: 2

Read full topic


Viewing all articles
Browse latest Browse all 6821

Trending Articles