API update
							parent
							
								
									beb9a4dff0
								
							
						
					
					
						commit
						922e4cf0f1
					
				
										
											Binary file not shown.
										
									
								
							|  | @ -1 +1 @@ | |||
| Subproject commit d2fca3654bd90817885f0006058cccd6437da22c | ||||
| Subproject commit 111df04c0f7be740108cc3536eda3629572714d8 | ||||
										
											Binary file not shown.
										
									
								
							|  | @ -1,11 +1,12 @@ | |||
| using System.Runtime.InteropServices; | ||||
| using MoonWorks.Math; | ||||
| 
 | ||||
| namespace MoonWorksTest | ||||
| { | ||||
|     [StructLayout(LayoutKind.Sequential)] | ||||
|     struct Vertex | ||||
|     struct PositionTexture | ||||
|     { | ||||
|         public float x, y, z; | ||||
|         public float u, v; | ||||
|         public Vector3 Position; | ||||
|         public Vector2 Texture; | ||||
|     } | ||||
| } | ||||
|  | @ -1,5 +1,5 @@ | |||
| using MoonWorks; | ||||
| using MoonWorks.Graphics; | ||||
| using MoonWorks.Window; | ||||
| 
 | ||||
| namespace MoonWorksTest | ||||
| { | ||||
|  | @ -15,7 +15,13 @@ namespace MoonWorksTest | |||
|                 ScreenMode = ScreenMode.Windowed | ||||
|             }; | ||||
| 
 | ||||
|             TestGame game = new TestGame(windowCreateInfo, PresentMode.FIFO, 60, true); | ||||
|             TestGame game = new TestGame( | ||||
|                 windowCreateInfo, | ||||
|                 PresentMode.FIFO, | ||||
|                 60, | ||||
|                 true | ||||
|             ); | ||||
| 
 | ||||
|             game.Run(); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										321
									
								
								src/TestGame.cs
								
								
								
								
							
							
						
						
									
										321
									
								
								src/TestGame.cs
								
								
								
								
							|  | @ -2,9 +2,8 @@ using MoonWorks; | |||
