Esempio n. 1
0
 private void OnLoad(object sender, EventArgs e)
 {
     // initialize shader
     _program = ProgramFactory.Create<SkyboxProgram>();
     // initialize cube shape
     _cube = new Cube();
     _cube.UpdateBuffers();
     // initialize vertex array and attributes
     _vao = new VertexArray();
     _vao.Bind();
     _vao.BindAttribute(_program.InPosition, _cube.VertexBuffer);
     _vao.BindElementBuffer(_cube.IndexBuffer);
     // create cubemap texture and load all faces
     for (var i = 0; i < 6; i++)
     {
         using (var bitmap = new Bitmap(string.Format("Data/Textures/city{0}.jpg", i)))
         {
             bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
             if (_skybox == null) BitmapTexture.CreateCompatible(bitmap, out _skybox, 1);
             _skybox.LoadBitmap(bitmap, i);
         }
     }
     // activate shader and bind texture to it
     _program.Use();
     _program.Texture.BindTexture(TextureUnit.Texture0, _skybox);
     // enable seamless filtering to reduce artifacts at the edges of the cube faces
     GL.Enable(EnableCap.TextureCubeMapSeamless);
     // cull front faces because we are inside the cube
     // this is not really necessary but removes some artifacts when the user leaves the cube
     // which should be impossible for a real skybox, but in this demonstration it is possible by zooming out
     GL.Enable(EnableCap.CullFace);
     GL.CullFace(CullFaceMode.Front);
     // set a nice clear color
     GL.ClearColor(Color.MidnightBlue);
 }
Esempio n. 2
0
        public SpriteRenderer(SpriteSheet spriteSheet)
        {
            SpriteSheet = spriteSheet;

            m_program = SpriteProgram.Instance;
            m_instances = new List<SpriteInstance>();
            m_vao = new VertexArray();

            GL.BindVertexArray(m_vao);

            m_bufferSprite = new Buffer<SpriteData>();
            m_bufferQuad = new Buffer<Vector3>();

            m_bufferQuad.SetData(new Vector3[] {
                new Vector3(0f, 0f, 0f),
                new Vector3(0f, 1f, 0f),
                new Vector3(1f, 1f, 0f),
                new Vector3(1f, 0f, 0f)
            });

            GL.UseProgram(m_program);

            m_program.Position.SetValue(m_bufferQuad.GetView());

            m_program.Transform.SetValue(m_bufferSprite.GetView<Matrix4>("Transform"));
            m_program.Transform.SetDivisor(1);
            m_program.TextureOrigin.SetValue(m_bufferSprite.GetView<Vector2>("TextureOrigin"));
            m_program.TextureOrigin.SetDivisor(1);
            m_program.TextureTarget.SetValue(m_bufferSprite.GetView<Vector2>("TextureTarget"));
            m_program.TextureTarget.SetDivisor(1);

            GL.BindVertexArray(null);

            m_isDirty = true;
        }
Esempio n. 3
0
        private void OnLoad(object sender, EventArgs e)
        {
            // initialize shader (load sources, create/compile/link shader program, error checking)
            // when using the factory method the shader sources are retrieved from the ShaderSourceAttributes
            _program = ProgramFactory.Create<ExampleProgram>();
            // this program will be used all the time so just activate it once and for all
            _program.Use();

            // create vertices for a triangle
            var vertices = new[] { new Vector3(-1,-1,0), new Vector3(1,-1,0), new Vector3(0,1,0) };

            // create buffer object and upload vertex data
            _vbo = new Buffer<Vector3>();
            _vbo.Init(BufferTarget.ArrayBuffer, vertices);

            // create and bind a vertex array
            _vao = new VertexArray();
            _vao.Bind();
            // set up binding of the shader variable to the buffer object
            _vao.BindAttribute(_program.InPosition, _vbo);

            // set camera position
            Camera.DefaultState.Position = new Vector3(0,0,3);
            Camera.ResetToDefault();

            // set a nice clear color
            GL.ClearColor(Color.MidnightBlue);
        }
        public SegmentRenderer()
        {
            m_program = TriangleProgram.Instance;
            m_instances = new List<SegmentInstance>();

            m_vao = new VertexArray();

            GL.BindVertexArray(m_vao);
            GL.UseProgram(m_program);

            m_bufferSprite = new Buffer<SegmentData>();
            m_bufferTriangle = new Buffer<Vector3>();

            m_program.Position.SetValue(m_bufferSprite.GetView<Vector3>("Position"));

            m_program.Color.SetValue(m_bufferSprite.GetView<Color4ub>("Color"));
            //m_program.Position.SetDivisor(1);
               // m_program.Normal.SetValue(m_bufferSprite.GetView<Vector3>("Normal"));
               //// m_program.Normal.SetDivisor(1);
               // m_program.Transform.SetValue(m_bufferSprite.GetView<Matrix4>("Transform"));
               // //m_program.Transform.SetDivisor(1);
               // m_program.TextureOrigin.SetValue(m_bufferSprite.GetView<Vector2>("TextureOrigin"));
               // //m_program.TextureOrigin.SetDivisor(1);
               // m_program.TextureTarget.SetValue(m_bufferSprite.GetView<Vector2>("TextureTarget"));
            //m_program.TextureTarget.SetDivisor(1);

            GL.BindVertexArray(null);

            m_isDirty = true;
        }
Esempio n. 5
0
        private void OnLoad(object sender, EventArgs e)
        {
            // initialize and bind framebuffer
            _framebuffer = new Framebuffer();
            _framebuffer.Bind(FramebufferTarget.Framebuffer);

            // initialize a renderbuffer and bind it to the depth attachment
            // to support depth testing while rendering to the texture
            _depthBuffer = new Renderbuffer();
            _depthBuffer.Init(RenderbufferStorage.DepthComponent, FramebufferWidth, FramebufferHeight);
            _framebuffer.Attach(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, _depthBuffer);

            // initialize texture and bind it to the color attachment
            _texture = new Texture2D(SizedInternalFormat.Rgba8, FramebufferWidth, FramebufferHeight, 1);
            _framebuffer.Attach(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, _texture);
            Framebuffer.Unbind(FramebufferTarget.Framebuffer);

            // initialize demonstration geometry
            _cube = new ColorCube();
            _cube.UpdateBuffers();
            _quad = new TexturedQuad();
            _quad.UpdateBuffers();

            // initialize shaders
            _colorProgram = ProgramFactory.Create<SimpleColorProgram>();
            _textureProgram = ProgramFactory.Create<SimpleTextureProgram>();

            // set up vertex attributes for the cube
            _cubeVao = new VertexArray();
            _cubeVao.Bind();
            _cubeVao.BindAttribute(_colorProgram.InPosition, _cube.VertexBuffer);
            _cubeVao.BindAttribute(_colorProgram.InColor, _cube.ColorBuffer);
            _cubeVao.BindElementBuffer(_cube.IndexBuffer);

            // set up vertex attributes for the quad
            _quadVao = new VertexArray();
            _quadVao.Bind();
            _quadVao.BindAttribute(_textureProgram.InPosition, _quad.VertexBuffer);
            _quadVao.BindAttribute(_textureProgram.InTexCoord, _quad.TexCoordBuffer);

            // set camera position
            Camera.DefaultState.Position = new Vector3(0,0,3);
            Camera.ResetToDefault();

            // enable depth testing
            GL.Enable(EnableCap.DepthTest);
        }
