微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从GameWindow到GLControl模型会失真

如何解决从GameWindow到GLControl模型会失真

我正在尝试使用OpenTK包装器在OpenGL中渲染一些.obj模型。我使用的是GameWindow,效果很好,但我想添加一些按钮以能够编辑一些变量。做到这一点的方法是使用GLControl库。问题是,当我从GameWindow切换到GLControl时,我的.obj完全失真,而代码几乎相同。 看起来就是这样,左边是从GameWindow,右边是从glControl

enter image description here

Form1.cs

public partial class Form1 : Form
{
    private MyApplication app;

    public Form1()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        glControl.Resize += new EventHandler(GlControl_Resize);
        glControl.Paint += new PaintEventHandler(GlControl_Paint);

        Text =
            GL.GetString(StringName.vendor) + " " +
            GL.GetString(StringName.Renderer) + " " +
            GL.GetString(StringName.Version);

        GL.ClearColor(Color.Black);
        GL.Enable(EnableCap.DepthTest);

        Application.Idle += Application_Idle;

        // Ensure that the viewport and projection matrix are set correctly.
        GlControl_Resize(glControl,EventArgs.Empty);

        app = new MyApplication
        {
            width = Width,height = Height
        };
        app.Init();
    }

    protected override void OnClosing(CancelEventArgs e)
    {
        Application.Idle -= Application_Idle;

        base.OnClosing(e);
    }

    void Application_Idle(object sender,EventArgs e)
    {
        while (glControl.IsIdle)
        {
            Render();
        }
    }

    void GlControl_Resize(object sender,EventArgs e)
    {
        GLControl c = sender as GLControl;

        if (c.ClientSize.Height == 0)
            c.ClientSize = new Size(c.ClientSize.Width,1);

        GL.Viewport(0,c.ClientSize.Width,c.ClientSize.Height);

        float aspect_ratio = Width / (float)Height;
        Matrix4 perpective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4,aspect_ratio,1,64);
        GL.MatrixMode(MatrixMode.Projection);
        GL.LoadMatrix(ref perpective);
    }

    void GlControl_Paint(object sender,PaintEventArgs e)
    {
        Render();
    }

    private void Render()
    {
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        app.RenderGL();
        glControl.SwapBuffers();
    }

    /// <summary>
    /// Entry point of this example.
    /// </summary>
    [STAThread]
    public static void Main()
    {
        using (Form1 example = new Form1())
        {
            example.Text = "OpenTK";
            example.ShowDialog();
        }
    }
}

Form1.Designer.cs

partial class Form1
{
    /// <summary>
    /// required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise,false.</param>
    protected override void dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.dispose();
        }
        base.dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.glControl = new OpenTK.GLControl();
        this.SuspendLayout();
        // 
        // glControl
        // 
        this.glControl.BackColor = System.Drawing.Color.Black;
        this.glControl.Dock = System.Windows.Forms.DockStyle.Fill;
        this.glControl.Location = new System.Drawing.Point(0,0);
        this.glControl.Name = "glControl";
        this.glControl.Size = new System.Drawing.Size(800,600);
        this.glControl.TabIndex = 0;
        this.glControl.VSync = false;
        // 
        // W02_Immediate_Mode_Cube
        // 
        this.AutoScaleDimensions = new System.Drawing.Sizef(6F,13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(800,600);
        this.Controls.Add(this.glControl);
        this.Name = "W02_Immediate_Mode_Cube";
        this.Text = "Cube";
        this.ResumeLayout(false);

    }

    #endregion

    private OpenTK.GLControl glControl;
}

Mesh.cs

public class Mesh
{
    // data members
    public ObjVertex[] vertices;            // vertex positions,model space
    public ObjTriangle[] triangles;         // triangles (3 vertex indices)
    int vertexBufferId;                     // vertex buffer
    int triangleBufferId;                   // triangle buffer

    // constructor
    public Mesh(string fileName)
    {
        MeshLoader loader = new MeshLoader();
        loader.Load(this,fileName);
    }

