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);
}
}
}