cscの作法 その375

# 概要
cscの作法、調べてみた。
opentkのgamewindow使ってみた。
Shader使ってみた。
GL.Uniform使ってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c6d555d2-d32b-8a94-4160-be0a89d29a91.png)


# サンプルコード

```


using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;

namespace App
{
	public class OpenGLUniform: System.IDisposable {
		public int Location;
		public string Name;
		public OpenGLProgram Program;
		public OpenGLUniform(OpenGLProgram program, string name) {
			Program = program;
			Name = name;
			Program.Use();
			Location = GL.GetUniformLocation(Program.Id, Name);
		}
		public void Uniform1(double value) {
			Program.Use();
			GL.Uniform1(Location, value);
		}
		public void Uniform1(float value) {
			Program.Use();
			GL.Uniform1(Location, value);
		}
		public void Uniform1(int value) {
			Program.Use();
			GL.Uniform1(Location, value);
		}
		public void Uniform2(Vector2 value) {
			Program.Use();
			GL.Uniform2(Location, value);
		}
		public void Uniform3(Vector3 value) {
			Program.Use();
			GL.Uniform3(Location, value);
		}
		public void Uniform4(Vector4 value) {
			Program.Use();
			GL.Uniform4(Location, value);
		}
		public void Matrix4(bool transpose, ref Matrix4 value) {
			Program.Use();
			GL.UniformMatrix4(Location, transpose, ref value);
		}
		public void Dispose() {
		}
	}
	public class OpenGLShader: System.IDisposable {
		public int Id;
		public ShaderType Type;
		public string SourceCode;
		public OpenGLShader(ShaderType shaderType, string sourceCode) {
			Type = shaderType;
			SourceCode = sourceCode;
			Id = GL.CreateShader(Type);
			GL.ShaderSource(Id, SourceCode);
			GL.CompileShader(Id);
		}
		public void Dispose() {
			GL.DeleteShader(Id);
		}
	}
	public class OpenGLProgram: System.IDisposable {
		public int Id;
		public OpenGLShader VertexShader;
		public OpenGLShader FragmentShader;
		public OpenGLProgram(OpenGLShader vertexShader, OpenGLShader fragmentShader) {
			VertexShader = vertexShader;
			FragmentShader = fragmentShader;
			Id = GL.CreateProgram();
			GL.AttachShader(Id, VertexShader.Id);
			GL.AttachShader(Id, FragmentShader.Id);
			GL.LinkProgram(Id);
		}
		public void Use() {
			GL.UseProgram(Id);
		}
		public void Unuse() {
			//GL.UseProgram(OpenGLConstant.NoneProgramId);
		}
		public void Dispose() {
			GL.DeleteProgram(Id);
		}
	}
	public class OpenGLBuffer: System.IDisposable {
		public int Count;
		public BufferTarget Target;
		public int[] Ids;
		public OpenGLBuffer(int count, BufferTarget bufferTarget) {
			Count = count;
			Target = bufferTarget;
			Ids = new int[Count];
			GL.GenBuffers(Count, Ids);
		}
		public void Bind(int index) {
			GL.BindBuffer(Target, Ids[index]);
		}
		public void Unbind() {
			//GL.BindBuffer(Target, OpenGLConstant.NoneBufferId);
		}
		public void SetData<T>(int index, int sizeInByte, T[] data, BufferUsageHint hint) where T : struct {
			Bind(index);
			GL.BufferData(Target, sizeInByte, data, hint);
		}
		public void Dispose() {
			GL.DeleteBuffers(Count, Ids);
		}
	}
	public class OpenGLVertexArray: System.IDisposable {
		public int Count;
		public int[] Ids;
		public OpenGLVertexArray(int count) {
			Count = count;
			Ids = new int[Count];
			GL.GenVertexArrays(Count, Ids);
		}
		public void Bind(int index) {
			GL.BindVertexArray(Ids[index]);
		}
		public void Unbind() {
			//GL.BindVertexArray(OpenGLConstant.NoneVertexArrayId);
		}
		public void EnableAttribute(int index, int location, int elementCount, VertexAttribPointerType elementType, bool normalized, int strideInByte, int offsetInByte) {
			Bind(index);
			GL.EnableVertexAttribArray(location);
			GL.VertexAttribPointer(location, elementCount, elementType, normalized, strideInByte, offsetInByte);
			//GL.EnableVertexAttribArray(OpenGLConstant.NoneLocation);
		}
		public void Dispose() {
			GL.DeleteBuffers(Count, Ids);
		}
	}
	class Gwin: GameWindow {
		private readonly float[] Vertices = {
			-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
			 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
			 0.0f,  0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
		};
		private int[] VertexBufferObjects = new int[1];
		private int[] VertexArrayObjects = new int[1];
		private readonly string VertexShaderSourceCode = "#version 330 core\r\n" +
			"layout(location = 0) in vec3 InPosition;\r\n" +
			"layout(location = 1) in vec3 InColor;\r\n" +
			"out vec3 OutColor;\r\n" +
			"void main() {\r\n" +
			"	gl_Position = vec4(InPosition, 1.0);\r\n" +
			"	OutColor = InColor;\r\n" +
			"}";
		private readonly string FragmentShaderSourceCode = "#version 330 core\r\n" +
			"uniform float elapsedTime;\r\n" +
			"in vec3 OutColor;\r\n" +
			"out vec4 FragColor;\r\n" +
			"void main() {\r\n" +
			"	FragColor = sin(elapsedTime) * vec4(OutColor, 1.0);\r\n" +
			"}";
		private OpenGLBuffer VertexBuffer;
		private OpenGLVertexArray VertexArray;
		private OpenGLShader VertexShader;
		private OpenGLShader FragmentShader;
		private OpenGLProgram Program;
		private OpenGLUniform ElapsedTimeUniform;
		private double ElapsedTime;
		public Gwin(int width, int height, GraphicsMode mode, string title): base(width, height, mode, title) {
			this.VSync = VSyncMode.On;
			InitializeBuffer();
			InitializeShader();
			InitializeProgram();
			InitializeUniform();
			InitializeVertexArrayObject();
			ElapsedTime = .0;
		}
		protected override void OnUpdateFrame(FrameEventArgs args) {
			base.OnUpdateFrame(args);
		}
		protected override void OnRenderFrame(FrameEventArgs e) {
			base.OnRenderFrame(e);
			GL.Clear(ClearBufferMask.ColorBufferBit);
			VertexBuffer.Bind(0);
			VertexArray.Bind(0);
			Program.Use();
			ElapsedTimeUniform.Uniform1((float) ElapsedTime);
			GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
			Program.Unuse();
			VertexArray.Unbind();
			VertexBuffer.Unbind();
			this.SwapBuffers();
			ElapsedTime += e.Time;
		}
		private void InitializeBuffer() {
			VertexBuffer = new OpenGLBuffer(1, BufferTarget.ArrayBuffer);
			VertexBuffer.SetData(0, 4 * 18, Vertices, BufferUsageHint.StaticDraw);
		}
		private void InitializeShader() {
			VertexShader = new OpenGLShader(ShaderType.VertexShader, VertexShaderSourceCode);
			FragmentShader = new OpenGLShader(ShaderType.FragmentShader, FragmentShaderSourceCode);
		}
		private void InitializeProgram() {
			Program = new OpenGLProgram(VertexShader, FragmentShader);
		}
		private void InitializeUniform() {
			ElapsedTimeUniform = new OpenGLUniform(Program, "elapsedTime");
		}
		private void InitializeVertexArrayObject() {
			VertexArray = new OpenGLVertexArray(1);
			Program.Use();
			VertexBuffer.Bind(0);
			VertexArray.Bind(0);
			VertexArray.EnableAttribute(0, 0, 3, VertexAttribPointerType.Float, false, 24, 0);
			VertexArray.EnableAttribute(0, 1, 3, VertexAttribPointerType.Float, false, 24, 12);
			VertexArray.Unbind();
			VertexBuffer.Unbind();
			Program.Unuse();
		}
		protected override void OnResize(EventArgs e) {
			GL.Viewport(0, 0, Width, Height);
		}
		protected override void OnUnload(EventArgs e) {
			base.OnUnload(e);
		}
	}
	class Program1 {
		static void Main(string[] args) {
			Gwin window = new Gwin(500, 500, OpenTK.Graphics.GraphicsMode.Default, "Test");
			window.Run();
		}
	}
}





```

以上。