Exemple #1
0
        public static void Export(GameObject[] gameObjects, string saveFileName, ExportSettings settings)
        {
            MeshConverter.ClearCaches();
            TextureConverter.ClearCaches();
            MaterialConverter.ClearCaches();
            ShaderMappingIO.ClearCaches();

            GraphBuilderInterface.unity2vsg_BeginExport();

            List <PipelineData> storePipelines = new List <PipelineData>();

            bool insideLODGroup = false;
            bool firstNodeAdded = false;

            System.Action <GameObject> processGameObject = null;
            processGameObject = (GameObject go) =>
            {
                // determine the gameObject type
                Transform gotrans = go.transform;

                bool nodeAdded = false;

                // does it have a none identiy local matrix
                if (gotrans.localPosition != Vector3.zero || gotrans.localRotation != Quaternion.identity || gotrans.localScale != Vector3.one)
                {
                    if (firstNodeAdded || !settings.zeroRootTransform)
                    {
                        // add as a transform
                        TransformData transformdata = TransformConverter.CreateTransformData(gotrans);
                        GraphBuilderInterface.unity2vsg_AddTransformNode(transformdata);
                        nodeAdded = true;
                    }
                }

                // do we need to insert a group
                if (!nodeAdded)// && gotrans.childCount > 0)
                {
                    //add as a group
                    GraphBuilderInterface.unity2vsg_AddGroupNode();
                    nodeAdded = true;
                }

                firstNodeAdded = true;
                bool meshexported = false;

                // get the meshrender here so we can check if the LOD exports the the mesh
                MeshFilter   meshFilter   = go.GetComponent <MeshFilter>();
                MeshRenderer meshRenderer = go.GetComponent <MeshRenderer>();

                // does this node have an LOD group
                LODGroup lodgroup = go.GetComponent <LODGroup>();
                if (lodgroup != null && !insideLODGroup)
                {
                    // rather than process the children we figure out which renderers are in which children and add them as LOD children
                    LOD[] lods = lodgroup.GetLODs();
                    if (lods.Length > 0)
                    {
                        // get bounds from first renderer
                        if (lods[0].renderers.Length > 0)
                        {
                            CullData lodCullData = new CullData();
                            Bounds   bounds      = new Bounds(lods[0].renderers[0].bounds.center, lods[0].renderers[0].bounds.size);
                            foreach (Renderer boundsrenderer in lods[0].renderers)
                            {
                                if (boundsrenderer != null)
                                {
                                    bounds.Encapsulate(boundsrenderer.bounds);
                                }
                            }
                            Vector3 center = bounds.center - gotrans.position;
                            CoordSytemConverter.Convert(ref center);
                            lodCullData.center = NativeUtils.ToNative(center);
                            lodCullData.radius = bounds.size.magnitude * 0.5f;
                            GraphBuilderInterface.unity2vsg_AddLODNode(lodCullData);

                            insideLODGroup = true;

                            for (int i = 0; i < lods.Length; i++)
                            {
                                // for now just support one renderer and assume it's under a seperate child gameObject
                                if (lods[i].renderers.Length == 0)
                                {
                                    continue;
                                }

                                LODChildData lodChild = new LODChildData();
                                lodChild.minimumScreenHeightRatio = lods[i].screenRelativeTransitionHeight;
                                GraphBuilderInterface.unity2vsg_AddLODChild(lodChild);

                                foreach (Renderer lodrenderer in lods[i].renderers)
                                {
                                    if (lodrenderer == meshRenderer)
                                    {
                                        meshexported = true;
                                        ExportMesh(meshFilter.sharedMesh, meshRenderer, gotrans, settings, storePipelines);
                                    }
                                    else if (lodrenderer != null)
                                    {
                                        // now process the renderers gameobject, it'll be added to the group we just created by adding an LOD child
                                        processGameObject(lodrenderer.gameObject);
                                    }
                                }

                                GraphBuilderInterface.unity2vsg_EndNode();
                            }

                            insideLODGroup = false;

                            GraphBuilderInterface.unity2vsg_EndNode(); // end the lod node
                        }
                    }
                }
                else
                {
                    // transverse any children
                    for (int i = 0; i < gotrans.childCount; i++)
                    {
                        processGameObject(gotrans.GetChild(i).gameObject);
                    }
                }

                // does it have a mesh
                if (!meshexported && meshFilter && meshFilter.sharedMesh && meshRenderer)
                {
                    Mesh mesh = meshFilter.sharedMesh;
                    ExportMesh(mesh, meshRenderer, gotrans, settings, storePipelines);
                }

                // does this node have a terrain
                Terrain terrain = go.GetComponent <Terrain>();
                if (terrain != null)
                {
                    ExportTerrainMesh(terrain, settings, storePipelines);
                }

                // if we added a group or transform step out
                if (nodeAdded)
                {
                    GraphBuilderInterface.unity2vsg_EndNode();
                }
            };

            foreach (GameObject go in gameObjects)
            {
                processGameObject(go);
            }

            //GraphBuilderInterface.unity2vsg_EndNode(); // step out of convert coord system node

            GraphBuilderInterface.unity2vsg_EndExport(saveFileName);
            NativeLog.PrintReport();
        }
        /// <summary>
        /// Create a new material data based off of the pass material also adds the new data to the cache
        /// </summary>
        /// <param name="material"></param>
        /// <returns></returns>

        public static MaterialInfo CreateMaterialData(Material material, ShaderMapping mapping = null)
        {
            // fetch the shadermapping for this materials shader
            if (mapping == null && material != null)
            {
                mapping = ShaderMappingIO.ReadFromJsonFile(material.shader);
                if (mapping == null) // if we fail to find a mapping try and load the default
                {
                    mapping = ShaderMappingIO.ReadFromJsonFile(ShaderMappingIO.GetPathForShaderMappingFile("Default"));
                }
            }

            MaterialInfo matdata = new MaterialInfo
            {
                id = material != null?material.GetInstanceID() : 0,
                         mapping = mapping
            };

            // process uniforms
            UniformMappedData[] uniformDatas = mapping.GetUniformDatasFromMaterial(material);

            foreach (UniformMappedData uniData in uniformDatas)
            {
                VkDescriptorType descriptorType  = VkDescriptorType.VK_DESCRIPTOR_TYPE_MAX_ENUM;
                uint             descriptorCount = 1;

                if (uniData.mapping.uniformType == UniformMapping.UniformType.Texture2DUniform)
                {
                    Texture tex = uniData.data as Texture;
                    if (tex == null)
                    {
                        continue;
                    }

                    // get imagedata for the texture
                    ImageData imageData = TextureConverter.GetOrCreateImageData(tex);
                    // get descriptor for the image data
                    DescriptorImageData descriptorImage = GetOrCreateDescriptorImageData(imageData, uniData.mapping.vsgBindingIndex);
                    matdata.imageDescriptors.Add(descriptorImage);

                    descriptorType = VkDescriptorType.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
                }
                else if (uniData.mapping.uniformType == UniformMapping.UniformType.Texture2DArrayUniform)
                {
                    Texture2DArray tex = uniData.data as Texture2DArray;
                    if (tex == null)
                    {
                        continue;
                    }
                    ImageData[]         imageDatas      = TextureConverter.GetOrCreateImageData(tex);
                    DescriptorImageData descriptorImage = GetOrCreateDescriptorImageData(imageDatas, uniData.mapping.vsgBindingIndex);
                    matdata.imageDescriptors.Add(descriptorImage);

                    descriptorType  = VkDescriptorType.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
                    descriptorCount = (uint)imageDatas.Length;
                }
                else if (uniData.mapping.uniformType == UniformMapping.UniformType.FloatUniform)
                {
                    float value = (float)uniData.data;
                    if (value == float.NaN)
                    {
                        continue;
                    }

                    // get descriptor for the image data
                    DescriptorFloatUniformData descriptorFloat = new DescriptorFloatUniformData
                    {
                        id      = material.GetInstanceID(),
                        binding = uniData.mapping.vsgBindingIndex,
                        value   = value
                    };
                    matdata.floatDescriptors.Add(descriptorFloat);

                    descriptorType = VkDescriptorType.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
                }
                else if (uniData.mapping.uniformType == UniformMapping.UniformType.Vec4Uniform || uniData.mapping.uniformType == UniformMapping.UniformType.ColorUniform)
                {
                    Vector4 vector = Vector4.zero;
                    if (uniData.mapping.uniformType == UniformMapping.UniformType.Vec4Uniform)
                    {
                        vector = (Vector4)uniData.data;
                    }
                    if (uniData.mapping.uniformType == UniformMapping.UniformType.ColorUniform)
                    {
                        Color color = (Color)uniData.data;
                        vector = new Vector4(color.r, color.g, color.b, color.a);
                    }
                    if (vector == null)
                    {
                        continue;
                    }

                    // get descriptor for the image data
                    DescriptorVectorUniformData descriptorVector = new DescriptorVectorUniformData
                    {
                        id      = material.GetInstanceID(),
                        binding = uniData.mapping.vsgBindingIndex,
                        value   = NativeUtils.ToNative(vector)
                    };

                    matdata.vectorDescriptors.Add(descriptorVector);

                    descriptorType = VkDescriptorType.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
                }

                if (descriptorType == VkDescriptorType.VK_DESCRIPTOR_TYPE_MAX_ENUM)
                {
                    continue;
                }

                // add any custom defines related to the texture
                if (uniData.mapping.vsgDefines != null && uniData.mapping.vsgDefines.Count > 0)
                {
                    matdata.customDefines.AddRange(uniData.mapping.vsgDefines);
                }

                // create the descriptor binding to match the descriptor image
                VkDescriptorSetLayoutBinding descriptorBinding = new VkDescriptorSetLayoutBinding
                {
                    binding            = (uint)uniData.mapping.vsgBindingIndex,
                    descriptorType     = descriptorType,
                    descriptorCount    = descriptorCount,
                    stageFlags         = uniData.mapping.stages,
                    pImmutableSamplers = System.IntPtr.Zero
                };
                matdata.descriptorBindings.Add(descriptorBinding);
            }

            if (material != null)
            {
                string rendertype = material.GetTag("RenderType", true, "Opaque");
                matdata.useAlpha = rendertype.Contains("Transparent") ? 1 : 0;
                if (matdata.useAlpha == 1)
                {
                    matdata.customDefines.Add("VSG_BLEND");
                }

                string lightmode = material.GetTag("LightMode", true, "ForwardBase");
                if (lightmode != "Always")
                {
                    matdata.customDefines.Add("VSG_LIGHTING");
                }
            }

            // lastly process shaders now we know the defines etc it will use
            string customDefinesStr = string.Join(",", matdata.customDefines.ToArray());

            matdata.shaderStages = GetOrCreateShaderStagesInfo(mapping.shaders.ToArray(), customDefinesStr, null);

            // add to the cache (double check it doesn't exist already)
            if (material != null && !_materialDataCache.ContainsKey(matdata.id))
            {
                _materialDataCache[matdata.id] = matdata;
            }

            return(matdata);
        }