Esempio n. 6
0
        public Graphics(int queueCapacity = 1000)
        {
            m_queueCapacity = queueCapacity;
            m_queue = new QuadData[m_queueCapacity];
            m_textureQueue = new Texture2D[TEXTURE_QUEUE_CAPACITY];

            m_transformStack = new Stack<Matrix3x2>();

            m_verticesBuffer = new Buffer<Vector2>();
            m_verticesBuffer.SetData(new Vector2[] {
                new Vector2(0,0),
                new Vector2(0,1),
                new Vector2(1,1),
                new Vector2(1,0)
            });

            m_quadsBuffer = new Buffer<QuadData>();
            m_quadsBuffer.SetData(m_queueCapacity, GL.STREAM_DRAW);

            m_program = QuadProgram.Instance;
            m_vertexArray = new VertexArray();

            GL.UseProgram(m_program);
            GL.BindVertexArray(m_vertexArray);

            m_program.Vertex.SetValue(m_verticesBuffer.GetView());

            m_program.TextureCoordinates0.SetValue(m_quadsBuffer.GetView<Vector2>("TextureCoordinates0"));
            m_program.TextureCoordinates0.SetDivisor(1);

            m_program.TextureCoordinates1.SetValue(m_quadsBuffer.GetView<Vector2>("TextureCoordinates1"));
            m_program.TextureCoordinates1.SetDivisor(1);

            m_program.Transform.SetValue(m_quadsBuffer.GetView<Matrix3x2>("Transform"));
            m_program.Transform.SetDivisor(1);

            m_program.Color.SetValue(m_quadsBuffer.GetView<Color4ub>("Color"));
            m_program.Color.SetDivisor(1);

            m_program.Texture.SetValue(m_quadsBuffer.GetView<int>("Texture"));
            m_program.Texture.SetDivisor(1);

            GL.BindVertexArray(null);

            Clear();
        }
Esempio n. 7
0
        public Renderer(TriangleProgram program)
        {
            m_program = program;
            m_datas = new List<RendererData>();

            m_vao = new VertexArray();

            GL.BindVertexArray(m_vao);

            m_buffer = new Buffer<RendererData>();

            GL.UseProgram(m_program);

            m_program.Position.SetValue(m_buffer.GetView(s => s.Position));
            m_program.Color.SetValue(m_buffer.GetView(s => s.Color));
            m_program.TextureCoordinates.SetValue(m_buffer.GetView(s => s.TextureCoordinates));

            GL.BindVertexArray(null);
        }
Esempio n. 8
0
        protected override void OnLoad(EventArgs e)
        {
            // Create and fill a vertex buffer
            this.vertexBuffer = new VertexBuffer<ColoredVertex>(ColoredVertex.Size);

            this.vertexBuffer.AddVertex(new ColoredVertex(new Vector3(-1, -1, -1.5f), Color4.Lime));
            this.vertexBuffer.AddVertex(new ColoredVertex(new Vector3(1, 1, -1.5f), Color4.Red));
            this.vertexBuffer.AddVertex(new ColoredVertex(new Vector3(1, -1, -1.5f), Color4.Blue));

            // Load shaders
            string fscode, vscode;
            var assembly = Assembly.GetExecutingAssembly();
            var fsresourceName = "VoxWorld.Shaders.fragment-shader.fs";
            var vsresourceName = "VoxWorld.Shaders.vertex-shader.vs";

            using (Stream stream = assembly.GetManifestResourceStream(fsresourceName))
            using (StreamReader reader = new StreamReader(stream))
                fscode = reader.ReadToEnd();

            using (Stream stream = assembly.GetManifestResourceStream(vsresourceName))
            using (StreamReader reader = new StreamReader(stream))
                vscode = reader.ReadToEnd();

            var vertexShader = new Shader(ShaderType.VertexShader, vscode);
            var fragmentShader = new Shader(ShaderType.FragmentShader, fscode);

            // Link shaders into shader program
            this.shaderProgram = new ShaderProgram(vertexShader, fragmentShader);

            // Create vertex array to specify vertex layout
            this.vertexArray = new VertexArray<ColoredVertex>(
                this.vertexBuffer, this.shaderProgram,
                new VertexAttribute("vPosition", 3, VertexAttribPointerType.Float, ColoredVertex.Size, 0),
                new VertexAttribute("vColor", 4, VertexAttribPointerType.Float, ColoredVertex.Size, 12)
                );

            // Create projection matrix uniform
            this.projectionMatrix = new Matrix4Uniform("projectionMatrix");
            this.projectionMatrix.Matrix = Matrix4.CreatePerspectiveFieldOfView(
                MathHelper.PiOver2, 16f / 9, 0.1f, 100f);
        }
Esempio n. 9
0
        public SpriteRenderer(SpriteSheet spriteSheet)
        {
            SpriteSheet = spriteSheet;
            textureFire = Texture2D.Load(typeof(Particle).Assembly.GetManifestResourceStream("Granite.Particle.Textures.fire_color.png"));

            m_program = SpriteProgram.Instance;
            m_instances = new List<SpriteInstance>();
            m_vao = new VertexArray();

            GL.BindVertexArray(m_vao);

            m_bufferSprite = new Buffer<SpriteData>();
            m_bufferQuad = new Buffer<Vector3>();

            m_bufferQuad.SetData(new Vector3[] {
                new Vector3(0f, 0f, 0f),
                new Vector3(0f, 1f, 0f),
                new Vector3(1f, 1f, 0f),
                new Vector3(1f, 0f, 0f)
            });

            GL.UseProgram(m_program);

            m_program.Position.SetValue(m_bufferQuad.GetView());

            //m_program.Color.SetValue(m_bufferSprite.GetView(s => s.Color));
            //m_program.Color.SetDivisor(1);
            m_program.Transform.SetValue(m_bufferSprite.GetView<Matrix4>("Transform"));
            m_program.Transform.SetDivisor(1);
            m_program.TextureOrigin.SetValue(m_bufferSprite.GetView<Vector2>("TextureOrigin"));
            m_program.TextureOrigin.SetDivisor(1);
            m_program.TextureTarget.SetValue(m_bufferSprite.GetView<Vector2>("TextureTarget"));
            m_program.TextureTarget.SetDivisor(1);
            m_program.Progress.SetValue(m_bufferSprite.GetView(s => s.Progress));
            m_program.Progress.SetDivisor(1);

            GL.BindVertexArray(null);

            m_isDirty = true;
        }
Esempio n. 10
0
 protected void OnLoad(object sender, EventArgs e)
 {
     // load textures into array
     for (var i = 0; i < _stateTextures.Length; i++)
     {
         using (var bitmap = new Bitmap(Path.Combine("Data/Textures/", _stateTextures[i])))
         {
             bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
             if (_textureArray == null) BitmapTexture.CreateCompatible(bitmap, out _textureArray, _stateTextures.Length, 1);
             _textureArray.LoadBitmap(bitmap, i);
         }
     }
     // initialize buffer
     var field = new Minefield[FieldWidth*FieldHeight];
     for (var i = 0; i < field.Length; i++)
     {
         field[i] = new Minefield(i%FieldWidth, i/FieldHeight, i%_stateTextures.Length);
     }
     _buffer = new Buffer<Minefield>();
     _buffer.Init(BufferTarget.ArrayBuffer, field);
     // load program
     _gridProgram = ProgramFactory.Create<TextureGridProgram>();
     _gridProgram.Use();
     // bind the texture and set uniform
     _gridProgram.TextureData.BindTexture(TextureUnit.Texture0, _textureArray);
     // set up vertex array and attributes
     _vao = new VertexArray();
     _vao.Bind();
     _vao.BindAttribute(_gridProgram.InPosition, _buffer);
     _vao.BindAttribute(_gridProgram.InTexture, _buffer, 8);
     // set nice clear color
     GL.ClearColor(Color.MidnightBlue);
     // initialize camera position
     Camera.DefaultState.Position = new Vector3(0, 5, 15);
     Camera.ResetToDefault();
 }
Esempio n. 11
0
 public static void BindVertexArray(VertexArray vertexArray)
 {
     BindVertexArray(vertexArray == null ? 0 : vertexArray.Name);
 }
Esempio n. 12
0
        private void OnLoad(object sender, EventArgs e)
        {
            // initialize shader (load sources, create/compile/link shader program, error checking)
            // when using the factory method the shader sources are retrieved from the ShaderSourceAttributes
            _program = ProgramFactory.Create<GravityProgram>();
            // this program will be used all the time so just activate it once and for all
            _program.Use();

            // create and bind a vertex array
            _vao = new VertexArray();
            _vao.Bind();

            // create and bind transform feedback object
            _feedback = new TransformFeedback();
            _feedback.Bind();

            // Writing to a buffer while reading from it is not allowed
            // so we need two buffer objects here, which can be achieved by using the BufferPod<T> type.
            // It contains two buffers, Ping and Pong, to simplify this process.
            _buffers = new BufferPod<Particle>();
            InitializeParticles(_particleCount);

            // enable point sprite rendering
            GL.Enable(EnableCap.PointSprite);
            // enable modification of the point sprite size from the program (vertex shader in this case)
            GL.Enable(EnableCap.ProgramPointSize);
            // enable depth testing
            GL.Enable(EnableCap.DepthTest);
            // set a nice clear color
            GL.ClearColor(Color.Black);

            // set a nice camera angle
            Camera.DefaultState.Position = new Vector3(0,2,-8);
            Camera.ResetToDefault();
        }
Esempio n. 13
0
 public DrawState(RenderState renderState, ShaderProgram shaderProgram, VertexArray vertexArray)
 {
     RenderState = renderState;
     ShaderProgram = shaderProgram;
     VertexArray = vertexArray;
 }
Esempio n. 14
0
 private void ApplyVertexArray(VertexArray vertexArray)
 {
     VertexArrayGL3x vertexArrayGL3x = (VertexArrayGL3x)vertexArray;
     vertexArrayGL3x.Bind();
     vertexArrayGL3x.Clean();
 }
Esempio n. 15
0
 public static void Append(this VertexArray vertices, float x, float y, Color color, float tx, float ty)
 {
     vertices.Append(new Vertex(new Vector2f(x, y), color.SFMLColor, new Vector2f(tx, ty)));
 }
