Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Text;
- using I1 = System.SByte;
- using I2 = System.Int16;
- using I4 = System.Int32;
- using I8 = System.Int64;
- using U1 = System.Byte;
- using U2 = System.UInt16;
- using U4 = System.UInt32;
- using U8 = System.UInt64;
- using Ptr = System.IntPtr;
- using Str = System.String;
- using R4 = System.Single;
- using R8 = System.Double;
- using Bool = System.Boolean;
- using GlmNet;
- using GLFW;
- using OpenGL;
- using System.Threading;
- public class RenderToTextureStudy {
- public enum VariableType {
- scalar = 5126,
- vec2 = 35664,
- vec3 = 35665,
- vec4 = 35666,
- mat4 = 35676,
- tex2d = 35678,
- }
- static readonly I4[]
- hints = {
- (I4)Hint.ContextVersionMajor, 4, // ask for OpenGL version 4.3
- (I4)Hint.ContextVersionMinor, 3,
- (I4)Hint.OpenglProfile, (I4)Profile.Core, // try avoiding backwards compatibility features
- (I4)Hint.Samples, (I4)Constants.Default, // antialiasing. Not working, it seems.
- (I4)Hint.Doublebuffer, (I4)Constants.True,
- (I4)Hint.OpenglDebugContext, (I4)Constants.True, // try to get more information if something goes wrong
- },
- texParams = {
- (I4)TextureParameterName.TextureWrapS, Gl.REPEAT,
- (I4)TextureParameterName.TextureWrapT, Gl.REPEAT,
- (I4)TextureParameterName.TextureMagFilter, Gl.LINEAR,
- (I4)TextureParameterName.TextureMinFilter, Gl.LINEAR,
- };
- static NativeWindow window;
- static StringBuilder stringBuilder = new StringBuilder();
- const R8 π = Math.PI, sqrt2 = 1.414;
- static U4 TextureFromImagefile (Str filename) {
- U4 tex0 = Gl.GenTexture(); // make a texture object, get its name
- Gl.BindTexture(TextureTarget.Texture2d, tex0); // focus on this texture object
- using (Bitmap bitmap = new Bitmap(System.Drawing.Image.FromFile(filename))) {
- bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
- Gl.TexStorage2D(TextureTarget.Texture2d, 1, InternalFormat.Rgba8, bitmap.Width, bitmap.Height);
- BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
- Gl.TexSubImage2D(TextureTarget.Texture2d, 0, 0, 0, bitmap.Width, bitmap.Height, OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bitmapData.Scan0);
- }
- return tex0;
- }
- const I4
- windowWidth = 640,
- windowHeight = 480;
- public static void Main () {
- OpenGL.ErrorCode err = Gl.GetError();
- Gl.Initialize();
- Debug.Assert(Glfw.Init());
- for (I4 i = 0; i < hints.Length >> 1; i += 2)
- Glfw.WindowHint((Hint)hints[i], hints[i + 1]); // set the hints mentioned above
- window = new NativeWindow(windowWidth, windowHeight, Str.Empty);
- Glfw.SetWindowPosition(window, 0, 0);
- Glfw.SetFramebufferSizeCallback(window, ForFramebufferSize);// it sets the viewport
- Glfw.SetErrorCallback(ForError);
- Glfw.SetKeyCallback(window, ForKey);
- Glfw.SetWindowAttribute(window, WindowAttribute.Decorated, false);
- Glfw.MakeContextCurrent(window); // 'window' now 'has' the OpenGL context
- Glfw.SwapInterval(1); // enables v-sync, probably
- /************ vertices and texture points ************/
- U4 vertexArray = Gl.GenVertexArray(); // make a vertex array object, get its 'name'
- Gl.BindVertexArray(vertexArray); // focus on this vertex array object
- U4 buffer = Gl.GenBuffer(); // make a buffer object, get its name
- Gl.BindBuffer(BufferTarget.ArrayBuffer, buffer); // focus on this buffer object
- R4[] data = { // point coordinates and texture coordinates for two triangles.
- // x y z s t
- -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
- 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
- 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
- -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
- 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
- -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
- };
- // ask for the data to be uploaded
- Gl.BufferData(BufferTarget.ArrayBuffer, (U4)(data.Length * sizeof(R4)), data, BufferUsage.StaticDraw);
- // first vertex attribute is position, with index 0, has 3 elements, is at beginning of vertex
- Gl.VertexAttribPointer(0U, 3, VertexAttribType.Float, false, 5 * sizeof(R4), Ptr.Zero);
- Gl.EnableVertexAttribArray(0U);
- // second vertex attribute is texture coordinates with index 1, has 2 elements, is 3 floats worth of bytes from beginning
- Gl.VertexAttribPointer(1U, 2, VertexAttribType.Float, false, 5 * sizeof(R4), Ptr.Zero + 3 * sizeof(R4));
- Gl.EnableVertexAttribArray(1U);
- /***************** textures ****************/
- U4 tex0 = TextureFromImagefile("..\\data\\b.png");// Gl.GenTexture(); // make a texture object, get its name
- U4 tex1 = TextureFromImagefile("..\\data\\a.png");// Gl.GenTexture(); // make a texture object, get its name
- Debug.WriteLine($"{nameof(tex0)}: {tex0}, {nameof(tex1)}: {tex1}");
- U4 program = Gl.CreateProgram(); // make a program object, get its name
- U4 vertexShader = Compile("test_vertex.glsl", ShaderType.VertexShader); // compile...
- Gl.AttachShader(program, vertexShader); // and attach the vertex shader to the program object.
- U4 fragmentShader = Compile("test_fragment.glsl", ShaderType.FragmentShader); // same with the fragment shader.
- Gl.AttachShader(program, fragmentShader);
- Gl.BindFragDataLocation(program, 0U, "fragOut"); // ask for 'colored' to be the default ('gl_FragColor') color output
- Gl.BindFragDataLocation(program, 1U, "secondaryOut"); // ask for 'colored' to be the default ('gl_FragColor') color output
- Gl.BindAttribLocation(program, 0U, "vertexPos"); // ask for 'vertexPos' to be at location 0
- Gl.BindAttribLocation(program, 1U, "texCoords"); // and 'texCoords' at 1
- Info(program);
- Gl.LinkProgram(program); // must link to have the changes made.
- Info(program);
- Gl.UseProgram(program); // ask for this program to be used for rendering
- // find the names/locations of the uniform variables
- R8
- scale = 0.0,
- ratio = 0.0;
- I4
- view = Gl.GetUniformLocation(program, nameof(view)),
- projection = Gl.GetUniformLocation(program, nameof(projection)),
- tex0Location = Gl.GetUniformLocation(program, nameof(tex0)),
- ratioLocation = Gl.GetUniformLocation(program, nameof(ratio)),
- scaleLocation = Gl.GetUniformLocation(program, nameof(scale)),
- tex1Location = Gl.GetUniformLocation(program, nameof(tex1));
- Debug.WriteLine($"view: {view}, projection: {projection}, tex0Location : {tex0Location}, tex1Location : {tex1Location}");
- mat4
- projectionMatrix = glm.perspective((R4)π / 2f, window.Size.Width / (R4)window.Size.Height, 0.1f, 100f),
- viewMatrix = glm.lookAt(new vec3(0f, 0f, 1f), new vec3(0f, 0f, 0f), new vec3(0f, 1f, 0f)); //(R4)Math.Cos(Glfw.Time) //(R4)Math.Sin(Glfw.Time))
- Gl.UniformMatrix4(projection, false, projectionMatrix.to_array());
- Gl.UniformMatrix4(view, false, viewMatrix.to_array());
- Gl.Uniform1(tex0Location, 0);
- Gl.Uniform1(tex1Location, 1);
- U4 framebuffer = Gl.GenFramebuffer();
- Gl.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);
- U4 colorRenderbuffer = Gl.GenRenderbuffer();
- Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, colorRenderbuffer);
- Gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, InternalFormat.Rgba, windowWidth, windowHeight);
- Gl.FramebufferRenderbuffer(FramebufferTarget.DrawFramebuffer, FramebufferAttachment.ColorAttachment0, RenderbufferTarget.Renderbuffer, colorRenderbuffer);
- Gl.DrawBuffers((I4)FramebufferAttachment.ColorAttachment0, (I4)FramebufferAttachment.ColorAttachment1);
- //Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0U);
- Debug.Assert((err = Gl.GetError()) == OpenGL.ErrorCode.NoError, $"{err}");
- //Gl.DrawBuffers(1);//, (I4)FramebufferAttachment.ColorAttachment1);
- //Gl.ReadBuffer(ReadBufferMode.ColorAttachment0);
- //U4 depthRenderbuffer = Gl.GenRenderbuffer();
- //Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, depthRenderbuffer);
- //Gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, InternalFormat.DepthComponent16, windowWidth, windowHeight);
- //Gl.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, depthRenderbuffer);
- Gl.ClearColor(0.5f, 0.5f, 0.5f, 0f);
- Debug.Assert(Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer) == FramebufferStatus.FramebufferComplete);
- //U4 framebufferTex = Gl.GenTexture();
- //Gl.BindTexture(TextureTarget.TextureRectangle, framebufferTex);
- //Gl.TexImage2D(TextureTarget.TextureRectangle, 0, InternalFormat.Rgba8, windowWidth, windowHeight, 0, OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, null);
- //Gl.TexParameteri(TextureTarget.TextureRectangle, TextureParameterName.TextureMinFilter, Gl.LINEAR);
- //Gl.TexParameteri(TextureTarget.TextureRectangle, TextureParameterName.TextureMagFilter, Gl.LINEAR);
- //Gl.BindTexture(TextureTarget.TextureRectangle, 0U);
- //
- //Gl.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.TextureRectangle, framebufferTex, 0);
- //Gl.BindFramebuffer(FramebufferTarget.Framebuffer, 0U);
- Gl.BindVertexArray(vertexArray); // focus on this vertex array object
- Gl.ActiveTexture(TextureUnit.Texture0); //
- Gl.BindTexture(TextureTarget.Texture2d, tex0); // focus on it
- Gl.ActiveTexture(TextureUnit.Texture1); //
- Gl.BindTexture(TextureTarget.Texture2d, tex1); // focus on it
- U8 lastTime = Glfw.TimerValue;
- R8 delta = 0.0;
- R8 θ = 0.0;
- Gl.ReadBuffer(ReadBufferMode.ColorAttachment1);
- Bitmap bitmap = new Bitmap(captureSize, captureSize, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
- BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
- while (!Glfw.WindowShouldClose(window)) {
- Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
- Gl.Uniform1(ratioLocation, (R4)Math.Pow(0.5 * (1.0 + Math.Sin(θ)), 1.0));
- Gl.Uniform1(scaleLocation, (R4)θ);//(R4)(1.0 + 0.5 * Math.Sin(θ))
- Gl.DrawArrays(PrimitiveType.Triangles, 0, data.Length / 5);
- Glfw.SwapBuffers(window);
- U8 thisTime = Glfw.TimerValue;
- delta = (thisTime - lastTime) / (R8)Glfw.TimerFrequency;
- θ = (θ + delta) % (2.0 * π);
- lastTime = thisTime;
- if (1 == Interlocked.CompareExchange(ref thing, 0, 1)) {
- //Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, colorRenderbuffer);
- Gl.ReadPixels((windowHeight - captureSize) >> 1, (windowHeight - captureSize) >> 1, captureSize, captureSize, OpenGL.PixelFormat.Bgra, PixelType.Byte, bitmapData.Scan0);
- //Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0U);
- bitmap.UnlockBits(bitmapData);
- bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
- using (Stream s = File.Open("out.png", FileMode.Create)) bitmap.Save(s, ImageFormat.Png);
- bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
- }
- Glfw.PollEvents();
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////
- const I4 captureSize = 256;
- static void Info (U4 program) {
- I4 inputCount = GetProgramInterface(program, ProgramInterface.ProgramInput, ProgramInterfacePName.ActiveResources);
- Str[] inputs = new Str[inputCount];
- for (I4 i = 0; i < inputCount; ++i) inputs[i] = GetProgramResourceName(program, ProgramInterface.ProgramInput, (U4)i, I4.MaxValue) + "(" + i + ")";
- Debug.WriteLine("inputs: " + Str.Join(", ", inputs));
- I4 outputCount = GetProgramInterface(program, ProgramInterface.ProgramOutput, ProgramInterfacePName.ActiveResources);
- Str[] outputs = new Str[outputCount];
- for (I4 i = 0; i < outputCount; ++i) {
- Str name = GetProgramResourceName(program, ProgramInterface.ProgramOutput, (U4)i, I4.MaxValue);
- //Gl.GetFragDataIndex(program, name);
- //Gl.GetFragDataLocation(program, name);
- outputs[i] = $"{name}({Gl.GetFragDataIndex(program, name)}/{Gl.GetFragDataLocation(program, name)})";// GetProgramResourceName(program, ProgramInterface.ProgramOutput, (U4)i, I4.MaxValue) + "(" + i + ")";
- }
- Debug.WriteLine("outputs: " + Str.Join(", ", outputs));
- I4 attCount = GetProgram(program, ProgramProperty.ActiveAttributes);
- Str[] atts = new Str[attCount];
- for (I4 i = 0; i < attCount; ++i) {
- stringBuilder.Clear();
- Gl.GetActiveAttrib(program, (U4)i, I4.MaxValue, out _, out I4 size, out I4 type, stringBuilder);
- Str name = stringBuilder.ToString();
- atts[i] = $"{(VariableType)type}{(size > 1 ? $"[{size}]" : Str.Empty)} {name}({Gl.GetAttribLocation(program, name)})";
- }
- Debug.WriteLine("atts: " + Str.Join(", ", atts));
- I4 uniCount = GetProgram(program, ProgramProperty.ActiveUniforms);
- Str[] unis = new Str[uniCount];
- for (I4 i = 0; i < uniCount; ++i) {
- stringBuilder.Clear();
- Gl.GetActiveUniform(program, (U4)i, I4.MaxValue, out _, out I4 size, out I4 type, stringBuilder);
- Str name = stringBuilder.ToString();
- unis[i] = $"{(VariableType)type}{(size > 1 ? $"[{size}]" : Str.Empty)} {name}({Gl.GetUniformLocation(program, name)})";
- }
- Debug.WriteLine("unis: " + Str.Join(", ", unis));
- }
- static U4 Compile (Str filename, ShaderType type) {
- //OpenGL.ErrorCode errorCode = OpenGL.ErrorCode.NoError;
- Debug.WriteLine($"compiling {filename} as {type}");
- U4 shader = Gl.CreateShader(type);
- Gl.ShaderSource(shader, new Str[] { File.ReadAllText(filename) });
- Gl.CompileShader(shader);
- //foreach (ShaderParameterName shaderParameterName in Enum.GetValues(typeof(ShaderParameterName)))
- // Debug.WriteLine($"{shaderParameterName} = {GetShader(shader, shaderParameterName)}" + ((errorCode = Gl.GetError()) == OpenGL.ErrorCode.NoError ? Str.Empty : $" ({errorCode})"));
- StringBuilder sb = new StringBuilder();
- Gl.GetShaderInfoLog(shader, 1000, out I4 logLength, sb);
- //Debug.WriteLine($"log({logLength}):\n{sb}");
- return shader;
- }
- static void ForError (GLFW.ErrorCode errorCode, Ptr message) {
- Debug.WriteLine(errorCode);
- }
- static void ForFramebufferSize (Ptr window, I4 width, I4 height) {
- Gl.Viewport(0, 0, width, height);
- }
- static void ForKey (Ptr window, Keys key, I4 scanCode, InputState state, ModifierKeys mods) {
- if (state != InputState.Release) return;
- switch (key) {
- case Keys.Escape:
- Glfw.SetWindowShouldClose(RenderToTextureStudy.window, true);
- return;
- case Keys.Space:
- thing = 1;//Debug.Assert(0 == Interlocked.CompareExchange(ref thing, 1, 0));
- return;
- }
- }
- static I4 thing = 0;
- static I4 GetProgram (U4 program, ProgramProperty programProperty) {
- Gl.GetProgram(program, programProperty, out I4 value); return value;
- }
- static I4 GetProgramInterface (U4 program, ProgramInterface programInterface, ProgramInterfacePName programInterfacePName) {
- Gl.GetProgramInterface(program, programInterface, programInterfacePName, out I4 value); return value;
- }
- static Str GetProgramResourceName (U4 program, ProgramInterface programInterface, U4 index, I4 bufSize) {
- StringBuilder s = new StringBuilder();
- Gl.GetProgramResourceName(program, programInterface, index, bufSize, out _, s);
- return s.ToString();
- }
- }
Add Comment
Please, Sign In to add comment