{"id":26556710,"url":"https://github.com/majormilk/processingsharp","last_synced_at":"2026-05-06T18:34:04.811Z","repository":{"id":283544798,"uuid":"951609435","full_name":"MajorMilk/ProcessingSharp","owner":"MajorMilk","description":"A work in progress Processing-esque creative coding library written in C# with OpenTK","archived":false,"fork":false,"pushed_at":"2025-03-22T22:57:53.000Z","size":29,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-01T06:37:24.606Z","etag":null,"topics":["creative-coding","csharp","graphics-library","opengl","opentk","p5cs","processing"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MajorMilk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-20T00:37:12.000Z","updated_at":"2025-04-09T02:12:31.000Z","dependencies_parsed_at":"2025-08-01T06:33:00.905Z","dependency_job_id":null,"html_url":"https://github.com/MajorMilk/ProcessingSharp","commit_stats":null,"previous_names":["majormilk/processingsharp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MajorMilk/ProcessingSharp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MajorMilk%2FProcessingSharp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MajorMilk%2FProcessingSharp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MajorMilk%2FProcessingSharp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MajorMilk%2FProcessingSharp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MajorMilk","download_url":"https://codeload.github.com/MajorMilk/ProcessingSharp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MajorMilk%2FProcessingSharp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271135021,"owners_count":24705101,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-19T02:00:09.176Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["creative-coding","csharp","graphics-library","opengl","opentk","p5cs","processing"],"created_at":"2025-03-22T11:25:10.999Z","updated_at":"2026-05-06T18:34:04.768Z","avatar_url":"https://github.com/MajorMilk.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ProcessingSharp\n\nA C# library that aims to bring similar functionality to the Java library 'Processing', to C# using OpenTK.\n\n## How to:\n\n- Clone the Repo\n- Type your code within Program.cs in the P5CS project\n- Global settings can be found in the Globals.cs in the ProcessingSharp project\n\nNot all features are yet to be added as this is a work in progress\n\n## Coming Soon™\n\n- Perlin noise\n- Lines and points\n- Better code lol\n- 3D? Maybe.\n\n## Already Added:\n\n- Circles, Ellipses, Rectangles, Squares\n- Shape specific fill color, stroke color, stroke weight\n- Transformations and rotations\n- Static functions from Processing such as map, dist, etc.\n\n# Why use this over Processing?\n\nDont... Well not yet anyway. That is unless you prefer C# over Java as I do. I'm developing this in the hope that this library becomes as functional as Processing.\n\nThis library is decently efficient so far, hopefully that will remain true in the future.\n\n# Docs\n\n## Hello Circle\n\nBegin by cloning this repository. Then navigate to the P5CS project. This is where you will type your code, similar to a P5JS project.\n\nYou'll find that an example is already provided. If you wish to start from fresh, simply remove all of the example code such that you're left with...\n\n```csharp\nusing OpenTK.Windowing.Desktop;\nusing OpenTK.Mathematics;\nusing OpenTK.Windowing.Common;\nusing P5CS;\nusing P5CSLIB;\nusing static P5CSLIB.PFuncs; // Optional global functions similar to processing\nclass Program\n{\n    static void Main()\n    {\n        var gameWindowSettings = new GameWindowSettings()\n        {\n            UpdateFrequency = Globals.FrameRate,\n        };\n        var nativeWindowSettings = new NativeWindowSettings() \n        { \n            ClientSize = Globals.CanvasSize, \n            Title = \"Name of your window\",\n            WindowBorder = WindowBorder.Fixed, // Resizeable? (very buggy if so)\n            WindowState = WindowState.Normal,\n        };\n        using var canvas = new Canvas(gameWindowSettings, nativeWindowSettings);\n        \n        \n        //Here is where you should place your code\n        \n        \n        canvas.Run();\n    }\n}\n```\n\nIn this state, nothing will be rendered. First, you'll need to create a shape object:\n```csharp\nCircle circle = new(Vector2 Position, float radius);\n```\nPlease note that all Vector2's used are from OpenTK.Mathematics, not System.Numerics.\n\nFrom here, you can alter the properties of your circle:\n```csharp\ncircle.FillColor = new Vector4i(R,G,B,A); //0-255 Colors are normalized automatically\ncircle.StrokeColor = new Vector4i(R,G,B,A);\ncircle.StrokeWeight = n; //Stroke weight in pixels\n```\n\nNow you can add your shape to the rendering pipeline:\n```csharp\ncanvas.AddShape(int ID, circle);\n```\nThe ID here is a key in a dictionary that links said ID to a shape on the canvas. This is so that you can maintain a reference to a specific shape.\n\nNow you should have a program like this:\n```csharp\nusing OpenTK.Windowing.Desktop;\nusing OpenTK.Mathematics;\nusing OpenTK.Windowing.Common;\nusing P5CS;\nusing P5CSLIB;\nusing static P5CSLIB.PFuncs; // Optional global functions similar to processing\nclass Program\n{\n    static void Main()\n    {\n        var gameWindowSettings = new GameWindowSettings()\n        {\n            UpdateFrequency = Globals.FrameRate,\n        };\n        var nativeWindowSettings = new NativeWindowSettings() \n        { \n            ClientSize = Globals.CanvasSize, \n            Title = \"Name of your window\",\n            WindowBorder = WindowBorder.Fixed, // Resizeable? (very buggy if so)\n            WindowState = WindowState.Normal,\n        };\n        using var canvas = new Canvas(gameWindowSettings, nativeWindowSettings);\n        \n        // CanvasCenter is a dynamic property that always points to the center of the window\n        Circle circle = new(Globals.CanvasCenter, 200);\n        circle.FillColor = new Vector4i(0,255,0,255); //0-255 Colors are normalized automatically\n        circle.StrokeColor = new Vector4i(0,0,0,255);\n        circle.StrokeWeight = 10; //Stroke weight in pixels\n        \n        canvas.AddShape(0, circle);\n        \n        canvas.Run();\n    }\n}\n```\nCongratulations, you now have a green circle.\n\n### OnDraw Behavior\nWhen you add a shape to the canvas, it is automatically drawn every frame. To run code every frame along side the drawing of the shape, you'll need to add a subscriber to the canvas' OnDraw action like so:\n```csharp\ncanvas.OnDraw += () =\u003e circle.Move(new Vector2(50 * Cos(Globals.FrameCount / 1000), 50 * Sin(Globals.FrameCount / 1000)));\n```\nHere, the Vector2 passed to the Move function is a displacement vector that will be added to the shapes position. There is also a Rotate function that rotates the shape by an angle.\n\nAll together you should have:\n```csharp\nusing OpenTK.Windowing.Desktop;\nusing OpenTK.Mathematics;\nusing OpenTK.Windowing.Common;\nusing P5CSLIB.Shapes;\nusing P5CSLIB;\nusing static P5CSLIB.PFuncs; // Optional global functions similar to processing\nclass Program\n{\n    static void Main()\n    {\n        var gameWindowSettings = new GameWindowSettings()\n        {\n            UpdateFrequency = Globals.FrameRate,\n        };\n        var nativeWindowSettings = new NativeWindowSettings() \n        { \n            ClientSize = Globals.CanvasSize, \n            Title = \"Name of your window\",\n            WindowBorder = WindowBorder.Fixed, // Resizeable? (very buggy if so)\n            WindowState = WindowState.Normal,\n        };\n        using var canvas = new Canvas(gameWindowSettings, nativeWindowSettings);\n        \n        // CanvasCenter is a dynamic property that always points to the center of the window\n        Circle circle = new(Globals.CanvasCenter, 200);\n        circle.FillColor = new Vector4i(0,255,0,255); //0-255 Colors are normalized automatically\n        circle.StrokeColor = new Vector4i(0,0,0,255);\n        circle.StrokeWeight = 10; //Stroke weight in pixels\n        \n        canvas.AddShape(0, circle);\n        \n        canvas.OnDraw += () =\u003e circle.Move(new Vector2(100 * Cos(Globals.FrameCount / 100f), 100 * Sin(Globals.FrameCount / 100f)));\n        \n        canvas.Run();\n    }\n}\n```\nCongratulations, now you have a green circle moving in a circle.\n\n## Custom Shaders\nMost shapes derive from a rect, or a shape that derives from a rect, and the shaders used on it are determined by its protected property called 'shaderProgram'\n\nFor those not familiar with creating shaders, you can look through the OpenTK docs [here](https://opentk.net/learn/chapter1/4-shaders.html)\n\nAlternatively, you could look at  *ProcessingSharp/Shapes/ShapeHelper.cs* and create a new helper function for creating your custom shader program.\n\n*Note: shaderProgram is an int, you need to use the opengl functions provided by OpenTK to get and assign that int*\n\nThe way you would do this is as follows:\n```csharp\nusing OpenTK.Graphics.OpenGL;\nnamespace P5CSLIB.Shapes;\n\npublic class SomeClass\n{\n    public static int CreateShaderProgram()\n    {\n        string vertexShaderSource = \"YOUR VERTEX SHADER SOURCE CODE\";\n\n        string fragmentShaderSource = \"YOUR FRAGMENT SHADERS SOURCE CODE\";\n\n\n        int vertexShader = CompileShader(ShaderType.VertexShader, vertexShaderSource);\n        int fragmentShader = CompileShader(ShaderType.FragmentShader, fragmentShaderSource);\n\n        int shaderProgram = GL.CreateProgram();\n        GL.AttachShader(shaderProgram, vertexShader);\n        GL.AttachShader(shaderProgram, fragmentShader);\n        GL.LinkProgram(shaderProgram);\n\n        GL.DeleteShader(vertexShader);\n        GL.DeleteShader(fragmentShader);\n\n        return shaderProgram;\n    }\n\n    private static int CompileShader(ShaderType type, string source)\n    {\n        int shader = GL.CreateShader(type);\n        GL.ShaderSource(shader, source);\n        GL.CompileShader(shader);\n\n        GL.GetShaderInfoLog(shader, out string infoLog);\n        if (!string.IsNullOrEmpty(infoLog))\n        {\n            Console.WriteLine($\"Shader Compilation Error ({type}): {infoLog}\");\n        }\n\n        return shader;\n    }\n}\n//Then in your custom shape object that inherits from Rect (including circles and ellipses)...\nshaderProgram = SomeClass.CreateShaderProgram()\n```\nNow your shape should have a custom shader applied to it.\n\n### IMPORTANT NOTE:\nCircles and ellipses are derived from the Rect class. This is because the rendering circles and ellipses is handled by the default shader.\nIf you want to put your own shader on a circle or ellipse, you'll need to account for that in your shader.\n\n## Shapes\n\n### Shape\n- The main object from which all 2D shapes derive from\n### Rect\n- The second most main shape that most other 2D shapes will inherit from\n- Includes functions like Move and Rotate, as well as properties that define its vertices and center point\n### Square\n- Just a Rect with equal diameters.\n### Ellipse\n- Inherits from Rect\n- Has its own Draw function that tells the shader to enable its circular rendering mode.\n### Circle\n- Just an ellipse with equal diameters.\n\n## Globals\nThis library has a multitude of global variables that define default behavior in the render pipeline such as:\n\n- float DeltaTime -- Set by OpenTK each frame\n- long FrameCount -- number of frames that have been rendered\n- bool Stroke -- enables or disables stroke\n- bool Fill -- enables or disables fill\n- int StrokeWeight -- default Stroke Weight\n- Vector4i FillColor -- RGBA 0-255\n- Vector4i StrokeColor -- RGBA 0-255\n- Vector4i BackgroundColor -- RGBA 0-255\n- bool FrameSmearMode -- if enabled, the renderer will no longer clear the canvas each frame\n- float FrameRate -- Target frame rate\n- Random RND -- a global random object to generate random behavior\n\n## Static Functions\nIn the interest of reducing verbosity, this library includes a public static class called PFuncs that contains many useful functions such as:\n\n```csharp\npublic static float Map(float value, float start1, float stop1, float start2, float stop2)\n{\n    return start2 + (value - start1) * (stop2 - start2) / (stop1 - start1);\n}\n\npublic static float Sq(float x) =\u003e x * x;\npublic static float Abs(float x) =\u003e x \u003c 0 ? -x : x;\npublic static float Min(float x, float y) =\u003e x \u003c y ? x : y;\npublic static float Max(float x, float y) =\u003e x \u003e y ? x : y;\n\npublic static float Lerp(float x, float y, float a) =\u003e x * (1 - a) + y * a;\npublic static Vector2 Lerp(Vector2 x, Vector2 y, float a) =\u003e x * (1 - a) + y * a;\n\npublic static float Rand(float a, float b) =\u003e a + ((b-a) * (float)Globals.RND.NextDouble());\n\npublic static int Floor(float x) =\u003e (int)Math.Floor(x);\npublic static int Ceil(float x) =\u003e (int)Math.Ceiling(x);\n\npublic static float Sqrt(float x) =\u003e MathF.Sqrt(x);\npublic static float Pow(float x, float y) =\u003e MathF.Pow(x, y);\npublic static float Exp(float x) =\u003e MathF.Exp(x);\npublic static float Log(float x) =\u003e MathF.Log(x);\npublic static float Log10(float x) =\u003e MathF.Log10(x);\npublic static float Sin(float x) =\u003e MathF.Sin(x);\npublic static float Cos(float x) =\u003e MathF.Cos(x);\n\npublic static float Dist(float x1, float y1, float x2, float y2) =\u003e MathF.Sqrt(Sq(x1 - x2) + Sq(y1 - y2));\npublic static float Dist(Vector2 a, Vector2 b) =\u003e Dist(a.X, a.Y, b.X, b.Y);\n\npublic static float GetHeading(Vector2 center, Vector2 point)\n{\n    Vector2 direction = point - center;\n    float angleInRadians = MathF.Atan2(direction.Y, direction.X);\n\n    return angleInRadians;\n}\n\npublic static float VLength(Vector2 v) =\u003e (float) Math.Sqrt(v.X * v.X + v.Y * v.Y);\n```\n\nTo use these functions statically, make sure to include it in your Program.cs file:\n```csharp\nusing static P5CSLIB.PFuncs;\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmajormilk%2Fprocessingsharp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmajormilk%2Fprocessingsharp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmajormilk%2Fprocessingsharp/lists"}