/// <summary> /// Calculates the bounding box of the whole model. /// </summary> private void ComputeBoundingBox(Model model, Scene scene) { var sceneMin = new Vector3(1e10f, 1e10f, 1e10f); var sceneMax = new Vector3(-1e10f, -1e10f, -1e10f); var transform = Matrix.Identity; ComputeBoundingBox(scene, scene.RootNode, ref sceneMin, ref sceneMax, ref transform); //set min and max of bounding box model.SetAxisAlignedBox(sceneMin, sceneMax); }
public Model Load(string fileName) { Scene scene = _importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality); //use this directory path to load textures from _modelPath = Path.GetDirectoryName(fileName); var model = new Model(); var identity = Matrix.Identity; AddVertexData(model, scene, scene.RootNode, _device, ref identity); ComputeBoundingBox(model, scene); return model; }
public override WriteableBitmap Initialize(Device device) { const int width = 600; const int height = 400; // Create device and swap chain. var swapChainPresenter = new WpfSwapChainPresenter(); _swapChain = device.CreateSwapChain(width, height, swapChainPresenter); _deviceContext = device.ImmediateContext; // Create RenderTargetView from the backbuffer. var backBuffer = Texture2D.FromSwapChain(_swapChain, 0); _renderTargetView = device.CreateRenderTargetView(backBuffer); // Compile Vertex and Pixel shaders var vertexShaderByteCode = ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/BasicTriangle/MiniTri.fx", "VS", "vs_4_0"); var vertexShader = device.CreateVertexShader(vertexShaderByteCode); var pixelShaderByteCode = ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/BasicTriangle/MiniTri.fx", "PS", "ps_4_0"); var pixelShader = device.CreatePixelShader(pixelShaderByteCode); // Layout from VertexShader input signature var layout = device.CreateInputLayout( new[] { new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0), new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 0) }, vertexShaderByteCode); // Instantiate Vertex buffer from vertex data var vertices = device.CreateBuffer(new BufferDescription(BindFlags.VertexBuffer), new[] { new Vector4(0.0f, 0.5f, 0.5f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), new Vector4(0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f) }); _model = new Model(); _model.AddMesh(new ModelMesh { IndexBuffer = device.CreateBuffer(new BufferDescription { BindFlags = BindFlags.IndexBuffer }, new uint[] { 0, 1, 2 }), IndexCount = 3, InputLayout = layout, PrimitiveCount = 1, PrimitiveTopology = PrimitiveTopology.TriangleList, VertexBuffer = vertices, VertexCount = 3, VertexSize = 32 }); // Prepare all the stages _deviceContext.VertexShader.Shader = vertexShader; _deviceContext.Rasterizer.SetViewports(new Viewport(0, 0, width, height, 0.0f, 1.0f)); _deviceContext.PixelShader.Shader = pixelShader; _deviceContext.OutputMerger.SetTargets(null, _renderTargetView); return swapChainPresenter.Bitmap; }
public override WriteableBitmap Initialize(Device device) { const int width = 600; const int height = 400; // Create device and swap chain. var swapChainPresenter = new WpfSwapChainPresenter(); _swapChain = device.CreateSwapChain(width, height, swapChainPresenter); _deviceContext = device.ImmediateContext; // Create RenderTargetView from the backbuffer. var backBuffer = Texture2D.FromSwapChain(_swapChain, 0); _renderTargetView = device.CreateRenderTargetView(backBuffer); // Create the depth buffer var depthBuffer = device.CreateTexture2D(new Texture2DDescription { ArraySize = 1, MipLevels = 1, Width = width, Height = height, BindFlags = BindFlags.DepthStencil }); // Create the depth buffer view _depthView = device.CreateDepthStencilView(depthBuffer); // Load model. var modelLoader = new ModelLoader(device, TextureLoader.CreateTextureFromStream); _model = modelLoader.Load("Modules/SampleBrowser/Samples/ModelLoading/Car/car.obj"); // Compile Vertex and Pixel shaders var vertexShaderByteCode = ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/ModelLoading/ModelLoading.fx", "VS", "vs_4_0"); var vertexShader = device.CreateVertexShader(vertexShaderByteCode); var pixelShaderByteCode = ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/ModelLoading/ModelLoading.fx", "PS", "ps_4_0"); var pixelShader = device.CreatePixelShader(pixelShaderByteCode); _model.SetInputLayout(device, vertexShaderByteCode.InputSignature); var sampler = device.CreateSamplerState(new SamplerStateDescription { Filter = Filter.MinMagMipPoint, AddressU = TextureAddressMode.Wrap, AddressV = TextureAddressMode.Wrap, AddressW = TextureAddressMode.Wrap, BorderColor = Color4.Black, ComparisonFunction = Comparison.Never, MaximumAnisotropy = 16, MipLodBias = 0, MinimumLod = 0, MaximumLod = 16, }); // Create constant buffers. _vertexConstantBuffer = device.CreateBuffer(new BufferDescription { SizeInBytes = Utilities.SizeOf<VertexShaderData>(), BindFlags = BindFlags.ConstantBuffer }); _pixelConstantBuffer = device.CreateBuffer(new BufferDescription { SizeInBytes = Utilities.SizeOf<PixelShaderData>(), BindFlags = BindFlags.ConstantBuffer }); // Prepare all the stages _deviceContext.VertexShader.SetConstantBuffers(0, _vertexConstantBuffer); _deviceContext.VertexShader.Shader = vertexShader; _deviceContext.PixelShader.SetConstantBuffers(0, _pixelConstantBuffer); _deviceContext.PixelShader.Shader = pixelShader; _deviceContext.PixelShader.SetSamplers(0, sampler); _vertexShaderData = new VertexShaderData(); _pixelShaderData = new PixelShaderData { LightDirection = new Vector4(Vector3.Normalize(new Vector3(0.5f, 0, -1)), 1) }; _deviceContext.SetBufferData(_pixelConstantBuffer, ref _pixelShaderData); // Setup targets and viewport for rendering _deviceContext.Rasterizer.SetViewports(new Viewport(0, 0, width, height, 0.0f, 1.0f)); _deviceContext.OutputMerger.SetTargets(_depthView, _renderTargetView); //_deviceContext.Rasterizer.State = device.CreateRasterizerState(new Pipeline.Rasterizer.RasterizerStateDescription //{ // FillMode = Pipeline.Rasterizer.FillMode.Wireframe //}); // Prepare matrices _projection = Matrix.PerspectiveFovLH(MathUtil.Pi / 3.0f, width / (float) height, 1f, 1000.0f); return swapChainPresenter.Bitmap; }
public override WriteableBitmap Initialize(Device device) { // Create device and swap chain. var swapChainPresenter = new WpfSwapChainPresenter(); _swapChain = device.CreateSwapChain(Width, Height, swapChainPresenter); _deviceContext = device.ImmediateContext; // Create RenderTargetView from the backbuffer. var backBuffer = Texture2D.FromSwapChain(_swapChain, 0); _renderTargetView = device.CreateRenderTargetView(backBuffer); // Create the depth buffer var depthBuffer = device.CreateTexture2D(new Texture2DDescription { ArraySize = 1, MipLevels = 1, Width = Width, Height = Height, BindFlags = BindFlags.DepthStencil }); // Create the depth buffer view _depthView = device.CreateDepthStencilView(depthBuffer); // Create cube map resources. var cubeMapTexture = device.CreateTexture2D(new Texture2DDescription { Width = CubeMapSize, Height= CubeMapSize, ArraySize = 6, BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, MipLevels = 1 }); _renderTargetViewCube = device.CreateRenderTargetView(cubeMapTexture); _resourceViewCube = device.CreateShaderResourceView(cubeMapTexture); var depthBufferCube = device.CreateTexture2D(new Texture2DDescription { ArraySize = 6, MipLevels = 1, Width = CubeMapSize, Height = CubeMapSize, BindFlags = BindFlags.DepthStencil }); _depthViewCube = device.CreateDepthStencilView(depthBufferCube); // Load model. var modelLoader = new ModelLoader(device, TextureLoader.CreateTextureFromStream); _model = modelLoader.Load("Modules/SampleBrowser/Samples/EnvironmentMapping/teapot.obj"); // Compile Vertex and Pixel shaders var vertexShaderByteCode = ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/EnvironmentMapping/EnvironmentMapping.fx", "VS_CubeMap", "vs_4_0"); _vertexShaderCubeMap = device.CreateVertexShader(vertexShaderByteCode); _vertexShaderStandard = device.CreateVertexShader(ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/EnvironmentMapping/EnvironmentMapping.fx", "VS_Standard", "vs_4_0")); _geometryShaderCubeMap = device.CreateGeometryShader(ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/EnvironmentMapping/EnvironmentMapping.fx", "GS_CubeMap", "gs_4_0")); _pixelShaderCubeMap = device.CreatePixelShader(ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/EnvironmentMapping/EnvironmentMapping.fx", "PS_CubeMap", "ps_4_0")); _pixelShaderStandard = device.CreatePixelShader(ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/EnvironmentMapping/EnvironmentMapping.fx", "PS_Standard", "ps_4_0")); _pixelShaderReflective = device.CreatePixelShader(ShaderCompiler.CompileFromFile("Modules/SampleBrowser/Samples/EnvironmentMapping/EnvironmentMapping.fx", "PS_Reflective", "ps_4_0")); _model.SetInputLayout(device, vertexShaderByteCode.InputSignature); var sampler = device.CreateSamplerState(SamplerStateDescription.Default); // Create constant buffers. _vertexConstantBuffer = device.CreateBuffer(new BufferDescription { SizeInBytes = Utilities.SizeOf<VertexShaderData>(), BindFlags = BindFlags.ConstantBuffer }); _geometryConstantBuffer = device.CreateBuffer(new BufferDescription { SizeInBytes = Utilities.SizeOf<GeometryShaderData>(), BindFlags = BindFlags.ConstantBuffer }); var pixelConstantBuffer = device.CreateBuffer(new BufferDescription { SizeInBytes = Utilities.SizeOf<PixelShaderData>(), BindFlags = BindFlags.ConstantBuffer }); // Prepare all the stages _deviceContext.VertexShader.SetConstantBuffers(0, _vertexConstantBuffer); _deviceContext.GeometryShader.SetConstantBuffers(0, _geometryConstantBuffer); _deviceContext.PixelShader.SetConstantBuffers(0, pixelConstantBuffer); _deviceContext.PixelShader.SetSamplers(0, sampler); _vertexShaderData = new VertexShaderData(); _view1 = Matrix.LookAtLH(Vector3.Zero, new Vector3(1, 0, 0), Vector3.UnitY); _view2 = Matrix.LookAtLH(Vector3.Zero, new Vector3(-1, 0, 0), Vector3.UnitY); _view3 = Matrix.LookAtLH(Vector3.Zero, new Vector3(0, 1, 0), -Vector3.UnitZ); _view4 = Matrix.LookAtLH(Vector3.Zero, new Vector3(0, -1, 0), Vector3.UnitZ); _view5 = Matrix.LookAtLH(Vector3.Zero, new Vector3(0, 0, 1), Vector3.UnitY); _view6 = Matrix.LookAtLH(Vector3.Zero, new Vector3(0, 0, -1), Vector3.UnitY); var from = new Vector3(0, 30, 70); var to = new Vector3(0, 0, 0); // Prepare matrices var view = Matrix.LookAtLH(from, to, Vector3.UnitY); _projectionCube = Matrix.PerspectiveFovLH(MathUtil.PiOverTwo, 1.0f, 1f, 10000.0f); _projection = Matrix.PerspectiveFovLH(MathUtil.Pi / 3.0f, Width / (float) Height, 1f, 10000.0f); _viewProjectionCube = Matrix.Multiply(view, _projectionCube); _viewProjection = Matrix.Multiply(view, _projection); var pixelShaderData = new PixelShaderData { LightDirection = new Vector4(Vector3.Normalize(new Vector3(0.5f, 0, -1)), 1), EyePosition = new Vector4(from, 1) }; _deviceContext.SetBufferData(pixelConstantBuffer, ref pixelShaderData); // Setup targets and viewport for rendering _deviceContext.Rasterizer.SetViewports(new Viewport(0, 0, Width, Height, 0.0f, 1.0f)); _deviceContext.OutputMerger.SetTargets(_depthView, _renderTargetView); return swapChainPresenter.Bitmap; }
/// <summary> /// Create meshes and add vertex and index buffers. /// </summary> private void AddVertexData( Model model, Scene scene, Node node, Device device, ref Matrix transform) { var previousTransform = transform; transform = Matrix.Multiply(previousTransform, node.Transform.ToMatrix()); // Also calculate inverse transpose matrix for normal/tangent/bitagent transformation. var invTranspose = transform; invTranspose.Invert(); invTranspose.Transpose(); if (node.HasMeshes) { foreach (int index in node.MeshIndices) { // Get a mesh from the scene. Mesh mesh = scene.Meshes[index]; // Create new mesh to add to model. var modelMesh = new ModelMesh(); model.AddMesh(modelMesh); // If mesh has a material extract the diffuse texture, if present. Material material = scene.Materials[mesh.MaterialIndex]; if (material != null && material.GetTextureCount(TextureType.Diffuse) > 0) { TextureSlot aiTexture = material.GetTexture(TextureType.Diffuse, 0); using (var fileStream = File.OpenRead(_modelPath + "\\" + Path.GetFileName(aiTexture.FilePath))) { var texture = _textureLoadHandler(_device, fileStream); modelMesh.AddTextureDiffuse(device, texture); } } // Determine the elements in the vertex. bool hasTexCoords = mesh.HasTextureCoords(0); bool hasColors = mesh.HasVertexColors(0); bool hasNormals = mesh.HasNormals; bool hasTangents = mesh.Tangents != null; bool hasBitangents = mesh.BiTangents != null; // Create vertex element list. var vertexElements = new InputElement[GetNumberOfInputElements(mesh)]; uint elementIndex = 0; vertexElements[elementIndex++] = new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0); var vertexSize = (short) Utilities.SizeOf<Vector3>(); if (hasColors) { vertexElements[elementIndex++] = new InputElement("COLOR", 0, Format.R8G8B8A8_UInt, 0, vertexSize); vertexSize += (short) Utilities.SizeOf<Color>(); } if (hasNormals) { vertexElements[elementIndex++] = new InputElement("NORMAL", 0, Format.R32G32B32_Float, 0, vertexSize); vertexSize += (short) Utilities.SizeOf<Vector3>(); } if (hasTangents) { vertexElements[elementIndex++] = new InputElement("TANGENT", 0, Format.R32G32B32_Float, 0, vertexSize); vertexSize += (short) Utilities.SizeOf<Vector3>(); } if (hasBitangents) { vertexElements[elementIndex++] = new InputElement("BITANGENT", 0, Format.R32G32B32_Float, 0, vertexSize); vertexSize += (short) Utilities.SizeOf<Vector3>(); } if (hasTexCoords) { vertexElements[elementIndex++] = new InputElement("TEXCOORD", 0, Format.R32G32_Float, 0, vertexSize); vertexSize += (short) Utilities.SizeOf<Vector2>(); } //set the vertex elements and size modelMesh.InputElements = vertexElements; modelMesh.VertexSize = vertexSize; //get pointers to vertex data Vector3D[] positions = mesh.Vertices; Vector3D[] texCoords = mesh.GetTextureCoords(0); Vector3D[] normals = mesh.Normals; Vector3D[] tangents = mesh.Tangents; Vector3D[] biTangents = mesh.BiTangents; Color4D[] colours = mesh.GetVertexColors(0); //also determine primitive type switch (mesh.PrimitiveType) { case PrimitiveType.Point: modelMesh.PrimitiveTopology = PrimitiveTopology.PointList; break; case PrimitiveType.Line: modelMesh.PrimitiveTopology = PrimitiveTopology.LineList; break; case PrimitiveType.Triangle: modelMesh.PrimitiveTopology = PrimitiveTopology.TriangleList; break; default: throw new Exception("ModelLoader::AddVertexData(): Unknown primitive type"); } // Create new vertex buffer. var vertexBuffer = device.CreateBuffer( new BufferDescription { BindFlags = BindFlags.VertexBuffer, SizeInBytes = mesh.VertexCount * vertexSize }); int byteOffset = 0; for (int i = 0; i < mesh.VertexCount; i++) { { // Add position, after transforming it with accumulated node transform. Vector4 tempResult; Vector3 pos = positions[i].ToVector3(); Vector3.Transform(ref pos, ref transform, out tempResult); var result = new Vector3(tempResult.X, tempResult.Y, tempResult.Z); device.ImmediateContext.SetBufferData(vertexBuffer, ref result, byteOffset); byteOffset += Vector3.SizeInBytes; } if (hasColors) { var vertColor = colours[i].ToColor(); device.ImmediateContext.SetBufferData(vertexBuffer, ref vertColor, byteOffset); byteOffset += 4; } if (hasNormals) { var normal = normals[i].ToVector3(); Vector4 tempResult; Vector3.Transform(ref normal, ref invTranspose, out tempResult); var result = new Vector3(tempResult.X, tempResult.Y, tempResult.Z); device.ImmediateContext.SetBufferData(vertexBuffer, ref result, byteOffset); byteOffset += Vector3.SizeInBytes; } if (hasTangents) { var tangent = tangents[i].ToVector3(); Vector4 tempResult; Vector3.Transform(ref tangent, ref invTranspose, out tempResult); var result = new Vector3(tempResult.X, tempResult.Y, tempResult.Z); device.ImmediateContext.SetBufferData(vertexBuffer, ref result, byteOffset); byteOffset += Vector3.SizeInBytes; } if (hasBitangents) { var biTangent = biTangents[i].ToVector3(); Vector4 tempResult; Vector3.Transform(ref biTangent, ref invTranspose, out tempResult); var result = new Vector3(tempResult.X, tempResult.Y, tempResult.Z); device.ImmediateContext.SetBufferData(vertexBuffer, ref result, byteOffset); byteOffset += Vector3.SizeInBytes; } if (hasTexCoords) { var result = new Vector2(texCoords[i].X, 1 - texCoords[i].Y); device.ImmediateContext.SetBufferData(vertexBuffer, ref result, byteOffset); byteOffset += Vector2.SizeInBytes; } } // Add it to the mesh. modelMesh.VertexBuffer = vertexBuffer; modelMesh.VertexCount = mesh.VertexCount; modelMesh.PrimitiveCount = mesh.FaceCount; // Get pointer to indices data. var indices = mesh.GetIndices(); // Create new index buffer. var indexBuffer = device.CreateBuffer( new BufferDescription { BindFlags = BindFlags.IndexBuffer, SizeInBytes = indices.Length * sizeof(uint) }, indices); // Add it to the mesh. modelMesh.IndexBuffer = indexBuffer; modelMesh.IndexCount = indices.Length; } } // If node has more children process them as well. for (var i = 0; i < node.ChildCount; i++) AddVertexData(model, scene, node.Children[i], device, ref transform); transform = previousTransform; }