    // initialization; called during first render
    public void Prepare()
    {
        if (vertexBufferId == 0)
        {
            // generate interleaved vertex data (uv/normal/position (total 8 floats) per vertex)
            GL.GenBuffers(1,out vertexBufferId);
            GL.BindBuffer(BufferTarget.ArrayBuffer,vertexBufferId);
            GL.BufferData(BufferTarget.ArrayBuffer,(IntPtr)(vertices.Length * Marshal.SizeOf(typeof(ObjVertex))),vertices,BufferUsageHint.StaticDraw);

            // generate triangle index array
            GL.GenBuffers(1,out triangleBufferId);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer,triangleBufferId);
            GL.BufferData(BufferTarget.ElementArrayBuffer,(IntPtr)(triangles.Length * Marshal.SizeOf(typeof(ObjTriangle))),triangles,BufferUsageHint.StaticDraw);
        }
    }

    // render the mesh using the supplied shader and matrix
    public void Render(Shader shader,Matrix4 transform,Texture texture)
    {
        // on first run,prepare buffers
        Prepare();

        // safety dance
        GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);

        // enable texture
        int texLoc = GL.GetUniformlocation(shader.programID,"pixels");
        GL.Uniform1(texLoc,0);
        GL.ActiveTexture(TextureUnit.Texture0);
        GL.BindTexture(TextureTarget.Texture2D,texture.id);

        // enable shader
        GL.UseProgram(shader.programID);

        // pass transform to vertex shader
        GL.UniformMatrix4(shader.uniform_mview,false,ref transform);

        // enable position,normal and uv attributes
        GL.EnabLevertexAttribArray(shader.attribute_vpos);
        GL.EnabLevertexAttribArray(shader.attribute_vnrm);
        GL.EnabLevertexAttribArray(shader.attribute_vuvs);

        // bind interleaved vertex data
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer,vertexBufferId);
        GL.InterleavedArrays(InterleavedArrayFormat.T2fN3fV3f,Marshal.SizeOf(typeof(ObjVertex)),IntPtr.Zero);

        // link vertex attributes to shader parameters 
        GL.VertexAttribPointer(shader.attribute_vuvs,2,VertexAttribPointerType.Float,32,0);
        GL.VertexAttribPointer(shader.attribute_vnrm,3,true,2 * 4);
        GL.VertexAttribPointer(shader.attribute_vpos,5 * 4);

        // bind triangle index data and render
        GL.BindBuffer(BufferTarget.ElementArrayBuffer,triangleBufferId);
        GL.DrawArrays(PrimitiveType.Triangles,triangles.Length * 3);

        // restore prevIoUs OpenGL state
        GL.UseProgram(0);
        GL.PopClientAttrib();
    }

    // layout of a single vertex
    [StructLayout(LayoutKind.Sequential)]
    public struct ObjVertex
    {
        public Vector2 TexCoord;
        public Vector3 normal;
        public Vector3 Vertex;
    }

    // layout of a single triangle
    [StructLayout(LayoutKind.Sequential)]
    public struct ObjTriangle
    {
        public int Index0,Index1,Index2;
    }
}

meshLoader.cs

public class MeshLoader
{
    public bool Load(Mesh mesh,string fileName)
    {
        try
        {
            using (StreamReader streamReader = new StreamReader(fileName))
            {
                Load(mesh,streamReader);
                streamReader.Close();
                return true;
            }
        }
        catch { return false; }
    }

    char[] splitCharacters = new char[] { ' ' };

    List<Vector3> vertices;
    List<Vector3> normals;
    List<Vector2> texCoords;
    List<Mesh.ObjVertex> objVertices;
    List<Mesh.ObjTriangle> objTriangles;

    void Load(Mesh mesh,TextReader textReader)
    {
        vertices = new List<Vector3>();
        normals = new List<Vector3>();
        texCoords = new List<Vector2>();
        objVertices = new List<Mesh.ObjVertex>();
        objTriangles = new List<Mesh.ObjTriangle>();
        string line;
        while ((line = textReader.ReadLine()) != null)
        {
            line = line.Trim(splitCharacters);
            line = line.Replace("  "," ");
            string[] parameters = line.Split(splitCharacters);
            switch (parameters[0])
            {
                case "p": // point
                    break;
                case "v": // vertex
                    float x = float.Parse(parameters[1]);
                    float y = float.Parse(parameters[2]);
                    float z = float.Parse(parameters[3]);
                    vertices.Add(new Vector3(x,y,z));
                    break;
                case "vt": // texCoord
                    float u = float.Parse(parameters[1]);
                    float v = float.Parse(parameters[2]);
                    texCoords.Add(new Vector2(u,v));
                    break;
                case "vn": // normal
                    float nx = float.Parse(parameters[1]);
                    float ny = float.Parse(parameters[2]);
                    float nz = float.Parse(parameters[3]);
                    normals.Add(new Vector3(nx,ny,nz));
                    break;
                case "f":
                    switch (parameters.Length)
                    {
                        case 4:
                            Mesh.ObjTriangle objTriangle = new Mesh.ObjTriangle();
                            objTriangle.Index0 = ParseFaceParameter(parameters[1]);
                            objTriangle.Index1 = ParseFaceParameter(parameters[2]);
                            objTriangle.Index2 = ParseFaceParameter(parameters[3]);
                            objTriangles.Add(objTriangle);
                            break;
                    }
                    break;
            }
        }
        mesh.vertices = objVertices.ToArray();
        mesh.triangles = objTriangles.ToArray();
        vertices = null;
        normals = null;
        texCoords = null;
        objVertices = null;
        objTriangles = null;
    }

    char[] faceParamaterSplitter = new char[] { '/' };
    int ParseFaceParameter(string faceParameter)
    {
        Vector3 vertex = new Vector3();
        Vector2 texCoord = new Vector2();
        Vector3 normal = new Vector3();
        string[] parameters = faceParameter.Split(faceParamaterSplitter);
        int vertexIndex = int.Parse(parameters[0]);
        if (vertexIndex < 0) vertexIndex = vertices.Count + vertexIndex;
        else vertexIndex = vertexIndex - 1;
        vertex = vertices[vertexIndex];
        if (parameters.Length > 1) if (parameters[1] != "")
            {
                int texCoordindex = int.Parse(parameters[1]);
                if (texCoordindex < 0) texCoordindex = texCoords.Count + texCoordindex;
                else texCoordindex = texCoordindex - 1;
                texCoord = texCoords[texCoordindex];
            }
        if (parameters.Length > 2)
        {
            int normalIndex = int.Parse(parameters[2]);
            if (normalIndex < 0) normalIndex = normals.Count + normalIndex;
            else normalIndex = normalIndex - 1;
            normal = normals[normalIndex];
        }
        return AddobjVertex(ref vertex,ref texCoord,ref normal);
    }

    int AddobjVertex(ref Vector3 vertex,ref Vector2 texCoord,ref Vector3 normal)
    {
        Mesh.ObjVertex newObjVertex = new Mesh.ObjVertex();
        newObjVertex.Vertex = vertex;
        newObjVertex.TexCoord = texCoord;
        newObjVertex.normal = normal;
        objVertices.Add(newObjVertex);
        return objVertices.Count - 1;
    }
}

MyApplication.cs

public class MyApplication
{
    Mesh mesh;
    Shader shader;
    Texture wood;
    public int width;
    public int height;

    // initialize
    public void Init()
    {
        // load teapot
        mesh = new Mesh("../../assets/teapot.obj");
        // create shaders
        shader = new Shader("../../shaders/vs.glsl","../../shaders/fs.glsl");
        // load a texture
        wood = new Texture("../../assets/wood.jpg");
    }

    // tick for OpenGL rendering code
    public void RenderGL()
    {
        // prepare matrix for vertex shader
        Matrix4 Tview = Matrix4.CreatePerspectiveFieldOfView(1.2f,width / (float)height,.1f,1000);

        // render scene
        mesh.Render(shader,Tview,wood);
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。