如何解决从GameWindow到GLControl模型会失真
我正在尝试使用OpenTK包装器在OpenGL中渲染一些.obj模型。我使用的是GameWindow,效果很好,但我想添加一些按钮以能够编辑一些变量。做到这一点的方法是使用GLControl库。问题是,当我从GameWindow切换到GLControl时,我的.obj完全失真,而代码几乎相同。 看起来就是这样,左边是从GameWindow,右边是从glControl 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 举报,一经查实,本站将立刻删除。