openTK c#roatating cube示例

时间:2012-02-13 14:10:14

标签: c# opengl opentk

我正在使用C#(visual studio 2008)开发老虎机, 使用OpenTK在我的项目中使用openGL 我们已经完成了基本功能,但是我们无法获得一个代码来绘制可以旋转的立方体。

这个人需要旋转一段时间,但我无法弄清楚该怎么做。

我们尝试了这个Cube

但我们想在表单上绘制

2 个答案:

答案 0 :(得分:3)

OpenTK提供了一个名为GLControl的Windows窗体控件。它没有内置的主循环,但是如果你按照this GLControl tutorial进行连续渲染来处理控件就不那么难了。

一旦连续渲染工作,您可以移动代码以渲染立方体,它将在表单上不断旋转。

答案 1 :(得分:0)

以下是使用 OpenTK 在 C# 中旋转立方体的示例:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

// adapted from : dreamstatecoding.blogspot.com

namespace RotatingCube
{
    public struct Vertex
    {
        public const int Size = (4 + 4) * 4; // size of struct in bytes

        private readonly Vector4 _position;
        private readonly Color4 _color;

        public Vertex(Vector4 position, Color4 color)
        {
            _position = position;
            _color = color;
        }
    }

    public sealed class MainWindow : GameWindow
    {
        private readonly string _title;
        private int _width;
        private int _height;

        private int _program;
        private double _time;
        private bool _initialized;
        private int _vertexArray;
        private int _buffer;
        private int _verticeCount;

        private Matrix4 _model;
        private Matrix4 _view;
        private Matrix4 _projection;
        private float _FOV = 45.0f;

        private float _lastTimestamp = Stopwatch.GetTimestamp();
        private float _freq = Stopwatch.Frequency;

        private float _angle;

        public MainWindow()
            : base(750, // initial width
                500, // initial height
                GraphicsMode.Default,
                "",  // initial title
                GameWindowFlags.Default,
                DisplayDevice.Default,
                3, // OpenGL major version
                3, // OpenGL minor version
                GraphicsContextFlags.ForwardCompatible)
        {
            _width = 750;
            _height = 500;
            _title += "Spinning Cube, OpenGL Version: " + GL.GetString(StringName.Version);
        }


