using System.Numerics;
using System.Runtime.InteropServices;
using System.Security;
namespace Raylib_cs
{
    [SuppressUnmanagedCodeSecurity]
    public static unsafe partial class Rlgl
    {
        /// 
        /// Used by DllImport to load the native library
        /// 
        public const string nativeLibName = "raylib";
        public const int DEFAULT_BATCH_BUFFER_ELEMENTS = 8192;
        public const int DEFAULT_BATCH_BUFFERS = 1;
        public const int DEFAULT_BATCH_DRAWCALLS = 256;
        public const int MAX_BATCH_ACTIVE_TEXTURES = 4;
        public const int MAX_MATRIX_STACK_SIZE = 32;
        public const float RL_CULL_DISTANCE_NEAR = 0.01f;
        public const float RL_CULL_DISTANCE_FAR = 1000.0f;
        // Texture parameters (equivalent to OpenGL defines)
        public const int RL_TEXTURE_WRAP_S = 0x2802;
        public const int RL_TEXTURE_WRAP_T = 0x2803;
        public const int RL_TEXTURE_MAG_FILTER = 0x2800;
        public const int RL_TEXTURE_MIN_FILTER = 0x2801;
        public const int RL_TEXTURE_FILTER_NEAREST = 0x2600;
        public const int RL_TEXTURE_FILTER_LINEAR = 0x2601;
        public const int RL_TEXTURE_FILTER_MIP_NEAREST = 0x2700;
        public const int RL_TEXTURE_FILTER_NEAREST_MIP_LINEAR = 0x2702;
        public const int RL_TEXTURE_FILTER_LINEAR_MIP_NEAREST = 0x2701;
        public const int RL_TEXTURE_FILTER_MIP_LINEAR = 0x2703;
        public const int RL_TEXTURE_FILTER_ANISOTROPIC = 0x3000;
        public const int RL_TEXTURE_MIPMAP_BIAS_RATIO = 0x4000;
        public const int RL_TEXTURE_WRAP_REPEAT = 0x2901;
        public const int RL_TEXTURE_WRAP_CLAMP = 0x812F;
        public const int RL_TEXTURE_WRAP_MIRROR_REPEAT = 0x8370;
        public const int RL_TEXTURE_WRAP_MIRROR_CLAMP = 0x8742;
        // GL equivalent data types
        public const int RL_UNSIGNED_BYTE = 0x1401;
        public const int RL_FLOAT = 0x1406;
        // Buffer usage hint
        public const int RL_STREAM_DRAW = 0x88E0;
        public const int RL_STREAM_READ = 0x88E1;
        public const int RL_STREAM_COPY = 0x88E2;
        public const int RL_STATIC_DRAW = 0x88E4;
        public const int RL_STATIC_READ = 0x88E5;
        public const int RL_STATIC_COPY = 0x88E6;
        public const int RL_DYNAMIC_DRAW = 0x88E8;
        public const int RL_DYNAMIC_READ = 0x88E9;
        public const int RL_DYNAMIC_COPY = 0x88EA;
        // GL blending factors
        public const int RL_ZERO = 0;
        public const int RL_ONE = 1;
        public const int RL_SRC_COLOR = 0x0300;
        public const int RL_ONE_MINUS_SRC_COLOR = 0x0301;
        public const int RL_SRC_ALPHA = 0x0302;
        public const int RL_ONE_MINUS_SRC_ALPHA = 0x0303;
        public const int RL_DST_ALPHA = 0x0304;
        public const int RL_ONE_MINUS_DST_ALPHA = 0x0305;
        public const int RL_DST_COLOR = 0x0306;
        public const int RL_ONE_MINUS_DST_COLOR = 0x0307;
        public const int RL_SRC_ALPHA_SATURATE = 0x0308;
        public const int RL_CONSTANT_COLOR = 0x8001;
        public const int RL_ONE_MINUS_CONSTANT_COLOR = 0x8002;
        public const int RL_CONSTANT_ALPHA = 0x8003;
        public const int RL_ONE_MINUS_CONSTANT_ALPHA = 0x8004;
        // GL blending functions/equations
        public const int RL_FUNC_ADD = 0x8006;
        public const int RL_MIN = 0x8007;
        public const int RL_MAX = 0x8008;
        public const int RL_FUNC_SUBTRACT = 0x800A;
        public const int RL_FUNC_REVERSE_SUBTRACT = 0x800B;
        public const int RL_BLEND_EQUATION = 0x8009;
        public const int RL_BLEND_EQUATION_RGB = 0x8009;
        public const int RL_BLEND_EQUATION_ALPHA = 0x883D;
        public const int RL_BLEND_DST_RGB = 0x80C8;
        public const int RL_BLEND_SRC_RGB = 0x80C9;
        public const int RL_BLEND_DST_ALPHA = 0x80CA;
        public const int RL_BLEND_SRC_ALPHA = 0x80CB;
        public const int RL_BLEND_COLOR = 0x8005;
        // ------------------------------------------------------------------------------------
        // Functions Declaration - Matrix operations
        // ------------------------------------------------------------------------------------
        /// Choose the current matrix to be transformed
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlMatrixMode(int mode);
        /// 
        public static void rlMatrixMode(MatrixMode mode)
        {
            rlMatrixMode((int)mode);
        }
        /// Push the current matrix to stack
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlPushMatrix();
        /// Pop lattest inserted matrix from stack
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlPopMatrix();
        /// Reset current matrix to identity matrix
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlLoadIdentity();
        /// Multiply the current matrix by a translation matrix
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlTranslatef(float x, float y, float z);
        /// Multiply the current matrix by a rotation matrix
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlRotatef(float angle, float x, float y, float z);
        /// Multiply the current matrix by a scaling matrix
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlScalef(float x, float y, float z);
        /// 
        /// Multiply the current matrix by another matrix
        /// Current Matrix can be set via 
        /// 
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlMultMatrixf(float* matf);
        /// 
        public static void rlMultMatrixf(Matrix4x4 matf)
        {
            float16 f = Raymath.MatrixToFloatV(matf);
            rlMultMatrixf(f.v);
        }
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlFrustum(
            double left,
            double right,
            double bottom,
            double top,
            double znear,
            double zfar
        );
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlOrtho(
            double left,
            double right,
            double bottom,
            double top,
            double znear,
            double zfar
        );
        /// Set the viewport area
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlViewport(int x, int y, int width, int height);
        // ------------------------------------------------------------------------------------
        // Functions Declaration - Vertex level operations
        // ------------------------------------------------------------------------------------
        /// Initialize drawing mode (how to organize vertex)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlBegin(int mode);
        public static void rlBegin(DrawMode mode)
        {
            rlBegin((int)mode);
        }
        /// Finish vertex providing
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnd();
        /// Define one vertex (position) - 2 int
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlVertex2i(int x, int y);
        /// Define one vertex (position) - 2 float
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlVertex2f(float x, float y);
        /// Define one vertex (position) - 3 float
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlVertex3f(float x, float y, float z);
        /// Define one vertex (texture coordinate) - 2 float
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlTexCoord2f(float x, float y);
        /// Define one vertex (normal) - 3 float
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlNormal3f(float x, float y, float z);
        /// Define one vertex (color) - 4 byte
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlColor4ub(byte r, byte g, byte b, byte a);
        /// Define one vertex (color) - 3 float
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlColor3f(float x, float y, float z);
        /// Define one vertex (color) - 4 float
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlColor4f(float x, float y, float z, float w);
        // ------------------------------------------------------------------------------------
        // Functions Declaration - OpenGL equivalent functions (common to 1.1, 3.3+, ES2)
        // NOTE: This functions are used to completely abstract raylib code from OpenGL layer
        // ------------------------------------------------------------------------------------
        /// Vertex buffers state
        /// Enable vertex array (VAO, if supported)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern CBool rlEnableVertexArray(uint vaoId);
        /// Disable vertex array (VAO, if supported)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableVertexArray();
        /// Enable vertex buffer (VBO)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableVertexBuffer(uint id);
        /// Disable vertex buffer (VBO)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableVertexBuffer();
        /// Enable vertex buffer element (VBO element)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableVertexBufferElement(uint id);
        /// Disable vertex buffer element (VBO element)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableVertexBufferElement();
        /// Enable vertex attribute index
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableVertexAttribute(uint index);
        /// Disable vertex attribute index
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableVertexAttribute(uint index);
        /// Enable attribute state pointer
        /// NOTE: Only available for GRAPHICS_API_OPENGL_11
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableStatePointer(int vertexAttribType, void* buffer);
        /// Disable attribute state pointer
        /// NOTE: Only available for GRAPHICS_API_OPENGL_11
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableStatePointer(int vertexAttribType);
        // Textures state
        /// Select and active a texture slot
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlActiveTextureSlot(int slot);
        /// Enable texture
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableTexture(uint id);
        /// Disable texture
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableTexture();
        /// Enable texture cubemap
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableTextureCubemap(uint id);
        /// Disable texture cubemap
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableTextureCubemap();
        /// Set texture parameters (filter, wrap)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlTextureParameters(uint id, int param, int value);
        /// Set cubemap parameters (filter, wrap)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlCubemapParameters(uint id, int param, int value);
        // Shader state
        /// Enable shader program
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableShader(uint id);
        /// Disable shader program
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableShader();
        // Framebuffer state
        /// Enable render texture (fbo)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableFramebuffer(uint id);
        /// Disable render texture (fbo), return to default framebuffer
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableFramebuffer();
        /// Activate multiple draw color buffers
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlActiveDrawBuffers(int count);
        // General render state
        /// Enable color blending
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableColorBlend();
        /// Disable color blending
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableColorBlend();
        /// Enable depth test
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableDepthTest();
        /// Disable depth test
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableDepthTest();
        /// Enable depth write
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableDepthMask();
        /// Disable depth write
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableDepthMask();
        /// Enable backface culling
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableBackfaceCulling();
        /// Disable backface culling
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableBackfaceCulling();
        /// Set face culling mode
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetCullFace(int mode);
        /// Enable scissor test
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableScissorTest();
        /// Disable scissor test
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableScissorTest();
        /// Scissor test
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlScissor(int x, int y, int width, int height);
        /// Enable wire mode
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableWireMode();
        /// Disable wire mode
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableWireMode();
        /// Set the line drawing width
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetLineWidth(float width);
        /// Get the line drawing width
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern float rlGetLineWidth();
        /// Enable line aliasing
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableSmoothLines();
        /// Disable line aliasing
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableSmoothLines();
        /// Enable stereo rendering
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlEnableStereoRender();
        /// Disable stereo rendering
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDisableStereoRender();
        /// Check if stereo render is enabled
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern CBool rlIsStereoRenderEnabled();
        /// Clear color buffer with color
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlClearColor(byte r, byte g, byte b, byte a);
        /// Clear used screen buffers (color and depth)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlClearScreenBuffers();
        /// Check and log OpenGL error codes
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlCheckErrors();
        /// Set blending mode
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetBlendMode(BlendMode mode);
        /// Set blending mode factor and equation (using OpenGL factors)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation);
        /// Set blending mode factors and equations separately (using OpenGL factors)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetBlendFactorsSeparate(
            int glSrcRGB,
            int glDstRGB,
            int glSrcAlpha,
            int glDstAlpha,
            int glEqRGB,
            int glEqAlpha
        );
        // ------------------------------------------------------------------------------------
        // Functions Declaration - rlgl functionality
        // ------------------------------------------------------------------------------------
        /// Initialize rlgl (buffers, shaders, textures, states)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlglInit(int width, int height);
        /// De-inititialize rlgl (buffers, shaders, textures)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlglClose();
        /// Load OpenGL extensions
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlLoadExtensions(void* loader);
        /// Get current OpenGL version
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern GlVersion rlGetVersion();
        /// Get default framebuffer width
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern int rlGetFramebufferWidth();
        /// Get default framebuffer height
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern int rlGetFramebufferHeight();
        /// Get default texture
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlGetTextureIdDefault();
        /// Get default shader
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlGetShaderIdDefault();
        /// Get default shader locations
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern int* rlGetShaderLocsDefault();
        // Render batch management
        /// Load a render batch system
        /// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
        /// but this render batch API is exposed in case custom batches are required
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements);
        /// Unload render batch system
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUnloadRenderBatch(RenderBatch batch);
        /// Draw render batch data (Update->Draw->Reset)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDrawRenderBatch(RenderBatch* batch);
        /// Set the active render batch for rlgl (NULL for default internal)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetRenderBatchActive(RenderBatch* batch);
        /// Update and draw internal render batch
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDrawRenderBatchActive();
        /// Check internal buffer overflow for a given number of vertex
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern CBool rlCheckRenderBatchLimit(int vCount);
        /// Set current texture for render batch and check buffers limits
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetTexture(uint id);
        // Vertex buffers management
        /// Load vertex array (vao) if supported
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadVertexArray();
        /// Load a vertex buffer attribute
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadVertexBuffer(void* buffer, int size, CBool dynamic);
        /// Load a new attributes element buffer
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadVertexBufferElement(void* buffer, int size, CBool dynamic);
        /// Update GPU buffer with new data
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUpdateVertexBuffer(uint bufferId, void* data, int dataSize, int offset);
        /// Update vertex buffer elements with new data
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUpdateVertexBufferElements(uint id, void* data, int dataSize, int offset);
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUnloadVertexArray(uint vaoId);
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUnloadVertexBuffer(uint vboId);
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetVertexAttribute(
            uint index,
            int compSize,
            int type,
            CBool normalized,
            int stride,
            void* pointer
        );
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetVertexAttributeDivisor(uint index, int divisor);
        /// Set vertex attribute default value
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetVertexAttributeDefault(int locIndex, void* value, int attribType, int count);
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDrawVertexArray(int offset, int count);
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDrawVertexArrayElements(int offset, int count, void* buffer);
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDrawVertexArrayInstanced(int offset, int count, int instances);
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlDrawVertexArrayElementsInstanced(
            int offset,
            int count,
            void* buffer,
            int instances
        );
        // Textures data management
        /// Load texture in GPU
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadTexture(void* data, int width, int height, PixelFormat format, int mipmapCount);
        /// Load depth texture/renderbuffer (to be attached to fbo)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadTextureDepth(int width, int height, CBool useRenderBuffer);
        /// Load texture cubemap
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadTextureCubemap(void* data, int size, PixelFormat format);
        /// Update GPU texture with new data
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUpdateTexture(
            uint id,
            int offsetX,
            int offsetY,
            int width,
            int height,
            PixelFormat format,
            void* data
        );
        /// Get OpenGL internal formats
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlGetGlTextureFormats(
            PixelFormat format,
            int* glInternalFormat,
            int* glFormat,
            int* glType
        );
        /// Get OpenGL internal formats
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern sbyte* rlGetPixelFormatName(PixelFormat format);
        /// Unload texture from GPU memory
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUnloadTexture(uint id);
        /// Generate mipmap data for selected texture
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlGenTextureMipmaps(uint id, int width, int height, PixelFormat format, int* mipmaps);
        /// Read texture pixel data
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void* rlReadTexturePixels(uint id, int width, int height, PixelFormat format);
        /// Read screen pixel data (color buffer)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern byte* rlReadScreenPixels(int width, int height);
        // Framebuffer management (fbo)
        /// Load an empty framebuffer
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadFramebuffer(int width, int height);
        /// Attach texture/renderbuffer to a framebuffer
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlFramebufferAttach(
            uint fboId,
            uint texId,
            FramebufferAttachType attachType,
            FramebufferAttachTextureType texType,
            int mipLevel
        );
        /// Verify framebuffer is complete
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern CBool rlFramebufferComplete(uint id);
        /// Delete framebuffer from GPU
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUnloadFramebuffer(uint id);
        // Shaders management
        /// Load shader from code strings
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadShaderCode(sbyte* vsCode, sbyte* fsCode);
        /// Compile custom shader and return shader id
        /// (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlCompileShader(sbyte* shaderCode, int type);
        /// Load custom shader program
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadShaderProgram(uint vShaderId, uint fShaderId);
        /// Unload shader program
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUnloadShaderProgram(uint id);
        /// Get shader location uniform
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern int rlGetLocationUniform(uint shaderId, sbyte* uniformName);
        /// Get shader location attribute
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern int rlGetLocationAttrib(uint shaderId, sbyte* attribName);
        /// Set shader value uniform
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetUniform(int locIndex, void* value, int uniformType, int count);
        /// Set shader value matrix
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetUniformMatrix(int locIndex, Matrix4x4 mat);
        /// Set shader value sampler
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetUniformSampler(int locIndex, uint textureId);
        /// Set shader currently active (id and locations)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetShader(uint id, int* locs);
        // Compute shader management
        /// Load compute shader program
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadComputeShaderProgram(uint shaderId);
        /// Dispatch compute shader (equivalent to *draw* for graphics pilepine)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlComputeShaderDispatch(uint groupX, uint groupY, uint groupZ);
        // Shader buffer storage object management (ssbo)
        /// Load shader storage buffer object (SSBO)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlLoadShaderBuffer(uint size, void* data, int usageHint);
        /// Unload shader storage buffer object (SSBO)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUnloadShaderBuffer(uint ssboId);
        /// Update SSBO buffer data
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlUpdateShaderBuffer(uint id, void* data, uint dataSize, uint offset);
        /// Bind SSBO buffer data
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlBindShaderBuffer(uint id, uint index);
        /// Read SSBO buffer data (GPU->CPU)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlReadShaderBuffer(uint id, void* dest, uint count, uint offset);
        /// Copy SSBO data between buffers
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlCopyShaderBuffer(
            uint destId,
            uint srcId,
            uint destOffset,
            uint srcOffset,
            uint count
        );
        /// Get SSBO buffer size
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint rlGetShaderBufferSize(uint id);
        // Buffer management
        /// Bind image texture
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlBindImageTexture(uint id, uint index, int format, CBool readOnly);
        // Matrix state management
        /// Get internal modelview matrix
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern Matrix4x4 rlGetMatrixModelview();
        /// Get internal projection matrix
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern Matrix4x4 rlGetMatrixProjection();
        /// Get internal accumulated transform matrix
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern Matrix4x4 rlGetMatrixTransform();
        /// Get internal projection matrix for stereo render (selected eye)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern Matrix4x4 rlGetMatrixProjectionStereo(int eye);
        /// Get internal view offset matrix for stereo render (selected eye)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern Matrix4x4 rlGetMatrixViewOffsetStereo(int eye);
        /// Set a custom projection matrix (replaces internal projection matrix)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetMatrixProjection(Matrix4x4 view);
        /// Set a custom modelview matrix (replaces internal modelview matrix)
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetMatrixModelview(Matrix4x4 proj);
        /// Set eyes projection matrices for stereo rendering
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetMatrixProjectionStereo(Matrix4x4 left, Matrix4x4 right);
        /// Set eyes view offsets matrices for stereo rendering
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlSetMatrixViewOffsetStereo(Matrix4x4 left, Matrix4x4 right);
        // Quick and dirty cube/quad buffers load->draw->unload
        /// Load and draw a cube
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlLoadDrawCube();
        /// Load and draw a quad
        [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void rlLoadDrawQuad();
    }
}