/// <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); }
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); }