阅读这篇以前,推荐阅读本专栏之前的内容,之前做过的解释这里不再赘述,专栏目录链接。这里直接上代码并展示最终的效果。
代码如下:
- 创建主程序中的类
using OpenTK.Mathematics;
using OpenTK.Windowing.Desktop;
namespace OpenTK_SelfMadeBasis
{
class Program
{
static void Main(string[] args)
{
NativeWindowSettings nativeWindowSettings = new NativeWindowSettings()
{
Size = new Vector2i(800, 600),
Title = "Draw Single Line",
};
using (Window window = new Window(GameWindowSettings.Default, nativeWindowSettings))
{
window.Run();
}
}
}
}
- 构建主程序中调用的
GUI
窗口界面的类
using OpenTK_SelfMadeBasis.Common;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.GraphicsLibraryFramework;
using OpenTK.Windowing.Desktop;
namespace OpenTK_SelfMadeBasis
{
public class Window : GameWindow
{
// 设定线段的两个端点坐标
private readonly float[] _vertices =
{
-0.5f, -0.5f, 0.0f, // 左边端点
0.5f, -0.5f, 0.0f, // 右边端点
};
private int _vertexBufferObject;
private int _vertexArrayObject;
private Shader _shader;
public Window(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings)
: base(gameWindowSettings, nativeWindowSettings)
{
}
protected override void onl oad()
{
GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
_vertexBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw);
_vertexArrayObject = GL.GenVertexArray();
GL.BindVertexArray(_vertexArrayObject);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);
GL.EnableVertexAttribArray(0);
_shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
_shader.Use();
base.OnLoad();
}
protected override void OnRenderFrame(FrameEventArgs e)
{
GL.Clear(ClearBufferMask.ColorBufferBit);
_shader.Use();
GL.BindVertexArray(_vertexArrayObject);
// 因为我们要画线,所以这里的PrimitiveType要使用Lines类型
GL.DrawArrays(PrimitiveType.Lines, 0, 2);
SwapBuffers();
base.OnRenderFrame(e);
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
var input = KeyboardState;
if (input.IsKeyDown(Keys.Escape))
{
Close();
}
base.OnUpdateFrame(e);
}
protected override void OnResize(ResizeEventArgs e)
{
GL.Viewport(0, 0, Size.X, Size.Y);
base.OnResize(e);
}
protected override void OnUnload()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
GL.UseProgram(0);
// Delete all the resources.
GL.DeleteBuffer(_vertexBufferObject);
GL.DeleteVertexArray(_vertexArrayObject);
GL.DeleteProgram(_shader.Handle);
base.OnUnload();
}
}
}
在之前的示例中我们并未详细介绍过GL.DrawArrays(PrimitiveType.Lines, 0, 2)
函数的参数,这里做一下补充。
GL.DrawArrays()
函数调用方法:
DrawArrays(PrimitiveType mode, int first, int count);
PrimitiveType mode
:我们需要设置基础的绘图类型,该参数所有可选的类型如下:
PrimitiveType可用参数 | 对应数字 |
---|---|
Points | 0 |
Lines | 1 |
LineLoop | 2 |
LineStrip | 3 |
Triangles | 4 |
TriangleStrip | 5 |
TriangleFan | 6 |
Quads | 7 |
QuadsExt | 7 |
LinesAdjacency | 10 |
LinesAdjacencyArb | 10 |
LinesAdjacencyExt | 10 |
LineStripAdjacency | 11 |
LineStripAdjacencyArb | 11 |
LineStripAdjacencyExt | 11 |
TrianglesAdjacency | 12 |
TrianglesAdjacencyArb | 12 |
TrianglesAdjacencyExt | 12 |
TriangleStripAdjacency | 13 |
TriangleStripAdjacencyArb | 13 |
TriangleStripAdjacencyExt | 13 |
Patches | 14 |
PatchesExt | 14 |
- 着色器类
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
// 注意这里的K是大写的
// 一定要注意这里改变了namespace的名字并且还要在project->properties中改变namespace的名字才行,否则无效
namespace OpenTK_SelfMadeBasis.Common
{
public class Shader
{
public readonly int Handle;
private readonly Dictionary<string, int> _uniformLocations;
public Shader(string vertPath, string fragPath)
{
var shaderSource = File.ReadAllText(vertPath);
var vertexShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertexShader, shaderSource);
CompileShader(vertexShader);
shaderSource = File.ReadAllText(fragPath);
var fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragmentShader, shaderSource);
CompileShader(fragmentShader);
Handle = GL.CreateProgram();
GL.AttachShader(Handle, vertexShader);
GL.AttachShader(Handle, fragmentShader);
LinkProgram(Handle);
GL.DetachShader(Handle, vertexShader);
GL.DetachShader(Handle, fragmentShader);
GL.DeleteShader(fragmentShader);
GL.DeleteShader(vertexShader);
GL.GetProgram(Handle, GetProgramParameterName.ActiveUniforms, out var numberOfUniforms);
_uniformLocations = new Dictionary<string, int>();
for (var i = 0; i < numberOfUniforms; i++)
{
var key = GL.GetActiveUniform(Handle, i, out _, out _);
var location = GL.GetUniformLocation(Handle, key);
_uniformLocations.Add(key, location);
}
}
private static void CompileShader(int shader)
{
GL.CompileShader(shader);
GL.GetShader(shader, ShaderParameter.CompileStatus, out var code);
if (code != (int)All.True)
{
var infoLog = GL.GetShaderInfoLog(shader);
throw new Exception($"Error occurred whilst compiling Shader({shader}).\n\n{infoLog}");
}
}
private static void LinkProgram(int program)
{
GL.LinkProgram(program);
GL.GetProgram(program, GetProgramParameterName.LinkStatus, out var code);
if (code != (int)All.True)
{
throw new Exception($"Error occurred whilst linking Program({program})");
}
}
public void Use()
{
GL.UseProgram(Handle);
}
public int GetAttribLocation(string attribName)
{
return GL.GetAttribLocation(Handle, attribName);
}
public void SetInt(string name, int data)
{
GL.UseProgram(Handle);
GL.Uniform1(_uniformLocations[name], data);
}
public void SetFloat(string name, float data)
{
GL.UseProgram(Handle);
GL.Uniform1(_uniformLocations[name], data);
}
public void SetMatrix4(string name, Matrix4 data)
{
GL.UseProgram(Handle);
GL.UniformMatrix4(_uniformLocations[name], true, ref data);
}
public void SetVector3(string name, Vector3 data)
{
GL.UseProgram(Handle);
GL.Uniform3(_uniformLocations[name], data);
}
}
}
- 端点着色器
#version 330 core
layout(location = 0) in vec3 aPosition;
void main(void)
{
gl_Position = vec4(aPosition, 1.0);
}
- 片段着色器
#version 330
out vec4 outputColor;
void main()
{
outputColor = vec4(1.0, 1.0, 0.0, 1.0);
}
运行程序可以得到下面的结果:
码字不易,如果大家觉得有用,请高抬贵手给一个赞让我上推荐让更多的人看到吧~