iOS OpenGL. Plusieurs vues simultanément

quelques jours avant j'ai demandé de remplir l'espace entre deux lignes de courbe avec gradient . Depuis que j'ai changé beaucoup de dans mon code – maintenant j'utilise des shaders. Le résultat est presque comme j'ai besoin. MAIS! Encore une fois, j'ai un problème avec l'utilisation de plusieurs vues OpenGL simultanément dans un controller mais elles doivent être absolument indépendantes les unes des autres. Donc, grâce à un tutoriel incroyable de raywenderlich.com et un exemple de code de bradley j'ai la situation suivante:

  • deux objects personnalisés de la class SoundWaveView.swift (améliorés à partir de OpenGLView.swift depuis bradley);
  • vertex / fragment shaders pour l'object openglView;
  • controller où je crée et ajoute deux objects SoundWaveView (avec le même context !!!!!):

c

override func viewDidLoad() { super.viewDidLoad() let context = EAGLContext(API: EAGLRenderingAPI.OpenGLES2) let viewPos1: CGRect = CGRectMake(0, 150, UIScreen.mainScreen().bounds.size.width, 150); let view1 = SoundWaveView(frame: viewPos1, fileName: "Personal Jesus", fileExtention: "mp3", c: context) view1.backgroundColor = UIColor.grayColor() self.view.addSubview(view1) let viewPos2: CGRect = CGRectMake(0, 350, UIScreen.mainScreen().bounds.size.width, 150); let view2 = SoundWaveView(frame: viewPos2, fileName: "Imagine", fileExtention: "mp3", c: context) view2.backgroundColor = UIColor.blackColor() self.view.addSubview(view2) } 

Chaque object SoundWaveView comstack les shaders comme dans les tutoriels ci-dessus:

  func comstackShaders() { let vertexShader = comstackShader("SimpleVertex", shaderType: GLenum(GL_VERTEX_SHADER)) let fragmentShader = comstackShader("SimpleFragment", shaderType: GLenum(GL_FRAGMENT_SHADER)) let programHandle: GLuint = glCreateProgram() glAttachShader(programHandle, vertexShader) glAttachShader(programHandle, fragmentShader) glLinkProgram(programHandle) var linkSuccess: GLint = GLint() glGetProgramiv(programHandle, GLenum(GL_LINK_STATUS), &linkSuccess) if (linkSuccess == GL_FALSE) { var message = [CChar](count: 256, repeatedValue: CChar(0)) var length = GLsizei(0) glGetProgramInfoLog(programHandle, 256, &length, &message) print("Failed to create shader program! : \( Ssortingng(UTF8Ssortingng: message) ) ") exit(1); } glUseProgram(programHandle) . . . . . shaderPeakId = glGetUniformLocation(programHandle, "peakId") shaderWaveAmp = glGetUniformLocation(programHandle, "waveAmp"); glEnableVertexAtsortingbArray(positionSlot) glEnableVertexAtsortingbArray(colorSlot) glUniform1f(shaderSceneWidth!, Float(self.frame.size.width)); glUniform1f(shaderSceneHeight!, Float(self.frame.size.height)); glUniform1i(shaderPeaksTotal!, GLint(total)); glUniform1i(shaderPeakId!, GLint(position)); } 

