✔ ☕ General Conversation Thread

Where does it state this?

Interesting however for UWP it is useless… unless Microsoft allows OpenCL GPU access for graphics processing… funny enough while Microsoft has its reasons to keep OpenGL off the platform… they do not help their own API in the same way that OpenGL is now forced to and that is supporting multiple languages [Which mind you neither has OpenGL up until and yet now… still C++ based as far as I know…]

That’s not really the same, it’s languages specific to Visual computation, can rule C# out of the list… though again, highly unlikely that it would make any use on UWP until Microsoft opens up OpenGL/Vulkan onto it… then perhaps some sort of C# related thing would make sense… for people like me…

Here’s the official stream for that milestone for Human Kind

It’s public so you can just ignore the sign in request by clicking Not Now, if you don’t have an account…

just to chime in, Vulkan is similar to DX12.

I know more about Dx12, but the general consensus is that it takes a lot of time to make it run as fast as DirectX11 and it’s not beginner friendly. The Api exposes a lot less stuff, which can be good, but it also means that even stuff like Mipmapping has to be implemented by hand.

Great for experienced devs, but I’m not sure if Monogame is the right target group.

1 Like

SlimDX supports DX12, MonoGame is using DX11, the same was said of DX11 yet here we are :slight_smile:

But I know what you mean as DX12 gives more lower level access too which is probably why it is less dev friendly I guess… plus, DX11 is mature enough to be flexible for simple games I guess…

actually directx11 can realize all things that dx12 does, too. MS even updated dx11 to 11.3 after 12 came out.

Btw, here i am now

4 Likes

Yep, precisely, DX12 was just as they say a rebuild to allow more direct access to the hardware otherwise it basically maintains the same functionality albeit more powerfully…

Awesome! so wish I could do that stuff… can you get it into a sphere? you could go into commercial advertising with that :wink:

sphere is a bit more simple, I basically solved that in my deferred engine for volumetric lights (unshadowed), which have spherical fog around

1 Like

About the SpriteBatch implementation, the transformations (except for the default SpriteBatch matrix and optionally a matrix you passed to SpriteBatch.Begin) happen on CPU. You can see that here: https://github.com/MonoGame/MonoGame/blob/develop/MonoGame.Framework/Graphics/SpriteBatchItem.cs#L26. All Draw calls internally use one of the Set methods in SpriteBatchItem.

There’s an interesting PR up that boosts performance by inlining some of the calls that are done internally in SpriteBatch. For example if you only pass a position for the sprite some redundant calculations would be made. Results are a lot better than you’d expect (or at least that was the case for me). Inline/Optimize SpriteBatch.DrawInternal() & SpriteFont.DrawInto() by nkast · Pull Request #5401 · MonoGame/MonoGame · GitHub

I meant the Vulkan tools are the best way forward to get cross-platform shader compilation. And once we have that set up we can look at implementing compute/geometry/other cool stuff.

I know, but would still need DirectX for Windows naturally :slight_smile: Keep in mind, OpenGL and Vulkan do not include drivers for input etc., that is separate, OpenGL … Khronos’s projects are strictly graphical processing… whereas DX is a lot more…

Hey jjag how does spriteBatch actually batch up separate groups of different textures into calls, Im not getting how the batcher chunks up its draws. I see this but i don’t get how it works with compare to in order to actually break up drawIndexedPrimitives when items with different textures are to actually be rendered?

                var item = _batcher.CreateBatchItem();

                item.Texture = texture;

                // set SortKey based on SpriteSortMode.
                switch ( _sortMode )
                {
                    // Comparison of Texture objects. 
                    case SpriteSortMode.Texture:
                        item.SortKey = texture.SortingKey;
                        break;
                    // Comparison of Depth
                    case SpriteSortMode.FrontToBack:
                        item.SortKey = depth;
                        break;
                    // Comparison of Depth in reverse
                    case SpriteSortMode.BackToFront:
                        item.SortKey = -depth;
                        break;
                }

Or am i totally looking at the idea behind it wrong.

Check out the spritebatcher code: https://github.com/MonoGame/MonoGame/blob/develop/MonoGame.Framework/Graphics/SpriteBatcher.cs#L199

Ah i kinda see ill have to check it out later on.

I was playing around with my little spritebuffer thingy and ran a bit more of a practical test it seems to hold up fairly well even when a bunch of other stuff is going on though there is a lot of garbage and im pretty sure cpu is the only thing slowing it down,

still pushing 12k sprites though the random doesn’t update fast enough made a cool picture though and its in motion falling,

1 Like

@willmotil that looks good, are you using an effect for the colour fading? random colours too?

On another note I have started to notice a problem developing for me…

I have spent the past 6 years, 2 months, 1 week, 5 days or 2265 days reading poorly used English on the web on dev forums and social media… [Mainly focussing on the forums side of things as this is where most of the misuse was occurring… and most of my reading]