| using MoonWorks.Audio; | ||||
| using MoonWorks.Graphics; | ||||
| using MoonWorks.Input; | ||||
| using MoonWorks.Window; | ||||
| using System.IO; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace MoonWorksTest | ||||
| { | ||||
|  | @ -20,28 +19,20 @@ namespace MoonWorksTest | |||
| 
 | ||||
|         Buffer vertexBuffer; | ||||
| 
 | ||||
|         Rect renderArea; | ||||
|         Rect flip; | ||||
|         Color clearColor; | ||||
|         DepthStencilValue depthStencilClear; | ||||
| 
 | ||||
|         Texture mainColorTargetTexture; | ||||
|         TextureSlice mainColorTargetTextureSlice; | ||||
|         RenderTarget mainColorTarget; | ||||
| 
 | ||||
|         RenderPass mainRenderPass; | ||||
|         Framebuffer mainFramebuffer; | ||||
|         GraphicsPipeline mainGraphicsPipeline; | ||||
| 
 | ||||
|         byte[] screenshotPixels; | ||||
|         Buffer screenshotBuffer; | ||||
|         uint screenShotBufferSize; | ||||
|         Thread screenshotThread; | ||||
|         uint screenshotBufferSize; | ||||
| 
 | ||||
|         StaticSound music; | ||||
|         StaticSoundInstance musicInstance; | ||||
|         StreamingSoundOgg musicStream; | ||||
| 
 | ||||
|         bool screenshotInProgress = false; | ||||
| 
 | ||||
|         public TestGame(WindowCreateInfo windowCreateInfo, PresentMode presentMode, int targetTimestep = 60, bool debugMode = false) : base(windowCreateInfo, presentMode, targetTimestep, debugMode) | ||||
|         { | ||||
|             var windowWidth = windowCreateInfo.WindowWidth; | ||||
|  | @ -64,206 +55,60 @@ namespace MoonWorksTest | |||
| 
 | ||||
|             /* Load Vertex Data */ | ||||
| 
 | ||||
|             var vertices = new Vertex[3]; | ||||
|             vertices[0].x = -1; | ||||
|             vertices[0].y = -1; | ||||
|             vertices[0].z = 0; | ||||
|             vertices[0].u = 0; | ||||
|             vertices[0].v = 1; | ||||
|             var vertices = new PositionTexture[3]; | ||||
|             vertices[0].Position.X = -1; | ||||
|             vertices[0].Position.Y = -1; | ||||
|             vertices[0].Position.Z = 0; | ||||
|             vertices[0].Texture.X = 0; | ||||
|             vertices[0].Texture.Y = 1; | ||||
| 
 | ||||
|             vertices[1].x = 3; | ||||
|             vertices[1].y = -1; | ||||
|             vertices[1].z = 0; | ||||
|             vertices[1].u = 1; | ||||
|             vertices[1].v = 1; | ||||
|             vertices[1].Position.X = 3; | ||||
|             vertices[1].Position.Y = -1; | ||||
|             vertices[1].Position.Z = 0; | ||||
|             vertices[1].Texture.X = 1; | ||||
|             vertices[1].Texture.Y = 1; | ||||
| 
 | ||||
|             vertices[2].x = -1; | ||||
|             vertices[2].y = 3; | ||||
|             vertices[2].z = 0; | ||||
|             vertices[2].u = 0; | ||||
|             vertices[2].v = 0; | ||||
|             vertices[2].Position.X = -1; | ||||
|             vertices[2].Position.Y = 3; | ||||
|             vertices[2].Position.Z = 0; | ||||
|             vertices[2].Texture.X = 0; | ||||
|             vertices[2].Texture.Y = 0; | ||||
| 
 | ||||
|             vertexBuffer = new Buffer(GraphicsDevice, BufferUsageFlags.Vertex, 4 * 5 * 3); | ||||
|             vertexBuffer = Buffer.Create<PositionTexture>(GraphicsDevice, BufferUsageFlags.Vertex, 3); | ||||
|             uploadCommandBuffer.SetBufferData(vertexBuffer, vertices); | ||||
| 
 | ||||
|             GraphicsDevice.Submit(uploadCommandBuffer); | ||||
| 
 | ||||
|             /* Render Pass */ | ||||
| 
 | ||||
|             renderArea.X = 0; | ||||
|             renderArea.Y = 0; | ||||
|             renderArea.W = (int) windowWidth; | ||||
|             renderArea.H = (int) windowHeight; | ||||
| 
 | ||||
|             flip.X = 0; | ||||
|             flip.Y = (int) windowHeight; | ||||
|             flip.W = (int) windowWidth; | ||||
|             flip.H = -(int) windowHeight; | ||||
| 
 | ||||
|             clearColor.R = 237; | ||||
|             clearColor.G = 41; | ||||
|             clearColor.B = 57; | ||||
|             clearColor.A = byte.MaxValue; | ||||
| 
 | ||||
|             ColorTargetDescription colorTargetDescription = new ColorTargetDescription | ||||
|             { | ||||
|                 Format = TextureFormat.R8G8B8A8, | ||||
|                 MultisampleCount = SampleCount.One, | ||||
|                 LoadOp = LoadOp.Clear, | ||||
|                 StoreOp = StoreOp.Store | ||||
|             }; | ||||
| 
 | ||||
|             mainRenderPass = new RenderPass(GraphicsDevice, colorTargetDescription); | ||||
| 
 | ||||
|             mainColorTargetTexture = Texture.CreateTexture2D( | ||||
|                 GraphicsDevice, | ||||
|                 windowWidth, | ||||
|                 windowHeight, | ||||
|                 TextureFormat.R8G8B8A8, | ||||
|                 TextureUsageFlags.ColorTarget | ||||
|             ); | ||||
| 
 | ||||
|             mainColorTargetTextureSlice = new TextureSlice(mainColorTargetTexture); | ||||
|             mainColorTarget = new RenderTarget(GraphicsDevice, mainColorTargetTextureSlice); | ||||
| 
 | ||||
|             mainFramebuffer = new Framebuffer( | ||||
|                 GraphicsDevice, | ||||
|                 windowWidth, | ||||
|                 windowHeight, | ||||
|                 mainRenderPass, | ||||
|                 null, | ||||
|                 mainColorTarget | ||||
|             ); | ||||
| 
 | ||||
|             /* Pipeline */ | ||||
| 
 | ||||
|             ColorTargetBlendState[] colorTargetBlendStates = new ColorTargetBlendState[1] | ||||
|             { | ||||
|                 ColorTargetBlendState.None | ||||
|             }; | ||||
| 
 | ||||
|             ColorBlendState colorBlendState = new ColorBlendState | ||||
|             { | ||||
|                 LogicOpEnable = false, | ||||
|                 LogicOp = LogicOp.NoOp, | ||||
|                 BlendConstants = new BlendConstants(), | ||||
|                 ColorTargetBlendStates = colorTargetBlendStates | ||||
|             }; | ||||
| 
 | ||||
|             DepthStencilState depthStencilState = DepthStencilState.Disable; | ||||
| 
 | ||||
|             ShaderStageState vertexShaderState = new ShaderStageState | ||||
|             { | ||||
|                 ShaderModule = passthroughVertexShaderModule, | ||||
|                 EntryPointName = "main", | ||||
|                 UniformBufferSize = 0 | ||||
|             }; | ||||
| 
 | ||||
|             ShaderStageState fragmentShaderState = new ShaderStageState | ||||
|             { | ||||
|                 ShaderModule = raymarchFragmentShaderModule, | ||||
|                 EntryPointName = "main", | ||||
|                 UniformBufferSize = 16 | ||||
|             }; | ||||
| 
 | ||||
|             MultisampleState multisampleState = MultisampleState.None; | ||||
| 
 | ||||
|             GraphicsPipelineLayoutInfo pipelineLayoutInfo = new GraphicsPipelineLayoutInfo | ||||
|             { | ||||
|                 VertexSamplerBindingCount = 0, | ||||
|                 FragmentSamplerBindingCount = 2 | ||||
|             }; | ||||
| 
 | ||||
|             RasterizerState rasterizerState = RasterizerState.CW_CullBack; | ||||
| 
 | ||||
|             var vertexBindings = new VertexBinding[1] | ||||
|             { | ||||
|                 new VertexBinding | ||||
|                 { | ||||
|                     Binding = 0, | ||||
|                     InputRate = VertexInputRate.Vertex, | ||||
|                     Stride = 4 * 5 | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
|             var vertexAttributes = new VertexAttribute[2] | ||||
|             { | ||||
|                 new VertexAttribute | ||||
|                 { | ||||
|                     Binding = 0, | ||||
|                     Location = 0, | ||||
|                     Format = VertexElementFormat.Vector3, | ||||
|                     Offset = 0 | ||||
|                 }, | ||||
|                 new VertexAttribute | ||||
|                 { | ||||
|                     Binding = 0, | ||||
|                     Location = 1, | ||||
|                     Format = VertexElementFormat.Vector2, | ||||
|                     Offset = 4 * 3 | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
|             VertexInputState vertexInputState = new VertexInputState | ||||
|             { | ||||
|                 VertexBindings = vertexBindings, | ||||
|                 VertexAttributes = vertexAttributes | ||||
|             }; | ||||
| 
 | ||||
|             var viewports = new Viewport[1] | ||||
|             { | ||||
|                 new Viewport | ||||
|                 { | ||||
|                     X = 0, | ||||
|                     Y = 0, | ||||
|                     W = windowWidth, | ||||
|                     H = windowHeight, | ||||
|                     MinDepth = 0, | ||||
|                     MaxDepth = 1 | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
|             var scissors = new Rect[1] | ||||
|             { | ||||
|                 new Rect | ||||
|                 { | ||||
|                     X = 0, | ||||
|                     Y = 0, | ||||
|                     W = (int) windowWidth, | ||||
|                     H = (int) windowHeight | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
|             ViewportState viewportState = new ViewportState | ||||
|             { | ||||
|                 Viewports = viewports, | ||||
|                 Scissors = scissors | ||||
|             }; | ||||
| 
 | ||||
|             var graphicsPipelineCreateInfo = new GraphicsPipelineCreateInfo | ||||
|             { | ||||
|                 ColorBlendState = colorBlendState, | ||||
|                 DepthStencilState = depthStencilState, | ||||
|                 VertexShaderState = vertexShaderState, | ||||
|                 FragmentShaderState = fragmentShaderState, | ||||
|                 MultisampleState = multisampleState, | ||||
|                 PipelineLayoutInfo = pipelineLayoutInfo, | ||||
|                 RasterizerState = rasterizerState, | ||||
|                 PrimitiveType = PrimitiveType.TriangleList, | ||||
|                 VertexInputState = vertexInputState, | ||||
|                 ViewportState = viewportState, | ||||
|                 RenderPass = mainRenderPass | ||||
|             }; | ||||
| 
 | ||||
|             mainGraphicsPipeline = new GraphicsPipeline( | ||||
|                 GraphicsDevice, | ||||
|                 graphicsPipelineCreateInfo | ||||
|                 new GraphicsPipelineCreateInfo | ||||
|                 { | ||||
|                     AttachmentInfo = new GraphicsPipelineAttachmentInfo( | ||||
|                         new ColorAttachmentDescription( | ||||
|                             GraphicsDevice.GetSwapchainFormat(Window), | ||||
|                             ColorAttachmentBlendState.None | ||||
|                         ) | ||||
|                     ), | ||||
|                     DepthStencilState = DepthStencilState.Disable, | ||||
|                     VertexShaderInfo = GraphicsShaderInfo.Create(passthroughVertexShaderModule, "main", 0), | ||||
|                     VertexInputState = new VertexInputState( | ||||
|                         VertexBinding.Create<PositionTexture>(), | ||||
|                         VertexAttribute.Create<PositionTexture>("Position", 0), | ||||
|                         VertexAttribute.Create<PositionTexture>("Texture", 1) | ||||
|                     ), | ||||
|                     PrimitiveType = PrimitiveType.TriangleList, | ||||
|                     FragmentShaderInfo = GraphicsShaderInfo.Create<RaymarchUniforms>(raymarchFragmentShaderModule, "main", 2), | ||||
|                     RasterizerState = RasterizerState.CW_CullBack, | ||||
|                     ViewportState = new ViewportState((int)Window.Width, (int)Window.Height), | ||||
|                     MultisampleState = MultisampleState.None | ||||
|                 } | ||||
|             ); | ||||
| 
 | ||||
|             screenShotBufferSize = windowWidth * windowHeight * 4; | ||||
|             screenshotPixels = new byte[screenShotBufferSize]; | ||||
|             screenshotBuffer = new Buffer(GraphicsDevice, 0, screenShotBufferSize); | ||||
|             screenshotThread = new Thread(new ThreadStart(SaveScreenshot)); | ||||
|             screenshotBufferSize = windowWidth * windowHeight * 4; | ||||
|             screenshotPixels = new byte[screenshotBufferSize]; | ||||
|             screenshotBuffer = new Buffer(GraphicsDevice, 0, screenshotBufferSize); | ||||
| 
 | ||||
|             music = StaticSound.LoadOgg(AudioDevice, Path.Combine("Content", "title_screen.ogg")); | ||||
|             musicInstance = music.CreateInstance(); | ||||
|  | @ -280,49 +125,69 @@ namespace MoonWorksTest | |||
| 
 | ||||
|         protected override void Draw(System.TimeSpan dt, double alpha) | ||||
|         { | ||||
|             var screenshotPressed = Inputs.Keyboard.IsPressed(Keycode.S); | ||||
| 
 | ||||
|             var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); | ||||
| 
 | ||||
|             commandBuffer.BeginRenderPass( | ||||
|                 mainRenderPass, | ||||
|                 mainFramebuffer, | ||||
|                 renderArea, | ||||
|                 depthStencilClear, | ||||
|                 clearColor.ToVector4() | ||||
|             ); | ||||
|             var swapchainTexture = commandBuffer.AcquireSwapchainTexture(Window); | ||||
|             var takeScreenshot = Inputs.Keyboard.IsPressed(Keycode.S) && !screenshotInProgress && (swapchainTexture != null); | ||||
| 
 | ||||
|             commandBuffer.BindGraphicsPipeline(mainGraphicsPipeline); | ||||
| 
 | ||||
|             commandBuffer.BindVertexBuffers(0, new BufferBinding(vertexBuffer, 0)); | ||||
|             commandBuffer.BindFragmentSamplers( | ||||
|                 new TextureSamplerBinding(woodTexture, sampler), | ||||
|                 new TextureSamplerBinding(noiseTexture, sampler) | ||||
|             ); | ||||
| 
 | ||||
|             var fragmentParamOffset = commandBuffer.PushFragmentShaderUniforms(raymarchUniforms); | ||||
|             commandBuffer.DrawPrimitives(0, 1, 0, fragmentParamOffset); | ||||
|             commandBuffer.EndRenderPass(); | ||||
| 
 | ||||
|             if (screenshotPressed) | ||||
|             if (swapchainTexture != null) | ||||
|             { | ||||
|                 commandBuffer.CopyTextureToBuffer(mainColorTargetTextureSlice, screenshotBuffer); | ||||
|                 commandBuffer.BeginRenderPass( | ||||
|                     new ColorAttachmentInfo(swapchainTexture, clearColor) | ||||
|                 ); | ||||
| 
 | ||||
|                 commandBuffer.BindGraphicsPipeline(mainGraphicsPipeline); | ||||
| 
 | ||||
|                 commandBuffer.BindVertexBuffers(vertexBuffer); | ||||
|                 commandBuffer.BindFragmentSamplers( | ||||
|                     new TextureSamplerBinding(woodTexture, sampler), | ||||
|                     new TextureSamplerBinding(noiseTexture, sampler) | ||||
|                 ); | ||||
| 
 | ||||
|                 var fragmentParamOffset = commandBuffer.PushFragmentShaderUniforms(raymarchUniforms); | ||||
|                 commandBuffer.DrawPrimitives(0, 1, 0, fragmentParamOffset); | ||||
|                 commandBuffer.EndRenderPass(); | ||||
| 
 | ||||
|                 if (takeScreenshot) | ||||
|                 { | ||||
|                     commandBuffer.CopyTextureToBuffer(new TextureSlice(swapchainTexture), screenshotBuffer); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             commandBuffer.QueuePresent(mainColorTargetTextureSlice, flip, Filter.Nearest); | ||||
|             GraphicsDevice.Submit(commandBuffer); | ||||
| 
 | ||||
|             if (screenshotPressed) | ||||
|             if (takeScreenshot) | ||||
|             { | ||||
|                 screenshotThread.Start(); | ||||
|                 Task.Run(() => SaveScreenshot()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void SaveScreenshot() | ||||
|         { | ||||
|             screenshotInProgress = true; | ||||
| 
 | ||||
|             var name = "MoonWorksTest-" + System.DateTime.Now.ToString("MM-dd-yyyy-hh-mm-ss") + ".png"; | ||||
|             System.Console.WriteLine("Saving screenshot " + name + " ..."); | ||||
| 
 | ||||
|             GraphicsDevice.Wait(); | ||||
|             screenshotBuffer.GetData(screenshotPixels, screenShotBufferSize); | ||||
|             Texture.SavePNG("screenshot.png", 1280, 720, screenshotPixels); | ||||
|             screenshotBuffer.GetData(screenshotPixels, screenshotBufferSize); | ||||
| 
 | ||||
|             Texture.SavePNG( | ||||
|                 name, | ||||
|                 1280, | ||||
|                 720, | ||||
|                 GraphicsDevice.GetSwapchainFormat(Window), | ||||
|                 screenshotPixels | ||||
|             ); | ||||
| 
 | ||||
|             System.Console.WriteLine("Screenshot saved!"); | ||||
| 
 | ||||
|             screenshotInProgress = false; | ||||
|         } | ||||
| 
 | ||||
|         protected override void OnDestroy() | ||||
|         { | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,550 @@ | |||
| // Created by inigo quilez - iq/2020 | ||||
| // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. | ||||
| 
 | ||||
| 
 | ||||
| // Everybody has to implement an hexagonal grid. This it mine. | ||||
| // It does raycasting on it, efficiently (just a few muls per step) and robustly | ||||
| // (works in integers). Each cell is visited only once and in the right order. | ||||
| // Based on https://www.shadertoy.com/view/WtSBWK Check castRay() in line 92. | ||||
| 
 | ||||
| // That, plus the fact the ambient occlusion is analytical means this shader should | ||||
| // run smoothly even on a crappy phone. It does on mine! | ||||
| 
 | ||||
| #version 450 | ||||
| 
 | ||||
| layout(set = 1, binding = 0) uniform sampler2D iChannel0; | ||||
| layout(set = 1, binding = 1) uniform sampler2D iChannel1; | ||||
| 
 | ||||
| layout(set = 3, binding = 0) uniform UniformBlock | ||||
| { | ||||
|     float time; | ||||
|     vec2 resolution; | ||||
| } Uniforms; | ||||
| 
 | ||||
| //layout(location = 0) in vec2 fragCoord; | ||||
| 
 | ||||
| layout(location = 0) out vec4 fragColor; | ||||
| 
 | ||||
| // make this bigger if you have a storng PC | ||||
| #define AA 2 | ||||
| 
 | ||||
| // ----------------------------------------- | ||||
| // mod3 - not as trivial as you first though | ||||
| // ----------------------------------------- | ||||
| int mod3( int n ) | ||||
| { | ||||
|     return (n<0) ? 2-((2-n)%3) : n%3; | ||||
| 
 | ||||
|     // Some methods of computing mod3:            // PC-WebGL  Native-OpenGL  Android WebGL | ||||
|     //                                            // --------  -------------  ------- | ||||
|     // 1.  return (n<0) ? 2-((2-n)%3) : n%3;      //    Ok        Ok            Ok | ||||
|     // 2.  return int((uint(n)+0x80000001U)%3u);  //    Ok        Ok            Broken | ||||
|     // 3.  n %= 3; return (n<0)?n+3:n;            //    Ok        Broken        Ok | ||||
|     // 4.  n %= 3; n+=((n>>31)&3); return n;      //    Ok        Broken        Ok | ||||
|     // 5.  return ((n%3)+3)%3;                    //    Ok        Broken        Ok | ||||
|     // 6.  return int[](1,2,0,1,2)[n%3+2];        //    Ok        Broken        Ok | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------- | ||||
| // hash by Hugo Elias) | ||||
| // -------------------------------------- | ||||
| int hash( int n ) { n=(n<<13)^n; return n*(n*n*15731+789221)+1376312589; } | ||||
| 
 | ||||
| 
 | ||||
| // -------------------------------------- | ||||
| // basic hexagon grid functions | ||||
| // -------------------------------------- | ||||
| ivec2 hexagonID( vec2 p ) | ||||
| { | ||||
|     const float k3 = 1.732050807; | ||||
| 	vec2 q = vec2( p.x, p.y*k3*0.5 + p.x*0.5 ); | ||||
| 
 | ||||
|     ivec2 pi = ivec2(floor(q)); | ||||
| 	vec2  pf =       fract(q); | ||||
| 
 | ||||
| 	int v = mod3(pi.x+pi.y); | ||||
| 
 | ||||
| 	int   ca = (v<1)?0:1; | ||||
| 	int   cb = (v<2)?0:1; | ||||
|     ivec2 ma = (pf.x>pf.y)?ivec2(0,1):ivec2(1,0); | ||||
| 
 | ||||
| 	ivec2 id = pi + ca - cb*ma; | ||||
| 
 | ||||
|     return ivec2( id.x, id.y - (id.x+id.y)/3 ); | ||||
| } | ||||
| 
 | ||||
| vec2 hexagonCenFromID( in ivec2 id ) | ||||
| { | ||||
|     const float k3 = 1.732050807; | ||||
|     return vec2(float(id.x),float(id.y)*k3); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------- | ||||
| // the height function. yes, i know reading from a video texture is cool | ||||
| // --------------------------------------------------------------------- | ||||
| const float kMaxH = 6.0; | ||||
| 
 | ||||
| float map( vec2 p, in float time ) | ||||
| { | ||||
|     p *= 0.5; | ||||
|     float f = 0.5+0.5*sin(0.53*p.x+0.5*time+1.0*sin(p.y*0.24))* | ||||
|                       sin(0.13*p.y+time); | ||||
|     f*= 0.75+0.25*sin(1.7*p.x+1.32*time)*sin(1.3*p.y+time*2.1); | ||||
| 	return kMaxH*(0.005+0.995*f); | ||||
| } | ||||
| 
 | ||||
| // -------------------------------------------------- | ||||
| // raycast. this function is the point of this shader | ||||
| // -------------------------------------------------- | ||||
| vec4 castRay( in vec3 ro, in vec3 rd, in float time, | ||||
|               out ivec2 outPrismID, out int outFaceID ) | ||||
| { | ||||
| 	ivec2 hid = hexagonID(ro.xz); | ||||
| 
 | ||||
| 	vec4 res = vec4( -1.0, 0.0, 0.0, 0.0 ); | ||||
| 
 | ||||
|     const float k3 = 0.866025; | ||||
|     const vec2 n1 = vec2( 1.0,0.0); | ||||
|     const vec2 n2 = vec2( 0.5,k3); | ||||
|     const vec2 n3 = vec2(-0.5,k3); | ||||
| 
 | ||||
|     float d1 = 1.0/dot(rd.xz,n1); | ||||
|     float d2 = 1.0/dot(rd.xz,n2); | ||||
|     float d3 = 1.0/dot(rd.xz,n3); | ||||
|     float d4 = 1.0/rd.y; | ||||
| 
 | ||||
|     float s1 = (d1<0.0)?-1.0:1.0; | ||||
|     float s2 = (d2<0.0)?-1.0:1.0; | ||||
|     float s3 = (d3<0.0)?-1.0:1.0; | ||||
|     float s4 = (d4<0.0)?-1.0:1.0; | ||||
| 
 | ||||
|     ivec2 i1 = ivec2( 2,0); if(d1<0.0) i1=-i1; | ||||
|     ivec2 i2 = ivec2( 1,1); if(d2<0.0) i2=-i2; | ||||
|     ivec2 i3 = ivec2(-1,1); if(d3<0.0) i3=-i3; | ||||
| 
 | ||||
|     // traverse hexagon grid (in 2D) | ||||
|     bool found = false; | ||||
|     vec2 t1, t2, t3, t4; | ||||
| 	for( int i=0; i<100; i++ ) | ||||
| 	{ | ||||
|         // fetch height for this hexagon | ||||
| 		vec2  ce = hexagonCenFromID( hid ); | ||||
|         float he = 0.5*map(ce, time); | ||||
| 
 | ||||
|         // compute ray-hexaprism intersection | ||||
|         vec3 oc = ro - vec3(ce.x,he,ce.y); | ||||
|         t1 = (vec2(-s1,s1)-dot(oc.xz,n1))*d1; | ||||
|         t2 = (vec2(-s2,s2)-dot(oc.xz,n2))*d2; | ||||
|         t3 = (vec2(-s3,s3)-dot(oc.xz,n3))*d3; | ||||
|         t4 = (vec2(-s4,s4)*he-oc.y)*d4; | ||||
|         float tN = max(max(t1.x,t2.x),max(t3.x,t4.x)); | ||||
|         float tF = min(min(t1.y,t2.y),min(t3.y,t4.y)); | ||||
|         if( tN<tF && tF>0.0 ) | ||||
|         { | ||||
|             found = true; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         // move to next hexagon | ||||
|              if( t1.y<t2.y && t1.y<t3.y ) hid += i1; | ||||
|         else if( t2.y<t3.y )              hid += i2; | ||||
|         else                              hid += i3; | ||||
| 	} | ||||
| 
 | ||||
| 	if( found ) | ||||
|     { | ||||
|                          {res=vec4(t1.x,s1*vec3(n1.x,0,n1.y)); outFaceID=(d1<0.0)?-1: 1;} | ||||
|         if( t2.x>res.x ) {res=vec4(t2.x,s2*vec3(n2.x,0,n2.y)); outFaceID=(d2<0.0)?-2: 2;} | ||||
|         if( t3.x>res.x ) {res=vec4(t3.x,s3*vec3(n3.x,0,n3.y)); outFaceID=(d3<0.0)?-3: 3;} | ||||
|         if( t4.x>res.x ) {res=vec4(t4.x,s4*vec3( 0.0,1,0));    outFaceID=(d4<0.0)? 4:-4;} | ||||
| 
 | ||||
|         outPrismID = hid; | ||||
|     } | ||||
| 
 | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| // ------------------------------------------------------------------------- | ||||
| // same as above, but simpler sinec we don't need the normal and primtive id | ||||
| // -------------------------------------------------------------------------- | ||||
| float castShadowRay( in vec3 ro, in vec3 rd, in float time ) | ||||
| { | ||||
|     float res = 1.0; | ||||
| 
 | ||||
|     ivec2 hid = hexagonID(ro.xz); | ||||
| 
 | ||||
|     const float k3 = 0.866025; | ||||
|     const vec2 n1 = vec2( 1.0,0.0); | ||||
|     const vec2 n2 = vec2( 0.5,k3); | ||||
|     const vec2 n3 = vec2(-0.5,k3); | ||||
| 
 | ||||
|     float d1 = 1.0/dot(rd.xz,n1); | ||||
|     float d2 = 1.0/dot(rd.xz,n2); | ||||
|     float d3 = 1.0/dot(rd.xz,n3); | ||||
|     float d4 = 1.0/rd.y; | ||||
| 
 | ||||
|     float s1 = (d1<0.0)?-1.0:1.0; | ||||
|     float s2 = (d2<0.0)?-1.0:1.0; | ||||
|     float s3 = (d3<0.0)?-1.0:1.0; | ||||
|     float s4 = (d4<0.0)?-1.0:1.0; | ||||
| 
 | ||||
|     ivec2 i1 = ivec2( 2,0); if(d1<0.0) i1=-i1; | ||||
|     ivec2 i2 = ivec2( 1,1); if(d2<0.0) i2=-i2; | ||||
|     ivec2 i3 = ivec2(-1,1); if(d3<0.0) i3=-i3; | ||||
| 
 | ||||
|     vec2 c1 = (vec2(-s1,s1)-dot(ro.xz,n1))*d1; | ||||
|     vec2 c2 = (vec2(-s2,s2)-dot(ro.xz,n2))*d2; | ||||
|     vec2 c3 = (vec2(-s3,s3)-dot(ro.xz,n3))*d3; | ||||
| 
 | ||||
|     // traverse regular grid (2D) | ||||
| 	for( int i=0; i<8; i++ ) | ||||
| 	{ | ||||
| 		vec2  ce = hexagonCenFromID( hid ); | ||||
|         float he = 0.5*map(ce, time); | ||||
| 
 | ||||
|         vec2 t1 = c1 + dot(ce,n1)*d1; | ||||
|         vec2 t2 = c2 + dot(ce,n2)*d2; | ||||
|         vec2 t3 = c3 + dot(ce,n3)*d3; | ||||
|         vec2 t4 = (vec2(1.0-s4,1.0+s4)*he-ro.y)*d4; | ||||
| 
 | ||||
|         float tN = max(max(t1.x,t2.x),max(t3.x,t4.x)); | ||||
|         float tF = min(min(t1.y,t2.y),min(t3.y,t4.y)); | ||||
|         if( tN < tF && tF > 0.0) | ||||
|         { | ||||
|             res = 0.0; | ||||
|             break; | ||||
| 		} | ||||
| 
 | ||||
|              if( t1.y<t2.y && t1.y<t3.y ) hid += i1; | ||||
|         else if( t2.y<t3.y )              hid += i2; | ||||
|         else                              hid += i3; | ||||
| 	} | ||||
| 
 | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| // ------------------------------------------------------------------------- | ||||
| // analytic occlusion of a quad and an hexagon | ||||
| // ------------------------------------------------------------------------- | ||||
| 
 | ||||
| float macos(float x ) { return acos(clamp(x,-1.0,1.0));} | ||||
| 
 | ||||
| float occlusionQuad( in vec3 pos, in vec3 nor, | ||||
|                      in vec3 v0, in vec3 v1, | ||||
|                      in vec3 v2, in vec3 v3 ) | ||||
| { | ||||
|     v0 = normalize(v0-pos); | ||||
|     v1 = normalize(v1-pos); | ||||
|     v2 = normalize(v2-pos); | ||||
|     v3 = normalize(v3-pos); | ||||
|     float k01 = dot( nor, normalize( cross(v0,v1)) ) * macos( dot(v0,v1) ); | ||||
|     float k12 = dot( nor, normalize( cross(v1,v2)) ) * macos( dot(v1,v2) ); | ||||
|     float k23 = dot( nor, normalize( cross(v2,v3)) ) * macos( dot(v2,v3) ); | ||||
|     float k30 = dot( nor, normalize( cross(v3,v0)) ) * macos( dot(v3,v0) ); | ||||
| 
 | ||||
|     return abs(k01+k12+k23+k30)/6.283185; | ||||
| } | ||||
| 
 | ||||
| float occlusionHexagon( in vec3 pos, in vec3 nor, | ||||
|                         in vec3 v0, in vec3 v1, | ||||
|                         in vec3 v2, in vec3 v3, | ||||
|                         in vec3 v4, in vec3 v5) | ||||
| { | ||||
|     v0 = normalize(v0-pos); | ||||
|     v1 = normalize(v1-pos); | ||||
|     v2 = normalize(v2-pos); | ||||
|     v3 = normalize(v3-pos); | ||||
|     v4 = normalize(v4-pos); | ||||
|     v5 = normalize(v5-pos); | ||||
|     float k01 = dot( nor, normalize( cross(v0,v1)) ) * macos( dot(v0,v1) ); | ||||
|     float k12 = dot( nor, normalize( cross(v1,v2)) ) * macos( dot(v1,v2) ); | ||||
|     float k23 = dot( nor, normalize( cross(v2,v3)) ) * macos( dot(v2,v3) ); | ||||
|     float k34 = dot( nor, normalize( cross(v3,v4)) ) * macos( dot(v3,v4) ); | ||||
|     float k45 = dot( nor, normalize( cross(v4,v5)) ) * macos( dot(v4,v5) ); | ||||
|     float k50 = dot( nor, normalize( cross(v5,v0)) ) * macos( dot(v5,v0) ); | ||||
| 
 | ||||
|     return abs(k01+k12+k23+k34+k45+k50)/6.283185; | ||||
| } | ||||
| 
 | ||||
| // ------------------------------------------------------------------------- | ||||
| // get the walls and top face vertex positions | ||||
| // ------------------------------------------------------------------------- | ||||
| 
 | ||||
| bool getPrismWall( ivec2 prismID, int sid, in float time, | ||||
|                    out vec3 v0, out vec3 v1, out vec3 v2, out vec3 v3 ) | ||||
| { | ||||
|     const ivec2 i1 = ivec2( 2,0); | ||||
|     const ivec2 i2 = ivec2( 1,1); | ||||
|     const ivec2 i3 = ivec2(-1,1); | ||||
| 
 | ||||
|     vec2  ce = hexagonCenFromID( prismID ); | ||||
|     vec3  ce3 = vec3(ce.x,0.0,ce.y); | ||||
| 	float he = map( ce, time); | ||||
| 
 | ||||
|     const float kRa = 2.0/sqrt(3.0); | ||||
|     const float kC1 = kRa*0.5; | ||||
|     const float kC2 = kRa*1.0; | ||||
| 
 | ||||
|     if( sid==0 ) | ||||
|     { | ||||
|     	float he1p = map(hexagonCenFromID( prismID+i1 ), time); | ||||
|         if( he1p<he ) return false; | ||||
|     	v0 = vec3(1.0,he,   kC1); | ||||
|     	v1 = vec3(1.0,he1p, kC1); | ||||
|     	v2 = vec3(1.0,he1p,-kC1); | ||||
|         v3 = vec3(1.0,he,  -kC1); | ||||
|     } | ||||
|     else if( sid==1 ) | ||||
|     { | ||||
|     	float he3m = map(hexagonCenFromID( prismID-i3 ), time); | ||||
|     	if( he3m<he ) return false; | ||||
|         v0 = vec3( 1.0,he,  -kC1); | ||||
|         v1 = vec3( 1.0,he3m,-kC1); | ||||
|         v2 = vec3( 0.0,he3m,-kC2); | ||||
|         v3 = vec3( 0.0,he,  -kC2); | ||||
|     } | ||||
|     else if( sid==2 ) | ||||
|     { | ||||
|     	float he2m = map(hexagonCenFromID( prismID-i2 ), time); | ||||
|         if( he2m<he ) return false; | ||||
|         v0 = vec3( 0.0,he,  -kC2); | ||||
|         v1 = vec3( 0.0,he2m,-kC2); | ||||
|         v2 = vec3(-1.0,he2m,-kC1); | ||||
|         v3 = vec3(-1.0,he,  -kC1); | ||||
|     } | ||||
|     else if( sid==3 ) | ||||
|     { | ||||
|         float he1m = map(hexagonCenFromID( prismID-i1 ), time); | ||||
|         if( he1m<he ) return false; | ||||
|         v0 = vec3(-1.0,he,  -kC1); | ||||
|         v1 = vec3(-1.0,he1m,-kC1); | ||||
|         v2 = vec3(-1.0,he1m, kC1); | ||||
|         v3 = vec3(-1.0,he,   kC1); | ||||
|     } | ||||
|     else if( sid==4 ) | ||||
|     { | ||||
|     	float he3p = map(hexagonCenFromID( prismID+i3 ), time); | ||||
|         if( he3p<he ) return false; | ||||
|         v0 = vec3(-1.0,he,   kC1); | ||||
|         v1 = vec3(-1.0,he3p, kC1); | ||||
|         v2 = vec3( 0.0,he3p, kC2); | ||||
|         v3 = vec3( 0.0,he,   kC2); | ||||
|     } | ||||
|     else //if( sid==5 ) | ||||
|     { | ||||
|     	float he2p = map(hexagonCenFromID( prismID+i2 ), time); | ||||
|         if( he2p<he ) return false; | ||||
|         v0 = vec3( 0.0,he,   kC2); | ||||
|         v1 = vec3( 0.0,he2p, kC2); | ||||
|         v2 = vec3( 1.0,he2p, kC1); | ||||
|         v3 = vec3( 1.0,he,   kC1); | ||||
|     } | ||||
| 
 | ||||
|     v0 += ce3; | ||||
|     v1 += ce3; | ||||
|     v2 += ce3; | ||||
|     v3 += ce3; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void getPrismTop( ivec2 prismID, in float time, | ||||
|                  out vec3 v0, out vec3 v1, out vec3 v2, | ||||
|                  out vec3 v3, out vec3 v4, out vec3 v5 ) | ||||
| { | ||||
|     vec2  ce = hexagonCenFromID( prismID ); | ||||
|     vec3  ce3 = vec3(ce.x,0.0,ce.y); | ||||
| 	float he = map( ce, time); | ||||
| 
 | ||||
|     const float kRa = 2.0/sqrt(3.0); | ||||
|     const float kC1 = kRa*0.5; | ||||
|     const float kC2 = kRa*1.0; | ||||
| 
 | ||||
|     v0 = ce3+vec3(  0.0,he, -kC2); | ||||
|     v1 = ce3+vec3( -1.0,he, -kC1); | ||||
|     v2 = ce3+vec3( -1.0,he,  kC1); | ||||
|     v3 = ce3+vec3(  0.0,he,  kC2); | ||||
|     v4 = ce3+vec3(  1.0,he,  kC1); | ||||
|     v5 = ce3+vec3(  1.0,he, -kC1); | ||||
| } | ||||
| 
 | ||||
| // ------------------------------------------------------------------------- | ||||
| // compute analytical ambient occlusion, by using the solid angle of the | ||||
| // faces surrounding the current point. if one face is missing (it's below | ||||
| // the current prism's height) we ignore the portal and assume light comes | ||||
| // through it. Ideally portals should be recursivelly traversed and clipped | ||||
| // ------------------------------------------------------------------------- | ||||
| 
 | ||||
| float calcOcclusion( in vec3 pos, in vec3 nor, in float time, | ||||
|                      in ivec2 prismID, in int faceID ) | ||||
| { | ||||
|     const ivec2 i1 = ivec2( 2,0); | ||||
|     const ivec2 i2 = ivec2( 1,1); | ||||
|     const ivec2 i3 = ivec2(-1,1); | ||||
| 
 | ||||
|     vec3 v0, v1, v2, v3, v4, v5; | ||||
| 
 | ||||
|          if( faceID==-1 ) prismID += i1; | ||||
|     else if( faceID== 1 ) prismID -= i1; | ||||
|     else if( faceID==-2 ) prismID += i2; | ||||
|     else if( faceID== 2 ) prismID -= i2; | ||||
|     else if( faceID==-3 ) prismID += i3; | ||||
|     else if( faceID== 3 ) prismID -= i3; | ||||
| 
 | ||||
|     float occ = 0.0; | ||||
|     if( faceID!=1 && getPrismWall( prismID, 0, time, v0, v1, v2, v3 ) ) | ||||
|         occ += occlusionQuad(pos,nor,v0,v1,v2,v3); | ||||
|     if( faceID!=-3 && getPrismWall( prismID, 1, time, v0, v1, v2, v3 ) ) | ||||
|         occ += occlusionQuad(pos,nor,v0,v1,v2,v3); | ||||
|     if( faceID!=-2 && getPrismWall( prismID, 2, time, v0, v1, v2, v3 ) ) | ||||
|         occ += occlusionQuad(pos,nor,v0,v1,v2,v3); | ||||
|     if( faceID!=-1 && getPrismWall( prismID, 3, time, v0, v1, v2, v3 ) ) | ||||
|         occ += occlusionQuad(pos,nor,v0,v1,v2,v3); | ||||
|     if( faceID!=3 && getPrismWall( prismID, 4, time, v0, v1, v2, v3 ) ) | ||||
|         occ += occlusionQuad(pos,nor,v0,v1,v2,v3); | ||||
|     if( faceID!=2 && getPrismWall( prismID, 5, time, v0, v1, v2, v3 ) ) | ||||
|         occ += occlusionQuad(pos,nor,v0,v1,v2,v3); | ||||
| 
 | ||||
|     if( faceID!=4 ) | ||||
|     { | ||||
|         getPrismTop( prismID, time, v0, v1, v2, v3, v4, v5 ); | ||||
|         occ += occlusionHexagon(pos,nor,v0,v1,v2,v3,v4,v5); | ||||
| 
 | ||||
|     	occ = 1.0-min(0.5,0.2+0.8*(1.0-occ)*pos.y/kMaxH); | ||||
|     } | ||||
| 
 | ||||
|     return 1.0-occ; | ||||
| } | ||||
| 
 | ||||
| // ------------------------------------------------------------------------- | ||||
| // render = raycast + shade + light | ||||
| // ------------------------------------------------------------------------- | ||||
| 
 | ||||
| vec3 render( in vec3 ro, in vec3 rd, in float time ) | ||||
| { | ||||
|     // raycast | ||||
|     vec3  col = vec3(1.0); | ||||
|     ivec2 prismID; int faceID; | ||||
|     vec4  tnor = castRay( ro, rd, time, prismID, faceID ); | ||||
|     float t = tnor.x; | ||||
|     // if intersection found | ||||
|     if( t>0.0 ) | ||||
|     { | ||||
|         // data at intersection point | ||||
|         vec3  pos = ro + rd*t; | ||||
|         vec3  nor = -tnor.yzw; | ||||
|         vec2  ce = hexagonCenFromID(prismID); | ||||
|         float he = map(ce,time); | ||||
|         int   id = prismID.x*131 + prismID.y*57; | ||||
| 
 | ||||
|         // uvs | ||||
|         vec2 uv = (faceID==4) ? (pos.xz-ce)*0.15 : | ||||
|                                 vec2(atan(pos.x-ce.x,pos.z-ce.y)/3.14156, | ||||
|                                      (pos.y-he)/4.0 ); | ||||
|         uv += ce; | ||||
| 
 | ||||
|         // material color | ||||
|         vec3 mate = vec3(1.0); | ||||
|         id = hash(id); mate *= 0.1+0.9*float((id>>13)&3)/3.0; | ||||
|         id = hash(id); mate  = ( ((id>>8)&15)==0 ) ? vec3(0.7,0.0,0.0) : mate; | ||||
|         vec3 tex = vec3(0.15,0.09,0.07)+0.75*pow(texture(iChannel0,uv.yx).xyz,vec3(1.0,0.95,0.9)); | ||||
|         mate *= tex; | ||||
| 
 | ||||
|         // lighting | ||||
|         float occ = calcOcclusion( pos, nor, time, prismID, faceID ); | ||||
| 
 | ||||
|         // diffuse | ||||
|         col = mate*pow(vec3(occ),vec3(0.95,1.05,1.1)); | ||||
| 
 | ||||
|         // specular | ||||
|         float ks = tex.x*2.0; | ||||
|         vec3 ref = reflect(rd,nor); | ||||
|         col *= 0.85; | ||||
|         float fre = clamp(1.0+dot(nor,rd),0.0,1.0); | ||||
|         col += vec3(1.1)*ks* | ||||
|                smoothstep(0.0,0.15,ref.y)* | ||||
|                (0.04 + 0.96*pow(fre,5.0))* | ||||
|                castShadowRay( pos+nor*0.001, ref, time ); | ||||
| 
 | ||||
|         // fog | ||||
|         col = mix(col,vec3(1.0), 1.0-exp2(-0.00005*t*t) ); | ||||
|     } | ||||
| 
 | ||||
|     return col; | ||||
| } | ||||
| 
 | ||||
| //----------------------------------------------- | ||||
| // main = animate + render + color grade | ||||
| //----------------------------------------------- | ||||
| void main() | ||||
| { | ||||
|     vec2 fragCoord = gl_FragCoord.xy; | ||||
| 
 | ||||
|     fragCoord.y = Uniforms.resolution.y - gl_FragCoord.y; | ||||
| 
 | ||||
| 	// init random seed | ||||
|     ivec2 q = ivec2(fragCoord); | ||||
| 
 | ||||
| 	// sample pixel	and time | ||||
| 	vec3 tot = vec3(0.0); | ||||
| 	for( int m=0; m<AA; m++ ) | ||||
| 	for( int n=0; n<AA; n++ ) | ||||
| 	{ | ||||
|         vec2  of = vec2(m,n)/float(AA) - 0.5; | ||||
|         vec2  p = (2.0*(fragCoord+of)-Uniforms.resolution.xy)/min(Uniforms.resolution.x,Uniforms.resolution.y); | ||||
|         #if AA>1 | ||||
|         float d = 0.5+0.5*sin(fragCoord.x*147.0)*sin(fragCoord.y*131.0); | ||||
|         float time = Uniforms.time - 0.5*(1.0/24.0)*(float(m*AA+n)+d)/float(AA*AA); | ||||
|         #else | ||||
|         float time = Uniforms.time; | ||||
|         #endif | ||||
| 
 | ||||
| 		// camera | ||||
|         float cr = -0.1; | ||||
|         float an = 3.0*time; | ||||
| 	    vec3 ro = vec3(0.1,13.0,1.0-an); | ||||
|         vec3 ta = vec3(0.0,12.0,0.0-an); | ||||
| 
 | ||||
|         // build camera matrix | ||||
|         vec3 ww = normalize( ta - ro); | ||||
|         vec3 uu = normalize(cross( ww,vec3(sin(cr),cos(cr),0.0) )); | ||||
|         vec3 vv = normalize(cross(uu,ww)); | ||||
|         // distort | ||||
|         p *= 0.9+0.1*(p.x*p.x*0.4 + p.y*p.y); | ||||
|         // buid ray | ||||
|         vec3 rd = normalize( p.x*uu + p.y*vv + 2.0*ww ); | ||||
| 
 | ||||
|         // dof | ||||
|         #if AA>1 | ||||
|         vec3 fp = ro + rd*17.0; | ||||
|         vec2 ra = texelFetch(iChannel1,(q+ivec2(13*m,31*n))&1023,0).xy; | ||||
|         ro.xy += 0.3*sqrt(ra.x)*vec2(cos(6.2831*ra.y),sin(6.2831*ra.y)); | ||||
|     	rd = normalize( fp - ro ); | ||||
|         #endif | ||||
| 
 | ||||
|         // render | ||||
|         vec3 col = render( ro, rd, time ); | ||||
| 
 | ||||
|         // accumulate for AA | ||||
| 		tot += col; | ||||
| 	} | ||||
| 	tot /= float(AA*AA); | ||||
| 
 | ||||
| 
 | ||||
|     // hdr->ldr tonemap | ||||
|     tot = tot*1.6/(1.0+tot); | ||||
|     tot = tot*tot*(3.0-2.0*tot); | ||||
| 
 | ||||
|     // gamma | ||||
| 	tot = pow( clamp(tot,0.0,1.0), vec3(0.45) ); | ||||
| 
 | ||||
|     // color grade | ||||
|     vec2 p = fragCoord/Uniforms.resolution.xy; | ||||
|     tot.xyz += (p.xyy-0.5)*0.1; | ||||
| 
 | ||||
|     // vignetting | ||||
| 	tot *= 0.5 + 0.5*pow( 16.0*p.x*p.y*(1.0-p.x)*(1.0-p.y), 0.1 ); | ||||
| 
 | ||||
|     // output | ||||
| 	fragColor = vec4( tot, 1.0 ); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue