Отправить текстуру в SCNProgram
Я передаю текстуру шейдеру с помощью SCNProgram и Metal. Проблема в том, что при передаче текстуры выделяется огромный объем памяти. Текстуры рамсера неблшой, примерно 50-100 кб. Приложение вылетает при достижении критического сектора использования памяти. Импортирую 25 разных моделей с их текстурами. Функция 1 загружает объект из файла obj. Функция 2, отправляет данные во фрагментный шейдер. Есть ли другие способы передать текстуру шейдеру без использования SCNMaterialProperty?
// 1
func load(name: String) -> SCNNode? {
guard let url = Bundle.main.url(
forResource: name,
withExtension: "obj",
subdirectory: "Models.scnassets") else { return nil }
let asset = MDLAsset(url: url)
let mesh = asset.object(at: 0) as! MDLMesh
mesh.addTangentBasis(forTextureCoordinateAttributeNamed: MDLVertexAttributeTextureCoordinate, normalAttributeNamed: MDLVertexAttributeNormal, tangentAttributeNamed: MDLVertexAttributeTangent)
let scene = SCNNode(geometry: SCNGeometry(mdlMesh: mesh))
scene.name = name
return scene
}
//2
func congigurate(model: inout SCNNode,
usePBR: Bool) {
let program = SCNProgram()
program.fragmentFunctionName = usePBR ? "fragment_mainPBR" : "fragment_main"
program.vertexFunctionName = "vertex_main"
//0 Загрузка уровня
guard let name = model.name else { fatalError("Lost name") }
let materialLevel = SCNMaterial()
var ligth = Light(position: [50, 50, 50],
color: [0.98, 0.95, 0.8],
specularColor: [1, 1, 1],
intensity: 1.0,
attenuation: [1, 1, 1],
type: .Sunlight,
coneAngle: 45,
coneDirection: [50, 50, 50],
coneAttenuation: 1)
var materal = Material(baseColor: [0.46, 0.68, 0.68],
specularColor: [1, 1, 1],
roughness: 0.9,
metallic: 0.25,
ambientOcclusion: [0.1, 0.1, 0.1],
shininess: 1000.0,
hasAlbedoTexture: true,
hasNormalTexture: false,
hasRougnessTexture: false,
hasMetalnesTexture: false,
hasAOTexture: false)
// SET TEXTURE
if materal.hasAlbedoTexture {
let albedoModel = UIImage(named: "\(name)Albedo")!
let texture = SCNMaterialProperty(contents: albedoModel)
materialLevel.setValue(texture, forKey: "baseColorTexture")
} else {
materialLevel.setValue(NSNull(), forKey: "baseColorTexture")
}
// Устаовка текстуры карты нормалей в материале
if materal.hasNormalTexture {
let normalModel = UIImage(named: "\(name)Normal")!
let texture = SCNMaterialProperty(contents: normalModel)
materialLevel.setValue(texture, forKey: "normalTexture")
} else {
materialLevel.setValue(NSNull(), forKey: "normalTexture")
}
// Установка текстуры карты металличности из материала
if materal.hasMetalnesTexture{
let metalnesModel = UIImage(named: "\(name)Metal")!
let metalnesProperty = SCNMaterialProperty(contents: metalnesModel)
materialLevel.setValue(metalnesProperty, forKey: "metallicTexture")
} else {
materialLevel.setValue(NSNull(), forKey: "metallicTexture")
}
// Установка карты шерховатоси из материала
if materal.hasRougnessTexture {
let roungnesModel = UIImage(named: "\(name)Roug")!
let roungnesProperty = SCNMaterialProperty(contents: roungnesModel)
materialLevel.setValue(roungnesProperty, forKey: "roughnessTexture")
} else {
materialLevel.setValue(NSNull(), forKey: "roughnessTexture")
}
// Установка карты глубокого затинения из материала
if materal.hasAOTexture {
let ambientModel = UIImage(named: "\(name)AO")!
let ambientProperty = SCNMaterialProperty(contents: ambientModel)
materialLevel.setValue(ambientProperty, forKey: "aoTexture")
} else {
materialLevel.setValue(NSNull(), forKey: "aoTexture")
}
materialLevel.setValue(NSData(bytes: &materal, length: Material.stride), forKey: "material")
materialLevel.setValue(NSData(bytes: &ligth, length: Light.stride), forKey: "lights")
materialLevel.program = program
model.geometry?.materials = [materialLevel]
}