Exemplo n.º 1
0
        private ModelMeshPart CreateModelMeshPartShaderMaterial(
            AssetLoadContext context,
            W3dMesh w3dMesh,
            W3dMaterialPass w3dMaterialPass,
            W3dShaderMaterial w3dShaderMaterial,
            ShaderMaterialShaderResources shaderResources)
        {
            var texCoords = new MeshShaderResources.MeshVertex.TexCoords[w3dMesh.Header.NumVertices];

            if (w3dMaterialPass.TexCoords != null)
            {
                for (var i = 0; i < texCoords.Length; i++)
                {
                    texCoords[i].UV0 = w3dMaterialPass.TexCoords.Items[i];
                }
            }

            var blendEnabled = false;

            var texCoordsVertexBuffer = AddDisposable(context.GraphicsDevice.CreateStaticBuffer(
                                                          texCoords,
                                                          BufferUsage.VertexBuffer));

            var material = shaderResources.GetCachedMaterial(w3dShaderMaterial, context);

            var materialPass = new MaterialPass(material, context.ShaderResources.MeshDepth.Material);

            return(new ModelMeshPart(
                       this,
                       texCoordsVertexBuffer,
                       0,
                       (uint)w3dMesh.Triangles.Items.Length * 3,
                       blendEnabled,
                       materialPass,
                       materialPass)); // TODO
        }
Exemplo n.º 2
0
        // One ModelMeshMaterialPass for each W3D_CHUNK_MATERIAL_PASS
        private void CreateModelMeshPartsFixedFunction(
            AssetLoadContext context,
            W3dMesh w3dMesh,
            W3dMaterialPass w3dMaterialPass,
            FixedFunctionShaderResources.VertexMaterial[] vertexMaterials,
            FixedFunctionShaderResources.ShadingConfiguration[] shadingConfigurations,
            List <ModelMeshPart> meshParts)
        {
            var hasTextureStage0 = w3dMaterialPass.TextureStages.Count > 0;
            var textureStage0    = hasTextureStage0
                ? w3dMaterialPass.TextureStages[0]
                : null;

            var hasTextureStage1 = w3dMaterialPass.TextureStages.Count > 1 && w3dMaterialPass.TextureStages[1].TexCoords != null;
            var textureStage1    = hasTextureStage1
                ? w3dMaterialPass.TextureStages[1]
                : null;

            var numTextureStages = hasTextureStage0 && hasTextureStage1
                ? 2u
                : hasTextureStage0 ? 1u : 0u;

            var texCoords = new MeshShaderResources.MeshVertex.TexCoords[w3dMesh.Header.NumVertices];

            if (hasTextureStage0)
            {
                for (var i = 0; i < texCoords.Length; i++)
                {
                    // TODO: What to do when this is null?
                    if (textureStage0.TexCoords != null)
                    {
                        texCoords[i].UV0 = textureStage0.TexCoords.Items[i];
                    }

                    if (hasTextureStage1)
                    {
                        texCoords[i].UV1 = textureStage1.TexCoords.Items[i];
                    }
                }
            }

            var texCoordsVertexBuffer = AddDisposable(context.GraphicsDevice.CreateStaticBuffer(
                                                          texCoords,
                                                          BufferUsage.VertexBuffer));

            // Optimisation for a fairly common case.
            if (w3dMaterialPass.VertexMaterialIds.Items.Length == 1 &&
                w3dMaterialPass.ShaderIds.Items.Length == 1 &&
                w3dMaterialPass.TextureStages.Count == 1 &&
                w3dMaterialPass.TextureStages[0].TextureIds.Items.Count == 1)
            {
                meshParts.Add(CreateModelMeshPart(
                                  context,
                                  texCoordsVertexBuffer,
                                  0,
                                  w3dMesh.Header.NumTris * 3,
                                  w3dMesh,
                                  vertexMaterials,
                                  shadingConfigurations,
                                  w3dMaterialPass.VertexMaterialIds.Items[0],
                                  w3dMaterialPass.ShaderIds.Items[0],
                                  numTextureStages,
                                  w3dMaterialPass.TextureStages[0].TextureIds.Items[0],
                                  null));
            }
            else
            {
                // Expand ShaderIds and TextureIds, if they have a single entry
                // (which means same ID for all faces)

                IEnumerable <uint?> getExpandedTextureIds(List <uint?> ids)
                {
                    if (ids == null)
                    {
                        for (var i = 0; i < w3dMesh.Header.NumTris; i++)
                        {
                            yield return(null);
                        }
                    }
                    else if (ids.Count == 1)
                    {
                        var result = ids[0];
                        for (var i = 0; i < w3dMesh.Header.NumTris; i++)
                        {
                            yield return(result);
                        }
                    }
                    else
                    {
                        foreach (var id in ids)
                        {
                            yield return(id);
                        }
                    }
                }

                IEnumerable <uint> getExpandedShaderIds()
                {
                    var ids = w3dMaterialPass.ShaderIds.Items;

                    if (ids.Length == 1)
                    {
                        var result = ids[0];
                        for (var i = 0; i < w3dMesh.Header.NumTris; i++)
                        {
                            yield return(result);
                        }
                    }
                    else
                    {
                        foreach (var id in ids)
                        {
                            yield return(id);
                        }
                    }
                }

                IEnumerable <uint> getExpandedVertexMaterialIDs()
                {
                    var ids = w3dMaterialPass.VertexMaterialIds.Items;

                    if (ids.Length == 1)
                    {
                        var result = ids[0];
                        for (var i = 0; i < w3dMesh.Header.NumTris; i++)
                        {
                            yield return(result);
                        }
                    }
                    else
                    {
                        for (var i = 0; i < w3dMesh.Header.NumTris; i++)
                        {
                            var triangle    = w3dMesh.Triangles.Items[i];
                            var materialID0 = ids[(int)triangle.VIndex0];
                            var materialID1 = ids[(int)triangle.VIndex1];
                            var materialID2 = ids[(int)triangle.VIndex2];
                            if (materialID0 != materialID1 || materialID1 != materialID2)
                            {
                                throw new NotSupportedException();
                            }
                            yield return(materialID0);
                        }

                        foreach (var id in ids)
                        {
                            yield return(id);
                        }
                    }
                }

                var combinedIds = getExpandedVertexMaterialIDs()
                                  .Zip(getExpandedShaderIds(), (x, y) => new { VertexMaterialID = x, ShaderID = y })
                                  .Zip(getExpandedTextureIds(textureStage0?.TextureIds.Items), (x, y) => new { x.VertexMaterialID, x.ShaderID, TextureIndex0 = y })
                                  .Zip(getExpandedTextureIds(textureStage1?.TextureIds.Items), (x, y) => new CombinedMaterialPermutation {
                    VertexMaterialID = x.VertexMaterialID, ShaderID = x.ShaderID, TextureIndex0 = x.TextureIndex0, TextureIndex1 = y
                });

                var combinedId = combinedIds.First();
                var startIndex = 0u;
                var indexCount = 0u;

                foreach (var newCombinedId in combinedIds)
                {
                    if (combinedId != newCombinedId)
                    {
                        meshParts.Add(CreateModelMeshPart(
                                          context,
                                          texCoordsVertexBuffer,
                                          startIndex,
                                          indexCount,
                                          w3dMesh,
                                          vertexMaterials,
                                          shadingConfigurations,
                                          combinedId.VertexMaterialID,
                                          combinedId.ShaderID,
                                          numTextureStages,
                                          combinedId.TextureIndex0,
                                          combinedId.TextureIndex1));

                        startIndex = startIndex + indexCount;
                        indexCount = 0;
                    }

                    combinedId = newCombinedId;

                    indexCount += 3;
                }

                if (indexCount > 0)
                {
                    meshParts.Add(CreateModelMeshPart(
                                      context,
                                      texCoordsVertexBuffer,
                                      startIndex,
                                      indexCount,
                                      w3dMesh,
                                      vertexMaterials,
                                      shadingConfigurations,
                                      combinedId.VertexMaterialID,
                                      combinedId.ShaderID,
                                      numTextureStages,
                                      combinedId.TextureIndex0,
                                      combinedId.TextureIndex1));
                }
            }
        }