Esempio n. 16
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, Array.Empty <ISymbolDefinitionNode>()));
            }

            ReadyToRunCodegenNodeFactory r2rFactory      = (ReadyToRunCodegenNodeFactory)factory;
            List <EntryPoint>            ridToEntryPoint = new List <EntryPoint>();

            foreach (MethodWithGCInfo method in r2rFactory.EnumerateCompiledMethods())
            {
                if (method.Method is EcmaMethod ecmaMethod)
                {
                    // Strip away the token type bits, keep just the low 24 bits RID
                    uint rid = SignatureBuilder.RidFromToken((mdToken)MetadataTokens.GetToken(ecmaMethod.Handle));
                    Debug.Assert(rid != 0);
                    rid--;

                    while (ridToEntryPoint.Count <= rid)
                    {
                        ridToEntryPoint.Add(EntryPoint.Null);
                    }

                    int methodIndex = r2rFactory.RuntimeFunctionsTable.GetIndex(method);
                    ridToEntryPoint[(int)rid] = new EntryPoint(methodIndex, method);
                }
            }

            NativeWriter writer = new NativeWriter();

            Section     arraySection = writer.NewSection();
            VertexArray vertexArray  = new VertexArray(arraySection);

            arraySection.Place(vertexArray);

            Section fixupSection = writer.NewSection();

            Dictionary <byte[], BlobVertex> uniqueFixups = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            for (int rid = 0; rid < ridToEntryPoint.Count; rid++)
            {
                EntryPoint entryPoint = ridToEntryPoint[rid];
                if (!entryPoint.IsNull)
                {
                    byte[] fixups = entryPoint.Method.GetFixupBlob(factory);

                    BlobVertex fixupBlobVertex = null;
                    if (fixups != null && !uniqueFixups.TryGetValue(fixups, out fixupBlobVertex))
                    {
                        fixupBlobVertex = new BlobVertex(fixups);
                        fixupSection.Place(fixupBlobVertex);
                        uniqueFixups.Add(fixups, fixupBlobVertex);
                    }
                    EntryPointVertex entryPointVertex = new EntryPointVertex((uint)entryPoint.MethodIndex, fixupBlobVertex);
                    vertexArray.Set(rid, entryPointVertex);
                }
            }

            vertexArray.ExpandLayout();

            MemoryStream arrayContent = new MemoryStream();

            writer.Save(arrayContent);
            return(new ObjectData(
                       data: arrayContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
        private void OnLoad(object sender, EventArgs e)
        {
            // load texture from file
            using (var bitmap = new Bitmap("Data/Textures/checker.jpg"))
            {
                BitmapTexture.CreateCompatible(bitmap, out _texture);
                _texture.LoadBitmap(bitmap);
            }
            _texture.GenerateMipMaps();

            // initialize sampler
            _sampler = new Sampler();
            _sampler.SetWrapMode(TextureWrapMode.Repeat);

            // create vertex data for a big plane
            const int a = 10;
            const int b = 10;
            var vertices = new[]
            {
                new Vertex(-a, 0,-a, 0, 0),
                new Vertex( a, 0,-a, b, 0),
                new Vertex(-a, 0, a, 0, b),
                new Vertex( a, 0, a, b, b)
            };

            // create buffer object and upload vertex data
            _vbo = new Buffer<Vertex>();
            _vbo.Init(BufferTarget.ArrayBuffer, vertices);

            // initialize shader
            _program = ProgramFactory.Create<SimpleTextureProgram>();
            // activate shader program
            _program.Use();
            // bind sampler
            _sampler.Bind(TextureUnit.Texture0);
            // bind texture
            _program.Texture.BindTexture(TextureUnit.Texture0, _texture);
            // which is equivalent to
            //_program.Texture.Set(TextureUnit.Texture0);
            //_texture.Bind(TextureUnit.Texture0);

            // set up vertex array and attributes
            _vao = new VertexArray();
            _vao.Bind();
            // memory layout of our data is XYZUVXYZUV...
            // the buffer abstraction knows the total size of one "pack" of vertex data
            // and if a vertex attribute is bound without further arguments the first N elements are taken from each pack
            // where N is provided via the VertexAttribAttribute on the program property:
            _vao.BindAttribute(_program.InPosition, _vbo);
            // if data should not be taken from the start of each pack, the offset must be given in bytes
            // to reach the texture coordinates UV the XYZ coordinates must be skipped, that is 3 floats, i.e. an offset of 12 bytes is needed
            _vao.BindAttribute(_program.InTexCoord, _vbo, 12);
            // if needed all the available arguments can be specified manually, e.g.
            //_vao.BindAttribute(_program.InTexCoord, _vbo, 2, VertexAttribPointerType.Float, Marshal.SizeOf(typeof(Vertex)), 12, false);

            // set default camera
            Camera.DefaultState.Position = new Vector3(0, 0.5f, 3);
            Camera.ResetToDefault();

            // set a nice clear color
            GL.ClearColor(Color.MidnightBlue);
        }
Esempio n. 18
0
            public MeshPartData(ModelMesh mesh)
            {
                ModelMeshPart part;
                IndexElementSize IndexSize = mesh.MeshParts[0].IndexBuffer.IndexElementSize;

                Indices = new IndexArray[mesh.MeshParts.Count];
                Vertices = new VertexArray[mesh.MeshParts.Count];

                // apparently the index data comes in 16 or 32 bit format
                if (IndexSize == IndexElementSize.SixteenBits)
                {
                    for (int j = 0; j < mesh.MeshParts.Count; j++)
                    {
                        part = mesh.MeshParts[j];
                        Indices[j] = new IndexArrayShort(part);
                        Vertices[j] = new VertexArray(part);
                    }
                }
                else if (IndexSize == IndexElementSize.ThirtyTwoBits)
                {
                    for (int j = 0; j < mesh.MeshParts.Count; j++)
                    {
                        part = mesh.MeshParts[j];
                        Indices[j] = new IndexArrayInt(part);
                        Vertices[j] = new VertexArray(part);
                    }
                }
            }
Esempio n. 19
0
 void Append(VertexArray v, float x, float y, float tx, float ty)
 {
     v.Append(new Vertex(new Vector2f(x, y), new Vector2f(tx, ty)));
 }
Esempio n. 20
0
        public int Start(params string[] args)
        {
#if UNSAFE
            Console.WriteLine("Usafe are enabled");
#else
            Console.WriteLine("Usafe are disabled");
#endif
            #region Something
            if (this != singleton)
            {
                return(-1);
            }

            fov = MathF.PI / 3;

            string title = "CSGL Window";

            width  = 1600;
            height = 900;

            //glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // Change this to your targeted major version
            //glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); // Change this to your targeted minor version

            if (args.Length > 0)
            {
                title = args[0];
            }
            window = new Window(width, height, title, monitor: IntPtr.Zero, share: IntPtr.Zero);

            glClearColor(0.125f, 0.125f, 0.125f, 1);

            glEnable(GL_DEPTH_TEST);
            glEnable(GL_CULL_FACE);
            #endregion

            #region Matrix Init
            Matrix4x4 model = Matrix4x4.Identity;
            view        = Matrix4x4.CreateTranslation(0, 0, -2);
            world       = Matrix4x4.CreatePerspectiveFieldOfView(fov, width / (float)height, 0.125f, 1024f);
            matrixStack = new Stack <Matrix4x4>();
            matrixStack.Push(Matrix4x4.Identity);
            ChangeFov(fov);
            #endregion

            #region File Checking
            string vertPath = @"resources/shaders/shader.vert";
            string fragPath = @"resources/shaders/shader.frag";
            if (!File.Exists(vertPath) || !File.Exists(fragPath))
            {
                Console.WriteLine("Cannot read shader files");
                return(-1);
            }
            string vert = File.ReadAllText(vertPath);

            string frag = File.ReadAllText(fragPath);

            string texPath = @"resources/textures/colorgrid512.bmp";
            if (!File.Exists(texPath))
            {
                Console.WriteLine("Cannot read texture file");
                return(-1);
            }
            #endregion

            #region Shader and polygon init
            var program = new ShaderProgram(vert, frag);
            program.Bind();

            var vao = new VertexArray();
            vao.Bind();

            const float z = 0.0625f;
            int         length;
            {
                var vertexList = new List <Vertex>()
                {
                    new Vertex(0, 1, z, 0, 0, 1, 0.5f, 1),
                    new Vertex(-t, 0.25f, z, 0, 0, 1, 0.5f - t * 0.5f, 0.625f),
                    new Vertex(t, 0.25f, z, 0, 0, 1, 0.5f + t * 0.5f, 0.625f),
                    new Vertex(-s, -0.5f, z, 0, 0, 1, 0.5f - t, 0.25f),
                    new Vertex(0, -0.5f, z, 0, 0, 1, 0.5f, 0.25f),
                    new Vertex(s, -0.5f, z, 0, 0, 1, 0.5f + t, 0.25f),

                    new Vertex(0, 1, -z, 0, 0, -1, 0.5f, 1),
                    new Vertex(t, 0.25f, -z, 0, 0, -1, 0.5f - t * 0.5f, 0.625f),
                    new Vertex(-t, 0.25f, -z, 0, 0, -1, 0.5f + t * 0.5f, 0.625f),
                    new Vertex(s, -0.5f, -z, 0, 0, -1, 0.5f - t, 0.25f),
                    new Vertex(0, -0.5f, -z, 0, 0, -1, 0.5f, 0.25f),
                    new Vertex(-s, -0.5f, -z, 0, 0, -1, 0.5f + t, 0.25f),

                    new Vertex(-s, -0.5f, -z, -0.5f, s, 0, 0, 0),
                    new Vertex(-s, -0.5f, z, -0.5f, s, 0, z, 0),
                    new Vertex(0, 1, z, -0.5f, s, 0, z, s),
                    new Vertex(0, 1, -z, -0.5f, s, 0, 0, s),

                    new Vertex(s, -0.5f, z, 0.5f, s, 0, 0, 0),
                    new Vertex(s, -0.5f, -z, 0.5f, s, 0, z, 0),
                    new Vertex(0, 1, -z, 0.5f, s, 0, z, s),
                    new Vertex(0, 1, z, 0.5f, s, 0, 0, s),

                    new Vertex(-s, -0.5f, z, 0, -1, 0, 0, 0),
                    new Vertex(-s, -0.5f, -z, 0, -1, 0, z, 0),
                    new Vertex(s, -0.5f, -z, 0, -1, 0, z, s),
                    new Vertex(s, -0.5f, z, 0, -1, 0, 0, s),

                    new Vertex(-t, 0.25f, z, 0, -1, 0, 0, 0),
                    new Vertex(-t, 0.25f, -z, 0, -1, 0, z, 0),
                    new Vertex(t, 0.25f, -z, 0, -1, 0, z, t),
                    new Vertex(t, 0.25f, z, 0, -1, 0, 0, t),

                    new Vertex(0, -0.5f, z, 0.5f, s, 0, 0, 0),
                    new Vertex(0, -0.5f, -z, 0.5f, s, 0, z, 0),
                    new Vertex(-t, 0.25f, -z, 0.5f, s, 0, z, t),
                    new Vertex(-t, 0.25f, z, 0.5f, s, 0, 0, t),

                    new Vertex(0, -0.5f, -z, -0.5f, s, 0, 0, 0),
                    new Vertex(0, -0.5f, z, -0.5f, s, 0, z, 0),
                    new Vertex(t, 0.25f, z, -0.5f, s, 0, z, t),
                    new Vertex(t, 0.25f, -z, -0.5f, s, 0, 0, t),
                };

                int[] indices =
                {
                    0,   1,  2,
                    1,   3,  4,
                    2,   4,  5,
                    6,   7,  8,
                    7,   9, 10,
                    8,  10, 11,

                    12, 13, 14, 14, 15, 12,
                    16, 17, 18, 18, 19, 16,
                    20, 21, 22, 22, 23, 20,
                    24, 25, 26, 26, 27, 24,
                    28, 29, 30, 30, 31, 28,
                    32, 33, 34, 34, 35, 32,
                };

                length = indices.Length;

                var interleaved = new StaticInterleavedVertexBuffer(vertexList);

                uint positionLocation = program.GetLocation("inPosition");
                uint normalLocation   = program.GetLocation("inNormal");
                uint texLocation      = program.GetLocation("inTexCoord");

                glEnableVertexAttribArray(positionLocation);
                glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, Vertex.SIZE_BYTES, NULL);

                glEnableVertexAttribArray(normalLocation);
                glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, Vertex.SIZE_BYTES, new IntPtr(3 * sizeof(float)));

                glEnableVertexAttribArray(texLocation);
                glVertexAttribPointer(texLocation, 2, GL_FLOAT, GL_FALSE, Vertex.SIZE_BYTES, new IntPtr(6 * sizeof(float)));

                StaticElementArrayBuffer indexBuffer = new StaticElementArrayBuffer(indices);

                uint ubo_location = program.GetLocation("UniformBufferObject");
                glUniformBlockBinding(program.Id, ubo_location, 0);

                uint ubo = 0;
                glGenBuffers(1, ref ubo);

                glBindBuffer(GL_UNIFORM_BUFFER, ubo);
                glBufferData(GL_UNIFORM_BUFFER, 48 * sizeof(float), NULL, GL_DYNAMIC_DRAW);

                glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, 48 * sizeof(float));

                glfwSetWindowSizeCallback(window.Id, (IntPtr _, int w, int h) => singleton.ResizeWindow(w, h));

                unsafe
                {
                    Matrix4x4 world     = this.world;
                    Matrix4x4 view      = this.view;
                    Matrix4x4 matrixTop = model * matrixStack.Peek();
                    glBufferSubData(GL_UNIFORM_BUFFER, 0 * sizeof(float), 16 * sizeof(float), new IntPtr(&matrixTop.M11));
                    glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof(float), 16 * sizeof(float), new IntPtr(&view.M11));
                    glBufferSubData(GL_UNIFORM_BUFFER, 32 * sizeof(float), 16 * sizeof(float), new IntPtr(&world.M11));
                }

                var texture = new Texture(texPath);

                if (texture.Data == null)
                {
                    return(-1);
                }
            }
            #endregion

            glfwSwapInterval(1);
            glLoadIdentity();
            glTranslatef(0, 0, 0.96875f);
            glScalef(height / (float)width, 1, 1);
            glColor3b(0, 0x22, 0x11);

            var speed = ((1 / 3.0f) / MathF.PI);
            var timer = Stopwatch.StartNew();

            Console.WriteLine($"High Resolution Stopwatch: {Stopwatch.IsHighResolution}");
            while (glfwWindowShouldClose(window.Id) == 0)
            {
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                var deltaTime = (float)timer.Elapsed.TotalSeconds;
                timer.Restart();

                //model *= Matrix4x4.CreateRotationX(deltaTime);
                model *= Matrix4x4.CreateRotationY(speed * deltaTime);
                //model *= Matrix4x4.CreateRotationZ(deltaTime);
                //matrix4x4 matrixtop = model * matrixstack.peek();

                #region Fallback Triangle
                program.Unbind();

                glBegin(GL_TRIANGLES);

                glVertex3f(0, 1, 0);
                glVertex3f(-s, -0.5f, 0);
                glVertex3f(s, -0.5f, 0);

                glEnd();
                #endregion


                program.Bind();

                unsafe
                {
                    glBufferSubData(GL_UNIFORM_BUFFER, 0 * sizeof(float), 16 * sizeof(float), new IntPtr(&model.M11));
                }

                glDrawElements(GL_TRIANGLES, length, GL_UNSIGNED_INT, NULL);


                glfwSwapBuffers(window.Id);
                glfwPollEvents();
            }

            glfwTerminate();
            return(0);
        }
Esempio n. 21
0
 public GridRenderable(Document document)
 {
     _program = new ShaderProgram(
         new Shader(ShaderType.VertexShader, VertexShader),
         new Shader(ShaderType.FragmentShader, FragmentShader));
     _document = document;
     _step = -1;
     _buffer = new VertexBuffer<float>(Specification, Modes, 0, sizeof(float), new float[0], new[] { new uint[0] });
     _array = new VertexArray<float>(_buffer);
     RebuildGrid(1);
 }
Esempio n. 22
0
        public Presenter(Context glContext)
        {
            this.glContext = glContext;
            glPipeline = glContext.Pipeline;

            sourceFramebuffer = new Framebuffer(glContext);
            destinationFramebuffer = new Framebuffer(glContext);

            vertices = new Buffer(glContext, BufferTarget.ArrayBuffer, 4 * 8 * sizeof(float), BufferUsageHint.StaticDraw, new Data(new[]
            {
                new Vertex(-1f, -1f),
                new Vertex(-1f, 1f),
                new Vertex(1f, 1f),
                new Vertex(1f, -1f)
            }));

            indices = new Buffer(glContext, BufferTarget.ElementArrayBuffer, 6 * sizeof(ushort), BufferUsageHint.StaticDraw, new Data(new ushort[]
            {
                0, 1, 2, 0, 2, 3
            }));

            sampler = new Sampler();
            sampler.SetMagFilter(TextureMagFilter.Nearest);
            sampler.SetMinFilter(TextureMinFilter.Nearest);

            string shaderErrors;
            if (!VertexShader.TryCompile(VertexShaderText, out vertexShader, out shaderErrors) ||
                !FragmentShader.TryCompile(FragmentShaderText, out fragmentShader, out shaderErrors) ||
                !ShaderProgram.TryLink(glContext, new ShaderProgramDescription
                    {
                        VertexShaders = vertexShader,
                        FragmentShaders = fragmentShader,
                        VertexAttributeNames = new[] { "in_position" },
                        SamplerNames = new[] { "Image" }
                    },
                    out program, out shaderErrors))
                throw new ArgumentException("Program errors:\n\n" + shaderErrors);

            vertexArray = new VertexArray(glContext);
            vertexArray.SetElementArrayBuffer(glContext, indices);
            vertexArray.SetVertexAttributeF(glContext, 0, vertices, VertexAttributeDimension.Two, VertexAttribPointerType.Float, false, 8, 0);
        }
