├── .gitignore ├── LICENSE ├── README.md ├── S01-Triangle ├── S01-Triangle.xcodeproj │ └── project.pbxproj └── S01-Triangle │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── MainMenu.xib │ ├── Info.plist │ ├── S01_Triangle.entitlements │ ├── ShaderTypes.hpp │ ├── Shaders.metal │ ├── main.mm │ └── screenshot.png ├── S02-TwoTriangles ├── S02-TwoTriangles.xcodeproj │ └── project.pbxproj └── S02-TwoTriangles │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── MainMenu.xib │ ├── Info.plist │ ├── S02_TwoTriangles.entitlements │ ├── ShaderTypes.hpp │ ├── Shaders.metal │ ├── main.mm │ └── screenshot.png ├── S03-Shapes ├── S03-Shapes.xcodeproj │ └── project.pbxproj └── S03-Shapes │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── MainMenu.xib │ ├── Info.plist │ ├── S03_Shapes.entitlements │ ├── ShaderTypes.hpp │ ├── Shaders.metal │ ├── main.mm │ └── screenshot.png └── S04-Texture ├── S04-Texture.xcodeproj └── project.pbxproj └── S04-Texture ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── Base.lproj └── MainMenu.xib ├── Info.plist ├── S04_Texture.entitlements ├── ShaderTypes.hpp ├── Shaders.metal ├── assets └── windmill.png └── main.mm /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | project.xcworkspace 20 | 21 | ## Other 22 | *.moved-aside 23 | *.xccheckout 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | *.dSYM.zip 30 | *.dSYM 31 | 32 | ## Playgrounds 33 | timeline.xctimeline 34 | playground.xcworkspace 35 | 36 | # Swift Package Manager 37 | # 38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 39 | # Packages/ 40 | # Package.pins 41 | # Package.resolved 42 | .build/ 43 | 44 | # CocoaPods 45 | # 46 | # We recommend against adding the Pods directory to your .gitignore. However 47 | # you should judge for yourself, the pros and cons are mentioned at: 48 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 49 | # 50 | # Pods/ 51 | # 52 | # Add this line if you want to avoid checking in source code from the Xcode workspace 53 | # *.xcworkspace 54 | 55 | # Carthage 56 | # 57 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 58 | # Carthage/Checkouts 59 | 60 | Carthage/Build 61 | 62 | # fastlane 63 | # 64 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 65 | # screenshots whenever they are needed. 66 | # For more information about the recommended setup visit: 67 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 68 | 69 | fastlane/report.xml 70 | fastlane/Preview.html 71 | fastlane/screenshots/**/*.png 72 | fastlane/test_output 73 | 74 | # Code Injection 75 | # 76 | # After new code Injection tools there's a generated folder /iOSInjectionProject 77 | # https://github.com/johnno1962/injectionforxcode 78 | 79 | iOSInjectionProject/ 80 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ryo Suzuki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SivMetal 2 | An experimental Metal project for OpenSiv3D 3 | 4 | ## S01. Triangle 5 | ![screenshot](S01-Triangle/S01-Triangle/screenshot.png) 6 | 7 | ## S02. Two Triangles 8 | ![screenshot](S02-TwoTriangles/S02-TwoTriangles/screenshot.png) 9 | 10 | ## S03. Shapes 11 | ![screenshot](S03-Shapes/S03-Shapes/screenshot.png) 12 | 13 | ## S04. Texture 14 | 15 | ## S05. Rendering States 16 | 17 | 18 | ## References 19 | 20 | - :memo: Metal Framework Reference | [Document](https://developer.apple.com/documentation/metal?language=objc) 21 | 22 | - :memo: MetalKit Framework Reference | [Document](https://developer.apple.com/documentation/metalkit?language=objc) 23 | 24 | - :memo: Metal Best Practices Guide | [Document](https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/index.html) 25 | 26 | - :memo: Metal Shading Language Specification | [PDF](https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf) 27 | 28 | - :memo: Metal Feature Set Tables | [PDF](https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf) 29 | 30 | - :memo: Metal Programming Guide | [Document](https://developer.apple.com/library/archive/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/Introduction/Introduction.html) 31 | 32 | - :memo: Sample Code 33 | - Devices and Commands | [Document](https://developer.apple.com/documentation/metal/devices_and_commands?language=objc) 34 | - Hello Triangle | [Document](https://developer.apple.com/documentation/metal/hello_triangle?language=objc) 35 | - Basic Buffers | [Document](https://developer.apple.com/documentation/metal/basic_buffers?language=objc) 36 | - Basic Texturing | [Document](https://developer.apple.com/documentation/metal/basic_texturing?language=objc) 37 | - Hello Compute | [Document](https://developer.apple.com/documentation/metal/hello_compute?language=objc) 38 | 39 | - Working with Metal: Overview (WWDC14) | [Video](https://developer.apple.com/videos/play/wwdc2014/603/) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2014/603xx33n8igr5n1/603/603_working_with_metal_overview.pdf) 40 | 41 | - Working with Metal: Fundamentals (WWDC14) | [Video](https://developer.apple.com/videos/play/wwdc2014/604/) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2014/604xxg7crkljcr8/604/604_working_with_metal_fundamentals.pdf) 42 | 43 | - Working with Metal: Advanced (WWDC14) | [Video](https://developer.apple.com/videos/play/wwdc2014/605/) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2014/605xxygcz4pd0h6/605/605_working_with_metal_advanced.pdf) 44 | 45 | - What's New in Metal, Part 1 (WWDC15) | [Video](https://developer.apple.com/videos/play/wwdc2015/603/) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2015/6037pi9rxl6tfss8w/603/603_whats_new_in_metal_part_1.pdf) 46 | 47 | - What's New in Metal, Part 2 (WWDC15) | [Video](https://developer.apple.com/videos/play/wwdc2015/607/) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2015/607g5z16fpl7pzgi/607/607_whats_new_in_metal_part_2.pdf) 48 | 49 | - Metal Performance Optimization Techniques (WWDC15) | [Video](https://developer.apple.com/videos/play/wwdc2015/610/) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2015/610kn68riy9ms89m/610/610_metal_performance_optimization_techniques.pdf) 50 | 51 | - Adopting Metal, Part 1 (WWDC16) | [Video](https://developer.apple.com/videos/play/wwdc2016/602) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2016/602o05a86ysk0ngvlgj/602/602_adopting_metal_part_1.pdf) 52 | 53 | - Adopting Metal, Part 2 (WWDC16) | [Video](https://developer.apple.com/videos/play/wwdc2016/603) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2016/603oba298b1v4z54011/603/603_adopting_metal_part_2.pdf) 54 | 55 | - What's New in Metal, Part 1 (WWDC16) | [Video](https://developer.apple.com/videos/play/wwdc2016/604) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2016/604oezpg3wmqrkxl0t7/604/604_whats_new_in_metal_part_1.pdf) 56 | 57 | - What's New in Metal, Part 2 (WWDC16) | [Video](https://developer.apple.com/videos/play/wwdc2016/605) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2016/605ooaey8tbzegv8fth/605/605_whats_new_in_metal_part_2.pdf) 58 | 59 | - Advanced Metal Shader Optimization (WWDC16) | [Video](https://developer.apple.com/videos/play/wwdc2016/606) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2016/606oluchfgwakjbymy8/606/606_advanced_metal_shader_optimization.pdf) 60 | 61 | - Introducing Metal 2 (WWDC17) | [Video](https://developer.apple.com/videos/play/wwdc2017/601) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2017/601nzg4idodih222/601/601_introducing_metal_2.pdf) 62 | 63 | - Metal 2 Optimization and Debugging (WWDC17) | [Video](https://developer.apple.com/videos/play/wwdc2017/607) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2017/607x3ix6ocbh8/607/607_metal_2_optimization_and_debugging.pdf) 64 | 65 | - Metal for OpenGL Developers (WWDC18) | [Video](https://developer.apple.com/videos/play/wwdc2018/604) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2018/604lh97z18yv96g6nhf/604/604_metal_for_opengl_developers.pdf) 66 | 67 | - Metal for Game Developers (WWDC18) | [Video](https://developer.apple.com/videos/play/wwdc2018/607/) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2018/607buro3d9jn66/607/607_metal_for_game_developers.pdf) 68 | 69 | - Metal Shader Debugging and Profiling (WWDC18) | [Video](https://developer.apple.com/videos/play/wwdc2018/608/) 70 | 71 | - Metal Game Performance Optimization (WWDC18) | [Video](https://developer.apple.com/videos/play/wwdc2018/612/) | [PDF](https://devstreaming-cdn.apple.com/videos/wwdc/2018/612wlpc4tnd47e9245/612/612_metal_game_performance_optimization.pdf) 72 | 73 | - Metal by Tutorials | [Book](https://www.raywenderlich.com/8982-metal-by-tutorials-full-book-now-available) 74 | -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2C6241CC2178AAD700921C84 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2C6241CB2178AAD700921C84 /* Assets.xcassets */; }; 11 | 2C6241CF2178AAD700921C84 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2C6241CD2178AAD700921C84 /* MainMenu.xib */; }; 12 | 2C6241D22178AAD700921C84 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2C6241D12178AAD700921C84 /* main.mm */; }; 13 | 2C6241DB2178AB6C00921C84 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 2C6241D92178AB6C00921C84 /* Shaders.metal */; }; 14 | 2C6241DF2178AB9C00921C84 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C6241DD2178AB9C00921C84 /* Metal.framework */; }; 15 | 2C6241E02178AB9C00921C84 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C6241DE2178AB9C00921C84 /* MetalKit.framework */; }; 16 | 2C6241E22178ABA100921C84 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C6241E12178ABA100921C84 /* AppKit.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 2C6241C52178AAD600921C84 /* S01-Triangle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "S01-Triangle.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 2C6241CB2178AAD700921C84 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 22 | 2C6241CE2178AAD700921C84 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 23 | 2C6241D02178AAD700921C84 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | 2C6241D12178AAD700921C84 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; 25 | 2C6241D32178AAD700921C84 /* S01_Triangle.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = S01_Triangle.entitlements; sourceTree = ""; }; 26 | 2C6241D92178AB6C00921C84 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; 27 | 2C6241DA2178AB6C00921C84 /* ShaderTypes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ShaderTypes.hpp; sourceTree = ""; }; 28 | 2C6241DD2178AB9C00921C84 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 29 | 2C6241DE2178AB9C00921C84 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 30 | 2C6241E12178ABA100921C84 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 2C6241C22178AAD600921C84 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | 2C6241E22178ABA100921C84 /* AppKit.framework in Frameworks */, 39 | 2C6241DF2178AB9C00921C84 /* Metal.framework in Frameworks */, 40 | 2C6241E02178AB9C00921C84 /* MetalKit.framework in Frameworks */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 2C6241BC2178AAD600921C84 = { 48 | isa = PBXGroup; 49 | children = ( 50 | 2C6241C72178AAD600921C84 /* S01-Triangle */, 51 | 2C6241C62178AAD600921C84 /* Products */, 52 | 2C6241DC2178AB9C00921C84 /* Frameworks */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 2C6241C62178AAD600921C84 /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 2C6241C52178AAD600921C84 /* S01-Triangle.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 2C6241C72178AAD600921C84 /* S01-Triangle */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 2C6241D92178AB6C00921C84 /* Shaders.metal */, 68 | 2C6241DA2178AB6C00921C84 /* ShaderTypes.hpp */, 69 | 2C6241CB2178AAD700921C84 /* Assets.xcassets */, 70 | 2C6241CD2178AAD700921C84 /* MainMenu.xib */, 71 | 2C6241D02178AAD700921C84 /* Info.plist */, 72 | 2C6241D12178AAD700921C84 /* main.mm */, 73 | 2C6241D32178AAD700921C84 /* S01_Triangle.entitlements */, 74 | ); 75 | path = "S01-Triangle"; 76 | sourceTree = ""; 77 | }; 78 | 2C6241DC2178AB9C00921C84 /* Frameworks */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 2C6241E12178ABA100921C84 /* AppKit.framework */, 82 | 2C6241DD2178AB9C00921C84 /* Metal.framework */, 83 | 2C6241DE2178AB9C00921C84 /* MetalKit.framework */, 84 | ); 85 | name = Frameworks; 86 | sourceTree = ""; 87 | }; 88 | /* End PBXGroup section */ 89 | 90 | /* Begin PBXNativeTarget section */ 91 | 2C6241C42178AAD600921C84 /* S01-Triangle */ = { 92 | isa = PBXNativeTarget; 93 | buildConfigurationList = 2C6241D62178AAD700921C84 /* Build configuration list for PBXNativeTarget "S01-Triangle" */; 94 | buildPhases = ( 95 | 2C6241C12178AAD600921C84 /* Sources */, 96 | 2C6241C22178AAD600921C84 /* Frameworks */, 97 | 2C6241C32178AAD600921C84 /* Resources */, 98 | ); 99 | buildRules = ( 100 | ); 101 | dependencies = ( 102 | ); 103 | name = "S01-Triangle"; 104 | productName = "S01-Triangle"; 105 | productReference = 2C6241C52178AAD600921C84 /* S01-Triangle.app */; 106 | productType = "com.apple.product-type.application"; 107 | }; 108 | /* End PBXNativeTarget section */ 109 | 110 | /* Begin PBXProject section */ 111 | 2C6241BD2178AAD600921C84 /* Project object */ = { 112 | isa = PBXProject; 113 | attributes = { 114 | LastUpgradeCheck = 1000; 115 | ORGANIZATIONNAME = Siv3D; 116 | TargetAttributes = { 117 | 2C6241C42178AAD600921C84 = { 118 | CreatedOnToolsVersion = 10.0; 119 | }; 120 | }; 121 | }; 122 | buildConfigurationList = 2C6241C02178AAD600921C84 /* Build configuration list for PBXProject "S01-Triangle" */; 123 | compatibilityVersion = "Xcode 9.3"; 124 | developmentRegion = en; 125 | hasScannedForEncodings = 0; 126 | knownRegions = ( 127 | en, 128 | Base, 129 | ); 130 | mainGroup = 2C6241BC2178AAD600921C84; 131 | productRefGroup = 2C6241C62178AAD600921C84 /* Products */; 132 | projectDirPath = ""; 133 | projectRoot = ""; 134 | targets = ( 135 | 2C6241C42178AAD600921C84 /* S01-Triangle */, 136 | ); 137 | }; 138 | /* End PBXProject section */ 139 | 140 | /* Begin PBXResourcesBuildPhase section */ 141 | 2C6241C32178AAD600921C84 /* Resources */ = { 142 | isa = PBXResourcesBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | 2C6241CC2178AAD700921C84 /* Assets.xcassets in Resources */, 146 | 2C6241CF2178AAD700921C84 /* MainMenu.xib in Resources */, 147 | ); 148 | runOnlyForDeploymentPostprocessing = 0; 149 | }; 150 | /* End PBXResourcesBuildPhase section */ 151 | 152 | /* Begin PBXSourcesBuildPhase section */ 153 | 2C6241C12178AAD600921C84 /* Sources */ = { 154 | isa = PBXSourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | 2C6241DB2178AB6C00921C84 /* Shaders.metal in Sources */, 158 | 2C6241D22178AAD700921C84 /* main.mm in Sources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXSourcesBuildPhase section */ 163 | 164 | /* Begin PBXVariantGroup section */ 165 | 2C6241CD2178AAD700921C84 /* MainMenu.xib */ = { 166 | isa = PBXVariantGroup; 167 | children = ( 168 | 2C6241CE2178AAD700921C84 /* Base */, 169 | ); 170 | name = MainMenu.xib; 171 | sourceTree = ""; 172 | }; 173 | /* End PBXVariantGroup section */ 174 | 175 | /* Begin XCBuildConfiguration section */ 176 | 2C6241D42178AAD700921C84 /* Debug */ = { 177 | isa = XCBuildConfiguration; 178 | buildSettings = { 179 | ALWAYS_SEARCH_USER_PATHS = NO; 180 | CLANG_ANALYZER_NONNULL = YES; 181 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 182 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 183 | CLANG_CXX_LIBRARY = "libc++"; 184 | CLANG_ENABLE_MODULES = YES; 185 | CLANG_ENABLE_OBJC_ARC = YES; 186 | CLANG_ENABLE_OBJC_WEAK = YES; 187 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 188 | CLANG_WARN_BOOL_CONVERSION = YES; 189 | CLANG_WARN_COMMA = YES; 190 | CLANG_WARN_CONSTANT_CONVERSION = YES; 191 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 193 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 194 | CLANG_WARN_EMPTY_BODY = YES; 195 | CLANG_WARN_ENUM_CONVERSION = YES; 196 | CLANG_WARN_INFINITE_RECURSION = YES; 197 | CLANG_WARN_INT_CONVERSION = YES; 198 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 199 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 200 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 201 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 202 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 203 | CLANG_WARN_STRICT_PROTOTYPES = YES; 204 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 205 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 206 | CLANG_WARN_UNREACHABLE_CODE = YES; 207 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 208 | CODE_SIGN_IDENTITY = "-"; 209 | COPY_PHASE_STRIP = NO; 210 | DEBUG_INFORMATION_FORMAT = dwarf; 211 | ENABLE_STRICT_OBJC_MSGSEND = YES; 212 | ENABLE_TESTABILITY = YES; 213 | GCC_C_LANGUAGE_STANDARD = gnu11; 214 | GCC_DYNAMIC_NO_PIC = NO; 215 | GCC_NO_COMMON_BLOCKS = YES; 216 | GCC_OPTIMIZATION_LEVEL = 0; 217 | GCC_PREPROCESSOR_DEFINITIONS = ( 218 | "DEBUG=1", 219 | "$(inherited)", 220 | ); 221 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 222 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 223 | GCC_WARN_UNDECLARED_SELECTOR = YES; 224 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 225 | GCC_WARN_UNUSED_FUNCTION = YES; 226 | GCC_WARN_UNUSED_VARIABLE = YES; 227 | MACOSX_DEPLOYMENT_TARGET = 10.13; 228 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 229 | MTL_FAST_MATH = YES; 230 | ONLY_ACTIVE_ARCH = YES; 231 | SDKROOT = macosx; 232 | }; 233 | name = Debug; 234 | }; 235 | 2C6241D52178AAD700921C84 /* Release */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | ALWAYS_SEARCH_USER_PATHS = NO; 239 | CLANG_ANALYZER_NONNULL = YES; 240 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 241 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 242 | CLANG_CXX_LIBRARY = "libc++"; 243 | CLANG_ENABLE_MODULES = YES; 244 | CLANG_ENABLE_OBJC_ARC = YES; 245 | CLANG_ENABLE_OBJC_WEAK = YES; 246 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 247 | CLANG_WARN_BOOL_CONVERSION = YES; 248 | CLANG_WARN_COMMA = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 252 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INFINITE_RECURSION = YES; 256 | CLANG_WARN_INT_CONVERSION = YES; 257 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 258 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 259 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 262 | CLANG_WARN_STRICT_PROTOTYPES = YES; 263 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 264 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 265 | CLANG_WARN_UNREACHABLE_CODE = YES; 266 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 267 | CODE_SIGN_IDENTITY = "-"; 268 | COPY_PHASE_STRIP = NO; 269 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 270 | ENABLE_NS_ASSERTIONS = NO; 271 | ENABLE_STRICT_OBJC_MSGSEND = YES; 272 | GCC_C_LANGUAGE_STANDARD = gnu11; 273 | GCC_NO_COMMON_BLOCKS = YES; 274 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 275 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 276 | GCC_WARN_UNDECLARED_SELECTOR = YES; 277 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 278 | GCC_WARN_UNUSED_FUNCTION = YES; 279 | GCC_WARN_UNUSED_VARIABLE = YES; 280 | MACOSX_DEPLOYMENT_TARGET = 10.13; 281 | MTL_ENABLE_DEBUG_INFO = NO; 282 | MTL_FAST_MATH = YES; 283 | SDKROOT = macosx; 284 | }; 285 | name = Release; 286 | }; 287 | 2C6241D72178AAD700921C84 /* Debug */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 291 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 292 | CODE_SIGN_ENTITLEMENTS = "S01-Triangle/S01_Triangle.entitlements"; 293 | CODE_SIGN_STYLE = Automatic; 294 | COMBINE_HIDPI_IMAGES = YES; 295 | INFOPLIST_FILE = "S01-Triangle/Info.plist"; 296 | LD_RUNPATH_SEARCH_PATHS = ( 297 | "$(inherited)", 298 | "@executable_path/../Frameworks", 299 | ); 300 | PRODUCT_BUNDLE_IDENTIFIER = "Siv3D.S01-Triangle"; 301 | PRODUCT_NAME = "$(TARGET_NAME)"; 302 | }; 303 | name = Debug; 304 | }; 305 | 2C6241D82178AAD700921C84 /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 309 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 310 | CODE_SIGN_ENTITLEMENTS = "S01-Triangle/S01_Triangle.entitlements"; 311 | CODE_SIGN_STYLE = Automatic; 312 | COMBINE_HIDPI_IMAGES = YES; 313 | INFOPLIST_FILE = "S01-Triangle/Info.plist"; 314 | LD_RUNPATH_SEARCH_PATHS = ( 315 | "$(inherited)", 316 | "@executable_path/../Frameworks", 317 | ); 318 | PRODUCT_BUNDLE_IDENTIFIER = "Siv3D.S01-Triangle"; 319 | PRODUCT_NAME = "$(TARGET_NAME)"; 320 | }; 321 | name = Release; 322 | }; 323 | /* End XCBuildConfiguration section */ 324 | 325 | /* Begin XCConfigurationList section */ 326 | 2C6241C02178AAD600921C84 /* Build configuration list for PBXProject "S01-Triangle" */ = { 327 | isa = XCConfigurationList; 328 | buildConfigurations = ( 329 | 2C6241D42178AAD700921C84 /* Debug */, 330 | 2C6241D52178AAD700921C84 /* Release */, 331 | ); 332 | defaultConfigurationIsVisible = 0; 333 | defaultConfigurationName = Release; 334 | }; 335 | 2C6241D62178AAD700921C84 /* Build configuration list for PBXNativeTarget "S01-Triangle" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | 2C6241D72178AAD700921C84 /* Debug */, 339 | 2C6241D82178AAD700921C84 /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | /* End XCConfigurationList section */ 345 | }; 346 | rootObject = 2C6241BD2178AAD600921C84 /* Project object */; 347 | } 348 | -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSMainNibFile 26 | MainMenu 27 | NSPrincipalClass 28 | NSApplication 29 | 30 | 31 | -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle/S01_Triangle.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle/ShaderTypes.hpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # pragma once 12 | # include 13 | 14 | // 15 | // このヘッダは .metal と Objective-C++ どちらからもインクルードできる 16 | // 17 | 18 | // 頂点シェーダにセットするデータのバッファ番号 19 | struct VertexInputIndex 20 | { 21 | enum 22 | { 23 | Vertices, // 0 24 | ViewportSize, // 1 25 | }; 26 | }; 27 | 28 | // 頂点データ 29 | struct Vertex 30 | { 31 | simd::float2 position; // 2D 座標 32 | simd::float4 color; // RGBA カラー 33 | }; 34 | -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle/Shaders.metal: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # include 12 | # include "ShaderTypes.hpp" 13 | using namespace metal; 14 | 15 | // 頂点シェーダから rasterization ステージに送るデータ 16 | struct RasterizerData 17 | { 18 | float4 clipSpacePosition [[position]]; // クリップスペース座標([[position]] attribute を使用) 19 | float4 color; // 色(補間される) 20 | }; 21 | 22 | // 頂点シェーダ用の関数 23 | vertex RasterizerData 24 | vertexShader(uint vertexID [[vertex_id]], // 頂点番号 25 | // セットされた頂点データ [[buffer(0)]] 26 | constant Vertex *vertices [[buffer(VertexInputIndex::Vertices)]], 27 | // セットされた描画領域の解像度 [[buffer(1)]] 28 | constant float2& viewportSize [[buffer(VertexInputIndex::ViewportSize)]]) 29 | { 30 | // 各頂点について、スクリーン座標をクリップスペース座標に変換 31 | float2 pixelSpacePosition = vertices[vertexID].position.xy; 32 | float2 pos = (pixelSpacePosition / (viewportSize * 0.5f)) - 1.0f; 33 | 34 | RasterizerData out; 35 | out.clipSpacePosition = float4(pos.x, -pos.y, 0.0f, 1.0f); 36 | out.color = vertices[vertexID].color; 37 | return out; 38 | } 39 | 40 | // フラグメントシェーダ用の関数 41 | // [[stage_in]] attribute は、このデータが rasterization ステージから送られてくることを表す 42 | fragment float4 43 | fragmentShader(RasterizerData in [[stage_in]]) 44 | { 45 | return in.color; 46 | } 47 | -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle/main.mm: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # import 12 | # import 13 | # import 14 | # import "ShaderTypes.hpp" 15 | 16 | @interface AppDelegate : NSObject 17 | // MainMenu.xib - Window 18 | @property (weak) IBOutlet NSWindow *window; 19 | 20 | + (AppDelegate *)sharedAppDelegate; 21 | @end 22 | 23 | // Metal で描画できる view, MTKView のサブクラス 24 | @interface AppMTKView : MTKView 25 | @end 26 | 27 | void Main(); 28 | 29 | static AppDelegate *instance = nil; 30 | 31 | struct InternalSivMetalData 32 | { 33 | // アプリケーションを続行するか 34 | bool shouldKeepRunning = true; 35 | 36 | // mainLoop が完了したか 37 | bool readyToTerminate = false; 38 | 39 | // 現在のフレームカウント 40 | int frameCount = 0; 41 | 42 | // GPU のインタフェース 43 | id device; 44 | 45 | // ウィンドウ 46 | NSWindow* window; 47 | 48 | // view 49 | AppMTKView* mtkView; 50 | 51 | // RenderPipelineState: レンダリングパイプラインを表現するオブジェクト 52 | id pipelineState; 53 | 54 | // CommandBuffer を発行するオブジェクト 55 | id commandQueue; 56 | } siv; 57 | 58 | @implementation AppDelegate 59 | 60 | + (AppDelegate *)sharedAppDelegate 61 | { 62 | return instance; 63 | } 64 | 65 | // アプリケーションの初期化 66 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 67 | { 68 | NSLog(@"#SivMetal# (1) applicationDidFinishLaunching"); 69 | 70 | instance = self; 71 | 72 | // デフォルトの GPU デバイスを取得する 73 | siv.device = MTLCreateSystemDefaultDevice(); 74 | 75 | // Metal 対応の view を作成する 76 | siv.mtkView = [[AppMTKView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) 77 | device:siv.device]; 78 | 79 | // ウィンドウ 80 | siv.window = _window; 81 | 82 | // ウィンドウに view を設定する 83 | [siv.window setContentView:siv.mtkView]; 84 | // ウィンドウを最前面に表示させる 85 | [NSApp activateIgnoringOtherApps:YES]; 86 | [siv.window makeKeyAndOrderFront:self]; 87 | 88 | // view の drawable のピクセルフォーマットを設定する 89 | [siv.mtkView setColorPixelFormat:MTLPixelFormatBGRA8Unorm_sRGB]; 90 | // depthStencilTexture のフォーマットを設定する 91 | [siv.mtkView setDepthStencilPixelFormat:MTLPixelFormatDepth32Float_Stencil8]; 92 | // MSAA を設定する 93 | // 1, 4 はすべての macOS でサポートされている 94 | // 参考: https://developer.apple.com/documentation/metal/mtldevice/1433355-supportstexturesamplecount 95 | [siv.mtkView setSampleCount:4]; 96 | // drawable クリア時の色を設定する (RGBA) 97 | [siv.mtkView setClearColor:MTLClearColorMake(0.8, 0.9, 1.0, 1.0)]; 98 | // mainLoop から draw するための設定 99 | [siv.mtkView setPaused:YES]; 100 | 101 | // プロジェクト内の .metal 拡張子のシェーダファイルをすべてロードする 102 | id defaultLibrary = [siv.device newDefaultLibrary]; 103 | // シェーダ関数 `vertexShader` をロードする 104 | id vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"]; 105 | // シェーダ関数 `fragmentShader` をロードする 106 | id fragmentFunction = [defaultLibrary newFunctionWithName:@"fragmentShader"]; 107 | 108 | // RenderPipelineState を作成するための設定 (RenderPipelineDescriptor) を記述する 109 | MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; 110 | pipelineStateDescriptor.label = @"Simple Pipeline"; // ラベルをつけておくとデバッグ時に便利(任意) 111 | pipelineStateDescriptor.vertexFunction = vertexFunction; // 頂点シェーダの関数 112 | pipelineStateDescriptor.fragmentFunction = fragmentFunction; // フラグメントシェーダの関数 113 | pipelineStateDescriptor.colorAttachments[0].pixelFormat = siv.mtkView.colorPixelFormat; // 出力先のフォーマット 114 | pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES; // アルファブレンディングのための設定 115 | pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; 116 | pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; 117 | pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; 118 | pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorZero; 119 | pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne; 120 | pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; 121 | pipelineStateDescriptor.rasterSampleCount = siv.mtkView.sampleCount; // MSAA 122 | pipelineStateDescriptor.depthAttachmentPixelFormat = siv.mtkView.depthStencilPixelFormat; // 深度フォーマット 123 | pipelineStateDescriptor.stencilAttachmentPixelFormat = siv.mtkView.depthStencilPixelFormat; // ステンシルフォーマット 124 | 125 | // RenderPipelineState を作成する 126 | NSError *error = NULL; 127 | siv.pipelineState = [siv.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor 128 | error:&error]; 129 | if (!siv.pipelineState) 130 | { 131 | // RenderPipelineDescriptor の記述が間違っているとエラー 132 | NSLog(@"#SivMetal# Failed to created pipeline state, error %@", error); 133 | return; 134 | } 135 | 136 | // CommandQueue を作成。1 つのアプリケーションに 1 つ作るだけで良い 137 | siv.commandQueue = [siv.device newCommandQueue]; 138 | 139 | // mainLoop を実行する 140 | [self performSelectorOnMainThread:@selector(mainLoop) withObject:nil waitUntilDone:NO]; 141 | } 142 | 143 | // terminate が呼ばれた 144 | -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 145 | { 146 | NSLog(@"#SivMetal# applicationShouldTerminate"); 147 | 148 | // handleMessages が false を返すようにする 149 | siv.shouldKeepRunning = false; 150 | 151 | if (siv.readyToTerminate) 152 | { 153 | NSLog(@"#SivMetal# (readyToTerminate == true)"); 154 | // mainLoop が終了していたらアプリケーションを終了 155 | return NSTerminateNow; 156 | } 157 | else 158 | { 159 | NSLog(@"#SivMetal# (readyToTerminate == false)"); 160 | // mainLoop が終了するまではアプリケーションを終了しない 161 | return NSTerminateCancel; 162 | } 163 | } 164 | 165 | // アプリケーションが終了 166 | - (void)applicationWillTerminate:(NSNotification *)aNotification 167 | { 168 | NSLog(@"#SivMetal# (4) applicationWillTerminate"); 169 | } 170 | 171 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication 172 | { 173 | // ウィンドウが閉じられたときに自動的に terminate が呼ばれるようにする 174 | return YES; 175 | } 176 | 177 | // イベントを処理 178 | - (bool)handleMessages 179 | { 180 | ++siv.frameCount; 181 | 182 | @autoreleasepool 183 | { 184 | for (;;) 185 | { 186 | NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny 187 | untilDate:[NSDate distantPast] 188 | inMode:NSDefaultRunLoopMode 189 | dequeue:YES]; 190 | if (event == nil) 191 | { 192 | break; 193 | } 194 | 195 | [NSApp sendEvent:event]; 196 | } 197 | } 198 | 199 | return siv.shouldKeepRunning; 200 | } 201 | 202 | - (BOOL)isVisible 203 | { 204 | return [siv.window isVisible] 205 | && ([siv.window occlusionState] & NSWindowOcclusionStateVisible); 206 | } 207 | 208 | // 描画処理 209 | - (void)draw 210 | { 211 | @autoreleasepool 212 | { 213 | // アニメーション 214 | const float x = 300.0f - (siv.frameCount * 0.2f); 215 | 216 | // 三角形を描くための頂点データ 217 | // アライメントされたベクトルデータ simf::float2, simd::float4 を 218 | // simd::make_float2(), simd::make_float4() で作成する 219 | const Vertex triangleVertices[] = 220 | { 221 | // 2D 座標, RGBA カラー 222 | { simd::make_float2(400 + x, 100), simd::make_float4(1, 0, 0, 1) }, 223 | { simd::make_float2(700, 500), simd::make_float4(0, 1, 0, 1) }, 224 | { simd::make_float2(100, 500), simd::make_float4(0, 0, 1, 1) }, 225 | }; 226 | 227 | // 現在の drawable に使う、新しいレンダーパスのための CommandBuffer を作成 228 | id commandBuffer = [siv.commandQueue commandBuffer]; 229 | commandBuffer.label = @"MyCommand"; // ラベルをつけておくとデバッグ時に便利(任意) 230 | 231 | // 現在の drawable texture の RenderPassDescriptor を取得する 232 | MTLRenderPassDescriptor *renderPassDescriptor = siv.mtkView.currentRenderPassDescriptor; 233 | 234 | if(renderPassDescriptor != nil) 235 | { 236 | // RenderPassDescriptor から RenderCommandEncoder を作成 237 | // RenderCommandEncoder によって、レンダリングコマンドが CommandBuffer に登録される 238 | id renderCommandEncoder = 239 | [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; 240 | renderCommandEncoder.label = @"MyRenderCommandEncoder"; // ラベルをつけておくとデバッグ時に便利(任意) 241 | 242 | // 現在のウィンドウの解像度を取得 243 | simd::float2 viewportSize; 244 | viewportSize.x = [siv.mtkView drawableSize].width; 245 | viewportSize.y = [siv.mtkView drawableSize].height; 246 | 247 | // RenderCommandEncoder にビューポートを設定する 248 | [renderCommandEncoder setViewport:(MTLViewport){0, 0, viewportSize.x, viewportSize.y, -1.0, 1.0 }]; 249 | 250 | // RenderPipelineState を設定する 251 | [renderCommandEncoder setRenderPipelineState:siv.pipelineState]; 252 | 253 | // ウィンドウの表示スケーリングを考慮 254 | const float scale = [siv.window backingScaleFactor];; 255 | viewportSize.x /= scale; 256 | viewportSize.y /= scale; 257 | 258 | // 頂点シェーダ用のデータ [[buffer(0)]] をセット 259 | // setVertexBytes で扱えるデータは 4kB 以下。大きなデータは setVertexBuffer を使う 260 | [renderCommandEncoder setVertexBytes:triangleVertices 261 | length:sizeof(triangleVertices) 262 | atIndex:VertexInputIndex::Vertices]; 263 | 264 | // 頂点シェーダ用のデータ [[buffer(1)]] をセット 265 | [renderCommandEncoder setVertexBytes:&viewportSize 266 | length:sizeof(viewportSize) 267 | atIndex:VertexInputIndex::ViewportSize]; 268 | 269 | // セットされた頂点データを使って 3 個の頂点を描画 270 | [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle 271 | vertexStart:0 272 | vertexCount:3]; 273 | 274 | // RenderCommandEncoder によるコマンド登録の終了 275 | [renderCommandEncoder endEncoding]; 276 | } 277 | 278 | // 現在の drawable を表示させるコマンドを CommandBuffer に登録 279 | [commandBuffer presentDrawable:siv.mtkView.currentDrawable]; 280 | 281 | // GPU に CommandBuffer を実行してもらう 282 | [commandBuffer commit]; 283 | 284 | // CommandBuffer の実行が完了するまで待機 285 | [commandBuffer waitUntilCompleted]; 286 | 287 | if (![self isVisible]) 288 | { 289 | // アプリケーションが不可視の場合 vSync しないので 16ms スリープ 290 | usleep(16 * 1000); 291 | } 292 | 293 | // 描画内容を反映 (vSync) 294 | [siv.mtkView draw]; 295 | } 296 | } 297 | 298 | // メインループ 299 | - (void)mainLoop 300 | { 301 | NSLog(@"#SivMetal# (2) mainLoop"); 302 | 303 | // drawable を初期化 304 | [siv.mtkView draw]; 305 | 306 | Main(); 307 | 308 | NSLog(@"#SivMetal# (3) ~mainLoop"); 309 | 310 | siv.readyToTerminate = true; 311 | 312 | // applicationShouldTerminate を呼び出してアプリケーションの終了を通知 313 | [NSApp terminate:nil]; 314 | } 315 | 316 | @end 317 | 318 | @implementation AppMTKView 319 | 320 | - (BOOL)isOpaque 321 | { 322 | return YES; 323 | } 324 | 325 | - (BOOL)canBecomeKey 326 | { 327 | return YES; 328 | } 329 | 330 | - (BOOL)acceptsFirstResponder 331 | { 332 | return YES; 333 | } 334 | 335 | // 左クリックされた 336 | - (void)mouseDown:(NSEvent *)event 337 | { 338 | NSLog(@"#SivMetal# MouseL.Down"); 339 | } 340 | 341 | // 右クリックされた 342 | - (void)rightMouseDown:(NSEvent *)event 343 | { 344 | NSLog(@"#SivMetal# MouseR.Down"); 345 | } 346 | 347 | @end 348 | 349 | int main(int argc, const char *argv[]) 350 | { 351 | return NSApplicationMain(argc, argv); 352 | } 353 | 354 | namespace SivMetal 355 | { 356 | void SetWindowTitle(const char* title); 357 | 358 | bool Update(); 359 | 360 | void Draw(); 361 | } 362 | 363 | namespace SivMetal 364 | { 365 | void SetWindowTitle(const char* title) 366 | { 367 | [siv.window setTitle:[NSString stringWithUTF8String:title]]; 368 | } 369 | 370 | bool Update() 371 | { 372 | return [[AppDelegate sharedAppDelegate] handleMessages]; 373 | } 374 | 375 | void Draw() 376 | { 377 | return [[AppDelegate sharedAppDelegate] draw]; 378 | } 379 | } 380 | 381 | void Main() 382 | { 383 | // ウィンドウタイトルを変更する 384 | SivMetal::SetWindowTitle("SivMetal | Experimental Metal project for OpenSiv3D"); 385 | 386 | while (SivMetal::Update()) 387 | { 388 | SivMetal::Draw(); 389 | } 390 | } 391 | -------------------------------------------------------------------------------- /S01-Triangle/S01-Triangle/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reputeless/SivMetal/03a9584ee315b7e7f4a5792fdab61086a8498a22/S01-Triangle/S01-Triangle/screenshot.png -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2CA775C5217B7CC200CDC6A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2CA775C4217B7CC200CDC6A3 /* Assets.xcassets */; }; 11 | 2CA775C8217B7CC200CDC6A3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CA775C6217B7CC200CDC6A3 /* MainMenu.xib */; }; 12 | 2CA775D5217B7CFB00CDC6A3 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2CA775D3217B7CFB00CDC6A3 /* main.mm */; }; 13 | 2CA775D6217B7CFB00CDC6A3 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 2CA775D4217B7CFB00CDC6A3 /* Shaders.metal */; }; 14 | 2CA775DA217B7D1100CDC6A3 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA775D8217B7D1100CDC6A3 /* MetalKit.framework */; }; 15 | 2CA775DB217B7D1100CDC6A3 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA775D9217B7D1100CDC6A3 /* Metal.framework */; }; 16 | 2CA775DD217B7D1800CDC6A3 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA775DC217B7D1800CDC6A3 /* AppKit.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 2CA775BE217B7CC100CDC6A3 /* S02-TwoTriangles.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "S02-TwoTriangles.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 2CA775C4217B7CC200CDC6A3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 22 | 2CA775C7217B7CC200CDC6A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 23 | 2CA775C9217B7CC200CDC6A3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | 2CA775CC217B7CC300CDC6A3 /* S02_TwoTriangles.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = S02_TwoTriangles.entitlements; sourceTree = ""; }; 25 | 2CA775D2217B7CFB00CDC6A3 /* ShaderTypes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ShaderTypes.hpp; sourceTree = ""; }; 26 | 2CA775D3217B7CFB00CDC6A3 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; 27 | 2CA775D4217B7CFB00CDC6A3 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; 28 | 2CA775D8217B7D1100CDC6A3 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 29 | 2CA775D9217B7D1100CDC6A3 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 30 | 2CA775DC217B7D1800CDC6A3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 2CA775BB217B7CC100CDC6A3 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | 2CA775DD217B7D1800CDC6A3 /* AppKit.framework in Frameworks */, 39 | 2CA775DA217B7D1100CDC6A3 /* MetalKit.framework in Frameworks */, 40 | 2CA775DB217B7D1100CDC6A3 /* Metal.framework in Frameworks */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 2CA775B5217B7CC100CDC6A3 = { 48 | isa = PBXGroup; 49 | children = ( 50 | 2CA775C0217B7CC100CDC6A3 /* S02-TwoTriangles */, 51 | 2CA775BF217B7CC100CDC6A3 /* Products */, 52 | 2CA775D7217B7D1100CDC6A3 /* Frameworks */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 2CA775BF217B7CC100CDC6A3 /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 2CA775BE217B7CC100CDC6A3 /* S02-TwoTriangles.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 2CA775C0217B7CC100CDC6A3 /* S02-TwoTriangles */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 2CA775D3217B7CFB00CDC6A3 /* main.mm */, 68 | 2CA775D4217B7CFB00CDC6A3 /* Shaders.metal */, 69 | 2CA775D2217B7CFB00CDC6A3 /* ShaderTypes.hpp */, 70 | 2CA775C4217B7CC200CDC6A3 /* Assets.xcassets */, 71 | 2CA775C6217B7CC200CDC6A3 /* MainMenu.xib */, 72 | 2CA775C9217B7CC200CDC6A3 /* Info.plist */, 73 | 2CA775CC217B7CC300CDC6A3 /* S02_TwoTriangles.entitlements */, 74 | ); 75 | path = "S02-TwoTriangles"; 76 | sourceTree = ""; 77 | }; 78 | 2CA775D7217B7D1100CDC6A3 /* Frameworks */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 2CA775DC217B7D1800CDC6A3 /* AppKit.framework */, 82 | 2CA775D9217B7D1100CDC6A3 /* Metal.framework */, 83 | 2CA775D8217B7D1100CDC6A3 /* MetalKit.framework */, 84 | ); 85 | name = Frameworks; 86 | sourceTree = ""; 87 | }; 88 | /* End PBXGroup section */ 89 | 90 | /* Begin PBXNativeTarget section */ 91 | 2CA775BD217B7CC100CDC6A3 /* S02-TwoTriangles */ = { 92 | isa = PBXNativeTarget; 93 | buildConfigurationList = 2CA775CF217B7CC300CDC6A3 /* Build configuration list for PBXNativeTarget "S02-TwoTriangles" */; 94 | buildPhases = ( 95 | 2CA775BA217B7CC100CDC6A3 /* Sources */, 96 | 2CA775BB217B7CC100CDC6A3 /* Frameworks */, 97 | 2CA775BC217B7CC100CDC6A3 /* Resources */, 98 | ); 99 | buildRules = ( 100 | ); 101 | dependencies = ( 102 | ); 103 | name = "S02-TwoTriangles"; 104 | productName = "S02-TwoTriangles"; 105 | productReference = 2CA775BE217B7CC100CDC6A3 /* S02-TwoTriangles.app */; 106 | productType = "com.apple.product-type.application"; 107 | }; 108 | /* End PBXNativeTarget section */ 109 | 110 | /* Begin PBXProject section */ 111 | 2CA775B6217B7CC100CDC6A3 /* Project object */ = { 112 | isa = PBXProject; 113 | attributes = { 114 | LastUpgradeCheck = 1000; 115 | ORGANIZATIONNAME = Siv3D; 116 | TargetAttributes = { 117 | 2CA775BD217B7CC100CDC6A3 = { 118 | CreatedOnToolsVersion = 10.0; 119 | }; 120 | }; 121 | }; 122 | buildConfigurationList = 2CA775B9217B7CC100CDC6A3 /* Build configuration list for PBXProject "S02-TwoTriangles" */; 123 | compatibilityVersion = "Xcode 9.3"; 124 | developmentRegion = en; 125 | hasScannedForEncodings = 0; 126 | knownRegions = ( 127 | en, 128 | Base, 129 | ); 130 | mainGroup = 2CA775B5217B7CC100CDC6A3; 131 | productRefGroup = 2CA775BF217B7CC100CDC6A3 /* Products */; 132 | projectDirPath = ""; 133 | projectRoot = ""; 134 | targets = ( 135 | 2CA775BD217B7CC100CDC6A3 /* S02-TwoTriangles */, 136 | ); 137 | }; 138 | /* End PBXProject section */ 139 | 140 | /* Begin PBXResourcesBuildPhase section */ 141 | 2CA775BC217B7CC100CDC6A3 /* Resources */ = { 142 | isa = PBXResourcesBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | 2CA775C5217B7CC200CDC6A3 /* Assets.xcassets in Resources */, 146 | 2CA775C8217B7CC200CDC6A3 /* MainMenu.xib in Resources */, 147 | ); 148 | runOnlyForDeploymentPostprocessing = 0; 149 | }; 150 | /* End PBXResourcesBuildPhase section */ 151 | 152 | /* Begin PBXSourcesBuildPhase section */ 153 | 2CA775BA217B7CC100CDC6A3 /* Sources */ = { 154 | isa = PBXSourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | 2CA775D6217B7CFB00CDC6A3 /* Shaders.metal in Sources */, 158 | 2CA775D5217B7CFB00CDC6A3 /* main.mm in Sources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXSourcesBuildPhase section */ 163 | 164 | /* Begin PBXVariantGroup section */ 165 | 2CA775C6217B7CC200CDC6A3 /* MainMenu.xib */ = { 166 | isa = PBXVariantGroup; 167 | children = ( 168 | 2CA775C7217B7CC200CDC6A3 /* Base */, 169 | ); 170 | name = MainMenu.xib; 171 | sourceTree = ""; 172 | }; 173 | /* End PBXVariantGroup section */ 174 | 175 | /* Begin XCBuildConfiguration section */ 176 | 2CA775CD217B7CC300CDC6A3 /* Debug */ = { 177 | isa = XCBuildConfiguration; 178 | buildSettings = { 179 | ALWAYS_SEARCH_USER_PATHS = NO; 180 | CLANG_ANALYZER_NONNULL = YES; 181 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 182 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 183 | CLANG_CXX_LIBRARY = "libc++"; 184 | CLANG_ENABLE_MODULES = YES; 185 | CLANG_ENABLE_OBJC_ARC = YES; 186 | CLANG_ENABLE_OBJC_WEAK = YES; 187 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 188 | CLANG_WARN_BOOL_CONVERSION = YES; 189 | CLANG_WARN_COMMA = YES; 190 | CLANG_WARN_CONSTANT_CONVERSION = YES; 191 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 193 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 194 | CLANG_WARN_EMPTY_BODY = YES; 195 | CLANG_WARN_ENUM_CONVERSION = YES; 196 | CLANG_WARN_INFINITE_RECURSION = YES; 197 | CLANG_WARN_INT_CONVERSION = YES; 198 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 199 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 200 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 201 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 202 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 203 | CLANG_WARN_STRICT_PROTOTYPES = YES; 204 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 205 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 206 | CLANG_WARN_UNREACHABLE_CODE = YES; 207 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 208 | CODE_SIGN_IDENTITY = "-"; 209 | COPY_PHASE_STRIP = NO; 210 | DEBUG_INFORMATION_FORMAT = dwarf; 211 | ENABLE_STRICT_OBJC_MSGSEND = YES; 212 | ENABLE_TESTABILITY = YES; 213 | GCC_C_LANGUAGE_STANDARD = gnu11; 214 | GCC_DYNAMIC_NO_PIC = NO; 215 | GCC_NO_COMMON_BLOCKS = YES; 216 | GCC_OPTIMIZATION_LEVEL = 0; 217 | GCC_PREPROCESSOR_DEFINITIONS = ( 218 | "DEBUG=1", 219 | "$(inherited)", 220 | ); 221 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 222 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 223 | GCC_WARN_UNDECLARED_SELECTOR = YES; 224 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 225 | GCC_WARN_UNUSED_FUNCTION = YES; 226 | GCC_WARN_UNUSED_VARIABLE = YES; 227 | MACOSX_DEPLOYMENT_TARGET = 10.13; 228 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 229 | MTL_FAST_MATH = YES; 230 | ONLY_ACTIVE_ARCH = YES; 231 | SDKROOT = macosx; 232 | }; 233 | name = Debug; 234 | }; 235 | 2CA775CE217B7CC300CDC6A3 /* Release */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | ALWAYS_SEARCH_USER_PATHS = NO; 239 | CLANG_ANALYZER_NONNULL = YES; 240 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 241 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 242 | CLANG_CXX_LIBRARY = "libc++"; 243 | CLANG_ENABLE_MODULES = YES; 244 | CLANG_ENABLE_OBJC_ARC = YES; 245 | CLANG_ENABLE_OBJC_WEAK = YES; 246 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 247 | CLANG_WARN_BOOL_CONVERSION = YES; 248 | CLANG_WARN_COMMA = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 252 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INFINITE_RECURSION = YES; 256 | CLANG_WARN_INT_CONVERSION = YES; 257 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 258 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 259 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 262 | CLANG_WARN_STRICT_PROTOTYPES = YES; 263 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 264 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 265 | CLANG_WARN_UNREACHABLE_CODE = YES; 266 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 267 | CODE_SIGN_IDENTITY = "-"; 268 | COPY_PHASE_STRIP = NO; 269 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 270 | ENABLE_NS_ASSERTIONS = NO; 271 | ENABLE_STRICT_OBJC_MSGSEND = YES; 272 | GCC_C_LANGUAGE_STANDARD = gnu11; 273 | GCC_NO_COMMON_BLOCKS = YES; 274 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 275 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 276 | GCC_WARN_UNDECLARED_SELECTOR = YES; 277 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 278 | GCC_WARN_UNUSED_FUNCTION = YES; 279 | GCC_WARN_UNUSED_VARIABLE = YES; 280 | MACOSX_DEPLOYMENT_TARGET = 10.13; 281 | MTL_ENABLE_DEBUG_INFO = NO; 282 | MTL_FAST_MATH = YES; 283 | SDKROOT = macosx; 284 | }; 285 | name = Release; 286 | }; 287 | 2CA775D0217B7CC300CDC6A3 /* Debug */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 291 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 292 | CODE_SIGN_ENTITLEMENTS = "S02-TwoTriangles/S02_TwoTriangles.entitlements"; 293 | CODE_SIGN_STYLE = Automatic; 294 | COMBINE_HIDPI_IMAGES = YES; 295 | INFOPLIST_FILE = "S02-TwoTriangles/Info.plist"; 296 | LD_RUNPATH_SEARCH_PATHS = ( 297 | "$(inherited)", 298 | "@executable_path/../Frameworks", 299 | ); 300 | PRODUCT_BUNDLE_IDENTIFIER = "Siv3D.S02-TwoTriangles"; 301 | PRODUCT_NAME = "$(TARGET_NAME)"; 302 | }; 303 | name = Debug; 304 | }; 305 | 2CA775D1217B7CC300CDC6A3 /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 309 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 310 | CODE_SIGN_ENTITLEMENTS = "S02-TwoTriangles/S02_TwoTriangles.entitlements"; 311 | CODE_SIGN_STYLE = Automatic; 312 | COMBINE_HIDPI_IMAGES = YES; 313 | INFOPLIST_FILE = "S02-TwoTriangles/Info.plist"; 314 | LD_RUNPATH_SEARCH_PATHS = ( 315 | "$(inherited)", 316 | "@executable_path/../Frameworks", 317 | ); 318 | PRODUCT_BUNDLE_IDENTIFIER = "Siv3D.S02-TwoTriangles"; 319 | PRODUCT_NAME = "$(TARGET_NAME)"; 320 | }; 321 | name = Release; 322 | }; 323 | /* End XCBuildConfiguration section */ 324 | 325 | /* Begin XCConfigurationList section */ 326 | 2CA775B9217B7CC100CDC6A3 /* Build configuration list for PBXProject "S02-TwoTriangles" */ = { 327 | isa = XCConfigurationList; 328 | buildConfigurations = ( 329 | 2CA775CD217B7CC300CDC6A3 /* Debug */, 330 | 2CA775CE217B7CC300CDC6A3 /* Release */, 331 | ); 332 | defaultConfigurationIsVisible = 0; 333 | defaultConfigurationName = Release; 334 | }; 335 | 2CA775CF217B7CC300CDC6A3 /* Build configuration list for PBXNativeTarget "S02-TwoTriangles" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | 2CA775D0217B7CC300CDC6A3 /* Debug */, 339 | 2CA775D1217B7CC300CDC6A3 /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | /* End XCConfigurationList section */ 345 | }; 346 | rootObject = 2CA775B6217B7CC100CDC6A3 /* Project object */; 347 | } 348 | -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2018年 Siv3D. All rights reserved. 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles/S02_TwoTriangles.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles/ShaderTypes.hpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # pragma once 12 | # include 13 | 14 | // 15 | // このヘッダは .metal と Objective-C++ どちらからもインクルードできる 16 | // 17 | 18 | // 頂点シェーダにセットするデータのバッファ番号 19 | struct VertexInputIndex 20 | { 21 | enum 22 | { 23 | Vertices, // 0 24 | ViewportSize, // 1 25 | }; 26 | }; 27 | 28 | // 頂点データ 29 | struct Vertex 30 | { 31 | simd::float2 position; // 2D 座標 32 | simd::float4 color; // RGBA カラー 33 | }; 34 | -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles/Shaders.metal: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # include 12 | # include "ShaderTypes.hpp" 13 | using namespace metal; 14 | 15 | // 頂点シェーダから rasterization ステージに送るデータ 16 | struct RasterizerData 17 | { 18 | float4 clipSpacePosition [[position]]; // クリップスペース座標([[position]] attribute を使用) 19 | float4 color; // 色(補間される) 20 | }; 21 | 22 | // 頂点シェーダ用の関数 23 | vertex RasterizerData 24 | vertexShader(uint vertexID [[vertex_id]], // 頂点番号 25 | // セットされた頂点データ [[buffer(0)]] 26 | constant Vertex *vertices [[buffer(VertexInputIndex::Vertices)]], 27 | // セットされた描画領域の解像度 [[buffer(1)]] 28 | constant float2& viewportSize [[buffer(VertexInputIndex::ViewportSize)]]) 29 | { 30 | // 各頂点について、スクリーン座標をクリップスペース座標に変換 31 | float2 pixelSpacePosition = vertices[vertexID].position.xy; 32 | float2 pos = (pixelSpacePosition / (viewportSize * 0.5f)) - 1.0f; 33 | 34 | RasterizerData out; 35 | out.clipSpacePosition = float4(pos.x, -pos.y, 0.0f, 1.0f); 36 | out.color = vertices[vertexID].color; 37 | return out; 38 | } 39 | 40 | // フラグメントシェーダ用の関数 41 | // [[stage_in]] attribute は、このデータが rasterization ステージから送られてくることを表す 42 | fragment float4 43 | fragmentShader(RasterizerData in [[stage_in]]) 44 | { 45 | return in.color; 46 | } 47 | -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles/main.mm: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # import 12 | # import 13 | # import 14 | # import 15 | # import 16 | # import "ShaderTypes.hpp" 17 | 18 | @interface AppDelegate : NSObject 19 | // MainMenu.xib - Window 20 | @property (weak) IBOutlet NSWindow *window; 21 | 22 | + (AppDelegate *)sharedAppDelegate; 23 | @end 24 | 25 | // Metal で描画できる view, MTKView のサブクラス 26 | @interface AppMTKView : MTKView 27 | @end 28 | 29 | void Main(); 30 | 31 | static AppDelegate *instance = nil; 32 | 33 | struct InternalSivMetalData 34 | { 35 | // アプリケーションを続行するか 36 | bool shouldKeepRunning = true; 37 | 38 | // mainLoop が完了したか 39 | bool readyToTerminate = false; 40 | 41 | // 現在のフレームカウント 42 | int frameCount = 0; 43 | 44 | // GPU のインタフェース 45 | id device; 46 | 47 | // ウィンドウ 48 | NSWindow* window; 49 | 50 | // view 51 | AppMTKView* mtkView; 52 | 53 | // RenderPipelineState: レンダリングパイプラインを表現するオブジェクト 54 | id pipelineState; 55 | 56 | // CommandBuffer を発行するオブジェクト 57 | id commandQueue; 58 | 59 | // 画面をクリアする色 60 | MTLClearColor clearColor; 61 | 62 | // 描画する頂点データ 63 | std::vector vertices; 64 | 65 | } siv; 66 | 67 | @implementation AppDelegate 68 | 69 | + (AppDelegate *)sharedAppDelegate 70 | { 71 | return instance; 72 | } 73 | 74 | // アプリケーションの初期化 75 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 76 | { 77 | NSLog(@"#SivMetal# (1) applicationDidFinishLaunching"); 78 | 79 | instance = self; 80 | 81 | // デフォルトの GPU デバイスを取得する 82 | siv.device = MTLCreateSystemDefaultDevice(); 83 | 84 | // Metal 対応の view を作成する 85 | siv.mtkView = [[AppMTKView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) 86 | device:siv.device]; 87 | 88 | // ウィンドウ 89 | siv.window = _window; 90 | 91 | // ウィンドウに view を設定する 92 | [siv.window setContentView:siv.mtkView]; 93 | // ウィンドウを最前面に表示させる 94 | [NSApp activateIgnoringOtherApps:YES]; 95 | [siv.window makeKeyAndOrderFront:self]; 96 | 97 | // view の drawable のピクセルフォーマットを設定する 98 | [siv.mtkView setColorPixelFormat:MTLPixelFormatBGRA8Unorm_sRGB]; 99 | // depthStencilTexture のフォーマットを設定する 100 | [siv.mtkView setDepthStencilPixelFormat:MTLPixelFormatDepth32Float_Stencil8]; 101 | // MSAA を設定する 102 | // 1, 4 はすべての macOS でサポートされている 103 | // 参考: https://developer.apple.com/documentation/metal/mtldevice/1433355-supportstexturesamplecount 104 | [siv.mtkView setSampleCount:4]; 105 | // drawable クリア時の色を設定する (RGBA) 106 | siv.clearColor = MTLClearColorMake(11/255.0, 22/255.0, 33/255.0, 1.0); 107 | [siv.mtkView setClearColor:siv.clearColor]; 108 | // mainLoop から draw するための設定 109 | [siv.mtkView setPaused:YES]; 110 | 111 | // プロジェクト内の .metal 拡張子のシェーダファイルをすべてロードする 112 | id defaultLibrary = [siv.device newDefaultLibrary]; 113 | // シェーダ関数 `vertexShader` をロードする 114 | id vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"]; 115 | // シェーダ関数 `fragmentShader` をロードする 116 | id fragmentFunction = [defaultLibrary newFunctionWithName:@"fragmentShader"]; 117 | 118 | // RenderPipelineState を作成するための設定 (RenderPipelineDescriptor) を記述する 119 | MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; 120 | pipelineStateDescriptor.label = @"Simple Pipeline"; // ラベルをつけておくとデバッグ時に便利(任意) 121 | pipelineStateDescriptor.vertexFunction = vertexFunction; // 頂点シェーダの関数 122 | pipelineStateDescriptor.fragmentFunction = fragmentFunction; // フラグメントシェーダの関数 123 | pipelineStateDescriptor.colorAttachments[0].pixelFormat = siv.mtkView.colorPixelFormat; // 出力先のフォーマット 124 | pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES; // アルファブレンディングのための設定 125 | pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; 126 | pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; 127 | pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; 128 | pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorZero; 129 | pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne; 130 | pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; 131 | pipelineStateDescriptor.rasterSampleCount = siv.mtkView.sampleCount; // MSAA 132 | pipelineStateDescriptor.depthAttachmentPixelFormat = siv.mtkView.depthStencilPixelFormat; // 深度フォーマット 133 | pipelineStateDescriptor.stencilAttachmentPixelFormat = siv.mtkView.depthStencilPixelFormat; // ステンシルフォーマット 134 | 135 | // RenderPipelineState を作成する 136 | NSError *error = NULL; 137 | siv.pipelineState = [siv.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor 138 | error:&error]; 139 | if (!siv.pipelineState) 140 | { 141 | // RenderPipelineDescriptor の記述が間違っているとエラー 142 | NSLog(@"#SivMetal# Failed to created pipeline state, error %@", error); 143 | return; 144 | } 145 | 146 | // CommandQueue を作成。1 つのアプリケーションに 1 つ作るだけで良い 147 | siv.commandQueue = [siv.device newCommandQueue]; 148 | 149 | // mainLoop を実行する 150 | [self performSelectorOnMainThread:@selector(mainLoop) withObject:nil waitUntilDone:NO]; 151 | } 152 | 153 | // terminate が呼ばれた 154 | -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 155 | { 156 | NSLog(@"#SivMetal# applicationShouldTerminate"); 157 | 158 | // handleMessages が false を返すようにする 159 | siv.shouldKeepRunning = false; 160 | 161 | if (siv.readyToTerminate) 162 | { 163 | NSLog(@"#SivMetal# (readyToTerminate == true)"); 164 | // mainLoop が終了していたらアプリケーションを終了 165 | return NSTerminateNow; 166 | } 167 | else 168 | { 169 | NSLog(@"#SivMetal# (readyToTerminate == false)"); 170 | // mainLoop が終了するまではアプリケーションを終了しない 171 | return NSTerminateCancel; 172 | } 173 | } 174 | 175 | // アプリケーションが終了 176 | - (void)applicationWillTerminate:(NSNotification *)aNotification 177 | { 178 | NSLog(@"#SivMetal# (4) applicationWillTerminate"); 179 | } 180 | 181 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication 182 | { 183 | // ウィンドウが閉じられたときに自動的に terminate が呼ばれるようにする 184 | return YES; 185 | } 186 | 187 | // イベントを処理 188 | - (bool)handleMessages 189 | { 190 | ++siv.frameCount; 191 | 192 | @autoreleasepool 193 | { 194 | for (;;) 195 | { 196 | NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny 197 | untilDate:[NSDate distantPast] 198 | inMode:NSDefaultRunLoopMode 199 | dequeue:YES]; 200 | if (event == nil) 201 | { 202 | break; 203 | } 204 | 205 | [NSApp sendEvent:event]; 206 | } 207 | } 208 | 209 | return siv.shouldKeepRunning; 210 | } 211 | 212 | // 描画処理 213 | - (void)draw 214 | { 215 | @autoreleasepool 216 | { 217 | // 現在の drawable に使う、新しいレンダーパスのための CommandBuffer を作成 218 | id commandBuffer = [siv.commandQueue commandBuffer]; 219 | commandBuffer.label = @"MyCommand"; // ラベルをつけておくとデバッグ時に便利(任意) 220 | 221 | // 現在の drawable texture の RenderPassDescriptor を取得する 222 | MTLRenderPassDescriptor *renderPassDescriptor = siv.mtkView.currentRenderPassDescriptor; 223 | 224 | if(renderPassDescriptor != nil) 225 | { 226 | // RenderPassDescriptor から RenderCommandEncoder を作成 227 | // RenderCommandEncoder によって、レンダリングコマンドが CommandBuffer に登録される 228 | id renderCommandEncoder = 229 | [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; 230 | renderCommandEncoder.label = @"MyRenderCommandEncoder"; // ラベルをつけておくとデバッグ時に便利(任意) 231 | 232 | // 現在のウィンドウの解像度を取得 233 | simd::float2 viewportSize; 234 | viewportSize.x = [siv.mtkView drawableSize].width; 235 | viewportSize.y = [siv.mtkView drawableSize].height; 236 | 237 | // RenderCommandEncoder にビューポートを設定する 238 | [renderCommandEncoder setViewport:(MTLViewport){0, 0, viewportSize.x, viewportSize.y, -1.0, 1.0 }]; 239 | 240 | // RenderPipelineState を設定する 241 | [renderCommandEncoder setRenderPipelineState:siv.pipelineState]; 242 | 243 | // ウィンドウの表示スケーリングを考慮 244 | const float scale = [siv.window backingScaleFactor];; 245 | viewportSize.x /= scale; 246 | viewportSize.y /= scale; 247 | 248 | if (!siv.vertices.empty()) 249 | { 250 | // 頂点シェーダ用のデータ [[buffer(0)]] をセット 251 | // setVertexBytes で扱えるデータは 4kB 以下。大きなデータは setVertexBuffer を使う 252 | [renderCommandEncoder setVertexBytes:siv.vertices.data() 253 | length:(sizeof(Vertex) * siv.vertices.size()) 254 | atIndex:VertexInputIndex::Vertices]; 255 | 256 | // 頂点シェーダ用のデータ [[buffer(1)]] をセット 257 | [renderCommandEncoder setVertexBytes:&viewportSize 258 | length:sizeof(viewportSize) 259 | atIndex:VertexInputIndex::ViewportSize]; 260 | 261 | // セットされた頂点データを使って頂点を描画 262 | [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle 263 | vertexStart:0 264 | vertexCount:siv.vertices.size()]; 265 | } 266 | 267 | // RenderCommandEncoder によるコマンド登録の終了 268 | [renderCommandEncoder endEncoding]; 269 | } 270 | 271 | // 現在の drawable を表示させるコマンドを CommandBuffer に登録 272 | [commandBuffer presentDrawable:siv.mtkView.currentDrawable]; 273 | 274 | // GPU に CommandBuffer を実行してもらう 275 | [commandBuffer commit]; 276 | 277 | // CommandBuffer の実行が完了するまで待機 278 | [commandBuffer waitUntilCompleted]; 279 | 280 | siv.vertices.clear(); 281 | } 282 | } 283 | 284 | // メインループ 285 | - (void)mainLoop 286 | { 287 | NSLog(@"#SivMetal# (2) mainLoop"); 288 | 289 | // drawable を初期化 290 | [siv.mtkView draw]; 291 | 292 | Main(); 293 | 294 | NSLog(@"#SivMetal# (3) ~mainLoop"); 295 | 296 | siv.readyToTerminate = true; 297 | 298 | // applicationShouldTerminate を呼び出してアプリケーションの終了を通知 299 | [NSApp terminate:nil]; 300 | } 301 | 302 | @end 303 | 304 | @implementation AppMTKView 305 | 306 | - (BOOL)isOpaque 307 | { 308 | return YES; 309 | } 310 | 311 | - (BOOL)canBecomeKey 312 | { 313 | return YES; 314 | } 315 | 316 | - (BOOL)acceptsFirstResponder 317 | { 318 | return YES; 319 | } 320 | 321 | // 左クリックされた 322 | - (void)mouseDown:(NSEvent *)event 323 | { 324 | NSLog(@"#SivMetal# MouseL.Down"); 325 | } 326 | 327 | // 右クリックされた 328 | - (void)rightMouseDown:(NSEvent *)event 329 | { 330 | NSLog(@"#SivMetal# MouseR.Down"); 331 | } 332 | 333 | @end 334 | 335 | int main(int argc, const char *argv[]) 336 | { 337 | return NSApplicationMain(argc, argv); 338 | } 339 | 340 | 341 | namespace SivMetal 342 | { 343 | using int8 = std::int8_t; 344 | using int16 = std::int16_t; 345 | using int32 = std::int32_t; 346 | using int64 = std::int64_t; 347 | using uint8 = std::uint8_t; 348 | using uint16 = std::uint16_t; 349 | using uint32 = std::uint32_t; 350 | using uint64 = std::uint64_t; 351 | 352 | struct Point 353 | { 354 | using value_type = int32; 355 | 356 | value_type x, y; 357 | 358 | Point() noexcept = default; 359 | 360 | constexpr Point(const Point&) noexcept = default; 361 | 362 | constexpr Point(int32 _x, int32 _y) noexcept 363 | : x(_x) 364 | , y(_y) {} 365 | 366 | template && std::is_integral_v>* = nullptr> 367 | constexpr Point(X _x, Y _y) noexcept 368 | : x(static_cast(_x)) 369 | , y(static_cast(_y)) {} 370 | 371 | template || !std::is_integral_v>* = nullptr> 372 | constexpr Point(X _x, Y _y) noexcept = delete; 373 | }; 374 | 375 | template 376 | struct Vector2D 377 | { 378 | template 379 | using vector_type = Vector2D; 380 | 381 | using value_type = Type; 382 | 383 | value_type x, y; 384 | 385 | Vector2D() noexcept = default; 386 | 387 | constexpr Vector2D(const Vector2D&) noexcept = default; 388 | 389 | template 390 | constexpr Vector2D(X _x, Y _y) noexcept 391 | : x(static_cast(_x)) 392 | , y(static_cast(_y)) {} 393 | 394 | constexpr Vector2D(value_type _x, value_type _y) noexcept 395 | : x(_x) 396 | , y(_y) {} 397 | 398 | constexpr Vector2D(const Point& v) noexcept 399 | : x(static_cast(v.x)) 400 | , y(static_cast(v.y)) {} 401 | 402 | template 403 | constexpr Vector2D(const Vector2D& v) noexcept 404 | : x(static_cast(v.x)) 405 | , y(static_cast(v.y)) {} 406 | }; 407 | 408 | using Float2 = Vector2D; 409 | using Vec2 = Vector2D; 410 | 411 | struct ColorF 412 | { 413 | double r, g, b, a; 414 | 415 | ColorF() = default; 416 | 417 | constexpr ColorF(const ColorF& color) noexcept = default; 418 | 419 | explicit constexpr ColorF(double rgb, double _a = 1.0) noexcept 420 | : r(rgb) 421 | , g(rgb) 422 | , b(rgb) 423 | , a(_a) {} 424 | 425 | constexpr ColorF(double _r, double _g, double _b, double _a = 1.0) noexcept 426 | : r(_r) 427 | , g(_g) 428 | , b(_b) 429 | , a(_a) {} 430 | }; 431 | 432 | void SetWindowTitle(const char* title); 433 | 434 | bool IsVisible(); 435 | 436 | bool Update(); 437 | 438 | int32 FrameCount(); 439 | 440 | void SetBackground(double r, double g, double b, double a); 441 | 442 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 443 | const ColorF& color); 444 | 445 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 446 | const ColorF& c0, const ColorF& c1, const ColorF& c2); 447 | } 448 | 449 | namespace SivMetal 450 | { 451 | void SetWindowTitle(const char* title) 452 | { 453 | [siv.window setTitle:[NSString stringWithUTF8String:title]]; 454 | } 455 | 456 | bool IsVisible() 457 | { 458 | return [siv.window isVisible] 459 | && ([siv.window occlusionState] & NSWindowOcclusionStateVisible); 460 | } 461 | 462 | bool Update() 463 | { 464 | if (!IsVisible()) 465 | { 466 | // アプリケーションが不可視の場合 vSync しないので 16ms スリープ 467 | usleep(16 * 1000); 468 | } 469 | 470 | [[AppDelegate sharedAppDelegate] draw]; 471 | 472 | // 描画内容を反映 (vSync) 473 | [siv.mtkView draw]; 474 | 475 | return [[AppDelegate sharedAppDelegate] handleMessages]; 476 | } 477 | 478 | int32 FrameCount() 479 | { 480 | return siv.frameCount; 481 | } 482 | 483 | void SetBackground(const ColorF& color) 484 | { 485 | siv.clearColor = MTLClearColorMake(color.r, color.g, color.b, color.a); 486 | [siv.mtkView setClearColor:siv.clearColor]; 487 | } 488 | 489 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 490 | const ColorF& color) 491 | { 492 | DrawTriangle(p0, p1, p2, color, color, color); 493 | } 494 | 495 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 496 | const ColorF& c0, const ColorF& c1, const ColorF& c2) 497 | { 498 | const size_t oldSize = siv.vertices.size(); 499 | 500 | if ((sizeof(Vertex) * (oldSize + 3)) > 4096) 501 | { 502 | return; 503 | } 504 | 505 | siv.vertices.resize(oldSize + 3); 506 | Vertex* vtx = siv.vertices.data() + oldSize; 507 | vtx[0].position = simd::make_float2(p0.x, p0.y); 508 | vtx[0].color = simd::make_float4(c0.r, c0.g, c0.b, c0.a); 509 | vtx[1].position = simd::make_float2(p1.x, p1.y); 510 | vtx[1].color = simd::make_float4(c1.r, c1.g, c1.b, c1.a); 511 | vtx[2].position = simd::make_float2(p2.x, p2.y); 512 | vtx[2].color = simd::make_float4(c2.r, c2.g, c2.b, c2.a); 513 | } 514 | } 515 | 516 | using SivMetal::Vec2; 517 | using SivMetal::ColorF; 518 | 519 | void Main() 520 | { 521 | // ウィンドウタイトルを変更する 522 | SivMetal::SetWindowTitle("SivMetal | Experimental Metal project for OpenSiv3D"); 523 | 524 | // 背景色を変更する 525 | SivMetal::SetBackground(ColorF(0.8, 0.9, 1.0)); 526 | 527 | while (SivMetal::Update()) 528 | { 529 | // アニメーション 530 | const double x = 300.0 - (SivMetal::FrameCount() * 0.2); 531 | 532 | // 三角形を描画 533 | SivMetal::DrawTriangle(Vec2(400 + x, 100), Vec2(700, 500), Vec2(100, 500), ColorF(1, 0, 0, 1), ColorF(0, 1, 0, 1), ColorF(0, 0, 1, 1)); 534 | 535 | // 半透明の三角形を描画 536 | SivMetal::DrawTriangle(Vec2(400 - x, 100), Vec2(700, 500), Vec2(100, 500), ColorF(1, 1, 1, 0.5)); 537 | } 538 | } 539 | -------------------------------------------------------------------------------- /S02-TwoTriangles/S02-TwoTriangles/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reputeless/SivMetal/03a9584ee315b7e7f4a5792fdab61086a8498a22/S02-TwoTriangles/S02-TwoTriangles/screenshot.png -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2CA775EE217D9F8E00CDC6A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2CA775ED217D9F8E00CDC6A3 /* Assets.xcassets */; }; 11 | 2CA775F1217D9F8E00CDC6A3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CA775EF217D9F8E00CDC6A3 /* MainMenu.xib */; }; 12 | 2CA775FE217D9FAE00CDC6A3 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA775FC217D9FAE00CDC6A3 /* MetalKit.framework */; }; 13 | 2CA775FF217D9FAE00CDC6A3 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA775FD217D9FAE00CDC6A3 /* Metal.framework */; }; 14 | 2CA77601217D9FB300CDC6A3 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA77600217D9FB300CDC6A3 /* AppKit.framework */; }; 15 | 2CA77605217D9FDD00CDC6A3 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 2CA77602217D9FDD00CDC6A3 /* Shaders.metal */; }; 16 | 2CA77606217D9FDD00CDC6A3 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2CA77604217D9FDD00CDC6A3 /* main.mm */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 2CA775E7217D9F8D00CDC6A3 /* S03-Shapes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "S03-Shapes.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 2CA775ED217D9F8E00CDC6A3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 22 | 2CA775F0217D9F8E00CDC6A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 23 | 2CA775F2217D9F8E00CDC6A3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | 2CA775F5217D9F8E00CDC6A3 /* S03_Shapes.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = S03_Shapes.entitlements; sourceTree = ""; }; 25 | 2CA775FC217D9FAE00CDC6A3 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 26 | 2CA775FD217D9FAE00CDC6A3 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 27 | 2CA77600217D9FB300CDC6A3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 28 | 2CA77602217D9FDD00CDC6A3 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; 29 | 2CA77603217D9FDD00CDC6A3 /* ShaderTypes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ShaderTypes.hpp; sourceTree = ""; }; 30 | 2CA77604217D9FDD00CDC6A3 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 2CA775E4217D9F8D00CDC6A3 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | 2CA77601217D9FB300CDC6A3 /* AppKit.framework in Frameworks */, 39 | 2CA775FE217D9FAE00CDC6A3 /* MetalKit.framework in Frameworks */, 40 | 2CA775FF217D9FAE00CDC6A3 /* Metal.framework in Frameworks */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 2CA775DE217D9F8D00CDC6A3 = { 48 | isa = PBXGroup; 49 | children = ( 50 | 2CA775E9217D9F8D00CDC6A3 /* S03-Shapes */, 51 | 2CA775E8217D9F8D00CDC6A3 /* Products */, 52 | 2CA775FB217D9FAE00CDC6A3 /* Frameworks */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 2CA775E8217D9F8D00CDC6A3 /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 2CA775E7217D9F8D00CDC6A3 /* S03-Shapes.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 2CA775E9217D9F8D00CDC6A3 /* S03-Shapes */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 2CA77604217D9FDD00CDC6A3 /* main.mm */, 68 | 2CA77602217D9FDD00CDC6A3 /* Shaders.metal */, 69 | 2CA77603217D9FDD00CDC6A3 /* ShaderTypes.hpp */, 70 | 2CA775ED217D9F8E00CDC6A3 /* Assets.xcassets */, 71 | 2CA775EF217D9F8E00CDC6A3 /* MainMenu.xib */, 72 | 2CA775F2217D9F8E00CDC6A3 /* Info.plist */, 73 | 2CA775F5217D9F8E00CDC6A3 /* S03_Shapes.entitlements */, 74 | ); 75 | path = "S03-Shapes"; 76 | sourceTree = ""; 77 | }; 78 | 2CA775FB217D9FAE00CDC6A3 /* Frameworks */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 2CA77600217D9FB300CDC6A3 /* AppKit.framework */, 82 | 2CA775FD217D9FAE00CDC6A3 /* Metal.framework */, 83 | 2CA775FC217D9FAE00CDC6A3 /* MetalKit.framework */, 84 | ); 85 | name = Frameworks; 86 | sourceTree = ""; 87 | }; 88 | /* End PBXGroup section */ 89 | 90 | /* Begin PBXNativeTarget section */ 91 | 2CA775E6217D9F8D00CDC6A3 /* S03-Shapes */ = { 92 | isa = PBXNativeTarget; 93 | buildConfigurationList = 2CA775F8217D9F8E00CDC6A3 /* Build configuration list for PBXNativeTarget "S03-Shapes" */; 94 | buildPhases = ( 95 | 2CA775E3217D9F8D00CDC6A3 /* Sources */, 96 | 2CA775E4217D9F8D00CDC6A3 /* Frameworks */, 97 | 2CA775E5217D9F8D00CDC6A3 /* Resources */, 98 | ); 99 | buildRules = ( 100 | ); 101 | dependencies = ( 102 | ); 103 | name = "S03-Shapes"; 104 | productName = "S03-Shapes"; 105 | productReference = 2CA775E7217D9F8D00CDC6A3 /* S03-Shapes.app */; 106 | productType = "com.apple.product-type.application"; 107 | }; 108 | /* End PBXNativeTarget section */ 109 | 110 | /* Begin PBXProject section */ 111 | 2CA775DF217D9F8D00CDC6A3 /* Project object */ = { 112 | isa = PBXProject; 113 | attributes = { 114 | LastUpgradeCheck = 1000; 115 | ORGANIZATIONNAME = Siv3D; 116 | TargetAttributes = { 117 | 2CA775E6217D9F8D00CDC6A3 = { 118 | CreatedOnToolsVersion = 10.0; 119 | }; 120 | }; 121 | }; 122 | buildConfigurationList = 2CA775E2217D9F8D00CDC6A3 /* Build configuration list for PBXProject "S03-Shapes" */; 123 | compatibilityVersion = "Xcode 9.3"; 124 | developmentRegion = en; 125 | hasScannedForEncodings = 0; 126 | knownRegions = ( 127 | en, 128 | Base, 129 | ); 130 | mainGroup = 2CA775DE217D9F8D00CDC6A3; 131 | productRefGroup = 2CA775E8217D9F8D00CDC6A3 /* Products */; 132 | projectDirPath = ""; 133 | projectRoot = ""; 134 | targets = ( 135 | 2CA775E6217D9F8D00CDC6A3 /* S03-Shapes */, 136 | ); 137 | }; 138 | /* End PBXProject section */ 139 | 140 | /* Begin PBXResourcesBuildPhase section */ 141 | 2CA775E5217D9F8D00CDC6A3 /* Resources */ = { 142 | isa = PBXResourcesBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | 2CA775EE217D9F8E00CDC6A3 /* Assets.xcassets in Resources */, 146 | 2CA775F1217D9F8E00CDC6A3 /* MainMenu.xib in Resources */, 147 | ); 148 | runOnlyForDeploymentPostprocessing = 0; 149 | }; 150 | /* End PBXResourcesBuildPhase section */ 151 | 152 | /* Begin PBXSourcesBuildPhase section */ 153 | 2CA775E3217D9F8D00CDC6A3 /* Sources */ = { 154 | isa = PBXSourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | 2CA77606217D9FDD00CDC6A3 /* main.mm in Sources */, 158 | 2CA77605217D9FDD00CDC6A3 /* Shaders.metal in Sources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXSourcesBuildPhase section */ 163 | 164 | /* Begin PBXVariantGroup section */ 165 | 2CA775EF217D9F8E00CDC6A3 /* MainMenu.xib */ = { 166 | isa = PBXVariantGroup; 167 | children = ( 168 | 2CA775F0217D9F8E00CDC6A3 /* Base */, 169 | ); 170 | name = MainMenu.xib; 171 | sourceTree = ""; 172 | }; 173 | /* End PBXVariantGroup section */ 174 | 175 | /* Begin XCBuildConfiguration section */ 176 | 2CA775F6217D9F8E00CDC6A3 /* Debug */ = { 177 | isa = XCBuildConfiguration; 178 | buildSettings = { 179 | ALWAYS_SEARCH_USER_PATHS = NO; 180 | CLANG_ANALYZER_NONNULL = YES; 181 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 182 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 183 | CLANG_CXX_LIBRARY = "libc++"; 184 | CLANG_ENABLE_MODULES = YES; 185 | CLANG_ENABLE_OBJC_ARC = YES; 186 | CLANG_ENABLE_OBJC_WEAK = YES; 187 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 188 | CLANG_WARN_BOOL_CONVERSION = YES; 189 | CLANG_WARN_COMMA = YES; 190 | CLANG_WARN_CONSTANT_CONVERSION = YES; 191 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 193 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 194 | CLANG_WARN_EMPTY_BODY = YES; 195 | CLANG_WARN_ENUM_CONVERSION = YES; 196 | CLANG_WARN_INFINITE_RECURSION = YES; 197 | CLANG_WARN_INT_CONVERSION = YES; 198 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 199 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 200 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 201 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 202 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 203 | CLANG_WARN_STRICT_PROTOTYPES = YES; 204 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 205 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 206 | CLANG_WARN_UNREACHABLE_CODE = YES; 207 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 208 | CODE_SIGN_IDENTITY = "-"; 209 | COPY_PHASE_STRIP = NO; 210 | DEBUG_INFORMATION_FORMAT = dwarf; 211 | ENABLE_STRICT_OBJC_MSGSEND = YES; 212 | ENABLE_TESTABILITY = YES; 213 | GCC_C_LANGUAGE_STANDARD = gnu11; 214 | GCC_DYNAMIC_NO_PIC = NO; 215 | GCC_NO_COMMON_BLOCKS = YES; 216 | GCC_OPTIMIZATION_LEVEL = 0; 217 | GCC_PREPROCESSOR_DEFINITIONS = ( 218 | "DEBUG=1", 219 | "$(inherited)", 220 | ); 221 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 222 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 223 | GCC_WARN_UNDECLARED_SELECTOR = YES; 224 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 225 | GCC_WARN_UNUSED_FUNCTION = YES; 226 | GCC_WARN_UNUSED_VARIABLE = YES; 227 | MACOSX_DEPLOYMENT_TARGET = 10.13; 228 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 229 | MTL_FAST_MATH = YES; 230 | ONLY_ACTIVE_ARCH = YES; 231 | SDKROOT = macosx; 232 | }; 233 | name = Debug; 234 | }; 235 | 2CA775F7217D9F8E00CDC6A3 /* Release */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | ALWAYS_SEARCH_USER_PATHS = NO; 239 | CLANG_ANALYZER_NONNULL = YES; 240 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 241 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 242 | CLANG_CXX_LIBRARY = "libc++"; 243 | CLANG_ENABLE_MODULES = YES; 244 | CLANG_ENABLE_OBJC_ARC = YES; 245 | CLANG_ENABLE_OBJC_WEAK = YES; 246 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 247 | CLANG_WARN_BOOL_CONVERSION = YES; 248 | CLANG_WARN_COMMA = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 252 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INFINITE_RECURSION = YES; 256 | CLANG_WARN_INT_CONVERSION = YES; 257 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 258 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 259 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 262 | CLANG_WARN_STRICT_PROTOTYPES = YES; 263 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 264 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 265 | CLANG_WARN_UNREACHABLE_CODE = YES; 266 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 267 | CODE_SIGN_IDENTITY = "-"; 268 | COPY_PHASE_STRIP = NO; 269 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 270 | ENABLE_NS_ASSERTIONS = NO; 271 | ENABLE_STRICT_OBJC_MSGSEND = YES; 272 | GCC_C_LANGUAGE_STANDARD = gnu11; 273 | GCC_NO_COMMON_BLOCKS = YES; 274 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 275 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 276 | GCC_WARN_UNDECLARED_SELECTOR = YES; 277 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 278 | GCC_WARN_UNUSED_FUNCTION = YES; 279 | GCC_WARN_UNUSED_VARIABLE = YES; 280 | MACOSX_DEPLOYMENT_TARGET = 10.13; 281 | MTL_ENABLE_DEBUG_INFO = NO; 282 | MTL_FAST_MATH = YES; 283 | SDKROOT = macosx; 284 | }; 285 | name = Release; 286 | }; 287 | 2CA775F9217D9F8E00CDC6A3 /* Debug */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 291 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 292 | CODE_SIGN_ENTITLEMENTS = "S03-Shapes/S03_Shapes.entitlements"; 293 | CODE_SIGN_STYLE = Automatic; 294 | COMBINE_HIDPI_IMAGES = YES; 295 | INFOPLIST_FILE = "S03-Shapes/Info.plist"; 296 | LD_RUNPATH_SEARCH_PATHS = ( 297 | "$(inherited)", 298 | "@executable_path/../Frameworks", 299 | ); 300 | PRODUCT_BUNDLE_IDENTIFIER = "Siv3D.S03-Shapes"; 301 | PRODUCT_NAME = "$(TARGET_NAME)"; 302 | }; 303 | name = Debug; 304 | }; 305 | 2CA775FA217D9F8E00CDC6A3 /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 309 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 310 | CODE_SIGN_ENTITLEMENTS = "S03-Shapes/S03_Shapes.entitlements"; 311 | CODE_SIGN_STYLE = Automatic; 312 | COMBINE_HIDPI_IMAGES = YES; 313 | INFOPLIST_FILE = "S03-Shapes/Info.plist"; 314 | LD_RUNPATH_SEARCH_PATHS = ( 315 | "$(inherited)", 316 | "@executable_path/../Frameworks", 317 | ); 318 | PRODUCT_BUNDLE_IDENTIFIER = "Siv3D.S03-Shapes"; 319 | PRODUCT_NAME = "$(TARGET_NAME)"; 320 | }; 321 | name = Release; 322 | }; 323 | /* End XCBuildConfiguration section */ 324 | 325 | /* Begin XCConfigurationList section */ 326 | 2CA775E2217D9F8D00CDC6A3 /* Build configuration list for PBXProject "S03-Shapes" */ = { 327 | isa = XCConfigurationList; 328 | buildConfigurations = ( 329 | 2CA775F6217D9F8E00CDC6A3 /* Debug */, 330 | 2CA775F7217D9F8E00CDC6A3 /* Release */, 331 | ); 332 | defaultConfigurationIsVisible = 0; 333 | defaultConfigurationName = Release; 334 | }; 335 | 2CA775F8217D9F8E00CDC6A3 /* Build configuration list for PBXNativeTarget "S03-Shapes" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | 2CA775F9217D9F8E00CDC6A3 /* Debug */, 339 | 2CA775FA217D9F8E00CDC6A3 /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | /* End XCConfigurationList section */ 345 | }; 346 | rootObject = 2CA775DF217D9F8D00CDC6A3 /* Project object */; 347 | } 348 | -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | Default 540 | 541 | 542 | 543 | 544 | 545 | 546 | Left to Right 547 | 548 | 549 | 550 | 551 | 552 | 553 | Right to Left 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | Default 565 | 566 | 567 | 568 | 569 | 570 | 571 | Left to Right 572 | 573 | 574 | 575 | 576 | 577 | 578 | Right to Left 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2018年 Siv3D. All rights reserved. 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/S03_Shapes.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/ShaderTypes.hpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # pragma once 12 | # include 13 | 14 | // 15 | // このヘッダは .metal と Objective-C++ どちらからもインクルードできる 16 | // 17 | 18 | // 頂点シェーダにセットするデータのバッファ番号 19 | struct VertexInputIndex 20 | { 21 | enum 22 | { 23 | Vertices, // 0 24 | ViewportSize, // 1 25 | }; 26 | }; 27 | 28 | // 頂点データ 29 | struct Vertex 30 | { 31 | simd::float2 position; // 2D 座標 32 | simd::float4 color; // RGBA カラー 33 | }; 34 | -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/Shaders.metal: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # include 12 | # include "ShaderTypes.hpp" 13 | using namespace metal; 14 | 15 | // 頂点シェーダから rasterization ステージに送るデータ 16 | struct RasterizerData 17 | { 18 | float4 clipSpacePosition [[position]]; // クリップスペース座標([[position]] attribute を使用) 19 | float4 color; // 色(補間される) 20 | }; 21 | 22 | // 頂点シェーダ用の関数 23 | vertex RasterizerData 24 | vertexShader(uint vertexID [[vertex_id]], // 頂点番号 25 | // セットされた頂点データ [[buffer(0)]] 26 | device Vertex *vertices [[buffer(VertexInputIndex::Vertices)]], 27 | // セットされた描画領域の解像度 [[buffer(1)]] 28 | constant float2& viewportSize [[buffer(VertexInputIndex::ViewportSize)]]) 29 | { 30 | // 各頂点について、スクリーン座標をクリップスペース座標に変換 31 | float2 pixelSpacePosition = vertices[vertexID].position.xy; 32 | float2 pos = (pixelSpacePosition / (viewportSize * 0.5f)) - 1.0f; 33 | 34 | RasterizerData out; 35 | out.clipSpacePosition = float4(pos.x, -pos.y, 0.0f, 1.0f); 36 | out.color = vertices[vertexID].color; 37 | return out; 38 | } 39 | 40 | // フラグメントシェーダ用の関数 41 | // [[stage_in]] attribute は、このデータが rasterization ステージから送られてくることを表す 42 | fragment float4 43 | fragmentShader(RasterizerData in [[stage_in]]) 44 | { 45 | return in.color; 46 | } 47 | -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/main.mm: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # import 12 | # import 13 | # import 14 | # import 15 | # import 16 | # import 17 | # import "ShaderTypes.hpp" 18 | 19 | @interface AppDelegate : NSObject 20 | // MainMenu.xib - Window 21 | @property (weak) IBOutlet NSWindow *window; 22 | 23 | + (AppDelegate *)sharedAppDelegate; 24 | @end 25 | 26 | // Metal で描画できる view, MTKView のサブクラス 27 | @interface AppMTKView : MTKView 28 | @end 29 | 30 | void Main(); 31 | 32 | static AppDelegate *instance = nil; 33 | 34 | class VertexBufferManager 35 | { 36 | private: 37 | 38 | // Triple buffering 39 | static constexpr size_t MaxInflightBuffers = 3; 40 | 41 | // MTLBuffer に格納する最大の頂点個数 42 | static constexpr size_t MaxVertices = 16384; 43 | 44 | // 描画する頂点データ 45 | std::vector m_vertices; 46 | 47 | dispatch_semaphore_t m_frameBoundarySemaphore = dispatch_semaphore_create(MaxInflightBuffers); 48 | 49 | size_t m_currentVertexBufferIndex = 0; 50 | 51 | // バッファ 52 | std::array, 3> m_vertexBuffers; 53 | 54 | public: 55 | 56 | void init(id device) 57 | { 58 | for(size_t i = 0; i < MaxInflightBuffers; ++i) 59 | { 60 | m_vertexBuffers[i] = [device newBufferWithLength:(sizeof(Vertex) * MaxVertices) 61 | options:MTLResourceStorageModeShared]; 62 | } 63 | } 64 | 65 | size_t update() 66 | { 67 | // Wait until the inflight command buffer has completed its work 68 | dispatch_semaphore_wait(m_frameBoundarySemaphore, DISPATCH_TIME_FOREVER); 69 | 70 | ++m_currentVertexBufferIndex %= MaxInflightBuffers; 71 | 72 | const size_t num_vertices = m_vertices.size(); 73 | 74 | memcpy(m_vertexBuffers[m_currentVertexBufferIndex].contents, 75 | m_vertices.data(), (sizeof(Vertex) * num_vertices)); 76 | 77 | m_vertices.clear(); 78 | 79 | return num_vertices; 80 | } 81 | 82 | auto getCurrentBuffer() const 83 | { 84 | return m_vertexBuffers[m_currentVertexBufferIndex]; 85 | } 86 | 87 | dispatch_semaphore_t getSemaphore() const 88 | { 89 | return m_frameBoundarySemaphore; 90 | } 91 | 92 | Vertex* prepare(size_t size) 93 | { 94 | if ((m_vertices.size() + size) > MaxVertices) 95 | { 96 | return nullptr; 97 | } 98 | 99 | m_vertices.resize(m_vertices.size() + size); 100 | 101 | return m_vertices.data() + (m_vertices.size() - size); 102 | } 103 | }; 104 | 105 | struct InternalSivMetalData 106 | { 107 | // アプリケーションを続行するか 108 | bool shouldKeepRunning = true; 109 | 110 | // mainLoop が完了したか 111 | bool readyToTerminate = false; 112 | 113 | // 現在のフレームカウント 114 | int frameCount = 0; 115 | 116 | // GPU のインタフェース 117 | id device; 118 | 119 | // ウィンドウ 120 | NSWindow* window; 121 | 122 | // view 123 | AppMTKView* mtkView; 124 | 125 | // RenderPipelineState: レンダリングパイプラインを表現するオブジェクト 126 | id pipelineState; 127 | 128 | // CommandBuffer を発行するオブジェクト 129 | id commandQueue; 130 | 131 | // 画面をクリアする色 132 | MTLClearColor clearColor; 133 | 134 | VertexBufferManager vertexBufferManager; 135 | 136 | } siv; 137 | 138 | @implementation AppDelegate 139 | 140 | + (AppDelegate *)sharedAppDelegate 141 | { 142 | return instance; 143 | } 144 | 145 | // アプリケーションの初期化 146 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 147 | { 148 | NSLog(@"#SivMetal# (1) applicationDidFinishLaunching"); 149 | 150 | instance = self; 151 | 152 | // デフォルトの GPU デバイスを取得する 153 | siv.device = MTLCreateSystemDefaultDevice(); 154 | 155 | // Metal 対応の view を作成する 156 | siv.mtkView = [[AppMTKView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) 157 | device:siv.device]; 158 | 159 | // ウィンドウ 160 | siv.window = _window; 161 | 162 | // ウィンドウに view を設定する 163 | [siv.window setContentView:siv.mtkView]; 164 | // ウィンドウを最前面に表示させる 165 | [NSApp activateIgnoringOtherApps:YES]; 166 | [siv.window makeKeyAndOrderFront:self]; 167 | 168 | // view の drawable のピクセルフォーマットを設定する 169 | [siv.mtkView setColorPixelFormat:MTLPixelFormatBGRA8Unorm_sRGB]; 170 | // depthStencilTexture のフォーマットを設定する 171 | [siv.mtkView setDepthStencilPixelFormat:MTLPixelFormatDepth32Float_Stencil8]; 172 | // MSAA を設定する 173 | // 1, 4 はすべての macOS でサポートされている 174 | // 参考: https://developer.apple.com/documentation/metal/mtldevice/1433355-supportstexturesamplecount 175 | [siv.mtkView setSampleCount:4]; 176 | // drawable クリア時の色を設定する (RGBA) 177 | siv.clearColor = MTLClearColorMake(11/255.0, 22/255.0, 33/255.0, 1.0); 178 | [siv.mtkView setClearColor:siv.clearColor]; 179 | // mainLoop から draw するための設定 180 | [siv.mtkView setPaused:YES]; 181 | 182 | // プロジェクト内の .metal 拡張子のシェーダファイルをすべてロードする 183 | id defaultLibrary = [siv.device newDefaultLibrary]; 184 | // シェーダ関数 `vertexShader` をロードする 185 | id vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"]; 186 | // シェーダ関数 `fragmentShader` をロードする 187 | id fragmentFunction = [defaultLibrary newFunctionWithName:@"fragmentShader"]; 188 | 189 | // RenderPipelineState を作成するための設定 (RenderPipelineDescriptor) を記述する 190 | MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; 191 | pipelineStateDescriptor.label = @"Simple Pipeline"; // ラベルをつけておくとデバッグ時に便利(任意) 192 | pipelineStateDescriptor.vertexFunction = vertexFunction; // 頂点シェーダの関数 193 | pipelineStateDescriptor.fragmentFunction = fragmentFunction; // フラグメントシェーダの関数 194 | pipelineStateDescriptor.colorAttachments[0].pixelFormat = siv.mtkView.colorPixelFormat; // 出力先のフォーマット 195 | pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES; // アルファブレンディングのための設定 196 | pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; 197 | pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; 198 | pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; 199 | pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorZero; 200 | pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne; 201 | pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; 202 | pipelineStateDescriptor.rasterSampleCount = siv.mtkView.sampleCount; // MSAA 203 | pipelineStateDescriptor.depthAttachmentPixelFormat = siv.mtkView.depthStencilPixelFormat; // 深度フォーマット 204 | pipelineStateDescriptor.stencilAttachmentPixelFormat = siv.mtkView.depthStencilPixelFormat; // ステンシルフォーマット 205 | 206 | // RenderPipelineState を作成する 207 | NSError *error = NULL; 208 | siv.pipelineState = [siv.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor 209 | error:&error]; 210 | if (!siv.pipelineState) 211 | { 212 | // RenderPipelineDescriptor の記述が間違っているとエラー 213 | NSLog(@"#SivMetal# Failed to created pipeline state, error %@", error); 214 | return; 215 | } 216 | 217 | // CommandQueue を作成。1 つのアプリケーションに 1 つ作るだけで良い 218 | siv.commandQueue = [siv.device newCommandQueue]; 219 | 220 | siv.vertexBufferManager.init(siv.device); 221 | 222 | // mainLoop を実行する 223 | [self performSelectorOnMainThread:@selector(mainLoop) withObject:nil waitUntilDone:NO]; 224 | } 225 | 226 | // terminate が呼ばれた 227 | -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 228 | { 229 | NSLog(@"#SivMetal# applicationShouldTerminate"); 230 | 231 | // handleMessages が false を返すようにする 232 | siv.shouldKeepRunning = false; 233 | 234 | if (siv.readyToTerminate) 235 | { 236 | NSLog(@"#SivMetal# (readyToTerminate == true)"); 237 | // mainLoop が終了していたらアプリケーションを終了 238 | return NSTerminateNow; 239 | } 240 | else 241 | { 242 | NSLog(@"#SivMetal# (readyToTerminate == false)"); 243 | // mainLoop が終了するまではアプリケーションを終了しない 244 | return NSTerminateCancel; 245 | } 246 | } 247 | 248 | // アプリケーションが終了 249 | - (void)applicationWillTerminate:(NSNotification *)aNotification 250 | { 251 | NSLog(@"#SivMetal# (4) applicationWillTerminate"); 252 | } 253 | 254 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication 255 | { 256 | // ウィンドウが閉じられたときに自動的に terminate が呼ばれるようにする 257 | return YES; 258 | } 259 | 260 | // イベントを処理 261 | - (bool)handleMessages 262 | { 263 | ++siv.frameCount; 264 | 265 | @autoreleasepool 266 | { 267 | for (;;) 268 | { 269 | NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny 270 | untilDate:[NSDate distantPast] 271 | inMode:NSDefaultRunLoopMode 272 | dequeue:YES]; 273 | if (event == nil) 274 | { 275 | break; 276 | } 277 | 278 | [NSApp sendEvent:event]; 279 | } 280 | } 281 | 282 | return siv.shouldKeepRunning; 283 | } 284 | 285 | // 描画処理 286 | - (void)draw 287 | { 288 | const size_t num_vertices = siv.vertexBufferManager.update(); 289 | 290 | @autoreleasepool 291 | { 292 | // 現在の drawable に使う、新しいレンダーパスのための CommandBuffer を作成 293 | id commandBuffer = [siv.commandQueue commandBuffer]; 294 | commandBuffer.label = @"MyCommand"; // ラベルをつけておくとデバッグ時に便利(任意) 295 | 296 | // 現在の drawable texture の RenderPassDescriptor を取得する 297 | MTLRenderPassDescriptor *renderPassDescriptor = siv.mtkView.currentRenderPassDescriptor; 298 | 299 | if(renderPassDescriptor != nil) 300 | { 301 | // RenderPassDescriptor から RenderCommandEncoder を作成 302 | // RenderCommandEncoder によって、レンダリングコマンドが CommandBuffer に登録される 303 | id renderCommandEncoder = 304 | [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; 305 | renderCommandEncoder.label = @"MyRenderCommandEncoder"; // ラベルをつけておくとデバッグ時に便利(任意) 306 | 307 | // 現在のウィンドウの解像度を取得 308 | simd::float2 viewportSize; 309 | viewportSize.x = [siv.mtkView drawableSize].width; 310 | viewportSize.y = [siv.mtkView drawableSize].height; 311 | 312 | // RenderCommandEncoder にビューポートを設定する 313 | [renderCommandEncoder setViewport:(MTLViewport){0, 0, viewportSize.x, viewportSize.y, -1.0, 1.0 }]; 314 | 315 | // RenderPipelineState を設定する 316 | [renderCommandEncoder setRenderPipelineState:siv.pipelineState]; 317 | 318 | // ウィンドウの表示スケーリングを考慮 319 | const float scale = [siv.window backingScaleFactor];; 320 | viewportSize.x /= scale; 321 | viewportSize.y /= scale; 322 | 323 | if (num_vertices) 324 | { 325 | // 頂点シェーダ用のデータ [[buffer(0)]] をセット 326 | [renderCommandEncoder setVertexBuffer:siv.vertexBufferManager.getCurrentBuffer() 327 | offset:0 328 | atIndex:VertexInputIndex::Vertices]; 329 | 330 | // 頂点シェーダ用のデータ [[buffer(1)]] をセット 331 | [renderCommandEncoder setVertexBytes:&viewportSize 332 | length:sizeof(viewportSize) 333 | atIndex:VertexInputIndex::ViewportSize]; 334 | 335 | // セットされた頂点データを使って頂点を描画 336 | [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle 337 | vertexStart:0 338 | vertexCount:num_vertices]; 339 | } 340 | 341 | // RenderCommandEncoder によるコマンド登録の終了 342 | [renderCommandEncoder endEncoding]; 343 | } 344 | 345 | // 現在の drawable を表示させるコマンドを CommandBuffer に登録 346 | [commandBuffer presentDrawable:siv.mtkView.currentDrawable]; 347 | 348 | __weak dispatch_semaphore_t semaphore = siv.vertexBufferManager.getSemaphore(); 349 | [commandBuffer addCompletedHandler:^(id commandBuffer) 350 | { 351 | // GPU work is complete 352 | // Signal the semaphore to start the CPU work 353 | dispatch_semaphore_signal(semaphore); 354 | }]; 355 | 356 | // GPU に CommandBuffer を実行してもらう 357 | [commandBuffer commit]; 358 | } 359 | } 360 | 361 | // メインループ 362 | - (void)mainLoop 363 | { 364 | NSLog(@"#SivMetal# (2) mainLoop"); 365 | 366 | // drawable を初期化 367 | [siv.mtkView draw]; 368 | 369 | Main(); 370 | 371 | NSLog(@"#SivMetal# (3) ~mainLoop"); 372 | 373 | siv.readyToTerminate = true; 374 | 375 | // applicationShouldTerminate を呼び出してアプリケーションの終了を通知 376 | [NSApp terminate:nil]; 377 | } 378 | 379 | @end 380 | 381 | @implementation AppMTKView 382 | 383 | - (BOOL)isOpaque 384 | { 385 | return YES; 386 | } 387 | 388 | - (BOOL)canBecomeKey 389 | { 390 | return YES; 391 | } 392 | 393 | - (BOOL)acceptsFirstResponder 394 | { 395 | return YES; 396 | } 397 | 398 | // 左クリックされた 399 | - (void)mouseDown:(NSEvent *)event 400 | { 401 | NSLog(@"#SivMetal# MouseL.Down"); 402 | } 403 | 404 | // 右クリックされた 405 | - (void)rightMouseDown:(NSEvent *)event 406 | { 407 | NSLog(@"#SivMetal# MouseR.Down"); 408 | } 409 | 410 | @end 411 | 412 | int main(int argc, const char *argv[]) 413 | { 414 | return NSApplicationMain(argc, argv); 415 | } 416 | 417 | 418 | namespace SivMetal 419 | { 420 | using int8 = std::int8_t; 421 | using int16 = std::int16_t; 422 | using int32 = std::int32_t; 423 | using int64 = std::int64_t; 424 | using uint8 = std::uint8_t; 425 | using uint16 = std::uint16_t; 426 | using uint32 = std::uint32_t; 427 | using uint64 = std::uint64_t; 428 | 429 | namespace Math 430 | { 431 | inline constexpr double Pi = 3.1415926535897932385; 432 | 433 | inline constexpr float PiF = 3.1415926535897932385f; 434 | 435 | inline constexpr double TwoPi = Pi * 2.0; 436 | 437 | inline constexpr float TwoPiF = PiF * 2.0f; 438 | } 439 | 440 | struct Point 441 | { 442 | using value_type = int32; 443 | 444 | value_type x, y; 445 | 446 | Point() noexcept = default; 447 | 448 | constexpr Point(const Point&) noexcept = default; 449 | 450 | constexpr Point(int32 _x, int32 _y) noexcept 451 | : x(_x) 452 | , y(_y) {} 453 | 454 | template && std::is_integral_v>* = nullptr> 455 | constexpr Point(X _x, Y _y) noexcept 456 | : x(static_cast(_x)) 457 | , y(static_cast(_y)) {} 458 | 459 | template || !std::is_integral_v>* = nullptr> 460 | constexpr Point(X _x, Y _y) noexcept = delete; 461 | }; 462 | 463 | template 464 | struct Vector2D 465 | { 466 | template 467 | using vector_type = Vector2D; 468 | 469 | using value_type = Type; 470 | 471 | value_type x, y; 472 | 473 | Vector2D() noexcept = default; 474 | 475 | constexpr Vector2D(const Vector2D&) noexcept = default; 476 | 477 | template 478 | constexpr Vector2D(X _x, Y _y) noexcept 479 | : x(static_cast(_x)) 480 | , y(static_cast(_y)) {} 481 | 482 | constexpr Vector2D(value_type _x, value_type _y) noexcept 483 | : x(_x) 484 | , y(_y) {} 485 | 486 | constexpr Vector2D(const Point& v) noexcept 487 | : x(static_cast(v.x)) 488 | , y(static_cast(v.y)) {} 489 | 490 | template 491 | constexpr Vector2D(const Vector2D& v) noexcept 492 | : x(static_cast(v.x)) 493 | , y(static_cast(v.y)) {} 494 | }; 495 | 496 | using Float2 = Vector2D; 497 | using Vec2 = Vector2D; 498 | 499 | struct ColorF 500 | { 501 | double r, g, b, a; 502 | 503 | ColorF() = default; 504 | 505 | constexpr ColorF(const ColorF& color) noexcept = default; 506 | 507 | explicit constexpr ColorF(double rgb, double _a = 1.0) noexcept 508 | : r(rgb) 509 | , g(rgb) 510 | , b(rgb) 511 | , a(_a) {} 512 | 513 | constexpr ColorF(double _r, double _g, double _b, double _a = 1.0) noexcept 514 | : r(_r) 515 | , g(_g) 516 | , b(_b) 517 | , a(_a) {} 518 | }; 519 | 520 | void SetWindowTitle(const char* title); 521 | 522 | bool IsVisible(); 523 | 524 | bool Update(); 525 | 526 | int32 FrameCount(); 527 | 528 | void SetBackground(double r, double g, double b, double a); 529 | 530 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 531 | const ColorF& color); 532 | 533 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 534 | const ColorF& c0, const ColorF& c1, const ColorF& c2); 535 | 536 | void DrawRect(const Vec2& pos, const Vec2& size, const ColorF& color); 537 | } 538 | 539 | namespace SivMetal 540 | { 541 | void SetWindowTitle(const char* title) 542 | { 543 | [siv.window setTitle:[NSString stringWithUTF8String:title]]; 544 | } 545 | 546 | bool IsVisible() 547 | { 548 | return [siv.window isVisible] 549 | && ([siv.window occlusionState] & NSWindowOcclusionStateVisible); 550 | } 551 | 552 | bool Update() 553 | { 554 | if (!IsVisible()) 555 | { 556 | // アプリケーションが不可視の場合 vSync しないので 16ms スリープ 557 | usleep(16 * 1000); 558 | } 559 | 560 | [[AppDelegate sharedAppDelegate] draw]; 561 | 562 | // 描画内容を反映 (vSync) 563 | [siv.mtkView draw]; 564 | 565 | return [[AppDelegate sharedAppDelegate] handleMessages]; 566 | } 567 | 568 | int32 FrameCount() 569 | { 570 | return siv.frameCount; 571 | } 572 | 573 | void SetBackground(const ColorF& color) 574 | { 575 | siv.clearColor = MTLClearColorMake(color.r, color.g, color.b, color.a); 576 | [siv.mtkView setClearColor:siv.clearColor]; 577 | } 578 | 579 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 580 | const ColorF& color) 581 | { 582 | DrawTriangle(p0, p1, p2, color, color, color); 583 | } 584 | 585 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 586 | const ColorF& c0, const ColorF& c1, const ColorF& c2) 587 | { 588 | Vertex* vtx = siv.vertexBufferManager.prepare(3); 589 | 590 | if (!vtx) 591 | { 592 | return; 593 | } 594 | 595 | vtx[0].position = simd::make_float2(p0.x, p0.y); 596 | vtx[0].color = simd::make_float4(c0.r, c0.g, c0.b, c0.a); 597 | vtx[1].position = simd::make_float2(p1.x, p1.y); 598 | vtx[1].color = simd::make_float4(c1.r, c1.g, c1.b, c1.a); 599 | vtx[2].position = simd::make_float2(p2.x, p2.y); 600 | vtx[2].color = simd::make_float4(c2.r, c2.g, c2.b, c2.a); 601 | } 602 | 603 | void DrawRect(const Vec2& pos, const Vec2& size, const ColorF& color) 604 | { 605 | Vertex* vtx = siv.vertexBufferManager.prepare(6); 606 | 607 | if (!vtx) 608 | { 609 | return; 610 | } 611 | 612 | const simd::float2 p0 = simd::make_float2(pos.x, pos.y); 613 | const simd::float2 p1 = simd::make_float2(pos.x + size.x, pos.y); 614 | const simd::float2 p2 = simd::make_float2(pos.x, pos.y + size.y); 615 | const simd::float2 p3 = simd::make_float2(pos.x + size.x, pos.y + size.y); 616 | const simd::float4 col = simd::make_float4(color.r, color.g, color.b, color.a); 617 | 618 | vtx[0].position = p0; 619 | vtx[1].position = p1; 620 | vtx[2].position = p2; 621 | vtx[3].position = p2; 622 | vtx[4].position = p1; 623 | vtx[5].position = p3; 624 | 625 | for (size_t i = 0; i < 6; ++i) 626 | { 627 | vtx[i].color = col; 628 | } 629 | } 630 | 631 | void DrawCircle(const Vec2& center, double r, const ColorF& color) 632 | { 633 | const uint32 quality = (r <= 5.0) ? (static_cast(r + 4) * 2) 634 | : static_cast(std::min(19 + (r - 5.0) / 2.2, 255.0)); 635 | const size_t vertexSize = quality * 3; 636 | 637 | Vertex* vtx = siv.vertexBufferManager.prepare(vertexSize); 638 | 639 | if (!vtx) 640 | { 641 | return; 642 | } 643 | 644 | const float rd = Math::TwoPiF / (quality - 1); 645 | const simd::float2 c = simd::make_float2(center.x, center.y); 646 | const simd::float4 col = simd::make_float4(color.r, color.g, color.b, color.a); 647 | simd::float2 p0 = simd::make_float2(center.x, center.y - r); 648 | 649 | for (size_t i = 0; i < quality; ++i) 650 | { 651 | const float rad = rd * (i - 1.0f); 652 | const simd::float2 p1 = simd::make_float2(center.x + r * std::cos(rad), 653 | center.y - r * std::sin(rad)); 654 | vtx[i * 3 + 0].position = p0; 655 | vtx[i * 3 + 1].position = p1; 656 | vtx[i * 3 + 2].position = c; 657 | p0 = p1; 658 | } 659 | 660 | for (size_t i = 0; i < vertexSize; ++i) 661 | { 662 | vtx[i].color = col; 663 | } 664 | } 665 | } 666 | 667 | using SivMetal::int32; 668 | using SivMetal::Vec2; 669 | using SivMetal::ColorF; 670 | 671 | void Main() 672 | { 673 | // ウィンドウタイトルを変更する 674 | SivMetal::SetWindowTitle("SivMetal | Experimental Metal project for OpenSiv3D"); 675 | 676 | // 背景色を変更する 677 | SivMetal::SetBackground(ColorF(0.8, 0.9, 1.0)); 678 | 679 | while (SivMetal::Update()) 680 | { 681 | for (int32 y = 0; y < 30; ++y) 682 | { 683 | for (int32 x = 0; x < 40; ++x) 684 | { 685 | // 長方形を描画 686 | SivMetal::DrawRect(Vec2(x * 20, y * 20), Vec2(15, 15), ColorF(0.5, 0.7, 0.9)); 687 | } 688 | } 689 | 690 | // アニメーション 691 | const double t = 300.0 - (SivMetal::FrameCount() * 0.2); 692 | 693 | // 三角形を描画 694 | SivMetal::DrawTriangle(Vec2(400 + t, 100), Vec2(700, 500), Vec2(100, 500), ColorF(1, 0, 0, 1), ColorF(0, 1, 0, 1), ColorF(0, 0, 1, 1)); 695 | 696 | // 半透明の三角形を描画 697 | SivMetal::DrawTriangle(Vec2(400 - t, 100), Vec2(700, 500), Vec2(100, 500), ColorF(1, 1, 1, 0.8)); 698 | 699 | // 円を描画 700 | SivMetal::DrawCircle(Vec2(400, 120), 80, ColorF(1.0, 0.5, 0, 1)); 701 | } 702 | } 703 | -------------------------------------------------------------------------------- /S03-Shapes/S03-Shapes/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reputeless/SivMetal/03a9584ee315b7e7f4a5792fdab61086a8498a22/S03-Shapes/S03-Shapes/screenshot.png -------------------------------------------------------------------------------- /S04-Texture/S04-Texture.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2CA77617217DEEFA00CDC6A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2CA77616217DEEFA00CDC6A3 /* Assets.xcassets */; }; 11 | 2CA7761A217DEEFA00CDC6A3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CA77618217DEEFA00CDC6A3 /* MainMenu.xib */; }; 12 | 2CA77627217DEF4900CDC6A3 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2CA77624217DEF4800CDC6A3 /* main.mm */; }; 13 | 2CA77628217DEF4900CDC6A3 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 2CA77625217DEF4800CDC6A3 /* Shaders.metal */; }; 14 | 2CA7762C217DEF7C00CDC6A3 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA7762A217DEF7C00CDC6A3 /* MetalKit.framework */; }; 15 | 2CA7762D217DEF7C00CDC6A3 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA7762B217DEF7C00CDC6A3 /* Metal.framework */; }; 16 | 2CA7762F217DEF8100CDC6A3 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA7762E217DEF8100CDC6A3 /* AppKit.framework */; }; 17 | 2CA77631217E04DC00CDC6A3 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 2CA77630217E04DC00CDC6A3 /* assets */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 2CA77610217DEEF900CDC6A3 /* S04-Texture.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "S04-Texture.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 2CA77616217DEEFA00CDC6A3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 23 | 2CA77619217DEEFA00CDC6A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 24 | 2CA7761B217DEEFA00CDC6A3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 25 | 2CA7761E217DEEFA00CDC6A3 /* S04_Texture.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = S04_Texture.entitlements; sourceTree = ""; }; 26 | 2CA77624217DEF4800CDC6A3 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; 27 | 2CA77625217DEF4800CDC6A3 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; 28 | 2CA77626217DEF4900CDC6A3 /* ShaderTypes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ShaderTypes.hpp; sourceTree = ""; }; 29 | 2CA7762A217DEF7C00CDC6A3 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 30 | 2CA7762B217DEF7C00CDC6A3 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 31 | 2CA7762E217DEF8100CDC6A3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 32 | 2CA77630217E04DC00CDC6A3 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = ""; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | 2CA7760D217DEEF900CDC6A3 /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | 2CA7762F217DEF8100CDC6A3 /* AppKit.framework in Frameworks */, 41 | 2CA7762C217DEF7C00CDC6A3 /* MetalKit.framework in Frameworks */, 42 | 2CA7762D217DEF7C00CDC6A3 /* Metal.framework in Frameworks */, 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | 2CA77607217DEEF900CDC6A3 = { 50 | isa = PBXGroup; 51 | children = ( 52 | 2CA77612217DEEF900CDC6A3 /* S04-Texture */, 53 | 2CA77611217DEEF900CDC6A3 /* Products */, 54 | 2CA77629217DEF7C00CDC6A3 /* Frameworks */, 55 | ); 56 | sourceTree = ""; 57 | }; 58 | 2CA77611217DEEF900CDC6A3 /* Products */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 2CA77610217DEEF900CDC6A3 /* S04-Texture.app */, 62 | ); 63 | name = Products; 64 | sourceTree = ""; 65 | }; 66 | 2CA77612217DEEF900CDC6A3 /* S04-Texture */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 2CA77630217E04DC00CDC6A3 /* assets */, 70 | 2CA77624217DEF4800CDC6A3 /* main.mm */, 71 | 2CA77625217DEF4800CDC6A3 /* Shaders.metal */, 72 | 2CA77626217DEF4900CDC6A3 /* ShaderTypes.hpp */, 73 | 2CA77616217DEEFA00CDC6A3 /* Assets.xcassets */, 74 | 2CA77618217DEEFA00CDC6A3 /* MainMenu.xib */, 75 | 2CA7761B217DEEFA00CDC6A3 /* Info.plist */, 76 | 2CA7761E217DEEFA00CDC6A3 /* S04_Texture.entitlements */, 77 | ); 78 | path = "S04-Texture"; 79 | sourceTree = ""; 80 | }; 81 | 2CA77629217DEF7C00CDC6A3 /* Frameworks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 2CA7762E217DEF8100CDC6A3 /* AppKit.framework */, 85 | 2CA7762B217DEF7C00CDC6A3 /* Metal.framework */, 86 | 2CA7762A217DEF7C00CDC6A3 /* MetalKit.framework */, 87 | ); 88 | name = Frameworks; 89 | sourceTree = ""; 90 | }; 91 | /* End PBXGroup section */ 92 | 93 | /* Begin PBXNativeTarget section */ 94 | 2CA7760F217DEEF900CDC6A3 /* S04-Texture */ = { 95 | isa = PBXNativeTarget; 96 | buildConfigurationList = 2CA77621217DEEFA00CDC6A3 /* Build configuration list for PBXNativeTarget "S04-Texture" */; 97 | buildPhases = ( 98 | 2CA7760C217DEEF900CDC6A3 /* Sources */, 99 | 2CA7760D217DEEF900CDC6A3 /* Frameworks */, 100 | 2CA7760E217DEEF900CDC6A3 /* Resources */, 101 | ); 102 | buildRules = ( 103 | ); 104 | dependencies = ( 105 | ); 106 | name = "S04-Texture"; 107 | productName = "S04-Texture"; 108 | productReference = 2CA77610217DEEF900CDC6A3 /* S04-Texture.app */; 109 | productType = "com.apple.product-type.application"; 110 | }; 111 | /* End PBXNativeTarget section */ 112 | 113 | /* Begin PBXProject section */ 114 | 2CA77608217DEEF900CDC6A3 /* Project object */ = { 115 | isa = PBXProject; 116 | attributes = { 117 | LastUpgradeCheck = 1000; 118 | ORGANIZATIONNAME = Siv3D; 119 | TargetAttributes = { 120 | 2CA7760F217DEEF900CDC6A3 = { 121 | CreatedOnToolsVersion = 10.0; 122 | }; 123 | }; 124 | }; 125 | buildConfigurationList = 2CA7760B217DEEF900CDC6A3 /* Build configuration list for PBXProject "S04-Texture" */; 126 | compatibilityVersion = "Xcode 9.3"; 127 | developmentRegion = en; 128 | hasScannedForEncodings = 0; 129 | knownRegions = ( 130 | en, 131 | Base, 132 | ); 133 | mainGroup = 2CA77607217DEEF900CDC6A3; 134 | productRefGroup = 2CA77611217DEEF900CDC6A3 /* Products */; 135 | projectDirPath = ""; 136 | projectRoot = ""; 137 | targets = ( 138 | 2CA7760F217DEEF900CDC6A3 /* S04-Texture */, 139 | ); 140 | }; 141 | /* End PBXProject section */ 142 | 143 | /* Begin PBXResourcesBuildPhase section */ 144 | 2CA7760E217DEEF900CDC6A3 /* Resources */ = { 145 | isa = PBXResourcesBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | 2CA77631217E04DC00CDC6A3 /* assets in Resources */, 149 | 2CA77617217DEEFA00CDC6A3 /* Assets.xcassets in Resources */, 150 | 2CA7761A217DEEFA00CDC6A3 /* MainMenu.xib in Resources */, 151 | ); 152 | runOnlyForDeploymentPostprocessing = 0; 153 | }; 154 | /* End PBXResourcesBuildPhase section */ 155 | 156 | /* Begin PBXSourcesBuildPhase section */ 157 | 2CA7760C217DEEF900CDC6A3 /* Sources */ = { 158 | isa = PBXSourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | 2CA77628217DEF4900CDC6A3 /* Shaders.metal in Sources */, 162 | 2CA77627217DEF4900CDC6A3 /* main.mm in Sources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXSourcesBuildPhase section */ 167 | 168 | /* Begin PBXVariantGroup section */ 169 | 2CA77618217DEEFA00CDC6A3 /* MainMenu.xib */ = { 170 | isa = PBXVariantGroup; 171 | children = ( 172 | 2CA77619217DEEFA00CDC6A3 /* Base */, 173 | ); 174 | name = MainMenu.xib; 175 | sourceTree = ""; 176 | }; 177 | /* End PBXVariantGroup section */ 178 | 179 | /* Begin XCBuildConfiguration section */ 180 | 2CA7761F217DEEFA00CDC6A3 /* Debug */ = { 181 | isa = XCBuildConfiguration; 182 | buildSettings = { 183 | ALWAYS_SEARCH_USER_PATHS = NO; 184 | CLANG_ANALYZER_NONNULL = YES; 185 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 186 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 187 | CLANG_CXX_LIBRARY = "libc++"; 188 | CLANG_ENABLE_MODULES = YES; 189 | CLANG_ENABLE_OBJC_ARC = YES; 190 | CLANG_ENABLE_OBJC_WEAK = YES; 191 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 192 | CLANG_WARN_BOOL_CONVERSION = YES; 193 | CLANG_WARN_COMMA = YES; 194 | CLANG_WARN_CONSTANT_CONVERSION = YES; 195 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 196 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 197 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 198 | CLANG_WARN_EMPTY_BODY = YES; 199 | CLANG_WARN_ENUM_CONVERSION = YES; 200 | CLANG_WARN_INFINITE_RECURSION = YES; 201 | CLANG_WARN_INT_CONVERSION = YES; 202 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 203 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 204 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 206 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 207 | CLANG_WARN_STRICT_PROTOTYPES = YES; 208 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 209 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 210 | CLANG_WARN_UNREACHABLE_CODE = YES; 211 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 212 | CODE_SIGN_IDENTITY = "-"; 213 | COPY_PHASE_STRIP = NO; 214 | DEBUG_INFORMATION_FORMAT = dwarf; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | ENABLE_TESTABILITY = YES; 217 | GCC_C_LANGUAGE_STANDARD = gnu11; 218 | GCC_DYNAMIC_NO_PIC = NO; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_OPTIMIZATION_LEVEL = 0; 221 | GCC_PREPROCESSOR_DEFINITIONS = ( 222 | "DEBUG=1", 223 | "$(inherited)", 224 | ); 225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 227 | GCC_WARN_UNDECLARED_SELECTOR = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 229 | GCC_WARN_UNUSED_FUNCTION = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | MACOSX_DEPLOYMENT_TARGET = 10.13; 232 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 233 | MTL_FAST_MATH = YES; 234 | ONLY_ACTIVE_ARCH = YES; 235 | SDKROOT = macosx; 236 | }; 237 | name = Debug; 238 | }; 239 | 2CA77620217DEEFA00CDC6A3 /* Release */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | ALWAYS_SEARCH_USER_PATHS = NO; 243 | CLANG_ANALYZER_NONNULL = YES; 244 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 246 | CLANG_CXX_LIBRARY = "libc++"; 247 | CLANG_ENABLE_MODULES = YES; 248 | CLANG_ENABLE_OBJC_ARC = YES; 249 | CLANG_ENABLE_OBJC_WEAK = YES; 250 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 251 | CLANG_WARN_BOOL_CONVERSION = YES; 252 | CLANG_WARN_COMMA = YES; 253 | CLANG_WARN_CONSTANT_CONVERSION = YES; 254 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 255 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 256 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 257 | CLANG_WARN_EMPTY_BODY = YES; 258 | CLANG_WARN_ENUM_CONVERSION = YES; 259 | CLANG_WARN_INFINITE_RECURSION = YES; 260 | CLANG_WARN_INT_CONVERSION = YES; 261 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 262 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 263 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 264 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 265 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 266 | CLANG_WARN_STRICT_PROTOTYPES = YES; 267 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 268 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | CODE_SIGN_IDENTITY = "-"; 272 | COPY_PHASE_STRIP = NO; 273 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 274 | ENABLE_NS_ASSERTIONS = NO; 275 | ENABLE_STRICT_OBJC_MSGSEND = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu11; 277 | GCC_NO_COMMON_BLOCKS = YES; 278 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 279 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 280 | GCC_WARN_UNDECLARED_SELECTOR = YES; 281 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 282 | GCC_WARN_UNUSED_FUNCTION = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | MACOSX_DEPLOYMENT_TARGET = 10.13; 285 | MTL_ENABLE_DEBUG_INFO = NO; 286 | MTL_FAST_MATH = YES; 287 | SDKROOT = macosx; 288 | }; 289 | name = Release; 290 | }; 291 | 2CA77622217DEEFA00CDC6A3 /* Debug */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 295 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 296 | CODE_SIGN_ENTITLEMENTS = "S04-Texture/S04_Texture.entitlements"; 297 | CODE_SIGN_STYLE = Automatic; 298 | COMBINE_HIDPI_IMAGES = YES; 299 | INFOPLIST_FILE = "S04-Texture/Info.plist"; 300 | LD_RUNPATH_SEARCH_PATHS = ( 301 | "$(inherited)", 302 | "@executable_path/../Frameworks", 303 | ); 304 | PRODUCT_BUNDLE_IDENTIFIER = "Siv3D.S04-Texture"; 305 | PRODUCT_NAME = "$(TARGET_NAME)"; 306 | }; 307 | name = Debug; 308 | }; 309 | 2CA77623217DEEFA00CDC6A3 /* Release */ = { 310 | isa = XCBuildConfiguration; 311 | buildSettings = { 312 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 313 | CLANG_CXX_LANGUAGE_STANDARD = "c++17"; 314 | CODE_SIGN_ENTITLEMENTS = "S04-Texture/S04_Texture.entitlements"; 315 | CODE_SIGN_STYLE = Automatic; 316 | COMBINE_HIDPI_IMAGES = YES; 317 | INFOPLIST_FILE = "S04-Texture/Info.plist"; 318 | LD_RUNPATH_SEARCH_PATHS = ( 319 | "$(inherited)", 320 | "@executable_path/../Frameworks", 321 | ); 322 | PRODUCT_BUNDLE_IDENTIFIER = "Siv3D.S04-Texture"; 323 | PRODUCT_NAME = "$(TARGET_NAME)"; 324 | }; 325 | name = Release; 326 | }; 327 | /* End XCBuildConfiguration section */ 328 | 329 | /* Begin XCConfigurationList section */ 330 | 2CA7760B217DEEF900CDC6A3 /* Build configuration list for PBXProject "S04-Texture" */ = { 331 | isa = XCConfigurationList; 332 | buildConfigurations = ( 333 | 2CA7761F217DEEFA00CDC6A3 /* Debug */, 334 | 2CA77620217DEEFA00CDC6A3 /* Release */, 335 | ); 336 | defaultConfigurationIsVisible = 0; 337 | defaultConfigurationName = Release; 338 | }; 339 | 2CA77621217DEEFA00CDC6A3 /* Build configuration list for PBXNativeTarget "S04-Texture" */ = { 340 | isa = XCConfigurationList; 341 | buildConfigurations = ( 342 | 2CA77622217DEEFA00CDC6A3 /* Debug */, 343 | 2CA77623217DEEFA00CDC6A3 /* Release */, 344 | ); 345 | defaultConfigurationIsVisible = 0; 346 | defaultConfigurationName = Release; 347 | }; 348 | /* End XCConfigurationList section */ 349 | }; 350 | rootObject = 2CA77608217DEEF900CDC6A3 /* Project object */; 351 | } 352 | -------------------------------------------------------------------------------- /S04-Texture/S04-Texture/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /S04-Texture/S04-Texture/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /S04-Texture/S04-Texture/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2018年 Siv3D. All rights reserved. 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /S04-Texture/S04-Texture/S04_Texture.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /S04-Texture/S04-Texture/ShaderTypes.hpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # pragma once 12 | # include 13 | 14 | // 15 | // このヘッダは .metal と Objective-C++ どちらからもインクルードできる 16 | // 17 | 18 | // 頂点シェーダにセットするデータのバッファ番号 19 | struct VertexInputIndex 20 | { 21 | enum 22 | { 23 | Vertices, // 0 24 | ViewportSize, // 1 25 | }; 26 | }; 27 | 28 | // 頂点データ 29 | struct Vertex 30 | { 31 | simd::float2 position; // 2D 座標 32 | simd::float2 textureCoordinate; // テクスチャ UV 座標 33 | simd::float4 color; // RGBA カラー 34 | }; 35 | -------------------------------------------------------------------------------- /S04-Texture/S04-Texture/Shaders.metal: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # include 12 | # include "ShaderTypes.hpp" 13 | using namespace metal; 14 | 15 | // 頂点シェーダから rasterization ステージに送るデータ 16 | struct RasterizerData 17 | { 18 | float4 clipSpacePosition [[position]]; // クリップスペース座標([[position]] attribute を使用) 19 | float2 textureCoordinate; // テクスチャ UV 座標(補間される) 20 | float4 color; // 色(補間される) 21 | }; 22 | 23 | // 頂点シェーダ用の関数 24 | vertex RasterizerData 25 | vertexShader(uint vertexID [[vertex_id]], // 頂点番号 26 | // セットされた頂点データ [[buffer(0)]] 27 | device Vertex *vertices [[buffer(VertexInputIndex::Vertices)]], 28 | // セットされた描画領域の解像度 [[buffer(1)]] 29 | constant float2& viewportSize [[buffer(VertexInputIndex::ViewportSize)]]) 30 | { 31 | // 各頂点について、スクリーン座標をクリップスペース座標に変換 32 | float2 pixelSpacePosition = vertices[vertexID].position.xy; 33 | float2 pos = (pixelSpacePosition / (viewportSize * 0.5f)) - 1.0f; 34 | 35 | RasterizerData out; 36 | out.clipSpacePosition = float4(pos.x, -pos.y, 0.0f, 1.0f); 37 | out.textureCoordinate = vertices[vertexID].textureCoordinate; 38 | out.color = vertices[vertexID].color; 39 | return out; 40 | } 41 | 42 | // フラグメントシェーダ用の関数 43 | // [[stage_in]] attribute は、このデータが rasterization ステージから送られてくることを表す 44 | fragment float4 45 | fragmentShader(RasterizerData in [[stage_in]]) 46 | { 47 | return in.color; 48 | } 49 | 50 | // フラグメントシェーダ用の関数 51 | // [[stage_in]] attribute は、このデータが rasterization ステージから送られてくることを表す 52 | fragment float4 53 | fragmentShaderTexture(RasterizerData in [[stage_in]], 54 | texture2d colorTexture [[texture(0)]]) 55 | { 56 | constexpr sampler textureSampler(mag_filter::linear, min_filter::linear); 57 | 58 | // Sample the texture to obtain a color 59 | const half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate); 60 | 61 | return float4(colorSample) * in.color; 62 | } 63 | -------------------------------------------------------------------------------- /S04-Texture/S04-Texture/assets/windmill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reputeless/SivMetal/03a9584ee315b7e7f4a5792fdab61086a8498a22/S04-Texture/S04-Texture/assets/windmill.png -------------------------------------------------------------------------------- /S04-Texture/S04-Texture/main.mm: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // 3 | // This file is part of the SivMetal. 4 | // 5 | // Copyright (c) 2018 Ryo Suzuki 6 | // 7 | // Licensed under the MIT License. 8 | // 9 | //----------------------------------------------- 10 | 11 | # import 12 | # import 13 | # import 14 | # import 15 | # import 16 | # import 17 | # import "ShaderTypes.hpp" 18 | 19 | @interface AppDelegate : NSObject 20 | // MainMenu.xib - Window 21 | @property (weak) IBOutlet NSWindow *window; 22 | 23 | + (AppDelegate *)sharedAppDelegate; 24 | @end 25 | 26 | // Metal で描画できる view, MTKView のサブクラス 27 | @interface AppMTKView : MTKView 28 | @end 29 | 30 | void Main(); 31 | 32 | static AppDelegate *instance = nil; 33 | 34 | struct Batch 35 | { 36 | bool isTextured = false; 37 | 38 | size_t count = 0; 39 | }; 40 | 41 | class VertexBufferManager 42 | { 43 | private: 44 | 45 | // Triple buffering 46 | static constexpr size_t MaxInflightBuffers = 3; 47 | 48 | // MTLBuffer に格納する最大の頂点個数 49 | static constexpr size_t MaxVertices = 16384; 50 | 51 | // 描画する頂点データ 52 | std::vector m_vertices; 53 | 54 | dispatch_semaphore_t m_frameBoundarySemaphore = dispatch_semaphore_create(MaxInflightBuffers); 55 | 56 | size_t m_currentVertexBufferIndex = 0; 57 | 58 | // バッファ 59 | std::array, 3> m_vertexBuffers; 60 | 61 | std::vector m_batches; 62 | 63 | public: 64 | 65 | void init(id device) 66 | { 67 | for(size_t i = 0; i < MaxInflightBuffers; ++i) 68 | { 69 | m_vertexBuffers[i] = [device newBufferWithLength:(sizeof(Vertex) * MaxVertices) 70 | options:MTLResourceStorageModeShared]; 71 | } 72 | } 73 | 74 | std::vector update() 75 | { 76 | // Wait until the inflight command buffer has completed its work 77 | dispatch_semaphore_wait(m_frameBoundarySemaphore, DISPATCH_TIME_FOREVER); 78 | 79 | ++m_currentVertexBufferIndex %= MaxInflightBuffers; 80 | 81 | const size_t num_vertices = m_vertices.size(); 82 | 83 | memcpy(m_vertexBuffers[m_currentVertexBufferIndex].contents, 84 | m_vertices.data(), (sizeof(Vertex) * num_vertices)); 85 | 86 | m_vertices.clear(); 87 | 88 | return std::move(m_batches); 89 | } 90 | 91 | auto getCurrentBuffer() const 92 | { 93 | return m_vertexBuffers[m_currentVertexBufferIndex]; 94 | } 95 | 96 | dispatch_semaphore_t getSemaphore() const 97 | { 98 | return m_frameBoundarySemaphore; 99 | } 100 | 101 | Vertex* prepare(size_t size, bool isTextured) 102 | { 103 | if ((m_vertices.size() + size) > MaxVertices) 104 | { 105 | return nullptr; 106 | } 107 | 108 | if (m_batches.empty() || (m_batches.back().isTextured != isTextured)) 109 | { 110 | m_batches.push_back(Batch{ isTextured, size }); 111 | } 112 | else 113 | { 114 | m_batches.back().count += size; 115 | } 116 | 117 | m_vertices.resize(m_vertices.size() + size); 118 | 119 | return m_vertices.data() + (m_vertices.size() - size); 120 | } 121 | }; 122 | 123 | struct InternalSivMetalData 124 | { 125 | // アプリケーションを続行するか 126 | bool shouldKeepRunning = true; 127 | 128 | // mainLoop が完了したか 129 | bool readyToTerminate = false; 130 | 131 | // 現在のフレームカウント 132 | int frameCount = 0; 133 | 134 | // GPU のインタフェース 135 | id device; 136 | 137 | // ウィンドウ 138 | NSWindow* window; 139 | 140 | // view 141 | AppMTKView* mtkView; 142 | 143 | // RenderPipelineState: レンダリングパイプラインを表現するオブジェクト 144 | id pipelineState0; 145 | id pipelineState1; 146 | 147 | // CommandBuffer を発行するオブジェクト 148 | id commandQueue; 149 | 150 | // 画面をクリアする色 151 | MTLClearColor clearColor; 152 | 153 | VertexBufferManager vertexBufferManager; 154 | 155 | // The Metal texture object 156 | id texture; 157 | 158 | } siv; 159 | 160 | @implementation AppDelegate 161 | 162 | + (AppDelegate *)sharedAppDelegate 163 | { 164 | return instance; 165 | } 166 | 167 | // アプリケーションの初期化 168 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 169 | { 170 | NSLog(@"#SivMetal# (1) applicationDidFinishLaunching"); 171 | 172 | instance = self; 173 | 174 | // デフォルトの GPU デバイスを取得する 175 | siv.device = MTLCreateSystemDefaultDevice(); 176 | 177 | // Metal 対応の view を作成する 178 | siv.mtkView = [[AppMTKView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) 179 | device:siv.device]; 180 | 181 | // ウィンドウ 182 | siv.window = _window; 183 | 184 | // ウィンドウに view を設定する 185 | [siv.window setContentView:siv.mtkView]; 186 | // ウィンドウを最前面に表示させる 187 | [NSApp activateIgnoringOtherApps:YES]; 188 | [siv.window makeKeyAndOrderFront:self]; 189 | 190 | // view の drawable のピクセルフォーマットを設定する 191 | [siv.mtkView setColorPixelFormat:MTLPixelFormatBGRA8Unorm_sRGB]; 192 | // depthStencilTexture のフォーマットを設定する 193 | [siv.mtkView setDepthStencilPixelFormat:MTLPixelFormatDepth32Float_Stencil8]; 194 | // MSAA を設定する 195 | // 1, 4 はすべての macOS でサポートされている 196 | // 参考: https://developer.apple.com/documentation/metal/mtldevice/1433355-supportstexturesamplecount 197 | [siv.mtkView setSampleCount:4]; 198 | // drawable クリア時の色を設定する (RGBA) 199 | siv.clearColor = MTLClearColorMake(11/255.0, 22/255.0, 33/255.0, 1.0); 200 | [siv.mtkView setClearColor:siv.clearColor]; 201 | // mainLoop から draw するための設定 202 | [siv.mtkView setPaused:YES]; 203 | 204 | // プロジェクト内の .metal 拡張子のシェーダファイルをすべてロードする 205 | id defaultLibrary = [siv.device newDefaultLibrary]; 206 | // シェーダ関数 `vertexShader` をロードする 207 | id vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"]; 208 | // シェーダ関数 `fragmentShader` をロードする 209 | id fragmentFunction0 = [defaultLibrary newFunctionWithName:@"fragmentShader"]; 210 | // シェーダ関数 `fragmentShaderTexture` をロードする 211 | id fragmentFunction1 = [defaultLibrary newFunctionWithName:@"fragmentShaderTexture"]; 212 | 213 | // RenderPipelineState を作成するための設定 (RenderPipelineDescriptor) を記述する 214 | MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; 215 | pipelineStateDescriptor.label = @"Simple Pipeline"; // ラベルをつけておくとデバッグ時に便利(任意) 216 | pipelineStateDescriptor.vertexFunction = vertexFunction; // 頂点シェーダの関数 217 | pipelineStateDescriptor.fragmentFunction = fragmentFunction0; // フラグメントシェーダの関数 218 | pipelineStateDescriptor.colorAttachments[0].pixelFormat = siv.mtkView.colorPixelFormat; // 出力先のフォーマット 219 | pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES; // アルファブレンディングのための設定 220 | pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; 221 | pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; 222 | pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; 223 | pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorZero; 224 | pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne; 225 | pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; 226 | pipelineStateDescriptor.rasterSampleCount = siv.mtkView.sampleCount; // MSAA 227 | pipelineStateDescriptor.depthAttachmentPixelFormat = siv.mtkView.depthStencilPixelFormat; // 深度フォーマット 228 | pipelineStateDescriptor.stencilAttachmentPixelFormat = siv.mtkView.depthStencilPixelFormat; // ステンシルフォーマット 229 | 230 | // RenderPipelineState を作成する 231 | NSError *error = NULL; 232 | siv.pipelineState0 = [siv.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor 233 | error:&error]; 234 | if (!siv.pipelineState0) 235 | { 236 | // RenderPipelineDescriptor の記述が間違っているとエラー 237 | NSLog(@"#SivMetal# Failed to created pipeline state, error %@", error); 238 | return; 239 | } 240 | 241 | pipelineStateDescriptor.fragmentFunction = fragmentFunction1; // フラグメントシェーダの関数 242 | siv.pipelineState1 = [siv.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor 243 | error:&error]; 244 | if (!siv.pipelineState1) 245 | { 246 | // RenderPipelineDescriptor の記述が間違っているとエラー 247 | NSLog(@"#SivMetal# Failed to created pipeline state, error %@", error); 248 | return; 249 | } 250 | 251 | // CommandQueue を作成。1 つのアプリケーションに 1 つ作るだけで良い 252 | siv.commandQueue = [siv.device newCommandQueue]; 253 | 254 | siv.vertexBufferManager.init(siv.device); 255 | 256 | MTKTextureLoader* textureLoader = [[MTKTextureLoader alloc] initWithDevice:siv.device]; 257 | 258 | NSDictionary *textureLoaderOptions = 259 | @{ 260 | MTKTextureLoaderOptionTextureUsage : @(MTLTextureUsageShaderRead), 261 | MTKTextureLoaderOptionTextureStorageMode : @(MTLStorageModePrivate) 262 | }; 263 | 264 | siv.texture = [textureLoader newTextureWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"assets/windmill" withExtension:@"png"] 265 | options:textureLoaderOptions 266 | error:&error]; 267 | 268 | if(!siv.texture || error) 269 | { 270 | NSLog(@"Failed to load texture"); 271 | return; 272 | } 273 | 274 | /* 275 | const int ImageWidth = 400, ImageHeight = 300; 276 | std::vector imageData(ImageWidth * ImageHeight, 0xFF8800FFu); 277 | 278 | MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init]; 279 | 280 | // Indicate that each pixel has a blue, green, red, and alpha channel, where each channel is 281 | // an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0) 282 | textureDescriptor.pixelFormat = MTLPixelFormatRGBA8Unorm; 283 | 284 | // Set the pixel dimensions of the texture 285 | textureDescriptor.width = ImageWidth; 286 | textureDescriptor.height = ImageHeight; 287 | 288 | // Create the texture from the device by using the descriptor 289 | siv.texture = [siv.device newTextureWithDescriptor:textureDescriptor]; 290 | 291 | MTLRegion region = 292 | { 293 | { 0, 0, 0 }, // MTLOrigin 294 | { ImageWidth, ImageHeight, 1} // MTLSize 295 | }; 296 | 297 | // Copy the bytes from our data object into the texture 298 | [siv.texture replaceRegion:region 299 | mipmapLevel:0 300 | withBytes:imageData.data() 301 | bytesPerRow:(ImageWidth * 4)]; 302 | */ 303 | // mainLoop を実行する 304 | [self performSelectorOnMainThread:@selector(mainLoop) withObject:nil waitUntilDone:NO]; 305 | } 306 | 307 | // terminate が呼ばれた 308 | -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 309 | { 310 | NSLog(@"#SivMetal# applicationShouldTerminate"); 311 | 312 | // handleMessages が false を返すようにする 313 | siv.shouldKeepRunning = false; 314 | 315 | if (siv.readyToTerminate) 316 | { 317 | NSLog(@"#SivMetal# (readyToTerminate == true)"); 318 | // mainLoop が終了していたらアプリケーションを終了 319 | return NSTerminateNow; 320 | } 321 | else 322 | { 323 | NSLog(@"#SivMetal# (readyToTerminate == false)"); 324 | // mainLoop が終了するまではアプリケーションを終了しない 325 | return NSTerminateCancel; 326 | } 327 | } 328 | 329 | // アプリケーションが終了 330 | - (void)applicationWillTerminate:(NSNotification *)aNotification 331 | { 332 | NSLog(@"#SivMetal# (4) applicationWillTerminate"); 333 | } 334 | 335 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication 336 | { 337 | // ウィンドウが閉じられたときに自動的に terminate が呼ばれるようにする 338 | return YES; 339 | } 340 | 341 | // イベントを処理 342 | - (bool)handleMessages 343 | { 344 | ++siv.frameCount; 345 | 346 | @autoreleasepool 347 | { 348 | for (;;) 349 | { 350 | NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny 351 | untilDate:[NSDate distantPast] 352 | inMode:NSDefaultRunLoopMode 353 | dequeue:YES]; 354 | if (event == nil) 355 | { 356 | break; 357 | } 358 | 359 | [NSApp sendEvent:event]; 360 | } 361 | } 362 | 363 | return siv.shouldKeepRunning; 364 | } 365 | 366 | // 描画処理 367 | - (void)draw 368 | { 369 | const std::vector batches = siv.vertexBufferManager.update(); 370 | 371 | @autoreleasepool 372 | { 373 | // 現在の drawable に使う、新しいレンダーパスのための CommandBuffer を作成 374 | id commandBuffer = [siv.commandQueue commandBuffer]; 375 | commandBuffer.label = @"MyCommand"; // ラベルをつけておくとデバッグ時に便利(任意) 376 | 377 | // 現在の drawable texture の RenderPassDescriptor を取得する 378 | MTLRenderPassDescriptor *renderPassDescriptor = siv.mtkView.currentRenderPassDescriptor; 379 | 380 | if(renderPassDescriptor != nil) 381 | { 382 | // RenderPassDescriptor から RenderCommandEncoder を作成 383 | // RenderCommandEncoder によって、レンダリングコマンドが CommandBuffer に登録される 384 | id renderCommandEncoder = 385 | [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; 386 | renderCommandEncoder.label = @"MyRenderCommandEncoder"; // ラベルをつけておくとデバッグ時に便利(任意) 387 | 388 | // 現在のウィンドウの解像度を取得 389 | simd::float2 viewportSize; 390 | viewportSize.x = [siv.mtkView drawableSize].width; 391 | viewportSize.y = [siv.mtkView drawableSize].height; 392 | 393 | // RenderCommandEncoder にビューポートを設定する 394 | [renderCommandEncoder setViewport:(MTLViewport){0, 0, viewportSize.x, viewportSize.y, -1.0, 1.0 }]; 395 | 396 | // ウィンドウの表示スケーリングを考慮 397 | const float scale = [siv.window backingScaleFactor];; 398 | viewportSize.x /= scale; 399 | viewportSize.y /= scale; 400 | 401 | if (!batches.empty()) 402 | { 403 | // 頂点シェーダ用のデータ [[buffer(0)]] をセット 404 | [renderCommandEncoder setVertexBuffer:siv.vertexBufferManager.getCurrentBuffer() 405 | offset:0 406 | atIndex:VertexInputIndex::Vertices]; 407 | 408 | // 頂点シェーダ用のデータ [[buffer(1)]] をセット 409 | [renderCommandEncoder setVertexBytes:&viewportSize 410 | length:sizeof(viewportSize) 411 | atIndex:VertexInputIndex::ViewportSize]; 412 | 413 | [renderCommandEncoder setFragmentTexture:siv.texture 414 | atIndex:0]; 415 | 416 | size_t vertexOffset = 0; 417 | 418 | for (const auto& batch : batches) 419 | { 420 | if (batch.isTextured) 421 | { 422 | // RenderPipelineState を設定する 423 | [renderCommandEncoder setRenderPipelineState:siv.pipelineState1]; 424 | } 425 | else 426 | { 427 | // RenderPipelineState を設定する 428 | [renderCommandEncoder setRenderPipelineState:siv.pipelineState0]; 429 | } 430 | 431 | // セットされた頂点データを使って頂点を描画 432 | [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle 433 | vertexStart:vertexOffset 434 | vertexCount:batch.count]; 435 | 436 | vertexOffset += batch.count; 437 | } 438 | } 439 | 440 | // RenderCommandEncoder によるコマンド登録の終了 441 | [renderCommandEncoder endEncoding]; 442 | } 443 | 444 | // 現在の drawable を表示させるコマンドを CommandBuffer に登録 445 | [commandBuffer presentDrawable:siv.mtkView.currentDrawable]; 446 | 447 | __weak dispatch_semaphore_t semaphore = siv.vertexBufferManager.getSemaphore(); 448 | [commandBuffer addCompletedHandler:^(id commandBuffer) 449 | { 450 | // GPU work is complete 451 | // Signal the semaphore to start the CPU work 452 | dispatch_semaphore_signal(semaphore); 453 | }]; 454 | 455 | // GPU に CommandBuffer を実行してもらう 456 | [commandBuffer commit]; 457 | } 458 | } 459 | 460 | // メインループ 461 | - (void)mainLoop 462 | { 463 | NSLog(@"#SivMetal# (2) mainLoop"); 464 | 465 | // drawable を初期化 466 | [siv.mtkView draw]; 467 | 468 | Main(); 469 | 470 | NSLog(@"#SivMetal# (3) ~mainLoop"); 471 | 472 | siv.readyToTerminate = true; 473 | 474 | // applicationShouldTerminate を呼び出してアプリケーションの終了を通知 475 | [NSApp terminate:nil]; 476 | } 477 | 478 | @end 479 | 480 | @implementation AppMTKView 481 | 482 | - (BOOL)isOpaque 483 | { 484 | return YES; 485 | } 486 | 487 | - (BOOL)canBecomeKey 488 | { 489 | return YES; 490 | } 491 | 492 | - (BOOL)acceptsFirstResponder 493 | { 494 | return YES; 495 | } 496 | 497 | // 左クリックされた 498 | - (void)mouseDown:(NSEvent *)event 499 | { 500 | NSLog(@"#SivMetal# MouseL.Down"); 501 | } 502 | 503 | // 右クリックされた 504 | - (void)rightMouseDown:(NSEvent *)event 505 | { 506 | NSLog(@"#SivMetal# MouseR.Down"); 507 | } 508 | 509 | @end 510 | 511 | int main(int argc, const char *argv[]) 512 | { 513 | return NSApplicationMain(argc, argv); 514 | } 515 | 516 | 517 | namespace SivMetal 518 | { 519 | using int8 = std::int8_t; 520 | using int16 = std::int16_t; 521 | using int32 = std::int32_t; 522 | using int64 = std::int64_t; 523 | using uint8 = std::uint8_t; 524 | using uint16 = std::uint16_t; 525 | using uint32 = std::uint32_t; 526 | using uint64 = std::uint64_t; 527 | 528 | namespace Math 529 | { 530 | inline constexpr double Pi = 3.1415926535897932385; 531 | 532 | inline constexpr float PiF = 3.1415926535897932385f; 533 | 534 | inline constexpr double TwoPi = Pi * 2.0; 535 | 536 | inline constexpr float TwoPiF = PiF * 2.0f; 537 | } 538 | 539 | struct Point 540 | { 541 | using value_type = int32; 542 | 543 | value_type x, y; 544 | 545 | Point() noexcept = default; 546 | 547 | constexpr Point(const Point&) noexcept = default; 548 | 549 | constexpr Point(int32 _x, int32 _y) noexcept 550 | : x(_x) 551 | , y(_y) {} 552 | 553 | template && std::is_integral_v>* = nullptr> 554 | constexpr Point(X _x, Y _y) noexcept 555 | : x(static_cast(_x)) 556 | , y(static_cast(_y)) {} 557 | 558 | template || !std::is_integral_v>* = nullptr> 559 | constexpr Point(X _x, Y _y) noexcept = delete; 560 | }; 561 | 562 | template 563 | struct Vector2D 564 | { 565 | template 566 | using vector_type = Vector2D; 567 | 568 | using value_type = Type; 569 | 570 | value_type x, y; 571 | 572 | Vector2D() noexcept = default; 573 | 574 | constexpr Vector2D(const Vector2D&) noexcept = default; 575 | 576 | template 577 | constexpr Vector2D(X _x, Y _y) noexcept 578 | : x(static_cast(_x)) 579 | , y(static_cast(_y)) {} 580 | 581 | constexpr Vector2D(value_type _x, value_type _y) noexcept 582 | : x(_x) 583 | , y(_y) {} 584 | 585 | constexpr Vector2D(const Point& v) noexcept 586 | : x(static_cast(v.x)) 587 | , y(static_cast(v.y)) {} 588 | 589 | template 590 | constexpr Vector2D(const Vector2D& v) noexcept 591 | : x(static_cast(v.x)) 592 | , y(static_cast(v.y)) {} 593 | }; 594 | 595 | using Float2 = Vector2D; 596 | using Vec2 = Vector2D; 597 | 598 | struct ColorF 599 | { 600 | double r, g, b, a; 601 | 602 | ColorF() = default; 603 | 604 | constexpr ColorF(const ColorF& color) noexcept = default; 605 | 606 | explicit constexpr ColorF(double rgb, double _a = 1.0) noexcept 607 | : r(rgb) 608 | , g(rgb) 609 | , b(rgb) 610 | , a(_a) {} 611 | 612 | constexpr ColorF(double _r, double _g, double _b, double _a = 1.0) noexcept 613 | : r(_r) 614 | , g(_g) 615 | , b(_b) 616 | , a(_a) {} 617 | }; 618 | 619 | void SetWindowTitle(const char* title); 620 | 621 | bool IsVisible(); 622 | 623 | bool Update(); 624 | 625 | int32 FrameCount(); 626 | 627 | void SetBackground(double r, double g, double b, double a); 628 | 629 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 630 | const ColorF& color); 631 | 632 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 633 | const ColorF& c0, const ColorF& c1, const ColorF& c2); 634 | 635 | void DrawRect(const Vec2& pos, const Vec2& size, const ColorF& color); 636 | 637 | void DrawCircle(const Vec2& center, double r, const ColorF& color); 638 | 639 | void DrawTexturedRect(const Vec2& pos, const Vec2& size, const ColorF& color); 640 | } 641 | 642 | namespace SivMetal 643 | { 644 | void SetWindowTitle(const char* title) 645 | { 646 | [siv.window setTitle:[NSString stringWithUTF8String:title]]; 647 | } 648 | 649 | bool IsVisible() 650 | { 651 | return [siv.window isVisible] 652 | && ([siv.window occlusionState] & NSWindowOcclusionStateVisible); 653 | } 654 | 655 | bool Update() 656 | { 657 | if (!IsVisible()) 658 | { 659 | // アプリケーションが不可視の場合 vSync しないので 16ms スリープ 660 | usleep(16 * 1000); 661 | } 662 | 663 | [[AppDelegate sharedAppDelegate] draw]; 664 | 665 | // 描画内容を反映 (vSync) 666 | [siv.mtkView draw]; 667 | 668 | return [[AppDelegate sharedAppDelegate] handleMessages]; 669 | } 670 | 671 | int32 FrameCount() 672 | { 673 | return siv.frameCount; 674 | } 675 | 676 | void SetBackground(const ColorF& color) 677 | { 678 | siv.clearColor = MTLClearColorMake(color.r, color.g, color.b, color.a); 679 | [siv.mtkView setClearColor:siv.clearColor]; 680 | } 681 | 682 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 683 | const ColorF& color) 684 | { 685 | DrawTriangle(p0, p1, p2, color, color, color); 686 | } 687 | 688 | void DrawTriangle(const Vec2& p0, const Vec2& p1, const Vec2& p2, 689 | const ColorF& c0, const ColorF& c1, const ColorF& c2) 690 | { 691 | Vertex* vtx = siv.vertexBufferManager.prepare(3, false); 692 | 693 | if (!vtx) 694 | { 695 | return; 696 | } 697 | 698 | vtx[0].position = simd::make_float2(p0.x, p0.y); 699 | vtx[0].color = simd::make_float4(c0.r, c0.g, c0.b, c0.a); 700 | vtx[1].position = simd::make_float2(p1.x, p1.y); 701 | vtx[1].color = simd::make_float4(c1.r, c1.g, c1.b, c1.a); 702 | vtx[2].position = simd::make_float2(p2.x, p2.y); 703 | vtx[2].color = simd::make_float4(c2.r, c2.g, c2.b, c2.a); 704 | } 705 | 706 | void DrawRect(const Vec2& pos, const Vec2& size, const ColorF& color) 707 | { 708 | Vertex* vtx = siv.vertexBufferManager.prepare(6, false); 709 | 710 | if (!vtx) 711 | { 712 | return; 713 | } 714 | 715 | const simd::float2 p0 = simd::make_float2(pos.x, pos.y); 716 | const simd::float2 p1 = simd::make_float2(pos.x + size.x, pos.y); 717 | const simd::float2 p2 = simd::make_float2(pos.x, pos.y + size.y); 718 | const simd::float2 p3 = simd::make_float2(pos.x + size.x, pos.y + size.y); 719 | const simd::float4 col = simd::make_float4(color.r, color.g, color.b, color.a); 720 | 721 | vtx[0].position = p0; 722 | vtx[1].position = p1; 723 | vtx[2].position = p2; 724 | vtx[3].position = p2; 725 | vtx[4].position = p1; 726 | vtx[5].position = p3; 727 | 728 | for (size_t i = 0; i < 6; ++i) 729 | { 730 | vtx[i].color = col; 731 | } 732 | } 733 | 734 | void DrawCircle(const Vec2& center, double r, const ColorF& color) 735 | { 736 | const uint32 quality = (r <= 5.0) ? (static_cast(r + 4) * 2) 737 | : static_cast(std::min(19 + (r - 5.0) / 2.2, 255.0)); 738 | const size_t vertexSize = quality * 3; 739 | 740 | Vertex* vtx = siv.vertexBufferManager.prepare(vertexSize, false); 741 | 742 | if (!vtx) 743 | { 744 | return; 745 | } 746 | 747 | const float rd = Math::TwoPiF / (quality - 1); 748 | const simd::float2 c = simd::make_float2(center.x, center.y); 749 | const simd::float4 col = simd::make_float4(color.r, color.g, color.b, color.a); 750 | simd::float2 p0 = simd::make_float2(center.x, center.y - r); 751 | 752 | for (size_t i = 0; i < quality; ++i) 753 | { 754 | const float rad = rd * (i - 1.0f); 755 | const simd::float2 p1 = simd::make_float2(center.x + r * std::cos(rad), 756 | center.y - r * std::sin(rad)); 757 | vtx[i * 3 + 0].position = p0; 758 | vtx[i * 3 + 1].position = p1; 759 | vtx[i * 3 + 2].position = c; 760 | p0 = p1; 761 | } 762 | 763 | for (size_t i = 0; i < vertexSize; ++i) 764 | { 765 | vtx[i].color = col; 766 | } 767 | } 768 | 769 | void DrawTexturedRect(const Vec2& pos, const Vec2& size, const ColorF& color) 770 | { 771 | Vertex* vtx = siv.vertexBufferManager.prepare(6, true); 772 | 773 | if (!vtx) 774 | { 775 | return; 776 | } 777 | 778 | const simd::float2 p0 = simd::make_float2(pos.x, pos.y); 779 | const simd::float2 p1 = simd::make_float2(pos.x + size.x, pos.y); 780 | const simd::float2 p2 = simd::make_float2(pos.x, pos.y + size.y); 781 | const simd::float2 p3 = simd::make_float2(pos.x + size.x, pos.y + size.y); 782 | const simd::float2 t0 = simd::make_float2(0.0f, 0.0f); 783 | const simd::float2 t1 = simd::make_float2(1.0f, 0.0f); 784 | const simd::float2 t2 = simd::make_float2(0.0f, 1.0f); 785 | const simd::float2 t3 = simd::make_float2(1.0f, 1.0f); 786 | const simd::float4 col = simd::make_float4(color.r, color.g, color.b, color.a); 787 | 788 | vtx[0].position = p0; 789 | vtx[1].position = p1; 790 | vtx[2].position = p2; 791 | vtx[3].position = p2; 792 | vtx[4].position = p1; 793 | vtx[5].position = p3; 794 | 795 | vtx[0].textureCoordinate = t0; 796 | vtx[1].textureCoordinate = t1; 797 | vtx[2].textureCoordinate = t2; 798 | vtx[3].textureCoordinate = t2; 799 | vtx[4].textureCoordinate = t1; 800 | vtx[5].textureCoordinate = t3; 801 | 802 | for (size_t i = 0; i < 6; ++i) 803 | { 804 | vtx[i].color = col; 805 | } 806 | } 807 | } 808 | 809 | using SivMetal::int32; 810 | using SivMetal::Vec2; 811 | using SivMetal::ColorF; 812 | 813 | void Main() 814 | { 815 | // ウィンドウタイトルを変更する 816 | SivMetal::SetWindowTitle("SivMetal | Experimental Metal project for OpenSiv3D"); 817 | 818 | // 背景色を変更する 819 | SivMetal::SetBackground(ColorF(0.8, 0.9, 1.0)); 820 | 821 | while (SivMetal::Update()) 822 | { 823 | for (int32 y = 0; y < 30; ++y) 824 | { 825 | for (int32 x = 0; x < 40; ++x) 826 | { 827 | // 長方形を描画 828 | SivMetal::DrawRect(Vec2(x * 20, y * 20), Vec2(15, 15), ColorF(0.5, 0.7, 0.9)); 829 | } 830 | } 831 | 832 | // テクスチャを描画 833 | SivMetal::DrawTexturedRect(Vec2(0, 0), Vec2(480, 320), ColorF(1)); 834 | 835 | // アニメーション 836 | const double t = 300.0 - (SivMetal::FrameCount() * 0.2); 837 | 838 | // 三角形を描画 839 | SivMetal::DrawTriangle(Vec2(500 + t, 200), Vec2(800, 600), Vec2(200, 600), ColorF(1, 0, 0, 1), ColorF(0, 1, 0, 1), ColorF(0, 0, 1, 1)); 840 | 841 | // 半透明の三角形を描画 842 | SivMetal::DrawTriangle(Vec2(500 - t, 200), Vec2(800, 600), Vec2(200, 600), ColorF(1, 1, 1, 0.8)); 843 | 844 | // 円を描画 845 | SivMetal::DrawCircle(Vec2(100, 500), 80, ColorF(1.0, 0.5, 0, 1)); 846 | } 847 | } 848 | --------------------------------------------------------------------------------