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 System.Runtime.InteropServices; | ||||||
|  | using MoonWorks.Math; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorksTest | namespace MoonWorksTest | ||||||
| { | { | ||||||
|     [StructLayout(LayoutKind.Sequential)] |     [StructLayout(LayoutKind.Sequential)] | ||||||
|     struct Vertex |     struct PositionTexture | ||||||
|     { |     { | ||||||
|         public float x, y, z; |         public Vector3 Position; | ||||||
|         public float u, v; |         public Vector2 Texture; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
|  | using MoonWorks; | ||||||
| using MoonWorks.Graphics; | using MoonWorks.Graphics; | ||||||
| using MoonWorks.Window; |  | ||||||
| 
 | 
 | ||||||
| namespace MoonWorksTest | namespace MoonWorksTest | ||||||
| { | { | ||||||
|  | @ -15,7 +15,13 @@ namespace MoonWorksTest | ||||||
|                 ScreenMode = ScreenMode.Windowed |                 ScreenMode = ScreenMode.Windowed | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             TestGame game = new TestGame(windowCreateInfo, PresentMode.FIFO, 60, true); |             TestGame game = new TestGame( | ||||||
|  |                 windowCreateInfo, | ||||||
|  |                 PresentMode.FIFO, | ||||||
|  |                 60, | ||||||
|  |                 true | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|             game.Run(); |             game.Run(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
							
								
								
									
										295
									
								
								src/TestGame.cs
								
								
								
								
							
							
						
						
									
										295
									
								
								src/TestGame.cs
								
								
								
								
							|  | @ -2,9 +2,8 @@ using MoonWorks; | ||||||
| using MoonWorks.Audio; | using MoonWorks.Audio; | ||||||
| using MoonWorks.Graphics; | using MoonWorks.Graphics; | ||||||
| using MoonWorks.Input; | using MoonWorks.Input; | ||||||
| using MoonWorks.Window; |  | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Threading; | using System.Threading.Tasks; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorksTest | namespace MoonWorksTest | ||||||
| { | { | ||||||
|  | @ -20,28 +19,20 @@ namespace MoonWorksTest | ||||||
| 
 | 
 | ||||||
|         Buffer vertexBuffer; |         Buffer vertexBuffer; | ||||||
| 
 | 
 | ||||||
|         Rect renderArea; |  | ||||||
|         Rect flip; |  | ||||||
|         Color clearColor; |         Color clearColor; | ||||||
|         DepthStencilValue depthStencilClear; |  | ||||||
| 
 | 
 | ||||||
|         Texture mainColorTargetTexture; |  | ||||||
|         TextureSlice mainColorTargetTextureSlice; |  | ||||||
|         RenderTarget mainColorTarget; |  | ||||||
| 
 |  | ||||||
|         RenderPass mainRenderPass; |  | ||||||
|         Framebuffer mainFramebuffer; |  | ||||||
|         GraphicsPipeline mainGraphicsPipeline; |         GraphicsPipeline mainGraphicsPipeline; | ||||||
| 
 | 
 | ||||||
|         byte[] screenshotPixels; |         byte[] screenshotPixels; | ||||||
|         Buffer screenshotBuffer; |         Buffer screenshotBuffer; | ||||||
|         uint screenShotBufferSize; |         uint screenshotBufferSize; | ||||||
|         Thread screenshotThread; |  | ||||||
| 
 | 
 | ||||||
|         StaticSound music; |         StaticSound music; | ||||||
|         StaticSoundInstance musicInstance; |         StaticSoundInstance musicInstance; | ||||||
|         StreamingSoundOgg musicStream; |         StreamingSoundOgg musicStream; | ||||||
| 
 | 
 | ||||||
|  |         bool screenshotInProgress = false; | ||||||
|  | 
 | ||||||
|         public TestGame(WindowCreateInfo windowCreateInfo, PresentMode presentMode, int targetTimestep = 60, bool debugMode = false) : base(windowCreateInfo, presentMode, targetTimestep, debugMode) |         public TestGame(WindowCreateInfo windowCreateInfo, PresentMode presentMode, int targetTimestep = 60, bool debugMode = false) : base(windowCreateInfo, presentMode, targetTimestep, debugMode) | ||||||
|         { |         { | ||||||
|             var windowWidth = windowCreateInfo.WindowWidth; |             var windowWidth = windowCreateInfo.WindowWidth; | ||||||
|  | @ -64,206 +55,60 @@ namespace MoonWorksTest | ||||||
| 
 | 
 | ||||||
|             /* Load Vertex Data */ |             /* Load Vertex Data */ | ||||||
| 
 | 
 | ||||||
|             var vertices = new Vertex[3]; |             var vertices = new PositionTexture[3]; | ||||||
|             vertices[0].x = -1; |             vertices[0].Position.X = -1; | ||||||
|             vertices[0].y = -1; |             vertices[0].Position.Y = -1; | ||||||
|             vertices[0].z = 0; |             vertices[0].Position.Z = 0; | ||||||
|             vertices[0].u = 0; |             vertices[0].Texture.X = 0; | ||||||
|             vertices[0].v = 1; |             vertices[0].Texture.Y = 1; | ||||||
| 
 | 
 | ||||||
|             vertices[1].x = 3; |             vertices[1].Position.X = 3; | ||||||
|             vertices[1].y = -1; |             vertices[1].Position.Y = -1; | ||||||
|             vertices[1].z = 0; |             vertices[1].Position.Z = 0; | ||||||
|             vertices[1].u = 1; |             vertices[1].Texture.X = 1; | ||||||
|             vertices[1].v = 1; |             vertices[1].Texture.Y = 1; | ||||||
| 
 | 
 | ||||||
|             vertices[2].x = -1; |             vertices[2].Position.X = -1; | ||||||
|             vertices[2].y = 3; |             vertices[2].Position.Y = 3; | ||||||
|             vertices[2].z = 0; |             vertices[2].Position.Z = 0; | ||||||
|             vertices[2].u = 0; |             vertices[2].Texture.X = 0; | ||||||
|             vertices[2].v = 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); |             uploadCommandBuffer.SetBufferData(vertexBuffer, vertices); | ||||||
| 
 | 
 | ||||||
|             GraphicsDevice.Submit(uploadCommandBuffer); |             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 */ |             /* 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( |             mainGraphicsPipeline = new GraphicsPipeline( | ||||||
|                 GraphicsDevice, |                 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; |             screenshotBufferSize = windowWidth * windowHeight * 4; | ||||||
|             screenshotPixels = new byte[screenShotBufferSize]; |             screenshotPixels = new byte[screenshotBufferSize]; | ||||||
|             screenshotBuffer = new Buffer(GraphicsDevice, 0, screenShotBufferSize); |             screenshotBuffer = new Buffer(GraphicsDevice, 0, screenshotBufferSize); | ||||||
|             screenshotThread = new Thread(new ThreadStart(SaveScreenshot)); |  | ||||||
| 
 | 
 | ||||||
|             music = StaticSound.LoadOgg(AudioDevice, Path.Combine("Content", "title_screen.ogg")); |             music = StaticSound.LoadOgg(AudioDevice, Path.Combine("Content", "title_screen.ogg")); | ||||||
|             musicInstance = music.CreateInstance(); |             musicInstance = music.CreateInstance(); | ||||||
|  | @ -280,21 +125,20 @@ namespace MoonWorksTest | ||||||
| 
 | 
 | ||||||
|         protected override void Draw(System.TimeSpan dt, double alpha) |         protected override void Draw(System.TimeSpan dt, double alpha) | ||||||
|         { |         { | ||||||
|             var screenshotPressed = Inputs.Keyboard.IsPressed(Keycode.S); |  | ||||||
| 
 |  | ||||||
|             var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); |             var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); | ||||||
| 
 | 
 | ||||||
|  |             var swapchainTexture = commandBuffer.AcquireSwapchainTexture(Window); | ||||||
|  |             var takeScreenshot = Inputs.Keyboard.IsPressed(Keycode.S) && !screenshotInProgress && (swapchainTexture != null); | ||||||
|  | 
 | ||||||
|  |             if (swapchainTexture != null) | ||||||
|  |             { | ||||||
|                 commandBuffer.BeginRenderPass( |                 commandBuffer.BeginRenderPass( | ||||||
|                 mainRenderPass, |                     new ColorAttachmentInfo(swapchainTexture, clearColor) | ||||||
|                 mainFramebuffer, |  | ||||||
|                 renderArea, |  | ||||||
|                 depthStencilClear, |  | ||||||
|                 clearColor.ToVector4() |  | ||||||
|                 ); |                 ); | ||||||
| 
 | 
 | ||||||
|                 commandBuffer.BindGraphicsPipeline(mainGraphicsPipeline); |                 commandBuffer.BindGraphicsPipeline(mainGraphicsPipeline); | ||||||
| 
 | 
 | ||||||
|             commandBuffer.BindVertexBuffers(0, new BufferBinding(vertexBuffer, 0)); |                 commandBuffer.BindVertexBuffers(vertexBuffer); | ||||||
|                 commandBuffer.BindFragmentSamplers( |                 commandBuffer.BindFragmentSamplers( | ||||||
|                     new TextureSamplerBinding(woodTexture, sampler), |                     new TextureSamplerBinding(woodTexture, sampler), | ||||||
|                     new TextureSamplerBinding(noiseTexture, sampler) |                     new TextureSamplerBinding(noiseTexture, sampler) | ||||||
|  | @ -304,25 +148,46 @@ namespace MoonWorksTest | ||||||
|                 commandBuffer.DrawPrimitives(0, 1, 0, fragmentParamOffset); |                 commandBuffer.DrawPrimitives(0, 1, 0, fragmentParamOffset); | ||||||
|                 commandBuffer.EndRenderPass(); |                 commandBuffer.EndRenderPass(); | ||||||
| 
 | 
 | ||||||
|             if (screenshotPressed) |                 if (takeScreenshot) | ||||||
|                 { |                 { | ||||||
|                 commandBuffer.CopyTextureToBuffer(mainColorTargetTextureSlice, screenshotBuffer); |                     commandBuffer.CopyTextureToBuffer(new TextureSlice(swapchainTexture), screenshotBuffer); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             commandBuffer.QueuePresent(mainColorTargetTextureSlice, flip, Filter.Nearest); |  | ||||||
|             GraphicsDevice.Submit(commandBuffer); |             GraphicsDevice.Submit(commandBuffer); | ||||||
| 
 | 
 | ||||||
|             if (screenshotPressed) |             if (takeScreenshot) | ||||||
|             { |             { | ||||||
|                 screenshotThread.Start(); |                 Task.Run(() => SaveScreenshot()); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void 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(); |             GraphicsDevice.Wait(); | ||||||
|             screenshotBuffer.GetData(screenshotPixels, screenShotBufferSize); |             screenshotBuffer.GetData(screenshotPixels, screenshotBufferSize); | ||||||
|             Texture.SavePNG("screenshot.png", 1280, 720, screenshotPixels); | 
 | ||||||
|  |             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