Esempio n. 23
0
        protected void OnLoad(object sender, EventArgs eventArgs)
        {
            VSync = VSyncMode.Off;

            // Check for necessary capabilities:
            var extensions = GL.GetString(StringName.Extensions);
            if (!GL.GetString(StringName.Extensions).Contains("GL_ARB_shading_language"))
            {
                throw new NotSupportedException(String.Format("This example requires OpenGL 2.0. Found {0}. Aborting.",
                    GL.GetString(StringName.Version).Substring(0, 3)));
            }

            if (!extensions.Contains("GL_ARB_texture_compression") ||
                 !extensions.Contains("GL_EXT_texture_compression_s3tc"))
            {
                throw new NotSupportedException("This example requires support for texture compression. Aborting.");
            }

            var temp = new int[1];
            GL.GetInteger(GetPName.MaxTextureImageUnits, out temp[0]);
            Trace.WriteLine(temp[0] + " TMU's for Fragment Shaders found. (2 required)");

            GL.GetInteger(GetPName.MaxVaryingFloats, out temp[0]);
            Trace.WriteLine(temp[0] + " varying floats between VS and FS allowed. (6 required)");

            GL.GetInteger(GetPName.MaxVertexUniformComponents, out temp[0]);
            Trace.WriteLine(temp[0] + " uniform components allowed in Vertex Shader. (6 required)");

            GL.GetInteger(GetPName.MaxFragmentUniformComponents, out temp[0]);
            Trace.WriteLine(temp[0] + " uniform components allowed in Fragment Shader. (11 required)");
            Trace.WriteLine("");

            // load textures
            TextureLoaderParameters.MagnificationFilter = TextureMagFilter.Linear;
            TextureLoaderParameters.MinificationFilter = TextureMinFilter.LinearMipmapLinear;
            TextureLoaderParameters.WrapModeS = TextureWrapMode.ClampToBorder;
            TextureLoaderParameters.WrapModeT = TextureWrapMode.ClampToBorder;
            TextureLoaderParameters.EnvMode = TextureEnvMode.Modulate;

            uint handle;
            TextureTarget target;
            ImageDDS.LoadFromDisk(TextureDiffuseHeightFilename, out handle, out target);
            _textureDiffuseHeight = TextureFactory.AquireTexture2D((int) handle);
            Trace.WriteLine("Loaded " + TextureDiffuseHeightFilename + " with handle " + handle + " as " + target);

            ImageDDS.LoadFromDisk(TextureNormalGlossFilename, out handle, out target);
            _textureNormalGloss = TextureFactory.AquireTexture2D((int) handle);
            Trace.WriteLine("Loaded " + TextureNormalGlossFilename + " with handle " + handle + " as " + target);

            Trace.WriteLine("End of Texture Loading. GL Error: " + GL.GetError());
            Trace.WriteLine("");

            // initialize buffer
            var normal = Vector3.UnitZ;
            var tangent = Vector3.UnitX;
            var vertices = new[]
            {
                new Vertex
                {
                    Position = new Vector3(-1,-1,0),
                    TexCoord = new Vector2(0,0),
                    Normal = normal,
                    Tangent = tangent
                },
                new Vertex
                {
                    Position = new Vector3(1,-1,0),
                    TexCoord = new Vector2(1,0),
                    Normal = normal,
                    Tangent = tangent
                },
                new Vertex
                {
                    Position = new Vector3(-1,1,0),
                    TexCoord = new Vector2(0,1),
                    Normal = normal,
                    Tangent = tangent
                },
                new Vertex
                {
                    Position = new Vector3(1,1,0),
                    TexCoord = new Vector2(1,1),
                    Normal = normal,
                    Tangent = tangent
                }
            };
            _buffer = new Buffer<Vertex>();
            _buffer.Init(BufferTarget.ArrayBuffer, vertices);

            // load shader
            _program = ProgramFactory.Create<ParallaxProgram>();
            _program.Use();

            // set up vertex array
            _vao = new VertexArray();
            _vao.Bind();
            // bind vertex attributes
            // the buffer layout is defined by the Vertex struct:
            //   data X Y Z NX NY NZ TX TY TZ  U  V *next vertex*
            // offset 0 4 8 12 16 20 24 28 32 36 40      44
            // having to work with offsets could be prevented by using seperate buffer objects for each attribute,
            // but that might reduce performance and can get annoying as well.
            // performance increase could also be achieved by improving coherent read access
            // by padding the struct so that each attribute begins at a multiple of 16 bytes, i.e. 4-floats
            // because the GPU can then read all 4 floats at once. I did not do that here to keep it simple.
            _vao.BindAttribute(_program.InPosition, _buffer);
            _vao.BindAttribute(_program.InNormal, _buffer, 12);
            _vao.BindAttribute(_program.InTangent, _buffer, 24);
            _vao.BindAttribute(_program.InTexCoord, _buffer, 36);

            // set camera position
            Camera.DefaultState.Position = new Vector3(0,0,3);
            Camera.ResetToDefault();

            // set state
            GL.ClearColor(0.2f, 0f, 0.4f, 0f);
            GL.PointSize(10f);
            GL.Disable(EnableCap.Dither);
            GL.FrontFace(FrontFaceDirection.Ccw);
            GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
            GL.PolygonMode(MaterialFace.Back, PolygonMode.Line);
        }
Esempio n. 24
0
        protected override void UpdateDrawable()
        {
            var minWidth = sliceX1 + tWidth - sliceX2;

            panelScaleX = (float)Width / (float)minWidth;
            if (panelScaleX > 1)
            {
                panelScaleX = 1;
            }

            var minHeight = sliceY1 + tHeight - sliceY2;

            panelScaleY = (float)Height / (float)minHeight;
            if (panelScaleY > 1)
            {
                panelScaleY = 1;
            }

            var v = new VertexArray(PrimitiveType.Quads);

            int x0, x1, x2, x3, y0, y1, y2, y3;
            int u0, u1, u2, u3, v0, v1, v2, v3;

            x0 = 0;
            y0 = 0;
            x1 = sliceX1;
            y1 = sliceY1;
            x2 = Width - (tWidth - sliceX2);
            y2 = Height - (tHeight - sliceY2);
            x3 = Width;
            y3 = Height;

            u0 = TextureLeft;
            v0 = TextureTop;
            u1 = TextureLeft + sliceX1;
            v1 = TextureTop + sliceY1;
            u2 = TextureLeft + sliceX2;
            v2 = TextureTop + sliceY2;
            u3 = TextureLeft + tWidth;
            v3 = TextureTop + tHeight;

            if (panelScaleX < 1)
            {
                x1 = (int)Math.Round(x1 * panelScaleX);
                x2 = x1;
            }
            if (panelScaleY < 1)
            {
                y1 = (int)Math.Round(y1 * panelScaleY);
                y2 = y1;
            }

            int tileX = sliceX2 - sliceX1;
            int tileY = sliceY2 - sliceY1;

            if (PanelType == PanelType.Stretch)
            {
                //top
                DrawQuad(v, x1, y0, x2, y1, u1, v0, u2, v1);

                //left
                DrawQuad(v, x0, y1, x1, y2, u0, v1, u1, v2);

                //right
                DrawQuad(v, x2, y1, x3, y2, u2, v1, u3, v2);

                //bottom
                DrawQuad(v, x1, y2, x2, y3, u1, v2, u2, v3);

                //middle
                DrawQuad(v, x1, y1, x2, y2, u1, v1, u2, v2);
            }
            else
            {
                for (int xx = x1; xx < x2; xx += tileX)
                {
                    for (int yy = y1; yy < y2; yy += tileY)
                    {
                        //middle
                        DrawQuad(v, xx, yy, xx + tileX, yy + tileY, u1, v1, u2, v2);
                    }
                }

                for (int yy = y1; yy < y2; yy += tileY)
                {
                    //left
                    DrawQuad(v, x0, yy, x1, yy + tileY, u0, v1, u1, v2);

                    //right
                    DrawQuad(v, x2, yy, x3, yy + tileY, u2, v1, u3, v2);
                }

                for (int xx = x1; xx < x2; xx += tileX)
                {
                    //top
                    DrawQuad(v, xx, y0, xx + tileX, y1, u1, v0, u2, v1);

                    //bottom
                    DrawQuad(v, xx, y2, xx + tileX, y3, u1, v2, u2, v3);
                }
            }

            //top left
            DrawQuad(v, x0, y0, x1, y1, u0, v0, u1, v1);

            //top right
            DrawQuad(v, x2, y0, x3, y1, u2, v0, u3, v1);

            //bottom left
            DrawQuad(v, x0, y2, x1, y3, u0, v2, u1, v3);

            //bottom right
            DrawQuad(v, x2, y2, x3, y3, u2, v2, u3, v3);

            SFMLVertices = v;
        }
