Родитель
2b733ae79c
Коммит
df51d134c0
|
@ -340,6 +340,7 @@ Copyright (C) 2014 Xamarin. All rights reserved.
|
|||
TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)"
|
||||
ResourcePrefix="$(XamMacResourcePrefix)"
|
||||
SdkDevPath="$(_SdkDevPath)"
|
||||
SdkIsSimulator="false"
|
||||
SdkRoot="$(_SdkRoot)"
|
||||
SdkVersion="$(MacOSXSdkVersion)"
|
||||
SourceFile="@(Metal)">
|
||||
|
|
|
@ -33,6 +33,9 @@ namespace Xamarin.MacDev.Tasks
|
|||
[Required]
|
||||
public string SdkVersion { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool SdkIsSimulator { get; set; }
|
||||
|
||||
[Required]
|
||||
public string SdkRoot { get; set; }
|
||||
|
||||
|
@ -55,13 +58,13 @@ namespace Xamarin.MacDev.Tasks
|
|||
get {
|
||||
switch (PlatformFrameworkHelper.GetFramework (TargetFrameworkIdentifier)) {
|
||||
case PlatformFramework.WatchOS:
|
||||
return "watchos";
|
||||
return SdkIsSimulator ? "watchos-simulator" : "watchos";
|
||||
case PlatformFramework.TVOS:
|
||||
return "tvos";
|
||||
return SdkIsSimulator ? "tvos-simulator" : "tvos";
|
||||
case PlatformFramework.MacOS:
|
||||
return "macosx";
|
||||
case PlatformFramework.iOS:
|
||||
return "ios";
|
||||
return SdkIsSimulator ? "iphonesimulator" : "ios";
|
||||
default:
|
||||
Log.LogError ($"Unknown target framework identifier: {TargetFrameworkIdentifier}.");
|
||||
return string.Empty;
|
||||
|
|
|
@ -602,8 +602,6 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved.
|
|||
</Target>
|
||||
|
||||
<Target Name="_SmeltMetal" Condition="'$(_CanOutputAppBundle)' == 'true' And '@(Metal)' != ''" DependsOnTargets="_DetectSdkLocations">
|
||||
<Error Condition="'$(ComputedPlatform)' == 'iPhoneSimulator'" Text="The iOS Simulator does not support metal. Build for a device instead."/>
|
||||
|
||||
<Metal
|
||||
SessionId="$(BuildSessionId)"
|
||||
Condition="'$(IsMacEnabled)' == 'true' and '%(Metal.Identity)' != ''"
|
||||
|
@ -613,6 +611,7 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved.
|
|||
TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)"
|
||||
ResourcePrefix="$(IPhoneResourcePrefix)"
|
||||
SdkDevPath="$(_SdkDevPath)"
|
||||
SdkIsSimulator="$(_SdkIsSimulator)"
|
||||
SdkRoot="$(_SdkRoot)"
|
||||
SdkVersion="$(MtouchSdkVersion)"
|
||||
SourceFile="@(Metal)">
|
||||
|
|
|
@ -208,6 +208,8 @@ namespace MyMetalGame
|
|||
// If we need a depth texture and don't have one, or if the depth texture we have is the wrong size
|
||||
// Then allocate one of the proper size
|
||||
MTLTextureDescriptor desc = MTLTextureDescriptor.CreateTexture2DDescriptor (MTLPixelFormat.Depth32Float, texture.Width, texture.Height, false);
|
||||
if (ObjCRuntime.Runtime.Arch == ObjCRuntime.Arch.SIMULATOR)
|
||||
desc.StorageMode = MTLStorageMode.Private;
|
||||
depthTex = device.CreateTexture (desc);
|
||||
depthTex.Label = "Depth";
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyMetalGame", "MyMetalGame.csproj", "{4598E620-3F15-4F66-B01A-B7F9E45CE659}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|iPhoneSimulator = Debug|iPhoneSimulator
|
||||
Release|iPhoneSimulator = Release|iPhoneSimulator
|
||||
Debug|iPhone = Debug|iPhone
|
||||
Release|iPhone = Release|iPhone
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4598E620-3F15-4F66-B01A-B7F9E45CE659}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{4598E620-3F15-4F66-B01A-B7F9E45CE659}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{4598E620-3F15-4F66-B01A-B7F9E45CE659}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{4598E620-3F15-4F66-B01A-B7F9E45CE659}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{4598E620-3F15-4F66-B01A-B7F9E45CE659}.Debug|iPhone.ActiveCfg = Debug|iPhone
|
||||
{4598E620-3F15-4F66-B01A-B7F9E45CE659}.Debug|iPhone.Build.0 = Debug|iPhone
|
||||
{4598E620-3F15-4F66-B01A-B7F9E45CE659}.Release|iPhone.ActiveCfg = Release|iPhone
|
||||
{4598E620-3F15-4F66-B01A-B7F9E45CE659}.Release|iPhone.Build.0 = Release|iPhone
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,56 @@
|
|||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
namespace MyTVMetalGame {
|
||||
// The UIApplicationDelegate for the application. This class is responsible for launching the
|
||||
// User Interface of the application, as well as listening (and optionally responding) to application events from iOS.
|
||||
[Register ("AppDelegate")]
|
||||
public class AppDelegate : UIApplicationDelegate {
|
||||
// class-level declarations
|
||||
|
||||
public override UIWindow Window {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
|
||||
{
|
||||
// Override point for customization after application launch.
|
||||
// If not required for your application you can safely delete this method
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnResignActivation (UIApplication application)
|
||||
{
|
||||
// Invoked when the application is about to move from active to inactive state.
|
||||
// This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message)
|
||||
// or when the user quits the application and it begins the transition to the background state.
|
||||
// Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
public override void DidEnterBackground (UIApplication application)
|
||||
{
|
||||
// Use this method to release shared resources, save user data, invalidate timers and store the application state.
|
||||
// If your application supports background exection this method is called instead of WillTerminate when the user quits.
|
||||
}
|
||||
|
||||
public override void WillEnterForeground (UIApplication application)
|
||||
{
|
||||
// Called as part of the transiton from background to active state.
|
||||
// Here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
public override void OnActivated (UIApplication application)
|
||||
{
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive.
|
||||
// If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
public override void WillTerminate (UIApplication application)
|
||||
{
|
||||
// Called when the application is about to terminate. Save data, if needed. See also DidEnterBackground.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"subtype": "retina4",
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "ipad"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"layers" : [
|
||||
{
|
||||
"filename" : "Front.imagestacklayer"
|
||||
},
|
||||
{
|
||||
"filename" : "Middle.imagestacklayer"
|
||||
},
|
||||
{
|
||||
"filename" : "Back.imagestacklayer"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"subtype": "retina4",
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "ipad"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"subtype": "retina4",
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "ipad"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"subtype": "retina4",
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "ipad"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"layers" : [
|
||||
{
|
||||
"filename" : "Front.imagestacklayer"
|
||||
},
|
||||
{
|
||||
"filename" : "Middle.imagestacklayer"
|
||||
},
|
||||
{
|
||||
"filename" : "Back.imagestacklayer"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"subtype": "retina4",
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "ipad"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"subtype": "retina4",
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "ipad"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"assets" : [
|
||||
{
|
||||
"size" : "1280x768",
|
||||
"idiom" : "tv",
|
||||
"filename" : "App Icon - Large.imagestack",
|
||||
"role" : "primary-app-icon"
|
||||
},
|
||||
{
|
||||
"size" : "400x240",
|
||||
"idiom" : "tv",
|
||||
"filename" : "App Icon - Small.imagestack",
|
||||
"role" : "primary-app-icon"
|
||||
},
|
||||
{
|
||||
"size" : "2320x720",
|
||||
"idiom" : "tv",
|
||||
"filename" : "Top Shelf Image Wide.imageset",
|
||||
"role" : "top-shelf-image-wide"
|
||||
},
|
||||
{
|
||||
"size" : "1920x720",
|
||||
"idiom" : "tv",
|
||||
"filename" : "Top Shelf Image.imageset",
|
||||
"role" : "top-shelf-image"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"subtype": "retina4",
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "ipad"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "universal"
|
||||
},
|
||||
{
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"subtype": "retina4",
|
||||
"scale": "2x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"idiom": "iphone"
|
||||
},
|
||||
{
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"idiom": "ipad"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"idiom": "ipad"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,366 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using CoreAnimation;
|
||||
using CoreGraphics;
|
||||
using Foundation;
|
||||
using OpenTK;
|
||||
using Metal;
|
||||
using UIKit;
|
||||
|
||||
namespace MyTVMetalGame {
|
||||
public partial class GameViewController : UIViewController {
|
||||
struct Uniforms {
|
||||
public Matrix4 ModelviewProjectionMatrix;
|
||||
public Matrix4 NormalMatrix;
|
||||
}
|
||||
|
||||
// The max number of command buffers in flight
|
||||
const int max_inflight_buffers = 3;
|
||||
|
||||
// Max API memory buffer size
|
||||
const int max_bytes_per_frame = 1024 * 1024;
|
||||
|
||||
float [] cubeVertexData = {
|
||||
// Data layout for each line below is:
|
||||
// positionX, positionY, positionZ, normalX, normalY, normalZ,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f
|
||||
};
|
||||
|
||||
// Layer
|
||||
CAMetalLayer metalLayer;
|
||||
MTLRenderPassDescriptor renderPassDescriptor;
|
||||
|
||||
// Controller
|
||||
CADisplayLink timer;
|
||||
Semaphore inflightSemaphore;
|
||||
IMTLBuffer dynamicConstantBuffer;
|
||||
byte constantDataBufferIndex;
|
||||
|
||||
// Renderer
|
||||
IMTLDevice device;
|
||||
IMTLCommandQueue commandQueue;
|
||||
IMTLLibrary defaultLibrary;
|
||||
IMTLRenderPipelineState pipelineState;
|
||||
IMTLBuffer vertexBuffer;
|
||||
IMTLDepthStencilState depthState;
|
||||
IMTLTexture depthTex;
|
||||
|
||||
// Uniforms
|
||||
Matrix4 projectionMatrix;
|
||||
Matrix4 viewMatrix;
|
||||
Uniforms uniformBuffer;
|
||||
float rotation;
|
||||
|
||||
public GameViewController (IntPtr handle) : base (handle)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ViewDidLoad ()
|
||||
{
|
||||
base.ViewDidLoad ();
|
||||
|
||||
constantDataBufferIndex = 0;
|
||||
inflightSemaphore = new Semaphore (max_inflight_buffers, max_inflight_buffers);
|
||||
|
||||
SetupMetal ();
|
||||
LoadAssets ();
|
||||
|
||||
timer = CADisplayLink.Create (Gameloop);
|
||||
timer.FrameInterval = 1;
|
||||
timer.AddToRunLoop (NSRunLoop.Main, NSRunLoop.NSDefaultRunLoopMode);
|
||||
}
|
||||
|
||||
public override void DidReceiveMemoryWarning ()
|
||||
{
|
||||
base.DidReceiveMemoryWarning ();
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
void SetupMetal ()
|
||||
{
|
||||
// Find a usable device
|
||||
device = MTLDevice.SystemDefault;
|
||||
|
||||
// Create a new command queue
|
||||
commandQueue = device.CreateCommandQueue ();
|
||||
|
||||
// Load all the shader files with a metal file extension in the project
|
||||
NSError error;
|
||||
|
||||
defaultLibrary = device.CreateLibrary ("default.metallib", out error);
|
||||
|
||||
// Setup metal layer and add as sub layer to view
|
||||
metalLayer = new CAMetalLayer ();
|
||||
metalLayer.Device = device;
|
||||
metalLayer.PixelFormat = MTLPixelFormat.BGRA8Unorm;
|
||||
|
||||
// Change this to NO if the compute encoder is used as the last pass on the drawable texture
|
||||
metalLayer.FramebufferOnly = true;
|
||||
|
||||
// Add metal layer to the views layer hierarchy
|
||||
metalLayer.Frame = View.Layer.Frame;
|
||||
View.Layer.AddSublayer (metalLayer);
|
||||
|
||||
View.Opaque = true;
|
||||
View.BackgroundColor = null;
|
||||
View.ContentScaleFactor = UIScreen.MainScreen.Scale;
|
||||
}
|
||||
|
||||
void LoadAssets ()
|
||||
{
|
||||
// Allocate one region of memory for the uniform buffer
|
||||
dynamicConstantBuffer = device.CreateBuffer (max_bytes_per_frame, 0);
|
||||
dynamicConstantBuffer.Label = "UniformBuffer";
|
||||
|
||||
// Load the fragment program into the library
|
||||
IMTLFunction fragmentProgram = defaultLibrary.CreateFunction ("lighting_fragment");
|
||||
|
||||
// Load the vertex program into the library
|
||||
IMTLFunction vertexProgram = defaultLibrary.CreateFunction ("lighting_vertex");
|
||||
|
||||
// Setup the vertex buffers
|
||||
vertexBuffer = device.CreateBuffer<float> (cubeVertexData, (MTLResourceOptions)0);
|
||||
vertexBuffer.Label = "Vertices";
|
||||
|
||||
// Create a reusable pipeline state
|
||||
var pipelineStateDescriptor = new MTLRenderPipelineDescriptor {
|
||||
Label = "MyPipeline",
|
||||
SampleCount = 1,
|
||||
VertexFunction = vertexProgram,
|
||||
FragmentFunction = fragmentProgram,
|
||||
DepthAttachmentPixelFormat = MTLPixelFormat.Depth32Float
|
||||
};
|
||||
|
||||
pipelineStateDescriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm;
|
||||
|
||||
NSError error;
|
||||
|
||||
pipelineState = device.CreateRenderPipelineState (pipelineStateDescriptor, out error);
|
||||
|
||||
if (pipelineState == null)
|
||||
Console.WriteLine ("Failed to created pipeline state, error " + error);
|
||||
|
||||
var depthStateDesc = new MTLDepthStencilDescriptor {
|
||||
DepthCompareFunction = MTLCompareFunction.Less,
|
||||
DepthWriteEnabled = true
|
||||
};
|
||||
|
||||
depthState = device.CreateDepthStencilState (depthStateDesc);
|
||||
}
|
||||
|
||||
void SetupRenderPassDescriptorForTexture (IMTLTexture texture)
|
||||
{
|
||||
if (renderPassDescriptor == null)
|
||||
renderPassDescriptor = MTLRenderPassDescriptor.CreateRenderPassDescriptor ();
|
||||
|
||||
renderPassDescriptor.ColorAttachments [0].Texture = texture;
|
||||
renderPassDescriptor.ColorAttachments [0].LoadAction = MTLLoadAction.Clear;
|
||||
renderPassDescriptor.ColorAttachments [0].ClearColor = new MTLClearColor (0.65f, 0.65f, 0.65f, 1.0f);
|
||||
renderPassDescriptor.ColorAttachments [0].StoreAction = MTLStoreAction.Store;
|
||||
|
||||
if (depthTex == null || (depthTex.Width != texture.Width || depthTex.Height != texture.Height)) {
|
||||
// If we need a depth texture and don't have one, or if the depth texture we have is the wrong size
|
||||
// Then allocate one of the proper size
|
||||
MTLTextureDescriptor desc = MTLTextureDescriptor.CreateTexture2DDescriptor (MTLPixelFormat.Depth32Float, texture.Width, texture.Height, false);
|
||||
if (ObjCRuntime.Runtime.Arch == ObjCRuntime.Arch.SIMULATOR)
|
||||
desc.StorageMode = MTLStorageMode.Private; depthTex = device.CreateTexture (desc);
|
||||
depthTex.Label = "Depth";
|
||||
|
||||
renderPassDescriptor.DepthAttachment.Texture = depthTex;
|
||||
renderPassDescriptor.DepthAttachment.LoadAction = MTLLoadAction.Clear;
|
||||
renderPassDescriptor.DepthAttachment.ClearDepth = 1.0f;
|
||||
renderPassDescriptor.DepthAttachment.StoreAction = MTLStoreAction.DontCare;
|
||||
}
|
||||
}
|
||||
|
||||
void Render ()
|
||||
{
|
||||
inflightSemaphore.WaitOne ();
|
||||
|
||||
Update ();
|
||||
|
||||
// Create a new command buffer for each renderpass to the current drawable
|
||||
IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer ();
|
||||
commandBuffer.Label = "MyCommand";
|
||||
|
||||
// Obtain a drawable texture for this render pass and set up the renderpass descriptor for the command encoder to render into
|
||||
ICAMetalDrawable drawable = GetCurrentDrawable ();
|
||||
|
||||
SetupRenderPassDescriptorForTexture (drawable.Texture);
|
||||
|
||||
// Create a render command encoder so we can render into something
|
||||
IMTLRenderCommandEncoder renderEncoder = commandBuffer.CreateRenderCommandEncoder (renderPassDescriptor);
|
||||
renderEncoder.Label = "MyRenderEncoder";
|
||||
renderEncoder.SetDepthStencilState (depthState);
|
||||
|
||||
// Set context state
|
||||
renderEncoder.PushDebugGroup ("DrawCube");
|
||||
renderEncoder.SetRenderPipelineState (pipelineState);
|
||||
renderEncoder.SetVertexBuffer (vertexBuffer, 0, 0);
|
||||
renderEncoder.SetVertexBuffer (dynamicConstantBuffer, (nuint)(Marshal.SizeOf (typeof (Uniforms)) * constantDataBufferIndex), 1);
|
||||
|
||||
// Tell the render context we want to draw our primitives
|
||||
renderEncoder.DrawPrimitives (MTLPrimitiveType.Triangle, 0, 36, 1);
|
||||
renderEncoder.PopDebugGroup ();
|
||||
|
||||
// We're done encoding commands
|
||||
renderEncoder.EndEncoding ();
|
||||
|
||||
// Call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer
|
||||
commandBuffer.AddCompletedHandler (buffer => {
|
||||
drawable.Dispose ();
|
||||
inflightSemaphore.Release ();
|
||||
});
|
||||
|
||||
// Schedule a present once the framebuffer is complete
|
||||
commandBuffer.PresentDrawable (drawable);
|
||||
|
||||
// Finalize rendering here & push the command buffer to the GPU
|
||||
commandBuffer.Commit ();
|
||||
|
||||
// The renderview assumes it can now increment the buffer index and that the previous index won't be touched until we cycle back around to the same index
|
||||
constantDataBufferIndex = (byte)((constantDataBufferIndex + 1) % max_inflight_buffers);
|
||||
}
|
||||
|
||||
void Reshape ()
|
||||
{
|
||||
// When reshape is called, update the view and projection matricies since this means the view orientation or size changed
|
||||
var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height);
|
||||
projectionMatrix = CreateMatrixFromPerspective (65.0f * ((float)Math.PI / 180.0f), aspect, 0.1f, 100.0f);
|
||||
|
||||
viewMatrix = Matrix4.Identity;
|
||||
}
|
||||
|
||||
void Update ()
|
||||
{
|
||||
var baseModel = Matrix4.Mult (CreateMatrixFromTranslation (0.0f, 0.0f, 5.0f), CreateMatrixFromRotation (rotation, 0.0f, 1.0f, 0.0f));
|
||||
var baseMv = Matrix4.Mult (viewMatrix, baseModel);
|
||||
var modelViewMatrix = Matrix4.Mult (baseMv, CreateMatrixFromRotation (rotation, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
uniformBuffer.NormalMatrix = Matrix4.Invert (Matrix4.Transpose (modelViewMatrix));
|
||||
uniformBuffer.ModelviewProjectionMatrix = Matrix4.Transpose (Matrix4.Mult (projectionMatrix, modelViewMatrix));
|
||||
|
||||
// Copy uniformBuffer's content into dynamicConstantBuffer.Contents
|
||||
int rawsize = Marshal.SizeOf (typeof (Uniforms));
|
||||
var rawdata = new byte [rawsize];
|
||||
IntPtr ptr = Marshal.AllocHGlobal (rawsize);
|
||||
Marshal.StructureToPtr (uniformBuffer, ptr, false);
|
||||
Marshal.Copy (ptr, rawdata, 0, rawsize);
|
||||
Marshal.FreeHGlobal (ptr);
|
||||
|
||||
Marshal.Copy (rawdata, 0, dynamicConstantBuffer.Contents + rawsize * constantDataBufferIndex, rawsize);
|
||||
|
||||
rotation += 0.01f;
|
||||
}
|
||||
|
||||
// The main game loop called by the CADisplayLine timer
|
||||
public void Gameloop ()
|
||||
{
|
||||
Render ();
|
||||
}
|
||||
|
||||
// Called whenever view changes orientation or layout is changed
|
||||
public override void ViewDidLayoutSubviews ()
|
||||
{
|
||||
Reshape ();
|
||||
}
|
||||
|
||||
ICAMetalDrawable GetCurrentDrawable ()
|
||||
{
|
||||
ICAMetalDrawable currentDrawable = null;
|
||||
|
||||
while (currentDrawable == null) {
|
||||
currentDrawable = metalLayer.NextDrawable ();
|
||||
if (currentDrawable == null)
|
||||
Console.WriteLine ("CurrentDrawable is null");
|
||||
}
|
||||
|
||||
return currentDrawable;
|
||||
}
|
||||
|
||||
static Matrix4 CreateMatrixFromPerspective (float fovY, float aspect, float nearZ, float farZ)
|
||||
{
|
||||
float yscale = 1.0f / (float)Math.Tan (fovY * 0.5f);
|
||||
float xscale = yscale / aspect;
|
||||
float q = farZ / (farZ - nearZ);
|
||||
|
||||
var m = new Matrix4 {
|
||||
Row0 = new Vector4 (xscale, 0.0f, 0.0f, 0.0f),
|
||||
Row1 = new Vector4 (0.0f, yscale, 0.0f, 0.0f),
|
||||
Row2 = new Vector4 (0.0f, 0.0f, q, q * -nearZ),
|
||||
Row3 = new Vector4 (0.0f, 0.0f, 1.0f, 0.0f)
|
||||
};
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static Matrix4 CreateMatrixFromTranslation (float x, float y, float z)
|
||||
{
|
||||
var m = Matrix4.Identity;
|
||||
m.Row0.W = x;
|
||||
m.Row1.W = y;
|
||||
m.Row2.W = z;
|
||||
m.Row3.W = 1.0f;
|
||||
return m;
|
||||
}
|
||||
|
||||
static Matrix4 CreateMatrixFromRotation (float radians, float x, float y, float z)
|
||||
{
|
||||
Vector3 v = Vector3.Normalize (new Vector3 (x, y, z));
|
||||
var cos = (float)Math.Cos (radians);
|
||||
var sin = (float)Math.Sin (radians);
|
||||
float cosp = 1.0f - cos;
|
||||
|
||||
var m = new Matrix4 {
|
||||
Row0 = new Vector4 (cos + cosp * v.X * v.X, cosp * v.X * v.Y - v.Z * sin, cosp * v.X * v.Z + v.Y * sin, 0.0f),
|
||||
Row1 = new Vector4 (cosp * v.X * v.Y + v.Z * sin, cos + cosp * v.Y * v.Y, cosp * v.Y * v.Z - v.X * sin, 0.0f),
|
||||
Row2 = new Vector4 (cosp * v.X * v.Z - v.Y * sin, cosp * v.Y * v.Z + v.X * sin, cos + cosp * v.Z * v.Z, 0.0f),
|
||||
Row3 = new Vector4 (0.0f, 0.0f, 0.0f, 1.0f)
|
||||
};
|
||||
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using Foundation;
|
||||
using System.CodeDom.Compiler;
|
||||
|
||||
namespace MyTVMetalGame {
|
||||
[Register ("GameViewController")]
|
||||
partial class GameViewController {
|
||||
void ReleaseDesignerOutlets ()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>MyTVMetalGame</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>MyTVMetalGame</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.xamarin.MyTVMetalGame</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>3</integer>
|
||||
</array>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>GCSupportedGameControllers</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>ProfileName</key>
|
||||
<string>ExtendedGamepad</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>ProfileName</key>
|
||||
<string>MicroGamepad</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GCSupportsControllerUserInteraction</key>
|
||||
<true/>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/App Icon & Top Shelf Image.brandassets</string>
|
||||
<key>XSLaunchImageAssets</key>
|
||||
<string>Assets.xcassets/LaunchImages.launchimage</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,13 @@
|
|||
using UIKit;
|
||||
|
||||
namespace MyTVMetalGame {
|
||||
public class Application {
|
||||
// This is the main entry point of the application.
|
||||
static void Main (string [] args)
|
||||
{
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
// you can specify it here.
|
||||
UIApplication.Main (args, null, "AppDelegate");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BV1-FR-VrT">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Game View Controller-->
|
||||
<scene sceneID="tXr-a1-R10">
|
||||
<objects>
|
||||
<viewController id="BV1-FR-VrT" customClass="GameViewController" customModuleProvider="" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="8aa-yV-Osq"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="qHh-Mt-9TT"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="3se-qz-xqx">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="SZV-WD-TEh" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,125 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
|
||||
<ProjectGuid>{CE09F37A-C1E9-488D-B72D-26269D735ECD}</ProjectGuid>
|
||||
<ProjectTypeGuids>{06FA79CB-D6CD-4721-BB4B-1BD202089C55};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>MyTVMetalGame</RootNamespace>
|
||||
<AssemblyName>MyTVMetalGame</AssemblyName>
|
||||
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<MtouchDebug>true</MtouchDebug>
|
||||
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
|
||||
<MtouchFastDev>true</MtouchFastDev>
|
||||
<IOSDebuggerPort>51092</IOSDebuggerPort>
|
||||
<MtouchLink>None</MtouchLink>
|
||||
<MtouchArch>x86_64</MtouchArch>
|
||||
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\iPhone\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<MtouchUseLlvm>true</MtouchUseLlvm>
|
||||
<MtouchFloat32>true</MtouchFloat32>
|
||||
<MtouchEnableBitcode>true</MtouchEnableBitcode>
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
|
||||
<MtouchLink>SdkOnly</MtouchLink>
|
||||
<MtouchArch>ARM64</MtouchArch>
|
||||
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\iPhoneSimulator\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
|
||||
<MtouchLink>None</MtouchLink>
|
||||
<MtouchArch>x86_64</MtouchArch>
|
||||
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\iPhone\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<DeviceSpecificBuild>true</DeviceSpecificBuild>
|
||||
<MtouchDebug>true</MtouchDebug>
|
||||
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
|
||||
<MtouchFastDev>true</MtouchFastDev>
|
||||
<MtouchFloat32>true</MtouchFloat32>
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
|
||||
<IOSDebuggerPort>39926</IOSDebuggerPort>
|
||||
<MtouchLink>SdkOnly</MtouchLink>
|
||||
<MtouchArch>ARM64</MtouchArch>
|
||||
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Xamarin.TVOS" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Large.imagestack\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Large.imagestack\Back.imagestacklayer\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Large.imagestack\Back.imagestacklayer\Content.imageset\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Large.imagestack\Front.imagestacklayer\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Large.imagestack\Front.imagestacklayer\Content.imageset\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Large.imagestack\Middle.imagestacklayer\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Large.imagestack\Middle.imagestacklayer\Content.imageset\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Small.imagestack\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Small.imagestack\Back.imagestacklayer\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Small.imagestack\Back.imagestacklayer\Content.imageset\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Small.imagestack\Front.imagestacklayer\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Small.imagestack\Front.imagestacklayer\Content.imageset\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Small.imagestack\Middle.imagestacklayer\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\App Icon - Small.imagestack\Middle.imagestacklayer\Content.imageset\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\Top Shelf Image Wide.imageset\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\App Icon & Top Shelf Image.brandassets\Top Shelf Image.imageset\Contents.json" />
|
||||
<ImageAsset Include="Assets.xcassets\Contents.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Metal Include="Shaders.metal" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Info.plist" />
|
||||
<None Include="Entitlements.plist" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="AppDelegate.cs" />
|
||||
<Compile Include="GameViewController.cs" />
|
||||
<Compile Include="GameViewController.designer.cs">
|
||||
<DependentUpon>GameViewController.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<InterfaceDefinition Include="Main.storyboard" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\TVOS\Xamarin.TVOS.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyTVMetalGame", "MyTVMetalGame.csproj", "{CE09F37A-C1E9-488D-B72D-26269D735ECD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|iPhoneSimulator = Debug|iPhoneSimulator
|
||||
Release|iPhone = Release|iPhone
|
||||
Release|iPhoneSimulator = Release|iPhoneSimulator
|
||||
Debug|iPhone = Debug|iPhone
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CE09F37A-C1E9-488D-B72D-26269D735ECD}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{CE09F37A-C1E9-488D-B72D-26269D735ECD}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{CE09F37A-C1E9-488D-B72D-26269D735ECD}.Release|iPhone.ActiveCfg = Release|iPhone
|
||||
{CE09F37A-C1E9-488D-B72D-26269D735ECD}.Release|iPhone.Build.0 = Release|iPhone
|
||||
{CE09F37A-C1E9-488D-B72D-26269D735ECD}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{CE09F37A-C1E9-488D-B72D-26269D735ECD}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{CE09F37A-C1E9-488D-B72D-26269D735ECD}.Debug|iPhone.ActiveCfg = Debug|iPhone
|
||||
{CE09F37A-C1E9-488D-B72D-26269D735ECD}.Debug|iPhone.Build.0 = Debug|iPhone
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,53 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
// Variables in constant address space
|
||||
constant float3 light_position = float3(0.0, 1.0, -1.0);
|
||||
constant float4 ambient_color = float4(0.18, 0.24, 0.8, 1.0);
|
||||
constant float4 diffuse_color = float4(0.4, 0.4, 1.0, 1.0);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4x4 modelview_projection_matrix;
|
||||
float4x4 normal_matrix;
|
||||
} uniforms_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
packed_float3 position;
|
||||
packed_float3 normal;
|
||||
} vertex_t;
|
||||
|
||||
typedef struct {
|
||||
float4 position [[position]];
|
||||
half4 color;
|
||||
} ColorInOut;
|
||||
|
||||
// Vertex shader function
|
||||
vertex ColorInOut lighting_vertex(device vertex_t* vertex_array [[ buffer(0) ]],
|
||||
constant uniforms_t& uniforms [[ buffer(1) ]],
|
||||
unsigned int vid [[ vertex_id ]])
|
||||
{
|
||||
ColorInOut out;
|
||||
|
||||
float4 in_position = float4(float3(vertex_array[vid].position), 1.0);
|
||||
out.position = uniforms.modelview_projection_matrix * in_position;
|
||||
|
||||
|
||||
float3 normal = vertex_array[vid].normal;
|
||||
float4 eye_normal = normalize(uniforms.normal_matrix * float4(normal, 0.0));
|
||||
float n_dot_l = dot(eye_normal.rgb, normalize(light_position));
|
||||
n_dot_l = fmax(0.0, n_dot_l);
|
||||
|
||||
out.color = half4(ambient_color + diffuse_color * n_dot_l);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Fragment shader function
|
||||
fragment half4 lighting_fragment(ColorInOut in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
}
|
|
@ -17,13 +17,8 @@ namespace Xamarin.iOS.Tasks {
|
|||
[Test]
|
||||
public void BasicTest ()
|
||||
{
|
||||
if (Platform == "iPhoneSimulator") {
|
||||
// Note: we expect an error due to Metal not being supported on iPhoneSimulator
|
||||
// Note 2: msbuild now is aware that Metal is device-only and throws an error thus this test becomes device-only for time being
|
||||
//this.BuildExtension ("MyMetalGame", "MyKeyboardExtension", Platform, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Platform == "iPhoneSimulator" && Environment.OSVersion.Version.Major < 19) // Environment.OSVersion = 19.* in macOS Catalina.
|
||||
Assert.Ignore ("Metal support is not available in the simulator until macOS 10.15.");
|
||||
this.BuildExtension ("MyMetalGame", "MyKeyboardExtension", Platform, "Debug");
|
||||
this.TestStoryboardC (AppBundlePath);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Xamarin.iOS.Tasks
|
||||
{
|
||||
|
@ -13,6 +15,8 @@ namespace Xamarin.iOS.Tasks
|
|||
[Test]
|
||||
public void BasicTest()
|
||||
{
|
||||
if (Platform == "iPhoneSimulator" && Environment.OSVersion.Version.Major < 19) // Environment.OSVersion = 19.* in macOS Catalina.
|
||||
Assert.Ignore ("Metal support is not available in the simulator until macOS 10.15.");
|
||||
BuildExtension ("MyTVApp", "MyTVServicesExtension", Platform, "Debug");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Xamarin.iOS.Tasks {
|
||||
[TestFixture ("iPhone")]
|
||||
[TestFixture ("iPhoneSimulator")]
|
||||
public class TVMetalGameTests : ProjectTest {
|
||||
public TVMetalGameTests (string platform) : base (platform)
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BasicTest ()
|
||||
{
|
||||
if (Platform == "iPhoneSimulator" && Environment.OSVersion.Version.Major < 19) // Environment.OSVersion = 19.* in macOS Catalina.
|
||||
Assert.Ignore ("Metal support is not available in the simulator until macOS 10.15.");
|
||||
BuildProject ("MyTVMetalGame", Platform, "Debug");
|
||||
}
|
||||
|
||||
public override string TargetFrameworkIdentifier {
|
||||
get {
|
||||
return "Xamarin.TVOS";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче