From a3a5a5807f55e4652ca02c3c67f3225bc8f24747 Mon Sep 17 00:00:00 2001 From: Ronja Enseleit Date: Sat, 1 Jul 2023 17:24:53 +0200 Subject: [PATCH] add metal sample code and xcode project --- app/src/main/KDE.xcodeproj/project.pbxproj | 418 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 44527 bytes .../xcschemes/xcschememanagement.plist | 14 + app/src/main/m/AppDelegate.h | 16 + app/src/main/m/AppDelegate.m | 44 ++ .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../ColorMap.textureset/Contents.json | 17 + .../Universal.mipmapset/ColorMap.png | Bin 0 -> 37539 bytes .../Universal.mipmapset/Contents.json | 12 + app/src/main/m/Assets.xcassets/Contents.json | 6 + .../main/m/Base.lproj/LaunchScreen.storyboard | 25 ++ app/src/main/m/Base.lproj/Main.storyboard | 24 + app/src/main/m/GameViewController.h | 16 + app/src/main/m/GameViewController.m | 41 ++ app/src/main/m/Renderer.h | 17 + app/src/main/m/Renderer.m | 316 +++++++++++++ app/src/main/m/ShaderTypes.h | 49 ++ app/src/main/m/Shaders.metal | 53 +++ app/src/main/m/main.m | 18 + 22 files changed, 1125 insertions(+) create mode 100644 app/src/main/KDE.xcodeproj/project.pbxproj create mode 100644 app/src/main/KDE.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 app/src/main/KDE.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 app/src/main/KDE.xcodeproj/project.xcworkspace/xcuserdata/ronjaenseleit.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 app/src/main/KDE.xcodeproj/xcuserdata/ronjaenseleit.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 app/src/main/m/AppDelegate.h create mode 100644 app/src/main/m/AppDelegate.m create mode 100644 app/src/main/m/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 app/src/main/m/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 app/src/main/m/Assets.xcassets/ColorMap.textureset/Contents.json create mode 100644 app/src/main/m/Assets.xcassets/ColorMap.textureset/Universal.mipmapset/ColorMap.png create mode 100644 app/src/main/m/Assets.xcassets/ColorMap.textureset/Universal.mipmapset/Contents.json create mode 100644 app/src/main/m/Assets.xcassets/Contents.json create mode 100644 app/src/main/m/Base.lproj/LaunchScreen.storyboard create mode 100644 app/src/main/m/Base.lproj/Main.storyboard create mode 100644 app/src/main/m/GameViewController.h create mode 100644 app/src/main/m/GameViewController.m create mode 100644 app/src/main/m/Renderer.h create mode 100644 app/src/main/m/Renderer.m create mode 100644 app/src/main/m/ShaderTypes.h create mode 100644 app/src/main/m/Shaders.metal create mode 100644 app/src/main/m/main.m diff --git a/app/src/main/KDE.xcodeproj/project.pbxproj b/app/src/main/KDE.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1896a4f --- /dev/null +++ b/app/src/main/KDE.xcodeproj/project.pbxproj @@ -0,0 +1,418 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + FBA9A7502A50790A00F960DA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A74F2A50790A00F960DA /* AppDelegate.m */; }; + FBA9A7532A50790A00F960DA /* Renderer.m in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A7522A50790A00F960DA /* Renderer.m */; }; + FBA9A7562A50790A00F960DA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A7552A50790A00F960DA /* GameViewController.m */; }; + FBA9A7582A50790A00F960DA /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A7572A50790A00F960DA /* Shaders.metal */; }; + FBA9A75C2A50790A00F960DA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FBA9A75A2A50790A00F960DA /* Main.storyboard */; }; + FBA9A75E2A50790A00F960DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FBA9A75D2A50790A00F960DA /* Assets.xcassets */; }; + FBA9A7612A50790A00F960DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FBA9A75F2A50790A00F960DA /* LaunchScreen.storyboard */; }; + FBA9A7632A50790A00F960DA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A7622A50790A00F960DA /* main.m */; }; + FBA9A7682A50795000F960DA /* StringRepository.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A7432A5078D800F960DA /* StringRepository.cpp */; }; + FBA9A7692A50795400F960DA /* AssetManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A73D2A5078B800F960DA /* AssetManager.cpp */; }; + FBA9A76A2A50795700F960DA /* Hash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A73A2A5078B800F960DA /* Hash.cpp */; }; + FBA9A76B2A5079BC00F960DA /* Texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBA9A73F2A5078D800F960DA /* Texture.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + FBA9A7342A5078B800F960DA /* AssetManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AssetManager.h; path = cpp/AssetManager.h; sourceTree = ""; }; + FBA9A7352A5078B800F960DA /* Font.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Font.cpp; path = cpp/Font.cpp; sourceTree = ""; }; + FBA9A7372A5078B800F960DA /* Hash.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Hash.h; path = cpp/Hash.h; sourceTree = ""; }; + FBA9A7382A5078B800F960DA /* Font.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Font.h; path = cpp/Font.h; sourceTree = ""; }; + FBA9A7392A5078B800F960DA /* Profiling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Profiling.h; path = cpp/Profiling.h; sourceTree = ""; }; + FBA9A73A2A5078B800F960DA /* Hash.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Hash.cpp; path = cpp/Hash.cpp; sourceTree = ""; }; + FBA9A73B2A5078B800F960DA /* Position.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Position.h; path = cpp/Position.h; sourceTree = ""; }; + FBA9A73C2A5078B800F960DA /* GameState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GameState.h; path = cpp/GameState.h; sourceTree = ""; }; + FBA9A73D2A5078B800F960DA /* AssetManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AssetManager.cpp; path = cpp/AssetManager.cpp; sourceTree = ""; }; + FBA9A73E2A5078D800F960DA /* StringRepository.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringRepository.h; path = cpp/StringRepository.h; sourceTree = ""; }; + FBA9A73F2A5078D800F960DA /* Texture.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Texture.cpp; path = cpp/Texture.cpp; sourceTree = ""; }; + FBA9A7402A5078D800F960DA /* stb_truetype.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stb_truetype.h; path = cpp/stb_truetype.h; sourceTree = ""; }; + FBA9A7412A5078D800F960DA /* stb_image.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stb_image.h; path = cpp/stb_image.h; sourceTree = ""; }; + FBA9A7422A5078D800F960DA /* Texture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Texture.h; path = cpp/Texture.h; sourceTree = ""; }; + FBA9A7432A5078D800F960DA /* StringRepository.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = StringRepository.cpp; path = cpp/StringRepository.cpp; sourceTree = ""; }; + FBA9A7452A5078D800F960DA /* TouchInput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TouchInput.h; path = cpp/TouchInput.h; sourceTree = ""; }; + FBA9A74B2A50790A00F960DA /* KDE.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KDE.app; sourceTree = BUILT_PRODUCTS_DIR; }; + FBA9A74E2A50790A00F960DA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + FBA9A74F2A50790A00F960DA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + FBA9A7512A50790A00F960DA /* Renderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Renderer.h; sourceTree = ""; }; + FBA9A7522A50790A00F960DA /* Renderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Renderer.m; sourceTree = ""; }; + FBA9A7542A50790A00F960DA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + FBA9A7552A50790A00F960DA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + FBA9A7572A50790A00F960DA /* Shaders.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; + FBA9A7592A50790A00F960DA /* ShaderTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShaderTypes.h; sourceTree = ""; }; + FBA9A75B2A50790A00F960DA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + FBA9A75D2A50790A00F960DA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + FBA9A7602A50790A00F960DA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + FBA9A7622A50790A00F960DA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FBA9A7482A50790A00F960DA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FBA9A7332A50789900F960DA /* cpp */ = { + isa = PBXGroup; + children = ( + FBA9A7412A5078D800F960DA /* stb_image.h */, + FBA9A7402A5078D800F960DA /* stb_truetype.h */, + FBA9A7432A5078D800F960DA /* StringRepository.cpp */, + FBA9A73E2A5078D800F960DA /* StringRepository.h */, + FBA9A73F2A5078D800F960DA /* Texture.cpp */, + FBA9A7422A5078D800F960DA /* Texture.h */, + FBA9A7452A5078D800F960DA /* TouchInput.h */, + FBA9A73D2A5078B800F960DA /* AssetManager.cpp */, + FBA9A7342A5078B800F960DA /* AssetManager.h */, + FBA9A7352A5078B800F960DA /* Font.cpp */, + FBA9A7382A5078B800F960DA /* Font.h */, + FBA9A73C2A5078B800F960DA /* GameState.h */, + FBA9A73A2A5078B800F960DA /* Hash.cpp */, + FBA9A7372A5078B800F960DA /* Hash.h */, + FBA9A73B2A5078B800F960DA /* Position.h */, + FBA9A7392A5078B800F960DA /* Profiling.h */, + ); + name = cpp; + sourceTree = ""; + }; + FBA9A7462A5078DC00F960DA /* m */ = { + isa = PBXGroup; + children = ( + FBA9A74E2A50790A00F960DA /* AppDelegate.h */, + FBA9A74F2A50790A00F960DA /* AppDelegate.m */, + FBA9A7512A50790A00F960DA /* Renderer.h */, + FBA9A7522A50790A00F960DA /* Renderer.m */, + FBA9A7542A50790A00F960DA /* GameViewController.h */, + FBA9A7552A50790A00F960DA /* GameViewController.m */, + FBA9A7572A50790A00F960DA /* Shaders.metal */, + FBA9A7592A50790A00F960DA /* ShaderTypes.h */, + FBA9A75A2A50790A00F960DA /* Main.storyboard */, + FBA9A75D2A50790A00F960DA /* Assets.xcassets */, + FBA9A75F2A50790A00F960DA /* LaunchScreen.storyboard */, + FBA9A7622A50790A00F960DA /* main.m */, + ); + path = m; + sourceTree = ""; + }; + FBA9A74C2A50790A00F960DA /* Products */ = { + isa = PBXGroup; + children = ( + FBA9A74B2A50790A00F960DA /* KDE.app */, + ); + name = Products; + sourceTree = ""; + }; + FBC6DF7A2A50782C00CA10E7 = { + isa = PBXGroup; + children = ( + FBA9A7462A5078DC00F960DA /* m */, + FBA9A7332A50789900F960DA /* cpp */, + FBA9A74C2A50790A00F960DA /* Products */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FBA9A74A2A50790A00F960DA /* KDE */ = { + isa = PBXNativeTarget; + buildConfigurationList = FBA9A7642A50790A00F960DA /* Build configuration list for PBXNativeTarget "KDE" */; + buildPhases = ( + FBA9A7472A50790A00F960DA /* Sources */, + FBA9A7482A50790A00F960DA /* Frameworks */, + FBA9A7492A50790A00F960DA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = KDE; + productName = KDE; + productReference = FBA9A74B2A50790A00F960DA /* KDE.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FBC6DF7B2A50782C00CA10E7 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1430; + TargetAttributes = { + FBA9A74A2A50790A00F960DA = { + CreatedOnToolsVersion = 14.3.1; + }; + }; + }; + buildConfigurationList = FBC6DF7E2A50782C00CA10E7 /* Build configuration list for PBXProject "KDE" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = FBC6DF7A2A50782C00CA10E7; + productRefGroup = FBA9A74C2A50790A00F960DA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FBA9A74A2A50790A00F960DA /* KDE */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + FBA9A7492A50790A00F960DA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FBA9A7612A50790A00F960DA /* LaunchScreen.storyboard in Resources */, + FBA9A75E2A50790A00F960DA /* Assets.xcassets in Resources */, + FBA9A75C2A50790A00F960DA /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FBA9A7472A50790A00F960DA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FBA9A7692A50795400F960DA /* AssetManager.cpp in Sources */, + FBA9A7632A50790A00F960DA /* main.m in Sources */, + FBA9A7582A50790A00F960DA /* Shaders.metal in Sources */, + FBA9A76B2A5079BC00F960DA /* Texture.cpp in Sources */, + FBA9A7682A50795000F960DA /* StringRepository.cpp in Sources */, + FBA9A7532A50790A00F960DA /* Renderer.m in Sources */, + FBA9A76A2A50795700F960DA /* Hash.cpp in Sources */, + FBA9A7562A50790A00F960DA /* GameViewController.m in Sources */, + FBA9A7502A50790A00F960DA /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + FBA9A75A2A50790A00F960DA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + FBA9A75B2A50790A00F960DA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + FBA9A75F2A50790A00F960DA /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + FBA9A7602A50790A00F960DA /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + FBA9A7652A50790A00F960DA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UIRequiredDeviceCapabilities = metal; + INFOPLIST_KEY_UIStatusBarHidden = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.fumblegames.KDE; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_EMIT_LOC_STRINGS = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FBA9A7662A50790A00F960DA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UIRequiredDeviceCapabilities = metal; + INFOPLIST_KEY_UIStatusBarHidden = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.fumblegames.KDE; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_EMIT_LOC_STRINGS = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + FBC6DF7F2A50782C00CA10E7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + FBC6DF802A50782C00CA10E7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FBA9A7642A50790A00F960DA /* Build configuration list for PBXNativeTarget "KDE" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FBA9A7652A50790A00F960DA /* Debug */, + FBA9A7662A50790A00F960DA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FBC6DF7E2A50782C00CA10E7 /* Build configuration list for PBXProject "KDE" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FBC6DF7F2A50782C00CA10E7 /* Debug */, + FBC6DF802A50782C00CA10E7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FBC6DF7B2A50782C00CA10E7 /* Project object */; +} diff --git a/app/src/main/KDE.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/src/main/KDE.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/app/src/main/KDE.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/src/main/KDE.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/src/main/KDE.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/app/src/main/KDE.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/src/main/KDE.xcodeproj/project.xcworkspace/xcuserdata/ronjaenseleit.xcuserdatad/UserInterfaceState.xcuserstate b/app/src/main/KDE.xcodeproj/project.xcworkspace/xcuserdata/ronjaenseleit.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..7352f0a751affeaa5f52f47ed1ced42fd6dc4be8 GIT binary patch literal 44527 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 + + + + SchemeUserState + + KDE.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/app/src/main/m/AppDelegate.h b/app/src/main/m/AppDelegate.h new file mode 100644 index 0000000..1a982b6 --- /dev/null +++ b/app/src/main/m/AppDelegate.h @@ -0,0 +1,16 @@ +// +// AppDelegate.h +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/app/src/main/m/AppDelegate.m b/app/src/main/m/AppDelegate.m new file mode 100644 index 0000000..5e6e681 --- /dev/null +++ b/app/src/main/m/AppDelegate.m @@ -0,0 +1,44 @@ +// +// AppDelegate.m +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + + +@end diff --git a/app/src/main/m/Assets.xcassets/AccentColor.colorset/Contents.json b/app/src/main/m/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/app/src/main/m/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/app/src/main/m/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/src/main/m/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/app/src/main/m/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/app/src/main/m/Assets.xcassets/ColorMap.textureset/Contents.json b/app/src/main/m/Assets.xcassets/ColorMap.textureset/Contents.json new file mode 100644 index 0000000..702494c --- /dev/null +++ b/app/src/main/m/Assets.xcassets/ColorMap.textureset/Contents.json @@ -0,0 +1,17 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "origin" : "bottom-left", + "interpretation" : "non-premultiplied-colors" + }, + "textures" : [ + { + "idiom" : "universal", + "filename" : "Universal.mipmapset" + } + ] +} + diff --git a/app/src/main/m/Assets.xcassets/ColorMap.textureset/Universal.mipmapset/ColorMap.png b/app/src/main/m/Assets.xcassets/ColorMap.textureset/Universal.mipmapset/ColorMap.png new file mode 100644 index 0000000000000000000000000000000000000000..ddf9519d4619fb02becb1157e8b8704d10a01547 GIT binary patch literal 37539 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 r$)xH}R>*L<@bp14E`X~(RdGy#_RQ<+j#?*o1V0 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/m/Base.lproj/Main.storyboard b/app/src/main/m/Base.lproj/Main.storyboard new file mode 100644 index 0000000..8cf58c2 --- /dev/null +++ b/app/src/main/m/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/m/GameViewController.h b/app/src/main/m/GameViewController.h new file mode 100644 index 0000000..2638859 --- /dev/null +++ b/app/src/main/m/GameViewController.h @@ -0,0 +1,16 @@ +// +// GameViewController.h +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +#import +#import +#import +#import "Renderer.h" + +// Our iOS view controller +@interface GameViewController : UIViewController + +@end diff --git a/app/src/main/m/GameViewController.m b/app/src/main/m/GameViewController.m new file mode 100644 index 0000000..924b187 --- /dev/null +++ b/app/src/main/m/GameViewController.m @@ -0,0 +1,41 @@ +// +// GameViewController.m +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +#import "GameViewController.h" +#import "Renderer.h" + +@implementation GameViewController +{ + MTKView *_view; + + Renderer *_renderer; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + _view = (MTKView *)self.view; + + _view.device = MTLCreateSystemDefaultDevice(); + _view.backgroundColor = UIColor.blackColor; + + if(!_view.device) + { + NSLog(@"Metal is not supported on this device"); + self.view = [[UIView alloc] initWithFrame:self.view.frame]; + return; + } + + _renderer = [[Renderer alloc] initWithMetalKitView:_view]; + + [_renderer mtkView:_view drawableSizeWillChange:_view.bounds.size]; + + _view.delegate = _renderer; +} + +@end diff --git a/app/src/main/m/Renderer.h b/app/src/main/m/Renderer.h new file mode 100644 index 0000000..30ac437 --- /dev/null +++ b/app/src/main/m/Renderer.h @@ -0,0 +1,17 @@ +// +// Renderer.h +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +#import + +// Our platform independent renderer class. Implements the MTKViewDelegate protocol which +// allows it to accept per-frame update and drawable resize callbacks. +@interface Renderer : NSObject + +-(nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)view; + +@end + diff --git a/app/src/main/m/Renderer.m b/app/src/main/m/Renderer.m new file mode 100644 index 0000000..dd50ba9 --- /dev/null +++ b/app/src/main/m/Renderer.m @@ -0,0 +1,316 @@ +// +// Renderer.m +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +#import +#import + +#import "Renderer.h" + +// Include header shared between C code here, which executes Metal API commands, and .metal files +#import "ShaderTypes.h" + +static const NSUInteger MaxBuffersInFlight = 3; + +@implementation Renderer +{ + dispatch_semaphore_t _inFlightSemaphore; + id _device; + id _commandQueue; + + id _dynamicUniformBuffer[MaxBuffersInFlight]; + id _pipelineState; + id _depthState; + id _colorMap; + MTLVertexDescriptor *_mtlVertexDescriptor; + + uint8_t _uniformBufferIndex; + + matrix_float4x4 _projectionMatrix; + + float _rotation; + + MTKMesh *_mesh; +} + +-(nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)view; +{ + self = [super init]; + if(self) + { + _device = view.device; + _inFlightSemaphore = dispatch_semaphore_create(MaxBuffersInFlight); + [self _loadMetalWithView:view]; + [self _loadAssets]; + } + + return self; +} + +- (void)_loadMetalWithView:(nonnull MTKView *)view; +{ + /// Load Metal state objects and initialize renderer dependent view properties + + view.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + view.colorPixelFormat = MTLPixelFormatBGRA8Unorm_sRGB; + view.sampleCount = 1; + + _mtlVertexDescriptor = [[MTLVertexDescriptor alloc] init]; + + _mtlVertexDescriptor.attributes[VertexAttributePosition].format = MTLVertexFormatFloat3; + _mtlVertexDescriptor.attributes[VertexAttributePosition].offset = 0; + _mtlVertexDescriptor.attributes[VertexAttributePosition].bufferIndex = BufferIndexMeshPositions; + + _mtlVertexDescriptor.attributes[VertexAttributeTexcoord].format = MTLVertexFormatFloat2; + _mtlVertexDescriptor.attributes[VertexAttributeTexcoord].offset = 0; + _mtlVertexDescriptor.attributes[VertexAttributeTexcoord].bufferIndex = BufferIndexMeshGenerics; + + _mtlVertexDescriptor.layouts[BufferIndexMeshPositions].stride = 12; + _mtlVertexDescriptor.layouts[BufferIndexMeshPositions].stepRate = 1; + _mtlVertexDescriptor.layouts[BufferIndexMeshPositions].stepFunction = MTLVertexStepFunctionPerVertex; + + _mtlVertexDescriptor.layouts[BufferIndexMeshGenerics].stride = 8; + _mtlVertexDescriptor.layouts[BufferIndexMeshGenerics].stepRate = 1; + _mtlVertexDescriptor.layouts[BufferIndexMeshGenerics].stepFunction = MTLVertexStepFunctionPerVertex; + + id defaultLibrary = [_device newDefaultLibrary]; + + id vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"]; + + id fragmentFunction = [defaultLibrary newFunctionWithName:@"fragmentShader"]; + + MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; + pipelineStateDescriptor.label = @"MyPipeline"; + pipelineStateDescriptor.rasterSampleCount = view.sampleCount; + pipelineStateDescriptor.vertexFunction = vertexFunction; + pipelineStateDescriptor.fragmentFunction = fragmentFunction; + pipelineStateDescriptor.vertexDescriptor = _mtlVertexDescriptor; + pipelineStateDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat; + pipelineStateDescriptor.depthAttachmentPixelFormat = view.depthStencilPixelFormat; + pipelineStateDescriptor.stencilAttachmentPixelFormat = view.depthStencilPixelFormat; + + NSError *error = NULL; + _pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error]; + if (!_pipelineState) + { + NSLog(@"Failed to created pipeline state, error %@", error); + } + + MTLDepthStencilDescriptor *depthStateDesc = [[MTLDepthStencilDescriptor alloc] init]; + depthStateDesc.depthCompareFunction = MTLCompareFunctionLess; + depthStateDesc.depthWriteEnabled = YES; + _depthState = [_device newDepthStencilStateWithDescriptor:depthStateDesc]; + + for(NSUInteger i = 0; i < MaxBuffersInFlight; i++) + { + _dynamicUniformBuffer[i] = [_device newBufferWithLength:sizeof(Uniforms) + options:MTLResourceStorageModeShared]; + + _dynamicUniformBuffer[i].label = @"UniformBuffer"; + } + + _commandQueue = [_device newCommandQueue]; +} + +- (void)_loadAssets +{ + /// Load assets into metal objects + + NSError *error; + + MTKMeshBufferAllocator *metalAllocator = [[MTKMeshBufferAllocator alloc] + initWithDevice: _device]; + + MDLMesh *mdlMesh = [MDLMesh newBoxWithDimensions:(vector_float3){4, 4, 4} + segments:(vector_uint3){2, 2, 2} + geometryType:MDLGeometryTypeTriangles + inwardNormals:NO + allocator:metalAllocator]; + + MDLVertexDescriptor *mdlVertexDescriptor = + MTKModelIOVertexDescriptorFromMetal(_mtlVertexDescriptor); + + mdlVertexDescriptor.attributes[VertexAttributePosition].name = MDLVertexAttributePosition; + mdlVertexDescriptor.attributes[VertexAttributeTexcoord].name = MDLVertexAttributeTextureCoordinate; + + mdlMesh.vertexDescriptor = mdlVertexDescriptor; + + _mesh = [[MTKMesh alloc] initWithMesh:mdlMesh + device:_device + error:&error]; + + if(!_mesh || error) + { + NSLog(@"Error creating MetalKit mesh %@", error.localizedDescription); + } + + MTKTextureLoader* textureLoader = [[MTKTextureLoader alloc] initWithDevice:_device]; + + NSDictionary *textureLoaderOptions = + @{ + MTKTextureLoaderOptionTextureUsage : @(MTLTextureUsageShaderRead), + MTKTextureLoaderOptionTextureStorageMode : @(MTLStorageModePrivate) + }; + + _colorMap = [textureLoader newTextureWithName:@"ColorMap" + scaleFactor:1.0 + bundle:nil + options:textureLoaderOptions + error:&error]; + + if(!_colorMap || error) + { + NSLog(@"Error creating texture %@", error.localizedDescription); + } +} + +- (void)_updateGameState +{ + /// Update any game state before encoding renderint commands to our drawable + + Uniforms * uniforms = (Uniforms*)_dynamicUniformBuffer[_uniformBufferIndex].contents; + + uniforms->projectionMatrix = _projectionMatrix; + + vector_float3 rotationAxis = {1, 1, 0}; + matrix_float4x4 modelMatrix = matrix4x4_rotation(_rotation, rotationAxis); + matrix_float4x4 viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0); + + uniforms->modelViewMatrix = matrix_multiply(viewMatrix, modelMatrix); + + _rotation += .01; +} + +- (void)drawInMTKView:(nonnull MTKView *)view +{ + /// Per frame updates here + + dispatch_semaphore_wait(_inFlightSemaphore, DISPATCH_TIME_FOREVER); + + _uniformBufferIndex = (_uniformBufferIndex + 1) % MaxBuffersInFlight; + + id commandBuffer = [_commandQueue commandBuffer]; + commandBuffer.label = @"MyCommand"; + + __block dispatch_semaphore_t block_sema = _inFlightSemaphore; + [commandBuffer addCompletedHandler:^(id buffer) + { + dispatch_semaphore_signal(block_sema); + }]; + + [self _updateGameState]; + + /// Delay getting the currentRenderPassDescriptor until absolutely needed. This avoids + /// holding onto the drawable and blocking the display pipeline any longer than necessary + MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor; + + if(renderPassDescriptor != nil) + { + /// Final pass rendering code here + + id renderEncoder = + [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + renderEncoder.label = @"MyRenderEncoder"; + + [renderEncoder pushDebugGroup:@"DrawBox"]; + + [renderEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; + [renderEncoder setCullMode:MTLCullModeBack]; + [renderEncoder setRenderPipelineState:_pipelineState]; + [renderEncoder setDepthStencilState:_depthState]; + + [renderEncoder setVertexBuffer:_dynamicUniformBuffer[_uniformBufferIndex] + offset:0 + atIndex:BufferIndexUniforms]; + + [renderEncoder setFragmentBuffer:_dynamicUniformBuffer[_uniformBufferIndex] + offset:0 + atIndex:BufferIndexUniforms]; + + for (NSUInteger bufferIndex = 0; bufferIndex < _mesh.vertexBuffers.count; bufferIndex++) + { + MTKMeshBuffer *vertexBuffer = _mesh.vertexBuffers[bufferIndex]; + if((NSNull*)vertexBuffer != [NSNull null]) + { + [renderEncoder setVertexBuffer:vertexBuffer.buffer + offset:vertexBuffer.offset + atIndex:bufferIndex]; + } + } + + [renderEncoder setFragmentTexture:_colorMap + atIndex:TextureIndexColor]; + + for(MTKSubmesh *submesh in _mesh.submeshes) + { + [renderEncoder drawIndexedPrimitives:submesh.primitiveType + indexCount:submesh.indexCount + indexType:submesh.indexType + indexBuffer:submesh.indexBuffer.buffer + indexBufferOffset:submesh.indexBuffer.offset]; + } + + [renderEncoder popDebugGroup]; + + [renderEncoder endEncoding]; + + [commandBuffer presentDrawable:view.currentDrawable]; + } + + [commandBuffer commit]; +} + +- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size +{ + /// Respond to drawable size or orientation changes here + + float aspect = size.width / (float)size.height; + _projectionMatrix = matrix_perspective_right_hand(65.0f * (M_PI / 180.0f), aspect, 0.1f, 100.0f); +} + +#pragma mark Matrix Math Utilities + +matrix_float4x4 matrix4x4_translation(float tx, float ty, float tz) +{ + return (matrix_float4x4) {{ + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { tx, ty, tz, 1 } + }}; +} + +static matrix_float4x4 matrix4x4_rotation(float radians, vector_float3 axis) +{ + axis = vector_normalize(axis); + float ct = cosf(radians); + float st = sinf(radians); + float ci = 1 - ct; + float x = axis.x, y = axis.y, z = axis.z; + + return (matrix_float4x4) {{ + { ct + x * x * ci, y * x * ci + z * st, z * x * ci - y * st, 0}, + { x * y * ci - z * st, ct + y * y * ci, z * y * ci + x * st, 0}, + { x * z * ci + y * st, y * z * ci - x * st, ct + z * z * ci, 0}, + { 0, 0, 0, 1} + }}; +} + +matrix_float4x4 matrix_perspective_right_hand(float fovyRadians, float aspect, float nearZ, float farZ) +{ + float ys = 1 / tanf(fovyRadians * 0.5); + float xs = ys / aspect; + float zs = farZ / (nearZ - farZ); + + return (matrix_float4x4) {{ + { xs, 0, 0, 0 }, + { 0, ys, 0, 0 }, + { 0, 0, zs, -1 }, + { 0, 0, nearZ * zs, 0 } + }}; +} + +@end diff --git a/app/src/main/m/ShaderTypes.h b/app/src/main/m/ShaderTypes.h new file mode 100644 index 0000000..ddd9121 --- /dev/null +++ b/app/src/main/m/ShaderTypes.h @@ -0,0 +1,49 @@ +// +// ShaderTypes.h +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +// +// Header containing types and enum constants shared between Metal shaders and Swift/ObjC source +// +#ifndef ShaderTypes_h +#define ShaderTypes_h + +#ifdef __METAL_VERSION__ +#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +typedef metal::int32_t EnumBackingType; +#else +#import +typedef NSInteger EnumBackingType; +#endif + +#include + +typedef NS_ENUM(EnumBackingType, BufferIndex) +{ + BufferIndexMeshPositions = 0, + BufferIndexMeshGenerics = 1, + BufferIndexUniforms = 2 +}; + +typedef NS_ENUM(EnumBackingType, VertexAttribute) +{ + VertexAttributePosition = 0, + VertexAttributeTexcoord = 1, +}; + +typedef NS_ENUM(EnumBackingType, TextureIndex) +{ + TextureIndexColor = 0, +}; + +typedef struct +{ + matrix_float4x4 projectionMatrix; + matrix_float4x4 modelViewMatrix; +} Uniforms; + +#endif /* ShaderTypes_h */ + diff --git a/app/src/main/m/Shaders.metal b/app/src/main/m/Shaders.metal new file mode 100644 index 0000000..1fb5a73 --- /dev/null +++ b/app/src/main/m/Shaders.metal @@ -0,0 +1,53 @@ +// +// Shaders.metal +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +// File for Metal kernel and shader functions + +#include +#include + +// Including header shared between this Metal shader code and Swift/C code executing Metal API commands +#import "ShaderTypes.h" + +using namespace metal; + +typedef struct +{ + float3 position [[attribute(VertexAttributePosition)]]; + float2 texCoord [[attribute(VertexAttributeTexcoord)]]; +} Vertex; + +typedef struct +{ + float4 position [[position]]; + float2 texCoord; +} ColorInOut; + +vertex ColorInOut vertexShader(Vertex in [[stage_in]], + constant Uniforms & uniforms [[ buffer(BufferIndexUniforms) ]]) +{ + ColorInOut out; + + float4 position = float4(in.position, 1.0); + out.position = uniforms.projectionMatrix * uniforms.modelViewMatrix * position; + out.texCoord = in.texCoord; + + return out; +} + +fragment float4 fragmentShader(ColorInOut in [[stage_in]], + constant Uniforms & uniforms [[ buffer(BufferIndexUniforms) ]], + texture2d colorMap [[ texture(TextureIndexColor) ]]) +{ + constexpr sampler colorSampler(mip_filter::linear, + mag_filter::linear, + min_filter::linear); + + half4 colorSample = colorMap.sample(colorSampler, in.texCoord.xy); + + return float4(colorSample); +} diff --git a/app/src/main/m/main.m b/app/src/main/m/main.m new file mode 100644 index 0000000..c53bf54 --- /dev/null +++ b/app/src/main/m/main.m @@ -0,0 +1,18 @@ +// +// main.m +// KDE +// +// Created by Ronja Enseleit on 01.07.23. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + NSString * appDelegateClassName; + @autoreleasepool { + // Setup code that might create autoreleased objects goes here. + appDelegateClassName = NSStringFromClass([AppDelegate class]); + } + return UIApplicationMain(argc, argv, nil, appDelegateClassName); +}