Esempio n. 25
0
 public void Dispose()
 {
     VertexArray.Dispose();
     ElementArray.Dispose();
 }
		/// <summary>
		/// Link an array buffer to an attribute of this vertex array.
		/// </summary>
		/// <param name="arrayBuffer">
		/// A <see cref="ArrayBufferObjectBase"/> that specify the contents of the array.
		/// </param>
		/// <param name="sectionIndex">
		/// A <see cref="UInt32"/> that specify the <paramref name="arrayBuffer"/> sub-array index.
		/// </param>
		/// <param name="attributeName">
		/// A <see cref="String"/> that specify the name of the attribute variable.
		/// </param>
		/// <param name="blockName">
		/// A <see cref="String"/> that specify the name of the attribute block encolosing <paramref name="semantic"/>. It
		/// can be null.
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// Exception thrown if <paramref name="arrayBuffer"/> is null.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// Exception throw if <paramref name="arrayBuffer"/> has no items.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// Exception thrown if <paramref name="sectionIndex"/> specify an invalid section of <paramref name="arrayBuffer"/>.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// Exception thrown if <paramref name="semantic"/> is null or is not a valid input name.
		/// </exception>
		public void SetArray(ArrayBufferObjectBase arrayBuffer, uint sectionIndex, string attributeName, string blockName)
		{
			if (String.IsNullOrEmpty(attributeName))
				throw new ArgumentException("invalid name", "attributeName");

			VertexArray vertexArray, previousVertexArray;

			// Dispose previous vertex array
			if (_VertexArrays.TryGetValue(attributeName, out previousVertexArray))
				previousVertexArray.Dispose();
			// Map buffer object with attribute name
			_VertexArrays[attributeName] = vertexArray = new VertexArray(arrayBuffer, sectionIndex);

			// Map buffer object with input name including block name also
			if (blockName != null) {
				// Attribute referenced in block
				attributeName = String.Format("{0}.{1}", blockName, attributeName);

				// Dispose previous vertex array
				if (_VertexArrays.TryGetValue(attributeName, out previousVertexArray))
					previousVertexArray.Dispose();
				// Map buffer object with attribute name
				_VertexArrays[attributeName] = vertexArray;
			}

			// Compute the actual vertex array length
			UpdateVertexArrayLength();
			// Update vertex arrays
			_VertexArrayDirty = true;
		}
Esempio n. 27
0
        public WndAppearance(BaseObject obj, Vector2f pos)
            : base(obj, WndWidth, pos)
        {
            var wrapper = new ColorWrapper(() => obj.Color);

            var renderImg = new Image(WndWidth, SqSize + 2 * Margin, BackColor);

            var selector = new Canvas();

            selector.SizeLayout = new Layout2d(renderImg.Size.X, renderImg.Size.Y);
            selector.Clear(BackColor);

            Add(selector);

            Color  oldColor   = default;
            IntPtr oldPointer = default;

            var userChanging = false;

            var previewRect    = new VertexArray(PrimitiveType.Quads, 4);
            var previewOutline = new VertexArray(PrimitiveType.LineStrip, 5);

            Vector2f[] previewCorners =
            {
                new Vector2f(Margin + PreviewOffset,                Margin),
                new Vector2f(Margin + PreviewOffset + PreviewWidth, Margin),
                new Vector2f(Margin + PreviewOffset + PreviewWidth, Margin + SqSize),
                new Vector2f(Margin + PreviewOffset,                Margin + SqSize),
            };

            var hueSelector = new RectangleShape(new Vector2f(HueWidth, 4))
            {
                OutlineColor = SelectorOutline, OutlineThickness = 2f, FillColor = Color.Transparent,
                Origin       = new Vector2f(HueWidth / 2, 2)
            };

            var colorSelector = new RectangleShape(new Vector2f(8, 8))
            {
                OutlineColor = SelectorOutline, OutlineThickness = 2f, FillColor = Color.Transparent,
                Origin       = new Vector2f(4, 4)
            };

            wrapper.ValueChanged += delegate { UpdateSelector(); };

            void DrawSelector()
            {
                var tex = selector.RenderTexture();

                if (tex == null)
                {
                    return;
                }

                oldPointer = tex.CPointer;

                oldColor = wrapper.Value;

                const float fac = 1f / SqSize;

                selector.Clear(BackColor);

                for (uint y = 0; y < renderImg.Size.Y; y++)
                {
                    for (uint x = 0; x < renderImg.Size.X; x++)
                    {
                        renderImg.SetPixel(x, y, BackColor);
                    }
                }

                renderImg.Copy(HueImg, Margin, Margin);

                var hue = wrapper.H;

                for (uint y = 0; y < SqSize; y++)
                {
                    var v = y * fac;

                    for (uint x = 0; x < SqSize; x++)
                    {
                        var s = x * fac;

                        renderImg.SetPixel(Margin + Offset + x, Margin + y, new Hsva(hue, s, 1 - v, 1));
                    }
                }

                tex.Texture.Update(renderImg);

                hueSelector.Position = new Vector2f(
                    Margin + HueWidth / 2,
                    Margin + (float)((360 - wrapper.H) / HueFac));
                tex.Draw(hueSelector);

                colorSelector.Position = new Vector2f(
                    (float)(Margin + Offset + wrapper.S * SqSize),
                    (float)(Margin + wrapper.V * SqSize));
                tex.Draw(colorSelector);

                var col = wrapper.Value;

                previewRect[0] = new Vertex(previewCorners[0], col);
                previewRect[1] = new Vertex(previewCorners[1], col);
                previewRect[2] = new Vertex(previewCorners[2], col);
                previewRect[3] = new Vertex(previewCorners[3], col);
                tex.Draw(previewRect);

                col.A             = 255;
                previewOutline[0] = new Vertex(previewCorners[0], col);
                previewOutline[1] = new Vertex(previewCorners[1], col);
                previewOutline[2] = new Vertex(previewCorners[2], col);
                previewOutline[3] = new Vertex(previewCorners[3], col);
                previewOutline[4] = new Vertex(previewCorners[0], col);
                tex.Draw(previewOutline);
            }

            void UpdateSelector()
            {
                if (userChanging)
                {
                    return;
                }

                if (Mouse.IsButtonPressed(Mouse.Button.Left))
                {
                    userChanging = true;

                    var mpos = Mouse.GetPosition(Render.Window).F() - AbsolutePosition -
                               new Vector2f(0, Renderer.TitleBarHeight);
                    if (selector.MouseOnWidget(mpos))
                    {
                        var(x, y) = (mpos - selector.Position).I();
                        x        -= Margin;
                        y        -= Margin;
                        if (x >= 0 && x <= TotalSize && y >= 0 && y < 140)
                        {
                            if (x <= HueWidth)
                            {
                                wrapper.H = y * HueFac;
                            }
                            else if (x >= Offset)
                            {
                                wrapper.Value = new Color(renderImg.GetPixel(Margin + (uint)x, Margin + (uint)y))
                                {
                                    A = wrapper.A
                                }
                            }
                            ;
                        }
                    }

                    userChanging = false;
                }

                if (wrapper.Value != oldColor || selector.RenderTexture()?.CPointer != oldPointer)
                {
                    DrawSelector();
                }
            }

            Ui.Drawn += UpdateSelector;

            Closed += delegate { Ui.Drawn -= UpdateSelector; };

            Add(new NumberField <double>(0, 360, () => wrapper.H, unit: "°", inline: true, round: 0));
            Add(new NumberField <double>(0, 100, () => wrapper.S, unit: "%",
                                         factor: 100, inline: true, round: 0));
            Add(new NumberField <double>(0, 100, () => wrapper.V, unit: "%",
                                         factor: 100, inline: true, round: 0));

            Add(new NumberField <double>(0, 100, () => wrapper.Ad, unit: "%",
                                         factor: 100, inline: true, round: 0));

            Add(new NumberField <byte>(0, 255, () => wrapper.R, deci: false, inline: true));
            Add(new NumberField <byte>(0, 255, () => wrapper.G, deci: false, inline: true));
            Add(new NumberField <byte>(0, 255, () => wrapper.B, deci: false, inline: true));

            var btnRandom = new BitmapButton(L["Random color"])
            {
                Image = new Texture("icons/small/random.png")
            };

            btnRandom.Clicked += delegate
            {
                wrapper.Value = new Color(Palette.Default.ColorRange.RandomColor())
                {
                    A = wrapper.A
                };
            };

            Add(btnRandom);

            if (obj is PhysicalObject phy)
            {
                Add(new NumberField <float>(30, 2000, () => phy.ColorFilterWidth, log: true)
                {
                    RightValue = float.PositiveInfinity
                });

                var absorbanceImg = new Image(WndWidth, AbsorbHeight + 2 * Margin, BackColor);

                var absorbance = new Canvas();
                absorbance.SizeLayout = new Layout2d(absorbanceImg.Size.X, absorbanceImg.Size.Y);
                absorbance.Clear(BackColor);

                var txtA = new Text("A", Ui.FontMono, AbsorbTextSize)
                {
                    FillColor = Color.White, Scale = new Vector2f(1, -1)
                }.CenterOriginText();
                var txtH = new Text("H", Ui.FontMono, AbsorbTextSize)
                {
                    FillColor = Color.White, Scale = new Vector2f(1, -1)
                }.CenterOriginText();

                Add(absorbance);

                IntPtr oldPointerAbs = default;

                var oldCol   = new Hsva(-1, -1, -1, -1);
                var oldWidth = -1f;

                void DrawAbsorbance()
                {
                    var tex = absorbance.RenderTexture();

                    if (tex == null)
                    {
                        return;
                    }

                    oldCol        = wrapper.ValueHsv;
                    oldWidth      = phy.ColorFilterWidth;
                    oldPointerAbs = tex.CPointer;

                    absorbance.Clear(BackColor);

                    absorbanceImg.Copy(HueImgHoriz, Margin + AbsorbTextSize, Margin + AbsorbTextSize);

                    var hsva   = phy.ColorHsva;
                    var objHue = hsva.H;
                    var objSat = hsva.S;
                    var alphaD = 1 - hsva.A;

                    for (uint x = 0; x < HueWidthHoriz; x++)
                    {
                        var transmittance = (int)((1 - alphaD * Transmittance(x * HueFacHoriz, objHue, phy.ColorFilterWidth, objSat)) *
                                                  HueHeightHoriz) + 1;
                        for (uint y = 0; y < transmittance; y++)
                        {
                            absorbanceImg.SetPixel(Margin + AbsorbTextSize + x, Margin + AbsorbTextSize + y, BackColor);
                        }
                    }

                    tex.Texture.Update(absorbanceImg);

                    var hx = (float)(Margin + AbsorbTextSize + objHue / HueFacHoriz);
                    var ay = (float)(Margin - 1 + alphaD * HueHeightHoriz);

                    tex.Draw(new[]
                    {
                        new Vertex(new Vector2f(hx, Margin), Color.White),
                        new Vertex(new Vector2f(hx, Margin + HueHeightHoriz + 2), Color.White),

                        new Vertex(new Vector2f(Margin, ay), Color.White),
                        new Vertex(new Vector2f(WndWidth - Margin, ay), Color.White),
                    }, PrimitiveType.Lines);

                    txtA.Position = new Vector2f(Margin + AbsorbTextSize / 2, ay + AbsorbTextSize);
                    tex.Draw(txtA);
                    txtH.Position = new Vector2f(hx, AbsorbHeight - Margin + AbsorbTextSize / 2);
                    tex.Draw(txtH);
                }

                void UpdateAbsorbance()
                {
                    if (wrapper.ValueHsv != oldCol || phy.ColorFilterWidth != oldWidth ||
                        absorbance.RenderTexture()?.CPointer != oldPointerAbs)
                    {
                        DrawAbsorbance();
                    }
                }

                Ui.Drawn += UpdateAbsorbance;

                Closed += delegate { Ui.Drawn -= UpdateAbsorbance; };

                Add(new CheckField(() => phy.Appearance.Borders, onChanged: () => { phy.UpdateOutline(); }));
                Add(new CheckField(() => phy.Appearance.OpaqueBorders, onChanged: () => { phy.UpdateOutline(); }));

                if (phy is Circle circle)
                {
                    Add(new CheckField(() => circle.Appearance.DrawCircleCakes));
                    Add(new CheckField(() => circle.Appearance.Protractor));
                }

                if (phy is Box box)
                {
                    Add(new CheckField(() => box.Appearance.Ruler));
                }
            }

            Show();
        }
    }