在我询问有关filling space between two curve lines with gradient的前两天。
从那以后,我在代码中做了很多更改-现在我正在使用着色器。结果几乎是我所需要的。但!同样,我在一个 Controller 中同时使用多个OpenGL View 时遇到问题,但它们必须彼此绝对独立。
因此,由于raywenderlich.com和code example from bradley令人难以置信的教程,我有了下一种情况:
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 中进行,并顺序更改:
请任何人!如何同时使用两个glView?
或者,也许我需要在一个 View 中使用两个着色器?
我想完成这个音频任务,并与大家分享。但是我还是不明白这个问题
最佳答案
在您发布的SoundWaveView类的代码中,它看起来像该 View 处理了上下文的初始化,上下文的帧缓冲区等等。由于您向两个 View 都发送了相同的EAGLContext,因此意味着正在初始化相同的上下文,然后很可能由第二个 View 重新初始化。这对我来说似乎不对。如果仅为另一个 View 创建单独的上下文,则实际上可能会很好地工作,并且在这两个 View 之间进行渲染时,GPU只会进行上下文切换,并将它们视为单独的应用程序。
但这不是应该设计这种简单的应用程序的方式。如果要同时在屏幕上绘制两个对象,那当然并不意味着您需要两个单独的 View 。您将必须构建一个系统来处理从每个波形中获取的信息,并将其自动转换为适当的绘图调用。这将充当您的应用程序的迷你绘制引擎。使用这种方法,您甚至可以为更酷的技术和图形编写更多的支持……也许更多的波形,它们各自的不同纹理/颜色,炫酷效果等。