        protected override void OnLoad(EventArgs e)
        {

            _model =  Matrix4.Identity;
            Vertex[] vertices =
            {
                new Vertex(new Vector4(-0.5f, -0.5f, -0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4( 0.5f, -0.5f, -0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4( 0.5f,  0.5f, -0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4( 0.5f,  0.5f, -0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4(-0.5f,  0.5f, -0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4(-0.5f, -0.5f, -0.5f,  1.0f), Color4.Blue),

                new Vertex(new Vector4(-0.5f, -0.5f,  0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4( 0.5f, -0.5f,  0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4( 0.5f,  0.5f,  0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4( 0.5f,  0.5f,  0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4(-0.5f,  0.5f,  0.5f,  1.0f), Color4.Blue),
                new Vertex(new Vector4(-0.5f, -0.5f,  0.5f,  1.0f), Color4.Blue),

                new Vertex(new Vector4(-0.5f,  0.5f,  0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4(-0.5f,  0.5f, -0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4(-0.5f, -0.5f, -0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4(-0.5f, -0.5f, -0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4(-0.5f, -0.5f,  0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4(-0.5f,  0.5f,  0.5f,  1.0f), Color4.Red),

                new Vertex(new Vector4( 0.5f,  0.5f,  0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4( 0.5f,  0.5f, -0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4( 0.5f, -0.5f, -0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4( 0.5f, -0.5f, -0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4( 0.5f, -0.5f,  0.5f,  1.0f), Color4.Red),
                new Vertex(new Vector4( 0.5f,  0.5f,  0.5f,  1.0f), Color4.Red),

                new Vertex(new Vector4(-0.5f, -0.5f, -0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4( 0.5f, -0.5f, -0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4( 0.5f, -0.5f,  0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4( 0.5f, -0.5f,  0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4(-0.5f, -0.5f,  0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4(-0.5f, -0.5f, -0.5f,  1.0f), Color4.Green),

                new Vertex(new Vector4(-0.5f,  0.5f, -0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4( 0.5f,  0.5f, -0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4( 0.5f,  0.5f,  0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4( 0.5f,  0.5f,  0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4(-0.5f,  0.5f,  0.5f,  1.0f), Color4.Green),
                new Vertex(new Vector4(-0.5f,  0.5f, -0.5f,  1.0f), Color4.Green),
            };

            _verticeCount = vertices.Length;
            _vertexArray = GL.GenVertexArray();
            _buffer = GL.GenBuffer();

            GL.BindVertexArray(_vertexArray);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexArray);

            // create first buffer: vertex
            GL.NamedBufferStorage(
                _buffer,
                Vertex.Size*vertices.Length,        // the size needed by this buffer
                vertices,                           // data to initialize with
                BufferStorageFlags.MapWriteBit);    // at this point we will only write to the buffer


            GL.VertexArrayAttribBinding(_vertexArray, 0, 0);
            GL.EnableVertexArrayAttrib(_vertexArray, 0);
            GL.VertexArrayAttribFormat(
                _vertexArray,
                0,                      // attribute index, from the shader location = 0
                4,                      // size of attribute, vec4
                VertexAttribType.Float, // contains floats
                false,                  // does not need to be normalized as it is already, floats ignore this flag anyway
                0);                     // relative offset, first item


            GL.VertexArrayAttribBinding(_vertexArray, 1, 0);
            GL.EnableVertexArrayAttrib(_vertexArray, 1);
            GL.VertexArrayAttribFormat(
                _vertexArray,
                1,                      // attribute index, from the shader location = 1
                4,                      // size of attribute, vec4
                VertexAttribType.Float, // contains floats
                false,                  // does not need to be normalized as it is already, floats ignore this flag anyway
                16);                     // relative offset after a vec4

            // link the vertex array and buffer and provide the stride as size of Vertex
            GL.VertexArrayVertexBuffer(_vertexArray, 0, _buffer, IntPtr.Zero, Vertex.Size);
            _initialized = true;

            CursorVisible = true;

            try
            {
                _program = GL.CreateProgram();
                var shaders = new List<int>();
                ShaderType type = ShaderType.VertexShader;
                var shader = GL.CreateShader(type);
                string src = @"#version 330 core
                                layout (location = 0) in vec4 position;
                                layout(location = 1) in vec4 color;
                                out vec4 vs_color;

                                out vec3 original_normal;
                                out vec3 transformed_normal;

                                uniform mat4 model;
                                uniform mat4 view;
                                uniform mat4 projection;

                                void main(void)
                                {
                                gl_Position = projection * view * model * position;
                                vs_color = color;
                                original_normal = vec3(color);
                                mat3 normal_matrix = transpose(inverse(mat3(view * model)));
                                transformed_normal = normal_matrix * original_normal;
                            }";
                GL.ShaderSource(shader, src);
                GL.CompileShader(shader);
                var info = GL.GetShaderInfoLog(shader);
                if (!string.IsNullOrWhiteSpace(info))
                    throw new Exception($"CompileShader {type} had errors: {info}");

                shaders.Add(shader);

                type = ShaderType.FragmentShader;
                shader = GL.CreateShader(type);
                src = @"#version 330 core
                        in vec4 vs_color;
                        in vec3 original_normal;
                        in vec3 transformed_normal;
                        out vec4 color;

                        void main(void)
                        {
                            float lighting = abs(dot(transformed_normal, vec3(0,0,-1)));
                            color = vs_color * lighting;
                        }";
                GL.ShaderSource(shader, src);
                GL.CompileShader(shader);
                info = GL.GetShaderInfoLog(shader);
                if (!string.IsNullOrWhiteSpace(info))
                    throw new Exception($"CompileShader {type} had errors: {info}");

                shaders.Add(shader);

                foreach (var shader_ in shaders)
                    GL.AttachShader(_program, shader_);
                GL.LinkProgram(_program);
                var info_ = GL.GetProgramInfoLog(_program);
                if (!string.IsNullOrWhiteSpace(info_))
                    throw new Exception($"CompileShaders ProgramLinking had errors: {info}");

                foreach (var shader_ in shaders)
                {
                    GL.DetachShader(_program, shader_);
                    GL.DeleteShader(shader_);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                throw;
            }

            GL.Enable(EnableCap.DepthTest);
            GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
            GL.PatchParameter(PatchParameterInt.PatchVertices, 3);
            Closed += OnClosed;
        }
        
        private void OnClosed(object sender, EventArgs eventArgs)
        {
            Exit();
        }

        public override void Exit()
        {
            Debug.WriteLine("Exit called");
            GL.DeleteVertexArray(_vertexArray);
            GL.DeleteBuffer(_buffer);
            GL.DeleteProgram(_program);
            base.Exit();
        }

        protected override void OnResize(EventArgs e)
        {
            // Resize the viewport to match the window size.
            GL.Viewport(0, 0, Width, Height);
            base.OnResize(e);
        }

private float[] Matrix4ToArray(Matrix4 matrix)
{
    float[] data = new float[16];
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            data[i*4+j] = matrix[i, j];

        }
    }
    return data;
}

        private void PrintMatrix(Matrix4 matrix)
        {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    Console.WriteLine(matrix[i,j]);

                }
            }
        }

        protected override void OnRenderFrame(FrameEventArgs e)
        {

            var timeStamp = Stopwatch.GetTimestamp();
            _angle += (float)((timeStamp - _lastTimestamp) / (double)_freq);
            _lastTimestamp = timeStamp;

            GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            // Clear the color buffer.
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // Bind the VBO
            GL.BindBuffer(BufferTarget.ArrayBuffer, _buffer);
            // Bind the VAO
            GL.BindVertexArray(_vertexArray);
            // Use/Bind the program
            GL.UseProgram(_program);

            _model = Matrix4.CreateFromAxisAngle(new Vector3(1.0f, 0.0f, 1.0f), _angle);
            _view = Matrix4.LookAt(new Vector3(0.0f,0.0f,5.0f), new Vector3(0.0f,0.0f,0.0f), Vector3.UnitY);
            _projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI * (_FOV/180f), _width / (float)_height, 0.2f, 256.0f);
            
            int location = GL.GetUniformLocation(_program, "model");
            GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_model));
            location = GL.GetUniformLocation(_program, "view");
            GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_view));
            location = GL.GetUniformLocation(_program, "projection");
            GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_projection));

            // This draws the triangle.
            GL.DrawArrays(PrimitiveType.Triangles, 0, _verticeCount);

            // Swap the front/back buffers so what we just rendered to the back buffer is displayed in the window.
            Context.SwapBuffers();
            base.OnRenderFrame(e);
        }

        [STAThread]
        static void Main()
        {
            new MainWindow().Run(60);
        }
        
    }

}

结果:

rotating cube