Exemplo n.º 3
0
        private ModelMeshPart CreateModelMeshPartShaderMaterial(
            AssetLoadContext context,
            W3dMesh w3dMesh,
            W3dMaterialPass w3dMaterialPass,
            W3dShaderMaterial w3dShaderMaterial,
            ShaderMaterialShaderResources shaderResources)
        {
            var texCoords = new MeshShaderResources.MeshVertex.TexCoords[w3dMesh.Header.NumVertices];

            if (w3dMaterialPass.TexCoords != null)
            {
                for (var i = 0; i < texCoords.Length; i++)
                {
                    texCoords[i].UV0 = w3dMaterialPass.TexCoords.Items[i];
                }
            }

            // TODO: Extract state properties from shader material.

            var blendEnabled = false;

            var pipeline = shaderResources.Pipeline;

            var materialResourceSetBuilder = AddDisposable(new ShaderMaterialResourceSetBuilder(
                                                               context.GraphicsDevice,
                                                               shaderResources));

            foreach (var w3dShaderProperty in w3dShaderMaterial.Properties)
            {
                switch (w3dShaderProperty.PropertyType)
                {
                case W3dShaderMaterialPropertyType.Texture:
                    var texture = context.AssetStore.Textures.GetByName(w3dShaderProperty.StringValue);
                    materialResourceSetBuilder.SetTexture(w3dShaderProperty.PropertyName, texture);
                    break;

                case W3dShaderMaterialPropertyType.Bool:
                    materialResourceSetBuilder.SetConstant(w3dShaderProperty.PropertyName, w3dShaderProperty.Value.Bool);
                    break;

                case W3dShaderMaterialPropertyType.Float:
                    materialResourceSetBuilder.SetConstant(w3dShaderProperty.PropertyName, w3dShaderProperty.Value.Float);
                    break;

                case W3dShaderMaterialPropertyType.Vector2:
                    materialResourceSetBuilder.SetConstant(w3dShaderProperty.PropertyName, w3dShaderProperty.Value.Vector2);
                    break;

                case W3dShaderMaterialPropertyType.Vector3:
                    materialResourceSetBuilder.SetConstant(w3dShaderProperty.PropertyName, w3dShaderProperty.Value.Vector3);
                    break;

                case W3dShaderMaterialPropertyType.Vector4:
                    materialResourceSetBuilder.SetConstant(w3dShaderProperty.PropertyName, w3dShaderProperty.Value.Vector4);
                    break;

                case W3dShaderMaterialPropertyType.Int:
                    materialResourceSetBuilder.SetConstant(w3dShaderProperty.PropertyName, w3dShaderProperty.Value.Int);
                    break;

                default:
                    throw new NotSupportedException();
                }
            }

            var materialResourceSet = materialResourceSetBuilder.CreateResourceSet();

            var texCoordsVertexBuffer = AddDisposable(context.GraphicsDevice.CreateStaticBuffer(
                                                          texCoords,
                                                          BufferUsage.VertexBuffer));

            return(new ModelMeshPart(
                       texCoordsVertexBuffer,
                       0,
                       (uint)w3dMesh.Triangles.Items.Length * 3,
                       blendEnabled,
                       pipeline,
                       pipeline, // TODO
                       materialResourceSet));
        }