diff options
Diffstat (limited to 'samples/Model')
| -rw-r--r-- | samples/Model/Model.csproj | 34 | ||||
| -rw-r--r-- | samples/Model/data/DamagedHelmet.bin | bin | 0 -> 558504 bytes | |||
| -rw-r--r-- | samples/Model/data/DamagedHelmet.gltf | 204 | ||||
| -rw-r--r-- | samples/Model/main.cs | 259 | ||||
| -rw-r--r-- | samples/Model/shaders/model.frag | 72 | ||||
| -rw-r--r-- | samples/Model/shaders/model.vert | 44 |
6 files changed, 613 insertions, 0 deletions
diff --git a/samples/Model/Model.csproj b/samples/Model/Model.csproj new file mode 100644 index 0000000..df98d01 --- /dev/null +++ b/samples/Model/Model.csproj @@ -0,0 +1,34 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <Import Project="$(RootDirectory)netfx.props" /> + <PropertyGroup> + <OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath> + <OutputType>Exe</OutputType> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DefineConstants>TRACE;DEBUG;NETSTANDARD;NETSTANDARD2_0</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + </PropertyGroup> + + <ItemGroup Condition="$(TargetFramework.StartsWith('net4'))"> + <Reference Include="System" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="glTF2Loader" Version="1.1.3-alpha" /> + <PackageReference Include="Vulkan" Version="0.1.3" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\..\vke\CVKL.csproj" /> + </ItemGroup> + + <ItemGroup> + <GLSLShader Include="shaders\**\*.frag;shaders\**\*.vert" /> + <None Remove="shaders\**\*.frag;shaders\**\*.vert" /> + </ItemGroup> + + <Import Project="$(SolutionDir)spirv.targets" /> +</Project> diff --git a/samples/Model/data/DamagedHelmet.bin b/samples/Model/data/DamagedHelmet.bin Binary files differnew file mode 100644 index 0000000..662eacc --- /dev/null +++ b/samples/Model/data/DamagedHelmet.bin diff --git a/samples/Model/data/DamagedHelmet.gltf b/samples/Model/data/DamagedHelmet.gltf new file mode 100644 index 0000000..c61145a --- /dev/null +++ b/samples/Model/data/DamagedHelmet.gltf @@ -0,0 +1,204 @@ +{ + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5123, + "count" : 46356, + "max" : [ + 14555 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 14556, + "max" : [ + 0.9424954056739807, + 0.8128451108932495, + 0.900973916053772 + ], + "min" : [ + -0.9474585652351379, + -1.18715500831604, + -0.9009949564933777 + ], + "type" : "VEC3" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 14556, + "max" : [ + 1.0, + 1.0, + 1.0 + ], + "min" : [ + -1.0, + -1.0, + -1.0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 3, + "componentType" : 5126, + "count" : 14556, + "max" : [ + 0.9999759793281555, + 1.998665988445282 + ], + "min" : [ + 0.002448640065267682, + 1.0005531199858524 + ], + "type" : "VEC2" + } + ], + "asset" : { + "generator" : "Khronos Blender glTF 2.0 exporter", + "version" : "2.0" + }, + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 92712, + "byteOffset" : 0, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 174672, + "byteOffset" : 92712, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 174672, + "byteOffset" : 267384, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 116448, + "byteOffset" : 442056, + "target" : 34962 + } + ], + "buffers" : [ + { + "byteLength" : 558504, + "uri" : "DamagedHelmet.bin" + } + ], + "images" : [ + { + "uri" : "Default_albedo.jpg" + }, + { + "uri" : "Default_metalRoughness.jpg" + }, + { + "uri" : "Default_emissive.jpg" + }, + { + "uri" : "Default_AO.jpg" + }, + { + "uri" : "Default_normal.jpg" + } + ], + "materials" : [ + { + "emissiveFactor" : [ + 1.0, + 1.0, + 1.0 + ], + "emissiveTexture" : { + "index" : 2 + }, + "name" : "Material_MR", + "normalTexture" : { + "index" : 4 + }, + "occlusionTexture" : { + "index" : 3 + }, + "pbrMetallicRoughness" : { + "baseColorTexture" : { + "index" : 0 + }, + "metallicRoughnessTexture" : { + "index" : 1 + } + } + } + ], + "meshes" : [ + { + "name" : "mesh_helmet_LP_13930damagedHelmet", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 2, + "POSITION" : 1, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0 + } + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "node_damagedHelmet_-6514", + "rotation" : [ + 0.7071068286895752, + 0.0, + -0.0, + 0.7071068286895752 + ] + } + ], + "samplers" : [ + {} + ], + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 0 + ] + } + ], + "textures" : [ + { + "sampler" : 0, + "source" : 0 + }, + { + "sampler" : 0, + "source" : 1 + }, + { + "sampler" : 0, + "source" : 2 + }, + { + "sampler" : 0, + "source" : 3 + }, + { + "sampler" : 0, + "source" : 4 + } + ] +} diff --git a/samples/Model/main.cs b/samples/Model/main.cs new file mode 100644 index 0000000..95a6e90 --- /dev/null +++ b/samples/Model/main.cs @@ -0,0 +1,259 @@ +using System.Collections.Generic; +using System.Numerics; +using System.Runtime.InteropServices; +using CVKL; +using VK; + +namespace ModelSample { + class Program : VkWindow { + static void Main (string[] args) { + + Instance.VALIDATION = true; + //Instance.DEBUG_UTILS = true; + //Instance.RENDER_DOC_CAPTURE = true; + + using (Program vke = new Program ()) { + vke.Run (); + } + } + + struct Matrices { + public Matrix4x4 projection; + public Matrix4x4 view; + public Matrix4x4 model; + //public Vector4 lightPos; + } + + public struct PushConstants { + public Matrix4x4 matrix; + } + + Matrices matrices; + + HostBuffer uboMats; + + DescriptorPool descriptorPool; + DescriptorSet dsMatrices, dsTextures; + DescriptorSetLayout descLayoutMatrix; + DescriptorSetLayout descLayoutTextures; + + Framebuffer[] frameBuffers; + + GraphicPipeline pipeline; + + VkSampleCountFlags NUM_SAMPLES = VkSampleCountFlags.SampleCount1; + + float rotSpeed = 0.01f, zoomSpeed = 0.01f; + float rotX, rotY, rotZ = 0f, zoom = 2f; + + SimpleModel helmet; + DebugReport dbgReport; + + Program () : base () { + //dbgReport = new DebugReport (instance); + + descriptorPool = new DescriptorPool (dev, 2, + new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer), + new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 3)); + + descLayoutMatrix = new DescriptorSetLayout (dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex, VkDescriptorType.UniformBuffer)); + + descLayoutTextures = new DescriptorSetLayout (dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) + ); + + + VkPushConstantRange pushConstantRange = new VkPushConstantRange { + stageFlags = VkShaderStageFlags.Vertex, + size = (uint)Marshal.SizeOf<PushConstants>(), + offset = 0 + }; + + GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, NUM_SAMPLES); + cfg.rasterizationState.cullMode = VkCullModeFlags.Back; + if (NUM_SAMPLES != VkSampleCountFlags.SampleCount1) { + cfg.multisampleState.sampleShadingEnable = true; + cfg.multisampleState.minSampleShading = 0.5f; + } + + cfg.Layout = new PipelineLayout (dev, pushConstantRange, descLayoutMatrix, descLayoutTextures); + cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), cfg.Samples); + cfg.AddVertexBinding<Model.Vertex> (0); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); + + cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/model.vert.spv"); + cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/model.frag.spv"); + + pipeline = new GraphicPipeline (cfg); + + helmet = new SimpleModel (presentQueue, "data/models/DamagedHelmet/glTF/DamagedHelmet.gltf"); + //helmet = new SimpleModel (presentQueue, "data/models/Hubble.glb"); + + //helmet = new SimpleModel (presentQueue, "/mnt/devel/vulkan/Lugdunum/resources/models/Box.gltf"); + + dsMatrices = descriptorPool.Allocate (descLayoutMatrix); + dsTextures = descriptorPool.Allocate (descLayoutTextures); + + uboMats = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices); + //matrices.lightPos = new Vector4 (0.0f, 0.0f, -2.0f, 1.0f); + + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMatrices, descLayoutMatrix); + uboUpdate.Write (dev, uboMats.Descriptor); + + DescriptorSetWrites texturesUpdate = new DescriptorSetWrites (dsTextures, descLayoutTextures); + texturesUpdate.Write (dev, + helmet.textures[0].Descriptor, + helmet.textures[1].Descriptor, + helmet.textures[2].Descriptor); + + uboMats.Map ();//permanent map + } + + public override void UpdateView () { + matrices.projection = Matrix4x4.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (45f), + (float)swapChain.Width / (float)swapChain.Height, 0.1f, 256.0f) * Camera.VKProjectionCorrection; + matrices.view = + Matrix4x4.CreateFromAxisAngle (Vector3.UnitZ, rotZ) * + Matrix4x4.CreateFromAxisAngle (Vector3.UnitY, rotY) * + Matrix4x4.CreateFromAxisAngle (Vector3.UnitX, rotX) * + Matrix4x4.CreateTranslation (0, 0, -3f * zoom); + matrices.model = Matrix4x4.Identity; + uboMats.Update (matrices, (uint)Marshal.SizeOf<Matrices> ()); + updateViewRequested = false; + } + + protected override void onMouseMove (double xPos, double yPos) { + double diffX = lastMouseX - xPos; + double diffY = lastMouseY - yPos; + if (MouseButton[0]) { + rotY -= rotSpeed * (float)diffX; + rotX += rotSpeed * (float)diffY; + } else if (MouseButton[1]) { + zoom += zoomSpeed * (float)diffY; + } + updateViewRequested = true; + } + void buildCommandBuffers () { + cmdPool.Reset (VkCommandPoolResetFlags.ReleaseResources); + cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount); + + for (int i = 0; i < swapChain.ImageCount; ++i) { + Framebuffer fb = frameBuffers[i]; + cmds[i].Start (); + + pipeline.RenderPass.Begin (cmds[i], fb); + + cmds[i].SetViewport (swapChain.Width, swapChain.Height); + cmds[i].SetScissor (swapChain.Width, swapChain.Height); + + cmds[i].BindDescriptorSet (pipeline.Layout, dsMatrices); + cmds[i].BindDescriptorSet (pipeline.Layout, dsTextures, 1); + + PushConstants pc = new PushConstants { matrix = Matrix4x4.Identity }; + cmds[i].PushConstant (pipeline.Layout, VkShaderStageFlags.Vertex, pc, (uint)Marshal.SizeOf<Matrix4x4> ()); + + cmds[i].BindPipeline (pipeline); + + helmet.DrawAll (cmds[i], pipeline.Layout); + + pipeline.RenderPass.End (cmds[i]); + + cmds[i].End (); + } + } + + protected override void OnResize () { + + if (frameBuffers != null) + for (int i = 0; i < swapChain.ImageCount; ++i) + frameBuffers[i]?.Dispose (); + frameBuffers = new Framebuffer[swapChain.ImageCount]; + + for (int i = 0; i < swapChain.ImageCount; ++i) + frameBuffers[i] = new Framebuffer (pipeline.RenderPass, swapChain.Width, swapChain.Height, + (pipeline.Samples == VkSampleCountFlags.SampleCount1) ? new Image[] { + swapChain.images[i], + null + } : new Image[] { + null, + null, + swapChain.images[i] + }); + + buildCommandBuffers (); + } + + class SimpleModel : Model { + public GPUBuffer vbo; + public GPUBuffer ibo; + public Image[] textures; + + public SimpleModel (Queue transferQ, string path) { + dev = transferQ.Dev; + + using (CommandPool cmdPool = new CommandPool (dev, transferQ.index)) { + using (CVKL.glTFLoader ctx = new CVKL.glTFLoader (path, transferQ, cmdPool)) { + ulong vertexCount, indexCount; + + ctx.GetVertexCount (out vertexCount, out indexCount, out IndexBufferType); + + ulong vertSize = vertexCount * (ulong)Marshal.SizeOf<Vertex> (); + ulong idxSize = indexCount * (IndexBufferType == VkIndexType.Uint16 ? 2ul : 4ul); + ulong size = vertSize + idxSize; + + vbo = new GPUBuffer (dev, VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, vertSize); + ibo = new GPUBuffer (dev, VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, idxSize); + + vbo.SetName ("vbo gltf"); + ibo.SetName ("ibo gltf"); + + Meshes = new List<Mesh> (ctx.LoadMeshes<Vertex> (IndexBufferType, vbo, 0, ibo, 0)); + Scenes = new List<Scene> (ctx.LoadScenes (out defaultSceneIndex)); + + textures = ctx.LoadImages (); + } + } + } + /// <summary> bind vertex and index buffers </summary> + public virtual void Bind (CommandBuffer cmd) { + cmd.BindVertexBuffer (vbo); + cmd.BindIndexBuffer (ibo, IndexBufferType); + } + public void DrawAll (CommandBuffer cmd, PipelineLayout pipelineLayout) { + //helmet.Meshes + cmd.BindVertexBuffer (vbo); + cmd.BindIndexBuffer (ibo, IndexBufferType); + cmd.DrawIndexed ((uint)Meshes[0].Primitives[0].indexCount); + //foreach (Scene sc in Scenes) { + // foreach (Node node in sc.Root.Children) + // RenderNode (cmd, pipelineLayout, node, sc.Root.localMatrix, shadowPass); + //} + } + } + + protected override void Dispose (bool disposing) { + if (disposing) { + if (!isDisposed) { + helmet.vbo.Dispose (); + helmet.ibo.Dispose (); + foreach (var t in helmet.textures) + t.Dispose (); + + pipeline.Dispose (); + descLayoutMatrix.Dispose (); + descLayoutTextures.Dispose (); + for (int i = 0; i < swapChain.ImageCount; i++) + frameBuffers[i]?.Dispose (); + descriptorPool.Dispose (); + uboMats.Dispose (); + dbgReport?.Dispose (); + } + } + + base.Dispose (disposing); + } + } +} diff --git a/samples/Model/shaders/model.frag b/samples/Model/shaders/model.frag new file mode 100644 index 0000000..351f156 --- /dev/null +++ b/samples/Model/shaders/model.frag @@ -0,0 +1,72 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (set = 1, binding = 0) uniform sampler2D samplerColor; +layout (set = 1, binding = 1) uniform sampler2D samplerNormal; +layout (set = 1, binding = 2) uniform sampler2D samplerOcclusion; + +layout (location = 0) in vec2 inUV; +layout (location = 1) in vec3 inN; +layout (location = 2) in vec3 inV;//ViewDir + +layout (location = 0) out vec4 outFragColor; + +vec3 light = vec3(1.0,.0,1.0); + +// http://www.thetenthplanet.de/archives/1180 +mat3 cotangent_frame(vec3 N, vec3 p, vec2 uv) +{ + // get edge vectors of the pixel triangle + vec3 dp1 = dFdx( p ); + vec3 dp2 = dFdy( p ); + vec2 duv1 = dFdx( uv ); + vec2 duv2 = dFdy( uv ); + + // solve the linear system + vec3 dp2perp = cross( dp2, N ); + vec3 dp1perp = cross( N, dp1 ); + vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; + vec3 B = dp2perp * duv1.y + dp1perp * duv2.y; + + // construct a scale-invariant frame + float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) ); + return mat3( T * invmax, B * invmax, N ); +} + +vec3 perturb_normal( vec3 N, vec3 V, vec2 texcoord ) +{ + // assume N, the interpolated vertex normal and + // V, the view vector (vertex to eye) + vec3 map = texture(samplerNormal, texcoord).xyz; + map = map * 255./127. - 128./127.; + mat3 TBN = cotangent_frame(N, -V, texcoord); + return normalize(TBN * map); +} + + + +void main() +{ + vec4 diff = texture(samplerColor, inUV); + + vec3 n = normalize(inN); + vec3 l = normalize(light); + vec3 pn = perturb_normal(n, inV, inUV); + + float lambert = max(0.0, dot(pn, l)); + + //diff.rgb *= lambert * texture(samplerOcclusion, inUV).rgb; + vec3 spec = vec3(0); + vec3 amb = vec3(0.1); + if (lambert >= 0.0) { + vec3 rd = reflect(l, pn); + float s = dot(rd, normalize(inV)); + spec = vec3(0.9,0.9,0.9)* //light.specular.xyz * material.specular.xyz * + pow(max(0.0, s), 0.5); //0.5 = mat shininess + } + //outFragColor = vec4(1.0); // + //outFragColor = vec4(diff.rgb , 1.0); // + outFragColor = vec4(diff.rgb + amb + spec , diff.a); // +}
\ No newline at end of file diff --git a/samples/Model/shaders/model.vert b/samples/Model/shaders/model.vert new file mode 100644 index 0000000..d63c794 --- /dev/null +++ b/samples/Model/shaders/model.vert @@ -0,0 +1,44 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec2 inUV; + +layout (binding = 0) uniform UBO +{ + mat4 projectionMatrix; + mat4 viewMatrix; + mat4 modelMatrix; +} ubo; + +layout (location = 0) out vec2 outUV; +layout (location = 1) out vec3 outN; +layout (location = 2) out vec3 outV;//ViewDir + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +layout(push_constant) uniform PushConsts { + mat4 model; +} pc; + +void main() +{ + outUV = inUV; + + mat4 mod = ubo.modelMatrix;// * pc.model; + vec4 pos = mod * vec4(inPos.xyz, 1.0); + + //outN = normalize(transpose(inverse(mat3(mod))) * inNormal); + outN = normalize(mat3(mod)* inNormal); + + mat4 viewInv = inverse(ubo.viewMatrix); + outV = -(ubo.viewMatrix * pos).xyz;//normalize(vec3(viewInv * vec4(0.0, 0.0, 0.0, 1.0) - pos)); + + gl_Position = ubo.projectionMatrix * ubo.viewMatrix * pos; +} |