using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using PoroCYon.FNAGLSL; //using VertexType = Microsoft.Xna.Framework.Graphics.VertexPositionColorTexture; [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)] struct VertexType { Vector3 pos; Vector2 uv ; Color col; public VertexType(Vector3 p, Color c, Vector2 uv) { pos = p; this.uv = uv; col = c; } public unsafe static VertexDeclaration Format = new VertexDeclaration( // what is the 4th argument even supposed to be?!! new VertexElement(0 , VertexElementFormat.Vector3, VertexElementUsage.Position , 0) , new VertexElement(0+sizeof(Vector3) , VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0) , new VertexElement(0+sizeof(Vector3)+sizeof(Vector2), VertexElementFormat.Color , VertexElementUsage.Color , 0) ); } class TestGame : Game { GraphicsDeviceManager gdm; SpriteBatch sb; KeyboardState ks; BasicEffect hlsl; GLSLEffect glsl; Texture2D thetex; public TestGame() : base() { gdm = new GraphicsDeviceManager(this); } // thanks Ralgor void Resize(Object s, EventArgs ea) { Window.ClientSizeChanged -= Resize; gdm.PreferredBackBufferWidth = Window.ClientBounds.Width ; gdm.PreferredBackBufferHeight = Window.ClientBounds.Height; gdm.ApplyChanges(); Window.ClientSizeChanged += Resize; } protected override void Initialize() { IsMouseVisible = true; Window.AllowUserResizing = true; Window.Title = "FNA GLSL hax"; gdm.SynchronizeWithVerticalRetrace = true; gdm.ApplyChanges(); base.Initialize(); Window.ClientSizeChanged += Resize; } protected override void LoadContent() { sb = new SpriteBatch(GraphicsDevice); using (var fs = File.OpenRead("checker.png")) { thetex = Texture2D.FromStream(GraphicsDevice, fs); } hlsl = new BasicEffect(GraphicsDevice); hlsl.LightingEnabled = false; hlsl.PreferPerPixelLighting = false; hlsl.FogEnabled = false; hlsl.TextureEnabled = false; hlsl.VertexColorEnabled = true; hlsl.World = hlsl.View = hlsl.Projection = Matrix.Identity; glsl = new GLSLEffect(GraphicsDevice, new Dictionary() { { GLSLPurpose.VertexShader , "#version 410 core\n"+ "\n"+ "in vec3 in_pos;\n"+ "in vec4 in_col;\n"+ "in vec2 in_texcoord;\n"+ "\n"+ "out vec2 out_texcoord;\n"+ "\n"+ "void main() {\n"+ " gl_Position = vec4(in_pos.x, in_pos.y, in_pos.z, 1.0);\n"+ " out_texcoord = in_texcoord;\n"+ "}\n" /*"#version 430 core\n"+ "vec2 y = vec2(1., -1.);\n"+ "vec4 x[4] = {y.yyxx, y.xyxx, y.yxxx, y.xxxx};\n"+ "void main() {\n"+ " gl_Position = x[gl_VertexID];\n"+ "}\n"*/ }, { GLSLPurpose.FragmentShader, "#version 330 core\n"+ "\n"+ "uniform float fGlobalTime;\n"+ "uniform vec2 v2Resolution;\n"+ "uniform sampler2D mytex;\n"+ "\n"+ "layout(location = 0) out vec4 C;\n"+ "\n"+ "vec4 plas(float time, vec2 v) {\n"+ " float c = 0.5 + sin(v.x * 10.0) + cos(sin(time + v.y) * 20.0);\n"+ " return vec4(sin(c * 0.2 + cos(time)), c * 0.15, cos(c * 0.1 + time / .4) * .25, 1.0);\n"+ "}\n"+ "\n"+ "void main() {\n"+ /*" vec2 v2Resolution = vec2(1920.0, 1080.0);\n"+ " float fGlobalTime = 0.0;\n"+ "\n"+*/ " float pi = 4*atan(1);\n"+ " vec2 uv = vec2(gl_FragCoord.x/v2Resolution.x, gl_FragCoord.y/v2Resolution.y);\n"+ " uv -= 0.5;\n"+ " uv /= vec2(v2Resolution.y/v2Resolution.x, 1.);\n"+ " vec2 ouv = uv;\n"+ "\n"+ " vec2 m;\n"+ " m.x = atan(uv.x / uv.y) / pi;\n"+ " m.y = 1 / length(uv) * .2;\n"+ " float d = m.y;\n"+ " m.x += sin(fGlobalTime) * 0.1;\n"+ " m.y += fGlobalTime * 0.25;\n"+ "\n"+ " vec4 t = plas(fGlobalTime, m * pi) / d;\n"+ " C = clamp(t, 0.0, 1.0)*texture2D(mytex, ouv);\n"+ " /*gl_FragColor = vec4(0);*/\n"+ "}\n"} }); base.LoadContent(); } protected override void UnloadContent() { base.UnloadContent(); if (thetex != null) { thetex.Dispose(); thetex = null; } if (hlsl != null) { hlsl.Dispose(); hlsl = null; } if (glsl != null) { glsl.Dispose(); glsl = null; } if (sb != null) { sb.Dispose(); sb = null; } } TimeSpan totalTime = TimeSpan.Zero; protected override void Update(GameTime gt) { totalTime += gt.ElapsedGameTime; ks = Keyboard.GetState(); base.Update(gt); if (ks.IsKeyDown(Keys.Escape)) { Exit(); return; } } protected override void Draw(GameTime gt) { GraphicsDevice.Clear(Color.CornflowerBlue); base.Draw(gt); /*for (int i = 0; i < hlsl.Techniques.Count; ++i) Console.WriteLine(String.Format("t{0}: {1}", i, hlsl.Techniques[i].Name));*/ /*var tech = hlsl.CurrentTechnique = hlsl.Techniques[0]; for (int i = 0; i < tech.Passes.Count; ++i) { //Console.WriteLine(String.Format("p{0}: {1}", i, tech.Passes[i].Name)); tech.Passes[i].Apply(); GraphicsDevice.DrawUserPrimitives( PrimitiveType.TriangleStrip, vertices_l, 0, 2, VertexType.Format); }*/ /*int i = 0; foreach (var p in glsl.Parameters) { Console.WriteLine("param[" + i + "] = " + p.Name); ++i; }*/ var vp = GraphicsDevice.Viewport; glsl.Parameters["fGlobalTime" ].SetValue((float)totalTime.TotalSeconds); glsl.Parameters["v2Resolution"].SetValue(new Vector2(vp.Width, vp.Height)); glsl.Parameters["mytex" ].SetValue(thetex); using (var act = glsl.Bind()) { GraphicsDevice.DrawUserPrimitives( PrimitiveType.TriangleStrip, vertices_fs, 0, 2, VertexType.Format); } } readonly VertexType[] vertices_fs = new[] { new VertexType(new Vector3(-1, -1, 0), Color.Red , new Vector2(0, 0)) , new VertexType(new Vector3(-1, 1, 0), Color.Blue , new Vector2(0, 1)) , new VertexType(new Vector3( 1, -1, 0), Color.Green , new Vector2(1, 0)) , new VertexType(new Vector3( 1, 1, 0), Color.Yellow, new Vector2(1, 1)) }; readonly VertexType[] vertices_r = new[] { new VertexType(new Vector3( 0, -1, 0), Color.Red , new Vector2(0, 0)) , new VertexType(new Vector3( 0, 1, 0), Color.Blue , new Vector2(0, 1)) , new VertexType(new Vector3( 1, -1, 0), Color.Green , new Vector2(1, 0)) , new VertexType(new Vector3( 1, 1, 0), Color.Yellow, new Vector2(1, 1)) }; readonly VertexType[] vertices_l = new[] { new VertexType(new Vector3(-1, -1, 0), Color.Red , new Vector2(0, 0)) , new VertexType(new Vector3(-1, 1, 0), Color.Blue , new Vector2(0, 1)) , new VertexType(new Vector3( 0, -1, 0), Color.Green , new Vector2(1, 0)) , new VertexType(new Vector3( 0, 1, 0), Color.Yellow, new Vector2(1, 1)) }; readonly VertexType[] vertices_tr = new[] { new VertexType(new Vector3( 0, 0, 0), Color.Red , new Vector2(0, 0)) , new VertexType(new Vector3( 0, 1, 0), Color.Blue , new Vector2(0, 1)) , new VertexType(new Vector3( 1, 0, 0), Color.Green , new Vector2(1, 0)) , new VertexType(new Vector3( 1, 1, 0), Color.Yellow, new Vector2(1, 1)) }; readonly VertexType[] vertices_br = new[] { new VertexType(new Vector3( 0, -1, 0), Color.Red , new Vector2(0, 0)) , new VertexType(new Vector3( 0, 0, 0), Color.Blue , new Vector2(0, 1)) , new VertexType(new Vector3( 1, -1, 0), Color.Green , new Vector2(1, 0)) , new VertexType(new Vector3( 1, 0, 0), Color.Yellow, new Vector2(1, 1)) }; readonly VertexType[] vertices_tl = new[] { new VertexType(new Vector3(-1, 0, 0), Color.Red , new Vector2(0, 0)) , new VertexType(new Vector3(-1, 1, 0), Color.Blue , new Vector2(0, 1)) , new VertexType(new Vector3( 0, 0, 0), Color.Green , new Vector2(1, 0)) , new VertexType(new Vector3( 0, 1, 0), Color.Yellow, new Vector2(1, 1)) }; readonly VertexType[] vertices_bl = new[] { new VertexType(new Vector3(-1, -1, 0), Color.Red , new Vector2(0, 0)) , new VertexType(new Vector3(-1, 0, 0), Color.Blue , new Vector2(0, 1)) , new VertexType(new Vector3( 0, -1, 0), Color.Green , new Vector2(1, 0)) , new VertexType(new Vector3( 0, 0, 0), Color.Yellow, new Vector2(1, 1)) }; } static class Program { [STAThread] static void Main(string[] args) { using (var g = new TestGame()) g.Run(); } }