在我询问有关filling space between two curve lines with gradient的前两天。
从那以后,我在代码中做了很多更改-现在我正在使用着色器。结果几乎是我所需要的。但!同样,我在一个 Controller 中同时使用多个OpenGL View 时遇到问题,但它们必须彼此绝对独立。
因此,由于raywenderlich.comcode example from bradley令人难以置信的教程,我有了下一种情况:

  • SoundWaveView.swift类的两个自定义对象(从bradley的OpenGLView.swift改进);
  • opentlView对象的
  • 顶点/片段着色器;
  • 我在其中创建和添加两个SoundWaveView对象(具有相同上下文!!!!)的
  • Controller :

  • 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)
    }
    

    每个SoundWaveView对象都会编译着色器,如上面的教程中所示:
        func compileShaders() {
    
        let vertexShader = compileShader("SimpleVertex", shaderType: GLenum(GL_VERTEX_SHADER))
        let fragmentShader = compileShader("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! : \( String(UTF8String: message) ) ")
            exit(1);
        }
    
        glUseProgram(programHandle)
    
        .  .  .  .  .
        shaderPeakId = glGetUniformLocation(programHandle, "peakId")
    
        shaderWaveAmp = glGetUniformLocation(programHandle, "waveAmp");
    
        glEnableVertexAttribArray(positionSlot)
        glEnableVertexAttribArray(colorSlot)
    
        glUniform1f(shaderSceneWidth!,  Float(self.frame.size.width));
        glUniform1f(shaderSceneHeight!, Float(self.frame.size.height));
        glUniform1i(shaderPeaksTotal!,  GLint(total));
        glUniform1i(shaderPeakId!,      GLint(position));
    
    }
    

    为了渲染音频波,需要将以下值传递给着色器值:A)振幅(我从avaudioplayer获得-完美工作,并且对于我在 Controller 中创建的两个对象,我对两个不同的音轨具有不同的振幅)和B)波数(又名peakId /位置)。

    因此,对于第一个创建的对象(灰色),位置等于1,并且该波必须为红色,并放置在屏幕的左侧。对于第二个对象(黑色),位置为3,则波浪为蓝色,并放置在右侧。 /位置2用于屏幕中心,现在不使用/

    每次音频更新都会导致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)
    
            glVertexAttribPointer(positionSlot, 3, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(Vertex)), nil)
            glVertexAttribPointer(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)
    
            glVertexAttribPointer(positionSlot, 3, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(Vertex)), nil);
            glVertexAttribPointer(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);
    }
    

    使用print()函数登录:
    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
    

    我希望我将有两个矩形-一个灰色,左边有红色波浪,一个黑色,右边是蓝色。
    但是我有下一个麻烦!渲染在一个(最后一个) View 中进行,并顺序更改:

    ios - iOS。 OpenGL。同时几个 View-LMLPHP ios - iOS。 OpenGL。同时几个 View-LMLPHP

    请任何人!如何同时使用两个glView?
    或者,也许我需要在一个 View 中使用两个着色器?

    我想完成这个音频任务,并与大家分享。但是我还是不明白这个问题

    最佳答案

    在您发布的SoundWaveView类的代码中,它看起来像该 View 处理了上下文的初始化,上下文的帧缓冲区等等。由于您向两个 View 都发送了相同的EAGLContext,因此意味着正在初始化相同的上下文,然后很可能由第二个 View 重新初始化。这对我来说似乎不对。如果仅为另一个 View 创建单独的上下文,则实际上可能会很好地工作,并且在这两个 View 之间进行渲染时,GPU只会进行上下文切换,并将它们视为单独的应用程序。

    但这不是应该设计这种简单的应用程序的方式。如果要同时在屏幕上绘制两个对象,那当然并不意味着您需要两个单独的 View 。您将必须构建一个系统来处理从每个波形中获取的信息,并将其自动转换为适当的绘图调用。这将充当您的应用程序的迷你绘制引擎。使用这种方法,您甚至可以为更酷的技术和图形编写更多的支持……也许更多的波形,它们各自的不同纹理/颜色,炫酷效果等。

    07-26 09:17