It has begun to affect my own English lol, only slightly but it is getting to the point where I have to re-read a sentence again to make sure I:

A- Read it correctly
B- Worked out if they used the correct grammar
C- Worked out if the correct version of a term was used
D- Know which is the correct term to be used
E- Just wasted a few seconds of my life figuring it out

So the main culprit here is You’re and Your, more You’re now as everybody just slaps Your everywhere and as such my brain is beginning to stupefy itself lol

Anyway just noticed it this one time tonight while reading some poorly written governmental material, but I think after venting this I will ignore it for another five years now…

Any new projects people? I am thinking to move along with my web dev soon, just packing to move in about a month or so however… and dealing with some other stuff which is now delaying me…

Hope all is well with you guys :slight_smile:

i honestly saw more of that in American High School than on the internet. On reddit etc. many people admit to doing it wrong even though it’s their mothertongue… this is especially infuriating

1 Like

that looks good, are you using an effect for the colour fading? random colours too?

Nop Just straight alpha blending scaling and rotating. The image itself has some transparency in it and the colors im passing sometimes have its alpha set lower.

This is a updated version of the earlier code. The shader is the same empty one used before to bypass spritebatch altogether.
The method AddSpriteToBatch(…) is basically a spriteBatch.Draw(…) call. It does it all without any matrices either. Just straight linear math, translations, rotations and projection. It bypasses everything and does it directly, but it only works on a single texture per buffer at least right now.

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace MyDirectSpriteBatcher
{
    public class LittleGpuSpriteBatcher
    {
        private Vector2 uvLT = new Vector2(0f, 0f);
        private Vector2 uvLB = new Vector2(0f, 1f);
        private Vector2 uvRT = new Vector2(1f, 0f);
        private Vector2 uvRB = new Vector2(1f, 1f);
        public Effect currentEffect;
        public Texture2D currentTexture;
        private static int windowWidth = 0;
        private static int windowHeight = 0;


        private int quadCapacity = 60;
        private int currentQuads = 0;
        private int ti_pointer = 0;
        private int vi_pointer = 0;
        private int[] triangleIndexList = new int[6];
        private VertexPositionColorTexture[] spriteVertices = new VertexPositionColorTexture[4];

        public int QuadCapacity
        {
            get { return quadCapacity; }
        }

        public LittleGpuSpriteBatcher(Rectangle windowClientBounds, int quadCapacity, Effect effectToUse)
        {
            windowWidth = windowClientBounds.Width;
            windowHeight = windowClientBounds.Height;
            this.quadCapacity = quadCapacity;
            triangleIndexList = new int[6 * quadCapacity];
            spriteVertices = new VertexPositionColorTexture[4 * quadCapacity];
            currentEffect = effectToUse;
        }

        public void ClearAll()
        {
            currentQuads = 0;
            vi_pointer = 0;
            ti_pointer = 0;
        }

        public void AddSpriteToBatch(Rectangle destinationRectangle)
        {
            AddSpriteToBatch(destinationRectangle, Color.White, 0f, Vector2.One, 0f);
        }


        public void AddSpriteToBatch(Rectangle destinationRectangle, Color color, float rotation, Vector2 scale, float depth)
        {
            // The 2x coefficent which is a mulitpiplier to put the rectangle in the 0 to 2 range.
            // With respect to the size of the window width and height.
            float cw = 2f / windowWidth;
            float ch = 2f / windowHeight;
            // Determine the vertice origin for rotation and scaling which i will do in place instead.
            Vector2 origin = new Vector2((destinationRectangle.Left + destinationRectangle.Right) * .5f, (destinationRectangle.Top + destinationRectangle.Bottom) * .5f);
            // Determines the vertice positions from the rectangle, translates and then scales
            // If we really want to just scale from top left to bottom right. 
            // Then below we may find RB = (...(...) - origin) * scale; then set RT.X = RB.X; and LB.Y = RB.Y;
            var LT = (new Vector2(destinationRectangle.Left, destinationRectangle.Top) - origin) * scale;
            var LB = (new Vector2(destinationRectangle.Left, destinationRectangle.Bottom) - origin) * scale;
            var RT = (new Vector2(destinationRectangle.Right, destinationRectangle.Top) - origin) * scale;
            var RB = (new Vector2(destinationRectangle.Right, destinationRectangle.Bottom) - origin) * scale;
            // If rotation is specified we will perform that now!
            if (rotation != 0)
            {
                // Sin Cos of rotation
                Vector2 q = new Vector2((float)Math.Sin(rotation), (float)Math.Cos(rotation));
                // Rotates the vertices from the origin here we make it the center as opposed to how spritebatch does it.
                // We could pass a offset here to further translate the origin like spritebatch.
                // However it is no longer necessary, this way we can pre transform the position of the rectangle itself.
                LT = GetRotatedVector(LT, q);
                LB = GetRotatedVector(LB, q);
                RT = GetRotatedVector(RT, q);
                RB = GetRotatedVector(RB, q);
            }
            // Translate the vertices from the origin local space back to world space 
            // Then transform the vertices by projecting them to screen space
            var _LT = Project(LT + origin, cw, ch, depth);
            var _LB = Project(LB + origin, cw, ch, depth);
            var _RT = Project(RT + origin, cw, ch, depth);
            var _RB = Project(RB + origin, cw, ch, depth);
            // create the vertice quad
            spriteVertices[vi_pointer + 0] = CreateVPCTstruct(_LT, color, uvLT);
            spriteVertices[vi_pointer + 1] = CreateVPCTstruct(_LB, color, uvLB);
            spriteVertices[vi_pointer + 2] = CreateVPCTstruct(_RT, color, uvRT);
            spriteVertices[vi_pointer + 3] = CreateVPCTstruct(_RB, color, uvRB);
            // create the indexs im not sure this parts not simply redundant.
            triangleIndexList[ti_pointer + 0] = 0 + vi_pointer;
            triangleIndexList[ti_pointer + 1] = 1 + vi_pointer;
            triangleIndexList[ti_pointer + 2] = 2 + vi_pointer;
            triangleIndexList[ti_pointer + 3] = 2 + vi_pointer;
            triangleIndexList[ti_pointer + 4] = 1 + vi_pointer;
            triangleIndexList[ti_pointer + 5] = 3 + vi_pointer;

            currentQuads += 1;
            vi_pointer += 4;
            ti_pointer += 6;
        }

        public Vector3 Project(Vector2 v, float cw, float ch, float depth)
        {
            // invert the Y positions upon the X axis
            return new Vector3(v.X * cw - 1f, v.Y * -ch + 1f, depth);
        }

        public Vector2 GetRotatedVector(Vector2 v, Vector2 q)
        {
            return new Vector2(v.X * q.Y - v.Y * q.X, v.X * q.X + v.Y * q.Y);
        }

        public Vector3 GetRotatedVector(Vector3 v, Vector2 q)
        {
            return new Vector3
                (
                v.X * q.Y - v.Y * q.X,
                v.X * q.X + v.Y * q.Y,
                v.Z
                );
        }

        /// <summary>
        /// simplest version
        /// </summary>
        public void DrawAll(GraphicsDevice gd)
        {
            if (TriangleDrawCount() > 0)
            {
                foreach (EffectPass pass in currentEffect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    gd.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, spriteVertices, 0, VerticesPerQuad(), triangleIndexList, 0, TriangleDrawCount());
                }
            }
        }

        public void SetCurrentEffect(Effect effectToUse)
        {
            currentEffect = effectToUse;
        }
        public void SetCurrentTexture(Texture2D t)
        {
            currentTexture = t;
            currentEffect.Parameters["Texture"].SetValue(currentTexture);
        }

        public int TotalQuads()
        {
            return currentQuads;
        }
        public int VerticesPerQuad()
        {
            return 4;
        }
        public int TriangleDrawCount()
        {
            return currentQuads * 2;
        }

        public static void OnResizeUpdateWindowWidthHeight(Rectangle windowClientBounds)
        {
            windowWidth = windowClientBounds.Width;
            windowHeight = windowClientBounds.Height;
        }

        private VertexPositionColorTexture CreateVPCTstruct(float vx, float vy, float vz, Color c, Vector2 uv)
        {
            return new VertexPositionColorTexture(new Vector3(vx, vy, vz), c, uv);
        }
        private VertexPositionColorTexture CreateVPCTstruct(Vector3 position, Color c, Vector2 uv)
        {
            return new VertexPositionColorTexture(position, c, uv);
        }
    }
}

The image itself is solid alpha at the center and fades as it goes outwards. Its in pure white, to work with any color i pass to the method as a parameter.

Check this out exact same lone image as before drawn a ton of times moving.

Same as above but with variably dependent decreasing alpha in the color. That is passed to the method.

It actually looks much cooler when you see it. Because all the soft colors are flashing like soft lightning in the background.

The class that moves the particles is just a footnote to the actual functional methods and classes.

For instance the particles are in a non sorted buffer that basically only moves things on death or creation of a particle. It only really moves the pointer most of the time so no huge re-sort ever occurs but that is more of my own pattern then a class. The class itself is full of junk to make the particles behave like in the picture but… the buffer pattern it uses is the cool part.

    public class DeadAliveBuffer
    {
        // This is my own little invention or pattern if you like quite proud of this one
        public static int width = 0;
        public static int height = 0;
        // technically this is pointless in most cases it can just grow forever. 
        // it still will function optimally, its always gonna sort O(n) or below.
        public int bufferLimit = 32; // default 

        // we could use a array here or a list if done properly i didnt create a proper swap

        /// <summary>
        /// Ideally a class that Implements either a base class with a isAlive bool or interface
        /// However we can just copy paste the entire class and just use a object of our own type
        /// </summary>
        public List<IsAliveOrDeadBaseObjectItem> itemList = new List<IsAliveOrDeadBaseObjectItem>();

        private int aliveMarker = 0;
        public int DeadMarker { get { return aliveMarker + 1; } }
        public int AliveMarker { get { return aliveMarker; } }


        public DeadAliveBuffer(int bufferlimit)
        {
            bufferLimit = bufferlimit;
            // initialize all the possible items in the buffer
            for (int i = 0; i < bufferlimit; i++)
            {
                itemList.Add(new IsAliveOrDeadBaseObjectItem());
            }
            aliveMarker = -1;
        }
        public void CreateDefaultItem(GameTime gameTime)
        {
            if (DeadMarker < bufferLimit)
            {
                int index = MakeAliveItemReturnIndex();
                // re use a dead item basically overwrite old data mark it alive
                itemList[index].ReUse(gameTime);
            }
        }
        public void MakeItemDead(int deadItemIndex)
        {
            // This is basically the entire sort it is simple.
            if (deadItemIndex == aliveMarker)
            {
                aliveMarker--;
                itemList[DeadMarker].isAlive = false;
            }
            else
            {
                // should redo this swap its not a very good way to swap it probably makes garbage
                IsAliveOrDeadBaseObjectItem A = itemList[aliveMarker];
                IsAliveOrDeadBaseObjectItem B = itemList[deadItemIndex];
                itemList[deadItemIndex] = A;
                itemList[aliveMarker] = B;
                aliveMarker--;
                itemList[DeadMarker].isAlive = false;
            }
        }
        public void MakeAliveItem()
        {
            if (DeadMarker < bufferLimit)
            {
                itemList[DeadMarker].isAlive = true;
                aliveMarker++;
            }
            else
            {
                // the buffer is completely filled with live objects
                // we have two choices expand the buffer or do nothing
            }
        }
        public int MakeAliveItemReturnIndex()
        {
            if (DeadMarker < bufferLimit)
            {
                itemList[DeadMarker].isAlive = true;
                aliveMarker++;
            }
            else
            {
                // the buffer is completely filled with live objects
                // we have two choices expand the buffer or do nothing
            }
            return aliveMarker;
        }
        public void Update()
        {
            for (int i = 0; i < DeadMarker; i++)
            {

                if (itemList[i].isAlive)
                {
                    if (itemList[i].duration < 1 || itemList[i].positionRect.Y > height)
                    {
                        MakeItemDead(i);
                    }
                }
                if (itemList[i].isAlive)
                {
                    //itemList[i].velocity.Y += .0010f; // gravitasity
                    //itemList[i].positionRect.X += itemList[i].velocity.X;
                    //itemList[i].positionRect.Y += itemList[i].velocity.Y;
                }
            }
        }
    }

That is especially infuriating… particularly when someone has a degree in English… [The times I have seen this…]

I thought so, was going to ask this :slight_smile:

Very slick, coding wise too…

Why is it blurry? because of movement or?

Hey, do any of you dabble in electronics?

No i have a bad habit of shocking myself.

Oh its blured due to stretching in one direction the width. As well as how many there are that have super low alpha nearly invisible, when they overlap it looks like blur. All the streaching and fading occurs at the top 10% and above offscreen. Particularly the slow moving particles get walloped as they stay in that part longer it makes them oblong and they get rotated too.

Also because unlike the solid ball looking image posted earlier. I turned off…
graphics.PreferMultiSampling = false;
and set
Blendstate = BlendState.NonPremultiplied;

So the edges aren’t black and they all blend with each other well. That previous solid ball look was a artificial effect of not turning stuff off…
The bottom most images are basically the fastest longest living so they they didn’t get butchered much till they die. They are all just a transparent white image colored like the bottom red image that’s blowing up.

here’s what it looks like with a square image.

1 Like

Nice! smart thinking! so it step changes rather than float change I mean it is more flickering than smooth motion right? reminds me of Chinese Lanterns in the night sky somewhat…

Are you not on Windows 10 or can you screen record somehow? [Windows 10 has built in recording DVR features!]

Just saw your updated picture, now if you added depth shadowing or FOG effect and played with size changes, larger being closer and smaller being further in the distance, it could look really cool… Something I aim to achieve soon…

Hows this for a bug in my secondary test method i messed up the math the rotational origin got screwed up and i got this bug with the same code lol.

Hence forth i will call this bug the wormhole effect bug.

1 Like