所以我一直试图用OpenGL ES 2.0 创建一个尾随粒子效果(见到这里).不幸的是,似乎OpenGL命令(累积缓冲区)无法在OpenGL中使用.这意味着有必要走长路.
本主题描述了执行此类操作的可能方法.但是我对如何在缓冲区中存储内容并组合缓冲区感到很困惑.所以我的想法是做以下事情.
到目前为止,我的理解是缓冲区以与纹理相同的方式存储像素数据,只需使用着色器可以更容易地绘制缓冲区.
因此,想法可能是渲染到缓冲区,然后将其移动到纹理中.
我发现这样做的一个理论就是这个
回想起来,你应该创建两个FBO(每个都有自己的纹理); 使用默认的帧缓冲区是不可靠的(不保证在帧之间保留内容).
绑定第一个FBO后,清除它然后正常渲染场景.渲染场景后,使用纹理作为源并使用混合将其渲染到第二个FBO(第二个FBO永远不会被清除).这将导致第二个FBO包含新场景和之前的场景的混合.最后,第二个FBO应直接渲染到窗口(这可以通过渲染纹理四边形来完成,类似于前一个操作,或者使用glBlitFramebuffer).
实质上,第一个FBO取代了默认的帧缓冲区,而第二个FBO取代了累积缓冲区.
综上所述:
初始化:
对于每个FBO: - glGenTextures - glBindTexture - glTexImage2D - glBindFrameBuffer - glFramebufferTexture2D
每一帧:
glBindFrameBuffer(GL_DRAW_FRAMEBUFFER,fbo1)glClear glDraw*//场景
glBindFrameBuffer(GL_DRAW_FRAMEBUFFER,fbo2)glBindTexture(tex1)glEnable(GL_BLEND)glBlendFunc glDraw*//全屏四边形
glBindFrameBuffer(GL_DRAW_FRAMEBUFFER,0)glBindFrameBuffer(GL_READ_FRAMEBUFFER,fbo2)glBlitFramebuffer
不幸的是它没有足够的代码(尤其是初始化让我开始).
但我已经尝试过,到目前为止我所得到的只是一个令人失望的空白屏幕.我真的不知道我在做什么,所以可能这段代码是错误的.
var fbo1:GLuint = 0
var fbo2:GLuint = 0
var tex1:GLuint = 0
Init()
{
//...Loading shaders OpenGL etc.
//FBO 1
glGenFramebuffers(1, &fbo1)
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), fbo1)
//Create texture for shader output
glGenTextures(1, &tex1)
glBindTexture(GLenum(GL_TEXTURE_2D), tex1)
glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGB, width, height, 0, GLenum(GL_RGB), …Run Code Online (Sandbox Code Playgroud) 我试图在一个已经很疯狂的应用程序上放置一个波纹模拟.现在cpu在最低处理器上运行大约11ms.到目前为止,它中的所有代码都在主线程上运行.
我希望可以将纹波模拟完全放在另一个线程上.
该模拟基于Apple GLCameraRipple项目.基本上它会创建一个镶嵌的矩形,并计算纹理坐标.因此,在理想的世界中,纹理坐标和纹波模拟数组都将位于不同的线程上.
我正在使用的更新功能现在看起来像这样.它确实可以利用GCD,但由于同步,它不会因此而获得速度.没有同步但是应用程序会崩溃,因为swift数组不是线程安全的.
var rippleTexCoords:[GLfloat] = []
var rippleSource:[GLfloat] = []
var rippleDest:[GLfloat] = []
func runSimulation()
{
if (firstUpdate)
{firstUpdate = false; Whirl.crashLog("First update")}
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
let block1: (y: size_t) -> Void = {
(y: size_t) -> Void in
objc_sync_enter(self)
defer { objc_sync_exit(self) } // */ This will actually run at the end
let pw = self.poolWidthi
for x in 1..<(pw - 1)
{
let ai:Int = (y ) * (pw + 2) …Run Code Online (Sandbox Code Playgroud) 我正在通过Metal iOS Swift示例尝试了解他们建议的三重缓冲实践.这是在演示内部显示的统一动画.
据我所知,对齐内存只是以一个特定的增量开始,这是设备真正喜欢的某个字节数的倍数.我的困惑是这行代码
// The 256 byte aligned size of our uniform structure
let alignedUniformsSize = (MemoryLayout<Uniforms>.size & ~0xFF) + 0x100
Run Code Online (Sandbox Code Playgroud)
他们用它来查找Uniforms结构的大小和字节.我很困惑为什么在这里有二进制操作我真的不确定他们做了什么.
如果它有助于这个对齐的大小用于创建这样的缓冲区.我很确定缓冲区会自动分配字节对齐的内存,因此可以用作制服的内存存储位置.
let buffer = self.device.makeBuffer(length:alignedUniformsSize * 3, options:[MTLResourceOptions.storageModeShared])
Run Code Online (Sandbox Code Playgroud)
所以基本上不是经历自己分配字节对齐内存的麻烦,而是让金属为它们做.
在那个时候,他们的策略时,他们没有使用任何理由let allignedUniformsSize =不会为其他类型,比如上班Int或Float等?
我的应用程序中有一些音乐可以播放AVAudioSessionCategoryAmbient.现在我的问题是,当Apple弹出一个像"登录iTunes Store"的弹出窗口时,它会暂停我的音乐,但不会恢复它.值得庆幸的是,它照顾了我SKScene......但不是音乐.是否有某种方法可以在警报解除时进行回调?
奇怪的是,UIAlertView我制作的其他内容不会对应用程序执行此操作,所以我真的不知道是什么.
暂停场景和音乐的警报列表:
我正在为我自己的目的编写一个应用程序,旨在无论系统中发生什么都可以获得播放暂停事件。我已经做了这么多工作
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.togglePlayPauseCommand.isEnabled = true
commandCenter.togglePlayPauseCommand.addTarget { (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus in
print("Play Pause Command")
return .success
}
commandCenter.nextTrackCommand.isEnabled = true
commandCenter.nextTrackCommand.addTarget { (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus in
print("NextTrackCommand")
return .success
}
commandCenter.previousTrackCommand.isEnabled = true
commandCenter.previousTrackCommand.addTarget { (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus in
print("previousTrackCommand")
return .success
}
commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus in
print("playCommand")
return .success
}
MPNowPlayingInfoCenter.default().playbackState = .playing
Run Code Online (Sandbox Code Playgroud)
大多数方法都在那里,因为很明显,如果没有实现 nextTrackCommand 或 previousTrackCommand 或 playCommand ,您将不会收到任何通知。
无论如何,我的一个问题是,一旦您打开另一个使用音频的应用程序,这些事件处理程序就会停止调用,我无法找到检测和解决此问题的方法。
我通常会尝试做 AVAudioSession 事情来将其声明为后台应用程序,但这似乎不起作用。无论系统处于何种状态,关于如何获得游戏暂停事件的任何想法?
我希望能够始终收听这些事件或获得其他人何时控制音频的指示?也许甚至可以重新订阅这些播放暂停事件。
所以我想知道,默认的"游戏"Xcode配置.你会如何制作另一款SKScene?比如说我想要一个菜单或什么?
基本上我将如何创建另一个标题为"title.swift"的文档,然后以编程方式来回切换它们?这样我可以从菜单到游戏场景而不会弄乱我的代码?
我无法在重新编码的代码中找到它实际上告诉swift显示用"游戏"配置预制的游戏场景.
我想我创建了一个新类并继承了SKScene.
所以我有一个我想做的项目.我试图让设备相对于重力旋转,并从它开始的位置进行平移.所以基本上为设备获取"跟踪"数据.我打算基本上通过制作一个3d pt来模拟我稍后从设备上记录的数据.
无论如何要尝试实现这一点,我认为最好使用场景工具包,这样我就可以看到三维中的东西,就像我想要记录的数据一样.现在我一直试图让船旋转,使它总是看起来像它的跟随重力(就像它在地面上或其他东西)无论设备旋转是什么.我想,一旦我把它弄下来,将这一点应用于某一点将是一个难题.所以我做了以下代码:
if let attitude = motionManager.deviceMotion?.attitude {
print(attitude)
ship.eulerAngles.y = -Float(attitude.roll)
ship.eulerAngles.z = -Float(attitude.yaw)
ship.eulerAngles.x = -Float(attitude.pitch)
}
Run Code Online (Sandbox Code Playgroud)
当你只运行其中一条旋转线时,一切都很完美.它确实在该轴上表现良好.然而,当我同时完成所有三个轴时,它变得混乱并且与抖动和所有事情的预期相差很远.
我想我的问题是:有没有人知道如何修复上面的代码,以便无论方向如何,船都能正常保持"直立"状态.
我很困惑,因为我在 Swift 4 中创建了一个 MTLBuffer,但无法使用 didModifyRange 方法。
有趣的是,我仍然可以在 Apple 文档中找到这一点,并且没有听说过这一点被改变了。
为什么会Value of type 'MTLBuffer' has no member 'didModifyRange'发生错误?
以下代码将在最新版本的 XCode 中生成此错误
let device = MTLCreateSystemDefaultDevice()
var buffer = device?.makeBuffer(length: 3, options: [])
let range = Range<Int>(NSRange())
buffer.didModifyRange(range)
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用MTKTextureLoader加载CGImage作为纹理。这是原始图片
但是,当我将该CGImage转换为MTLTexture并将该纹理转换回CGImage时,它看起来很可怕,如下所示:
这是代码中正在发生的事情。
图像作为CGImage加载(我已经检查过了,该图像确实具有完整的视觉质量)
我有一个功能view(),可以通过在CALayer中使用它来查看NSImage,如下所示:
func view() {
.....
imageView!.layer = CALayer()
imageView!.layer!.contentsGravity = kCAGravityResizeAspectFill
imageView!.layer!.contents = img
imageView!.wantsLayer = true
Run Code Online (Sandbox Code Playgroud)
所以我做了以下
let cg = CoolImage()
let ns = NSImage(cgImage: cg, size: Size(width: cg.width, height: cg.height))
view(image: ns)
Run Code Online (Sandbox Code Playgroud)
并检查是否足够具有完整的视觉保真度。
因此,我将cg图像加载到MTLTexture中,如下所示
let textureLoader = MTKTextureLoader(device: metalState.sharedDevice!)
let options = [
MTKTextureLoader.Option.textureUsage: NSNumber(value: MTLTextureUsage.shaderRead.rawValue | MTLTextureUsage.shaderWrite.rawValue | MTLTextureUsage.renderTarget.rawValue),
MTKTextureLoader.Option.SRGB: false
]
return ensure(try textureLoader.newTexture(cgImage: cg, options: options))
Run Code Online (Sandbox Code Playgroud)
然后,我将MTLTexture转换回UIImage,如下所示:
let texture = self
let width = texture.width
let height = texture.height
let bytesPerRow …Run Code Online (Sandbox Code Playgroud) 无论出于何种原因,我都遇到了金属中 alpha 混合的问题。我正在绘制 MTKView,对于我创建的每个管道,我执行以下操作:
descriptor.colorAttachments[0].blendingEnabled = YES;
descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
Run Code Online (Sandbox Code Playgroud)
但是,无论出于何种原因,这都不会导致 alpha 测试发生。您甚至可以检查帧调试器,您将看到 alpha 为 0 的顶点被绘制为黑色而不是透明。
我的一个想法是,某些几何体最终位于完全相同的 z 平面上,因此如果 alpha 混合在同一 z 平面上不起作用,则可能会导致问题。但我不认为那是一回事。
为什么 alpha 混合不起作用?
我希望像透明玻璃一样混合。这样想。