Pour rendre les ondes audio un besoin de passer aux valeurs de shader comme A) amplitude (je les obtiens de avaudioplayer – il fonctionne parfaitement et pour deux objects je crée dans le controller j'ai différentes amplitudes pour deux pistes différentes) et B) numéro d'onde (aka peakId / position).

Donc, pour le premier object créé (gris), la position est égale à 1 et cette onde doit être rouge et placée dans la partie gauche de l'écran. Pour le deuxième object (noir) la position est 3, l'onde est bleue et placée dans la partie droite. / la position 2 est pour le centre à l'écran, ne pas utiliser maintenant /

Chaque mise à jour audio provoque la mise à jour pour opengl:

 var waveAmp :Float = 0 . . . . . func updateMeters(){ player!.updateMeters() var normalizedValue = normalizedPowerLevelFromDecibels(player!.averagePowerForChannel(0)) waveAmp = normalizedValue! } func render(displayLink: CADisplayLink?) { glBlendFunc(GLenum(GL_ONE), GLenum(GL_ONE_MINUS_SRC_ALPHA)) glEnable(GLenum(GL_BLEND)) // glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0) glClearColor(0, 0, 0, 0) glClear(GLenum(GL_COLOR_BUFFER_BIT) | GLenum(GL_DEPTH_BUFFER_BIT)) glEnable(GLenum(GL_DEPTH_TEST)) glViewport(0, 0, GLsizei(self.frame.size.width), GLsizei(self.frame.size.height)) glBindBuffer(GLenum(GL_ARRAY_BUFFER), vertexBuffer) glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexBuffer) glVertexAtsortingbPointer(positionSlot, 3, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(Vertex)), nil) glVertexAtsortingbPointer(colorSlot, 4, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(Vertex)), UnsafePointer<Void>(bitPattern: (sizeof(Float) * 3))) glDrawElements(GLenum(GL_TRIANGLE_FAN), GLsizei(Indices.size()), GLenum(GL_UNSIGNED_BYTE), nil) glVertexAtsortingbPointer(positionSlot, 3, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(Vertex)), nil); glVertexAtsortingbPointer(colorSlot, 4, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(Vertex)), UnsafePointer<Void>(bitPattern: (sizeof(Float) * 3))); context.presentRenderbuffer(Int(GL_RENDERBUFFER)) print("position=\(position) waveAmp=\(waveAmp)") glUniform1i(shaderPeakId!, GLint(position)); glUniform1f(shaderWaveAmp!, waveAmp); } 

Connectez-vous avec print () – fonction:

 position=1 waveAmp=0.209313 position=3 waveAmp=0.47332 position=1 waveAmp=0.207556 position=3 waveAmp=0.446235 position=1 waveAmp=0.20769 position=3 waveAmp=0.446235 position=1 waveAmp=0.246206 position=3 waveAmp=0.430118 

Je m'attends à avoir deux rectangles – un gris avec une vague rouge à gauche et un noir avec une ligne bleue à droite. MAIS j'ai le prochain problème! Le rendu a lieu dans une (dernière) vue et change séquentiellement:

entrez la description de l'image ici entrez la description de l'image ici

S'il vous plait quelqu'un! Comment utiliser deux glViews simultanément? Ou peut-être que j'ai besoin d'utiliser deux shaders dans une vue?

Je veux terminer cette tâche audio et les partager avec tout le monde. Mais je ne comprends toujours pas ce problème

En regardant dans le code de la class SoundWaveView que vous avez posté, il semble que cette vue gère l'initialisation du context, le framebuffer pour le context, et plus encore pour vous. Puisque vous envoyez le même EAGLContext aux deux vues, cela signifie que le même context est initialisé, puis probablement réinitialisé par la deuxième vue. Cela ne me semble pas juste. Cela pourrait bien fonctionner si vous ne faites qu'un context séparé pour l'autre vue, et le GPU changera simplement de context lors du rendu entre ces deux vues, et les traitera comme s'il s'agissait d'applications séparées.

Mais ce n'est pas comme cela qu'une application aussi simple devrait être conçue. Si vous voulez que deux objects soient dessinés en même time sur l'écran, cela ne signifie certainement pas que vous avez besoin de deux vues séparées. Vous devriez build un système qui gère la prise d'information de chaque forme d'onde et la convertir en appels de tirage appropriés automatiquement. Cela agirait comme un moteur de mini-tirage pour votre application. Avec cette approche, vous pourriez écrire un support supplémentaire pour des techniques et des dessins encore plus cool … peut-être plus de forms d'onde, de textures / colors différentes pour chacun d'entre eux, d'effets sympas, etc.