Guest User

Untitled

a guest
Jun 30th, 2019
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.71 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.Drawing.Drawing2D;
  6. using System.Drawing.Imaging;
  7. using System.IO;
  8. using System.Reflection;
  9. using System.Runtime.CompilerServices;
  10. using System.Text;
  11. using I1 = System.SByte;
  12. using I2 = System.Int16;
  13. using I4 = System.Int32;
  14. using I8 = System.Int64;
  15. using U1 = System.Byte;
  16. using U2 = System.UInt16;
  17. using U4 = System.UInt32;
  18. using U8 = System.UInt64;
  19. using Ptr = System.IntPtr;
  20. using Str = System.String;
  21. using R4 = System.Single;
  22. using R8 = System.Double;
  23. using Bool = System.Boolean;
  24. using GlmNet;
  25. using GLFW;
  26. using OpenGL;
  27. using System.Threading;
  28.  
  29. public class RenderToTextureStudy {
  30.  
  31.     public enum VariableType {
  32.         scalar = 5126,
  33.         vec2 = 35664,
  34.         vec3 = 35665,
  35.         vec4 = 35666,
  36.         mat4 = 35676,
  37.         tex2d = 35678,
  38.     }
  39.  
  40.     static readonly I4[]
  41.         hints = {
  42.             (I4)Hint.ContextVersionMajor, 4, // ask for OpenGL version 4.3
  43.             (I4)Hint.ContextVersionMinor, 3,
  44.             (I4)Hint.OpenglProfile, (I4)Profile.Core, // try avoiding backwards compatibility features
  45.             (I4)Hint.Samples, (I4)Constants.Default, // antialiasing. Not working, it seems.
  46.             (I4)Hint.Doublebuffer, (I4)Constants.True,
  47.             (I4)Hint.OpenglDebugContext, (I4)Constants.True, // try to get more information if something goes wrong
  48.         },
  49.         texParams = {
  50.             (I4)TextureParameterName.TextureWrapS, Gl.REPEAT,
  51.             (I4)TextureParameterName.TextureWrapT, Gl.REPEAT,
  52.             (I4)TextureParameterName.TextureMagFilter, Gl.LINEAR,
  53.             (I4)TextureParameterName.TextureMinFilter, Gl.LINEAR,
  54.         };
  55.  
  56.     static NativeWindow window;
  57.     static StringBuilder stringBuilder = new StringBuilder();
  58.     const R8 π = Math.PI, sqrt2 = 1.414;
  59.  
  60.     static U4 TextureFromImagefile (Str filename) {
  61.         U4 tex0 = Gl.GenTexture(); // make a texture object, get its name
  62.         Gl.BindTexture(TextureTarget.Texture2d, tex0); // focus on this texture object
  63.         using (Bitmap bitmap = new Bitmap(System.Drawing.Image.FromFile(filename))) {
  64.             bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
  65.             Gl.TexStorage2D(TextureTarget.Texture2d, 1, InternalFormat.Rgba8, bitmap.Width, bitmap.Height);
  66.             BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
  67.             Gl.TexSubImage2D(TextureTarget.Texture2d, 0, 0, 0, bitmap.Width, bitmap.Height, OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bitmapData.Scan0);
  68.         }
  69.         return tex0;
  70.     }
  71.  
  72.     const I4
  73.         windowWidth = 640,
  74.         windowHeight = 480;
  75.  
  76.     public static void Main () {
  77.         OpenGL.ErrorCode err = Gl.GetError();
  78.         Gl.Initialize();
  79.  
  80.         Debug.Assert(Glfw.Init());
  81.  
  82.         for (I4 i = 0; i < hints.Length >> 1; i += 2)
  83.             Glfw.WindowHint((Hint)hints[i], hints[i + 1]); // set the hints mentioned above
  84.  
  85.         window = new NativeWindow(windowWidth, windowHeight, Str.Empty);
  86.         Glfw.SetWindowPosition(window, 0, 0);
  87.         Glfw.SetFramebufferSizeCallback(window, ForFramebufferSize);// it sets the viewport
  88.         Glfw.SetErrorCallback(ForError);
  89.         Glfw.SetKeyCallback(window, ForKey);
  90.         Glfw.SetWindowAttribute(window, WindowAttribute.Decorated, false);
  91.         Glfw.MakeContextCurrent(window); // 'window' now 'has' the OpenGL context
  92.         Glfw.SwapInterval(1); // enables v-sync, probably
  93.  
  94.  
  95.         /************ vertices and texture points ************/
  96.         U4 vertexArray = Gl.GenVertexArray(); // make a vertex array object, get its 'name'
  97.         Gl.BindVertexArray(vertexArray); // focus on this vertex array object
  98.         U4 buffer = Gl.GenBuffer(); // make a buffer object, get its name
  99.         Gl.BindBuffer(BufferTarget.ArrayBuffer, buffer); // focus on this buffer object
  100.  
  101.         R4[] data = { // point coordinates and texture coordinates for two triangles.
  102.             // x     y     z     s     t
  103.            -0.5f, -0.5f,  0.0f,  0.0f, 0.0f,
  104.             0.5f, -0.5f,  0.0f,  1.0f, 0.0f,
  105.             0.5f,  0.5f,  0.0f,  1.0f, 1.0f,
  106.            -0.5f, -0.5f,  0.0f,  0.0f, 0.0f,
  107.             0.5f,  0.5f,  0.0f,  1.0f, 1.0f,
  108.            -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
  109.         };
  110.  
  111.         // ask for the data to be uploaded
  112.         Gl.BufferData(BufferTarget.ArrayBuffer, (U4)(data.Length * sizeof(R4)), data, BufferUsage.StaticDraw);
  113.  
  114.         // first vertex attribute is position, with index 0, has 3 elements, is at beginning of vertex
  115.         Gl.VertexAttribPointer(0U, 3, VertexAttribType.Float, false, 5 * sizeof(R4), Ptr.Zero);
  116.         Gl.EnableVertexAttribArray(0U);
  117.  
  118.         // second vertex attribute is texture coordinates with index 1, has 2 elements, is 3 floats worth of bytes from beginning
  119.         Gl.VertexAttribPointer(1U, 2, VertexAttribType.Float, false, 5 * sizeof(R4), Ptr.Zero + 3 * sizeof(R4));
  120.         Gl.EnableVertexAttribArray(1U);
  121.  
  122.         /***************** textures ****************/
  123.  
  124.         U4 tex0 = TextureFromImagefile("..\\data\\b.png");// Gl.GenTexture(); // make a texture object, get its name
  125.         U4 tex1 = TextureFromImagefile("..\\data\\a.png");// Gl.GenTexture(); // make a texture object, get its name
  126.         Debug.WriteLine($"{nameof(tex0)}: {tex0}, {nameof(tex1)}: {tex1}");
  127.  
  128.         U4 program = Gl.CreateProgram(); // make a program object, get its name
  129.  
  130.         U4 vertexShader = Compile("test_vertex.glsl", ShaderType.VertexShader); // compile...
  131.         Gl.AttachShader(program, vertexShader); // and attach the vertex shader to the program object.
  132.  
  133.         U4 fragmentShader = Compile("test_fragment.glsl", ShaderType.FragmentShader); // same with the fragment shader.
  134.         Gl.AttachShader(program, fragmentShader);
  135.  
  136.         Gl.BindFragDataLocation(program, 0U, "fragOut"); // ask for 'colored' to be the default ('gl_FragColor') color output
  137.         Gl.BindFragDataLocation(program, 1U, "secondaryOut"); // ask for 'colored' to be the default ('gl_FragColor') color output
  138.  
  139.         Gl.BindAttribLocation(program, 0U, "vertexPos"); // ask for 'vertexPos' to be at location 0
  140.         Gl.BindAttribLocation(program, 1U, "texCoords"); // and 'texCoords' at 1
  141.  
  142.         Info(program);
  143.         Gl.LinkProgram(program); // must link to have the changes made.
  144.         Info(program);
  145.  
  146.         Gl.UseProgram(program); // ask for this program to be used for rendering
  147.  
  148.         // find the names/locations of the uniform variables
  149.         R8
  150.             scale = 0.0,
  151.             ratio = 0.0;
  152.         I4
  153.             view = Gl.GetUniformLocation(program, nameof(view)),
  154.             projection = Gl.GetUniformLocation(program, nameof(projection)),
  155.             tex0Location = Gl.GetUniformLocation(program, nameof(tex0)),
  156.             ratioLocation = Gl.GetUniformLocation(program, nameof(ratio)),
  157.             scaleLocation = Gl.GetUniformLocation(program, nameof(scale)),
  158.             tex1Location = Gl.GetUniformLocation(program, nameof(tex1));
  159.  
  160.         Debug.WriteLine($"view: {view}, projection: {projection}, tex0Location : {tex0Location}, tex1Location : {tex1Location}");
  161.  
  162.         mat4
  163.             projectionMatrix = glm.perspective((R4)π / 2f, window.Size.Width / (R4)window.Size.Height, 0.1f, 100f),
  164.             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))
  165.  
  166.         Gl.UniformMatrix4(projection, false, projectionMatrix.to_array());
  167.         Gl.UniformMatrix4(view, false, viewMatrix.to_array());
  168.         Gl.Uniform1(tex0Location, 0);
  169.         Gl.Uniform1(tex1Location, 1);
  170.  
  171.         U4 framebuffer = Gl.GenFramebuffer();
  172.         Gl.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);
  173.  
  174.         U4 colorRenderbuffer = Gl.GenRenderbuffer();
  175.         Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, colorRenderbuffer);
  176.  
  177.         Gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, InternalFormat.Rgba, windowWidth, windowHeight);
  178.  
  179.         Gl.FramebufferRenderbuffer(FramebufferTarget.DrawFramebuffer, FramebufferAttachment.ColorAttachment0, RenderbufferTarget.Renderbuffer, colorRenderbuffer);
  180.  
  181.         Gl.DrawBuffers((I4)FramebufferAttachment.ColorAttachment0, (I4)FramebufferAttachment.ColorAttachment1);
  182.         //Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0U);
  183.         Debug.Assert((err = Gl.GetError()) == OpenGL.ErrorCode.NoError, $"{err}");
  184.  
  185.         //Gl.DrawBuffers(1);//, (I4)FramebufferAttachment.ColorAttachment1);
  186.         //Gl.ReadBuffer(ReadBufferMode.ColorAttachment0);
  187.         //U4 depthRenderbuffer = Gl.GenRenderbuffer();
  188.         //Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, depthRenderbuffer);
  189.         //Gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, InternalFormat.DepthComponent16, windowWidth, windowHeight);
  190.         //Gl.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, depthRenderbuffer);
  191.         Gl.ClearColor(0.5f, 0.5f, 0.5f, 0f);
  192.         Debug.Assert(Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer) == FramebufferStatus.FramebufferComplete);
  193.         //U4 framebufferTex = Gl.GenTexture();
  194.         //Gl.BindTexture(TextureTarget.TextureRectangle, framebufferTex);
  195.         //Gl.TexImage2D(TextureTarget.TextureRectangle, 0, InternalFormat.Rgba8, windowWidth, windowHeight, 0, OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, null);
  196.         //Gl.TexParameteri(TextureTarget.TextureRectangle, TextureParameterName.TextureMinFilter, Gl.LINEAR);
  197.         //Gl.TexParameteri(TextureTarget.TextureRectangle, TextureParameterName.TextureMagFilter, Gl.LINEAR);
  198.         //Gl.BindTexture(TextureTarget.TextureRectangle, 0U);
  199.         //
  200.         //Gl.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.TextureRectangle, framebufferTex, 0);
  201.         //Gl.BindFramebuffer(FramebufferTarget.Framebuffer, 0U);
  202.  
  203.  
  204.  
  205.  
  206.  
  207.         Gl.BindVertexArray(vertexArray); // focus on this vertex array object
  208.  
  209.         Gl.ActiveTexture(TextureUnit.Texture0); //
  210.         Gl.BindTexture(TextureTarget.Texture2d, tex0); // focus on it
  211.  
  212.         Gl.ActiveTexture(TextureUnit.Texture1); //
  213.         Gl.BindTexture(TextureTarget.Texture2d, tex1); // focus on it
  214.  
  215.         U8 lastTime = Glfw.TimerValue;
  216.         R8 delta = 0.0;
  217.         R8 θ = 0.0;
  218.         Gl.ReadBuffer(ReadBufferMode.ColorAttachment1);
  219.  
  220.         Bitmap bitmap = new Bitmap(captureSize, captureSize, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
  221.         BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
  222.         while (!Glfw.WindowShouldClose(window)) {
  223.             Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
  224.             Gl.Uniform1(ratioLocation, (R4)Math.Pow(0.5 * (1.0 + Math.Sin(θ)), 1.0));
  225.             Gl.Uniform1(scaleLocation, (R4)θ);//(R4)(1.0 + 0.5 * Math.Sin(θ))
  226.             Gl.DrawArrays(PrimitiveType.Triangles, 0, data.Length / 5);
  227.             Glfw.SwapBuffers(window);
  228.             U8 thisTime = Glfw.TimerValue;
  229.             delta = (thisTime - lastTime) / (R8)Glfw.TimerFrequency;
  230.             θ = (θ + delta) % (2.0 * π);
  231.             lastTime = thisTime;
  232.             if (1 == Interlocked.CompareExchange(ref thing, 0, 1)) {
  233.                 //Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, colorRenderbuffer);
  234.                 Gl.ReadPixels((windowHeight - captureSize) >> 1, (windowHeight - captureSize) >> 1, captureSize, captureSize, OpenGL.PixelFormat.Bgra, PixelType.Byte, bitmapData.Scan0);
  235.                 //Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0U);
  236.                 bitmap.UnlockBits(bitmapData);
  237.                 bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
  238.                 using (Stream s = File.Open("out.png", FileMode.Create)) bitmap.Save(s, ImageFormat.Png);
  239.                 bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
  240.             }
  241.             Glfw.PollEvents();
  242.         }
  243.     }
  244.  
  245.  
  246.     ///////////////////////////////////////////////////////////////////////////////////////////////
  247.  
  248.     const I4 captureSize = 256;
  249.     static void Info (U4 program) {
  250.  
  251.         I4 inputCount = GetProgramInterface(program, ProgramInterface.ProgramInput, ProgramInterfacePName.ActiveResources);
  252.         Str[] inputs = new Str[inputCount];
  253.         for (I4 i = 0; i < inputCount; ++i) inputs[i] = GetProgramResourceName(program, ProgramInterface.ProgramInput, (U4)i, I4.MaxValue) + "(" + i + ")";
  254.         Debug.WriteLine("inputs: " + Str.Join(", ", inputs));
  255.  
  256.         I4 outputCount = GetProgramInterface(program, ProgramInterface.ProgramOutput, ProgramInterfacePName.ActiveResources);
  257.         Str[] outputs = new Str[outputCount];
  258.         for (I4 i = 0; i < outputCount; ++i) {
  259.             Str name = GetProgramResourceName(program, ProgramInterface.ProgramOutput, (U4)i, I4.MaxValue);
  260.             //Gl.GetFragDataIndex(program, name);
  261.             //Gl.GetFragDataLocation(program, name);
  262.             outputs[i] = $"{name}({Gl.GetFragDataIndex(program, name)}/{Gl.GetFragDataLocation(program, name)})";// GetProgramResourceName(program, ProgramInterface.ProgramOutput, (U4)i, I4.MaxValue) + "(" + i + ")";
  263.         }
  264.         Debug.WriteLine("outputs: " + Str.Join(", ", outputs));
  265.  
  266.         I4 attCount = GetProgram(program, ProgramProperty.ActiveAttributes);
  267.         Str[] atts = new Str[attCount];
  268.         for (I4 i = 0; i < attCount; ++i) {
  269.             stringBuilder.Clear();
  270.             Gl.GetActiveAttrib(program, (U4)i, I4.MaxValue, out _, out I4 size, out I4 type, stringBuilder);
  271.             Str name = stringBuilder.ToString();
  272.             atts[i] = $"{(VariableType)type}{(size > 1 ? $"[{size}]" : Str.Empty)} {name}({Gl.GetAttribLocation(program, name)})";
  273.         }
  274.         Debug.WriteLine("atts: " + Str.Join(", ", atts));
  275.  
  276.         I4 uniCount = GetProgram(program, ProgramProperty.ActiveUniforms);
  277.         Str[] unis = new Str[uniCount];
  278.         for (I4 i = 0; i < uniCount; ++i) {
  279.             stringBuilder.Clear();
  280.             Gl.GetActiveUniform(program, (U4)i, I4.MaxValue, out _, out I4 size, out I4 type, stringBuilder);
  281.             Str name = stringBuilder.ToString();
  282.             unis[i] = $"{(VariableType)type}{(size > 1 ? $"[{size}]" : Str.Empty)} {name}({Gl.GetUniformLocation(program, name)})";
  283.         }
  284.         Debug.WriteLine("unis: " + Str.Join(", ", unis));
  285.  
  286.  
  287.     }
  288.  
  289.     static U4 Compile (Str filename, ShaderType type) {
  290.         //OpenGL.ErrorCode errorCode = OpenGL.ErrorCode.NoError;
  291.         Debug.WriteLine($"compiling {filename} as {type}");
  292.         U4 shader = Gl.CreateShader(type);
  293.         Gl.ShaderSource(shader, new Str[] { File.ReadAllText(filename) });
  294.         Gl.CompileShader(shader);
  295.         //foreach (ShaderParameterName shaderParameterName in Enum.GetValues(typeof(ShaderParameterName)))
  296.         //    Debug.WriteLine($"{shaderParameterName} = {GetShader(shader, shaderParameterName)}" + ((errorCode = Gl.GetError()) == OpenGL.ErrorCode.NoError ? Str.Empty : $" ({errorCode})"));
  297.  
  298.         StringBuilder sb = new StringBuilder();
  299.         Gl.GetShaderInfoLog(shader, 1000, out I4 logLength, sb);
  300.         //Debug.WriteLine($"log({logLength}):\n{sb}");
  301.  
  302.         return shader;
  303.     }
  304.  
  305.     static void ForError (GLFW.ErrorCode errorCode, Ptr message) {
  306.         Debug.WriteLine(errorCode);
  307.     }
  308.  
  309.     static void ForFramebufferSize (Ptr window, I4 width, I4 height) {
  310.         Gl.Viewport(0, 0, width, height);
  311.     }
  312.  
  313.     static void ForKey (Ptr window, Keys key, I4 scanCode, InputState state, ModifierKeys mods) {
  314.         if (state != InputState.Release) return;
  315.         switch (key) {
  316.         case Keys.Escape:
  317.             Glfw.SetWindowShouldClose(RenderToTextureStudy.window, true);
  318.             return;
  319.         case Keys.Space:
  320.             thing = 1;//Debug.Assert(0 == Interlocked.CompareExchange(ref thing, 1, 0));
  321.             return;
  322.         }
  323.     }
  324.     static I4 thing = 0;
  325.     static I4 GetProgram (U4 program, ProgramProperty programProperty) {
  326.         Gl.GetProgram(program, programProperty, out I4 value); return value;
  327.     }
  328.  
  329.     static I4 GetProgramInterface (U4 program, ProgramInterface programInterface, ProgramInterfacePName programInterfacePName) {
  330.         Gl.GetProgramInterface(program, programInterface, programInterfacePName, out I4 value); return value;
  331.     }
  332.  
  333.     static Str GetProgramResourceName (U4 program, ProgramInterface programInterface, U4 index, I4 bufSize) {
  334.         StringBuilder s = new StringBuilder();
  335.         Gl.GetProgramResourceName(program, programInterface, index, bufSize, out _, s);
  336.         return s.ToString();
  337.     }
  338. }
Add Comment
Please, Sign In to add comment