internal void Draw(GameObject g, ref Matrix4 viewProjection, HelperFrustum frustum, int textureIndex)
        {
            if (g == null || !g.HasModel || g.CurrentWorld == null || g.Opacity <= 0)
            {
                return;
            }

            if (KWEngine.Projection == ProjectionType.Perspective)
            {
                g.IsInsideScreenSpace = frustum.SphereVsFrustum(g.GetCenterPointForAllHitboxes(), g.GetMaxDiameter() / 2);
            }
            else
            {
                Vector3 lookAt       = CurrentWorld.GetCameraLookAtVectorEitherWay();
                Vector3 camPos       = CurrentWorld.GetCameraPositionEitherWay();
                Vector3 objectCenter = g.GetCenterPointForAllHitboxes();
                float   dot          = Vector3.Dot(objectCenter - camPos, lookAt);
                g.IsInsideScreenSpace = dot > 0;
            }
            if (!g.IsInsideScreenSpace)
            {
                return;
            }

            GL.Disable(EnableCap.Blend);
            lock (g)
            {
                if (g.Opacity < 1)
                {
                    GL.Enable(EnableCap.Blend);
                }

                GL.Uniform4(mUniform_Glow, g.Glow);
                GL.Uniform4(mUniform_Outline, g.ColorOutline);
                GL.Uniform3(mUniform_TintColor, g.Color);

                GL.Uniform1(mUniform_LightAffection, g.IsAffectedByLight ? 1 : 0);

                // Camera
                if (!CurrentWorld.IsFirstPersonMode)
                {
                    GL.Uniform3(mUniform_uCameraPos, g.CurrentWorld.GetCameraPosition().X, g.CurrentWorld.GetCameraPosition().Y, g.CurrentWorld.GetCameraPosition().Z);
                    GL.Uniform3(mUniform_uCameraDirection, g.CurrentWorld.GetCameraLookAtVector());
                }
                else
                {
                    GL.Uniform3(mUniform_uCameraPos, g.CurrentWorld.GetFirstPersonObject().Position.X, g.CurrentWorld.GetFirstPersonObject().Position.Y + g.CurrentWorld.GetFirstPersonObject().FPSEyeOffset, g.CurrentWorld.GetFirstPersonObject().Position.Z);
                    GL.Uniform3(mUniform_uCameraDirection, HelperCamera.GetLookAtVector());
                }

                Matrix4.Mult(ref g.ModelMatrixForRenderPass[0], ref viewProjection, out _modelViewProjection);
                Matrix4.Transpose(ref g.ModelMatrixForRenderPass[0], out _normalMatrix);
                Matrix4.Invert(ref _normalMatrix, out _normalMatrix);

                GL.UniformMatrix4(mUniform_ModelMatrix, false, ref g.ModelMatrixForRenderPass[0]);
                GL.UniformMatrix4(mUniform_NormalMatrix, false, ref _normalMatrix);
                GL.UniformMatrix4(mUniform_MVP, false, ref _modelViewProjection);

                if (g.ColorEmissive.W > 0)
                {
                    GL.Uniform4(mUniform_EmissiveColor, g.ColorEmissive);
                }
                else
                {
                    GL.Uniform4(mUniform_EmissiveColor, Vector4.Zero);
                }

                string      meshName     = g.Model.Meshes.Keys.ElementAt(0);
                GeoMesh     mesh         = g.Model.Meshes[meshName];
                GeoMaterial meshMaterial = mesh.Material;

                GL.Uniform1(mUniform_Roughness, meshMaterial.Roughness);
                GL.Uniform1(mUniform_Metalness, meshMaterial.Metalness);


                GL.Uniform4(mUniform_TextureTransform, mesh.Terrain.mTexX, mesh.Terrain.mTexY, g.mTextureOffset.X, g.mTextureOffset.Y);

                // albedo map:
                int texId = -1;
                texId = mesh.Material.TextureAlbedo.OpenGLID;
                GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                GL.BindTexture(TextureTarget.Texture2D, texId > 0 ? texId : KWEngine.TextureWhite);
                GL.Uniform1(mUniform_Texture, textureIndex);
                GL.Uniform1(mUniform_TextureUse, texId > 0 ? 1 : 0);
                GL.Uniform3(mUniform_BaseColor, texId > 0 ? new Vector3(1f, 1f, 1f) : new Vector3(meshMaterial.ColorAlbedo.X, meshMaterial.ColorAlbedo.Y, meshMaterial.ColorAlbedo.Z));
                textureIndex++;

                // normal map:
                texId = meshMaterial.TextureNormal.OpenGLID;
                GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                GL.BindTexture(TextureTarget.Texture2D, texId > 0 ? texId : KWEngine.TextureWhite);
                GL.Uniform1(mUniform_TextureNormalMap, textureIndex);
                GL.Uniform1(mUniform_TextureUseNormalMap, texId > 0 ? 1 : 0);
                textureIndex++;

                // roughness map:
                GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                if (meshMaterial.TextureRoughness.OpenGLID > 0)
                {
                    GL.BindTexture(TextureTarget.Texture2D, meshMaterial.TextureRoughness.OpenGLID);
                    GL.Uniform1(mUniform_TextureRoughnessMap, textureIndex);
                    GL.Uniform1(mUniform_TextureUseRoughnessMap, 1);
                    GL.Uniform1(mUniform_TextureRoughnessIsSpecular, meshMaterial.TextureRoughnessIsSpecular ? 1 : 0);
                }
                else
                {
                    if (meshMaterial.TextureRoughnessInMetalness && meshMaterial.TextureMetalness.OpenGLID > 0)
                    {
                        GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureWhite);
                        GL.Uniform1(mUniform_TextureRoughnessMap, textureIndex);
                        GL.Uniform1(mUniform_TextureUseRoughnessMap, 0);
                        GL.Uniform1(mUniform_TextureRoughnessIsSpecular, 1);
                    }
                    else
                    {
                        GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureWhite);
                        GL.Uniform1(mUniform_TextureRoughnessMap, textureIndex);
                        GL.Uniform1(mUniform_TextureUseRoughnessMap, 0);
                        GL.Uniform1(mUniform_TextureRoughnessIsSpecular, 0);
                    }
                }
                textureIndex++;

                // metalness map:
                GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                if (meshMaterial.TextureMetalness.OpenGLID > 0)
                {
                    GL.BindTexture(TextureTarget.Texture2D, meshMaterial.TextureMetalness.OpenGLID);
                    GL.Uniform1(mUniform_TextureMetalnessMap, textureIndex);
                    GL.Uniform1(mUniform_TextureUseMetalnessMap, 1);
                }
                else
                {
                    GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureBlack);
                    GL.Uniform1(mUniform_TextureMetalnessMap, textureIndex);
                    GL.Uniform1(mUniform_TextureUseMetalnessMap, 0);
                }
                textureIndex++;

                // emissive map:
                GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                if (meshMaterial.TextureEmissive.OpenGLID > 0)
                {
                    GL.BindTexture(TextureTarget.Texture2D, meshMaterial.TextureEmissive.OpenGLID);
                    GL.Uniform1(mUniform_TextureEmissiveMap, textureIndex);
                    GL.Uniform1(mUniform_TextureUseEmissiveMap, 1);
                }
                else
                {
                    GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureBlack);
                    GL.Uniform1(mUniform_TextureEmissiveMap, textureIndex);
                    GL.Uniform1(mUniform_TextureUseEmissiveMap, 0);
                }
                textureIndex++;

                // Blendmapping:
                if (mesh.Terrain._texBlend > 0 && mesh.Terrain._texBlend != KWEngine.TextureBlack)
                {
                    GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                    GL.BindTexture(TextureTarget.Texture2D, mesh.Terrain._texBlend);
                    GL.Uniform1(mUniform_TextureBlend, textureIndex);
                    textureIndex++;

                    GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                    GL.BindTexture(TextureTarget.Texture2D, mesh.Terrain._texR);
                    GL.Uniform1(mUniform_TextureRed, textureIndex);
                    textureIndex++;

                    GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                    if (mesh.Terrain._texG > 0 && mesh.Terrain._texG != KWEngine.TextureAlpha)
                    {
                        GL.BindTexture(TextureTarget.Texture2D, mesh.Terrain._texG);
                    }
                    else
                    {
                        GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureAlpha);
                    }
                    GL.Uniform1(mUniform_TextureGreen, textureIndex);
                    textureIndex++;

                    GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                    if (mesh.Terrain._texB > 0 && mesh.Terrain._texB != KWEngine.TextureAlpha)
                    {
                        GL.BindTexture(TextureTarget.Texture2D, mesh.Terrain._texB);
                    }
                    else
                    {
                        GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureAlpha);
                    }
                    GL.Uniform1(mUniform_TextureBlue, textureIndex);
                    textureIndex++;


                    GL.Uniform1(mUniform_UseBlend, 1);
                }
                else
                {
                    GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                    GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureBlack);
                    GL.Uniform1(mUniform_TextureBlend, textureIndex);
                    textureIndex++;

                    GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                    GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureBlack);
                    GL.Uniform1(mUniform_TextureRed, textureIndex);
                    textureIndex++;

                    GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                    GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureBlack);
                    GL.Uniform1(mUniform_TextureGreen, textureIndex);
                    textureIndex++;

                    GL.ActiveTexture(TextureUnit.Texture0 + textureIndex);
                    GL.BindTexture(TextureTarget.Texture2D, KWEngine.TextureBlack);
                    GL.Uniform1(mUniform_TextureBlue, textureIndex);
                    textureIndex++;

                    GL.Uniform1(mUniform_UseBlend, 0);
                }

                GL.BindVertexArray(mesh.VAO);
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, mesh.VBOIndex);
                GL.DrawElements(mesh.Primitive, mesh.IndexCount, DrawElementsType.UnsignedInt, 0);
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
                GL.BindVertexArray(0);
            }

            if (g.Opacity < 1)
            {
                GL.Disable(EnableCap.Blend);
            }
        }