Exemple #3
0
        public static TerrainInfo CreateTerrainInfo(Terrain terrain, GraphBuilder.ExportSettings settings)
        {
            TerrainInfo terrainInfo         = new TerrainInfo();
            bool        usingCustomMaterial = false;

            if (terrain.materialType == Terrain.MaterialType.Custom)
            {
                // try and load a shader mapping file to match the custom terrain material
                terrainInfo.shaderMapping = ShaderMappingIO.ReadFromJsonFile(terrain.materialTemplate.shader);
                if (terrainInfo.shaderMapping != null)
                {
                    usingCustomMaterial = true;
                }
            }
            else
            {
                // load the default terrain shader mapping file
                terrainInfo.shaderMapping = ShaderMappingIO.ReadFromJsonFile(ShaderMappingIO.GetPathForShaderMappingFile("DefaultTerrain"));
            }

            if (terrainInfo.shaderMapping == null)
            {
                // no mapping loaded, use a default shader so we can at least export and render the terrain mesh
                NativeLog.WriteLine("GraphBuilder: Failed to load Terrain Shader Mapping file for terrain '" + terrain.name + "'.");
                terrainInfo.shaderMapping = ShaderMappingIO.ReadFromJsonFile(ShaderMappingIO.GetPathForShaderMappingFile("Default"));
                usingCustomMaterial       = true;
                return(null);
            }

            terrainInfo.shaderDefines.Add("VSG_LIGHTING");

            // build mesh
            int samplew = terrain.terrainData.heightmapWidth;
            int sampleh = terrain.terrainData.heightmapHeight;

            int cellw = terrain.terrainData.heightmapWidth - 1;
            int cellh = terrain.terrainData.heightmapHeight - 1;

            Vector3 size = terrain.terrainData.size;

            Vector2 cellsize   = new Vector3(size.x / cellw, size.z / cellh);
            Vector2 uvcellsize = new Vector2(1.0f / cellw, 1.0f / cellh);

            float[,] terrainHeights = terrain.terrainData.GetHeights(0, 0, samplew, sampleh);

            int vertcount = samplew * sampleh;

            Vector3[] verts   = new Vector3[vertcount];
            Vector3[] normals = new Vector3[vertcount];
            Vector2[] uvs     = new Vector2[vertcount];

            int[] indicies = new int[(cellw * cellh) * 6];

            // vertices and UVs
            for (int y = 0; y < samplew; y++)
            {
                for (int x = 0; x < sampleh; x++)
                {
                    verts[y * samplew + x].Set(x * cellsize.x, terrainHeights[y, x] * size.y, y * cellsize.y);
                    normals[y * samplew + x] = terrain.terrainData.GetInterpolatedNormal((float)x / (float)samplew, (float)y / (float)sampleh);
                    uvs[y * samplew + x].Set(x * uvcellsize.x, y * uvcellsize.y);
                }
            }

            CoordSytemConverter.Convert(verts);
            CoordSytemConverter.Convert(normals);

            // triangles
            int index = 0;

            for (int y = 0; y < cellw; y++)
            {
                for (int x = 0; x < cellh; x++)
                {
                    indicies[index++] = (y * samplew) + x;
                    indicies[index++] = ((y + 1) * samplew) + x;
                    indicies[index++] = (y * samplew) + x + 1;

                    indicies[index++] = ((y + 1) * samplew) + x;
                    indicies[index++] = ((y + 1) * samplew) + x + 1;
                    indicies[index++] = (y * samplew) + x + 1;
                }
            }

            CoordSytemConverter.FlipTriangleFaces(indicies);

            // convert to meshinfo
            MeshInfo mesh = null;

            if (!MeshConverter.GetMeshInfoFromCache(terrain.GetInstanceID(), out mesh))
            {
                mesh = new MeshInfo
                {
                    id               = terrain.GetInstanceID(),
                    verticies        = NativeUtils.WrapArray(verts),
                    normals          = NativeUtils.WrapArray(normals),
                    uv0              = NativeUtils.WrapArray(uvs),
                    triangles        = NativeUtils.WrapArray(indicies),
                    use32BitIndicies = 1
                };

                MeshConverter.AddMeshInfoToCache(mesh, terrain.GetInstanceID());
            }
            terrainInfo.terrainMesh = mesh;
            terrainInfo.terrainSize = size;

            // gather material info

            if (!usingCustomMaterial)
            {
                // use standard terrain layers
                TerrainLayer[] layers = terrain.terrainData.terrainLayers;
                for (int i = 0; i < layers.Length; i++)
                {
                    ImageData layerData = TextureConverter.GetOrCreateImageData(layers[i].diffuseTexture);
                    terrainInfo.diffuseTextureDatas.Add(layerData);

                    terrainInfo.diffuseScales.Add(new Vector4(1.0f / layers[i].tileSize.x, 1.0f / layers[i].tileSize.y));
                }

                for (int i = 0; i < terrain.terrainData.alphamapTextureCount; i++)
                {
                    Texture2D srcmask   = terrain.terrainData.GetAlphamapTexture(i);
                    ImageData splatData = TextureConverter.GetOrCreateImageData(srcmask);

                    terrainInfo.maskTextureDatas.Add(splatData);
                }

                if (terrainInfo.diffuseTextureDatas.Count > 0)
                {
                    terrainInfo.descriptorBindings.Add(new VkDescriptorSetLayoutBinding()
                    {
                        binding = 0, descriptorType = VkDescriptorType.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stageFlags = VkShaderStageFlagBits.VK_SHADER_STAGE_FRAGMENT_BIT, descriptorCount = (uint)terrainInfo.diffuseTextureDatas.Count
                    });
                    terrainInfo.descriptorBindings.Add(new VkDescriptorSetLayoutBinding()
                    {
                        binding = 2, descriptorType = VkDescriptorType.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stageFlags = VkShaderStageFlagBits.VK_SHADER_STAGE_FRAGMENT_BIT, descriptorCount = (uint)terrainInfo.diffuseScales.Count
                    });

                    terrainInfo.shaderConsts.Add(terrainInfo.diffuseTextureDatas.Count);
                    terrainInfo.shaderDefines.Add("VSG_TERRAIN_LAYERS");
                }

                terrainInfo.descriptorBindings.Add(new VkDescriptorSetLayoutBinding()
                {
                    binding = 3, descriptorType = VkDescriptorType.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stageFlags = VkShaderStageFlagBits.VK_SHADER_STAGE_FRAGMENT_BIT, descriptorCount = 1
                });

                if (terrainInfo.maskTextureDatas.Count > 0)
                {
                    terrainInfo.descriptorBindings.Add(new VkDescriptorSetLayoutBinding()
                    {
                        binding = 1, descriptorType = VkDescriptorType.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stageFlags = VkShaderStageFlagBits.VK_SHADER_STAGE_FRAGMENT_BIT, descriptorCount = (uint)terrainInfo.maskTextureDatas.Count
                    });
                    terrainInfo.shaderConsts.Add(terrainInfo.maskTextureDatas.Count);
                }
            }
            else
            {
                Material customMaterial = terrain.materialTemplate;
                terrainInfo.customMaterial = MaterialConverter.CreateMaterialData(customMaterial, terrainInfo.shaderMapping);
                terrainInfo.customMaterial.customDefines = terrainInfo.shaderDefines;
            }

            return(terrainInfo);
        }