我知道使用glGet获取各种参数.我需要知道如何获取当前的GL_FRAMEBUFFER_OES并获取GLuint类型的帧缓冲区ID.
我需要使用renderToTexture.当切换回普通帧缓冲时,这将使其中一个类代码更容易.
我正在使用opengl es 2.0编写Android 2d游戏.在我将精灵绘制到后备缓冲区后,我将灯光绘制到FBO并尝试将其再次混合到后台缓冲区.当我将FBO绘制到帧缓冲区时,即使没有任何颜色也没有任何颜色,帧率在三星Galaxy w上从60降到30(它有一个adreno 205作为gpu).我到处搜索并尝试了一切,即使我在场景中绘制了一个精灵并将一个透明的FBO纹理混合到帧速率下降的屏幕上.我在手机上尝试了其他带有灯光效果的游戏,它们运行良好,几乎所有游戏都可以在手机上运行,我相信它们也使用了帧缓冲.在Galaxy SII(mali 400 gpu)运行正常,我对opengl很新,所以我相信我在某个地方犯了错误,我分享了我的代码.
// Create a framebuffer and renderbuffer
GLES20.glGenFramebuffers(1, fb, offset);
GLES20.glGenRenderbuffers(1, depthRb, offset);
// Create a texture to hold the frame buffer
GLES20.glGenTextures(1, renderTex, offset);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[offset]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
screenWidth, screenHeight, 0,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
null);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_LINEAR);
//bind renderbuffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[offset]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16,
screenWidth, screenHeight);
// bind the framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[offset]);
// specify texture as color attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, renderTex[offset], …Run Code Online (Sandbox Code Playgroud) 当我将 MTKView 的内容捕获到 UIImage 中时,生成的图像看起来有质的不同,如下所示:
我用来生成 UIImage 的代码如下:
let kciOptions = [kCIContextWorkingColorSpace: CGColorSpace(name: CGColorSpace.sRGB)!,
kCIContextOutputPremultiplied: true,
kCIContextUseSoftwareRenderer: false] as [String : Any]
let lastDrawableDisplayed = self.currentDrawable! // needed to hold the last drawable presented to screen
drawingUIView.image = UIImage(ciImage: CIImage(mtlTexture: lastDrawableDisplayed.texture, options: kciOptions)!)
Run Code Online (Sandbox Code Playgroud)
由于我没有修改 ciImage 方向 (.orientation(CGImagePropertyOrientation.downMirrored)),因此生成的图像是颠倒的,如上图所示。我保持镜像方向不变,以便我可以指出两个图像捕获之间的颜色差异。
无论我如何更改 kciOptions 参数(例如,甚至将色彩空间更改为灰度),我都没有看到生成的 UIImage 有任何变化,它看起来比原始图像更暗/不饱和。有人对我如何准确地将我在 MTKView 上绘制的内容捕获到 UIImage 有任何建议吗?任何建议将不胜感激。
以下是我可能证明相关的 MTKView 设置:
let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
renderPipelineDescriptor.vertexFunction = vertexProgram
renderPipelineDescriptor.sampleCount = self.sampleCount
renderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat.bgra8Unorm
renderPipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
renderPipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
renderPipelineDescriptor.colorAttachments[0].alphaBlendOperation = …Run Code Online (Sandbox Code Playgroud) 我试图(徒劳地)使用OpenGL和NVIDIA的Cg着色器系统设置MRT,最终目的是推迟渲染。我已经成功为单个目标同时使用了着色器和“渲染到纹理”,但是当我尝试将一个对象渲染到多个渲染目标时,它在任何一个中都无法显示。
我以以下方式设置帧缓冲区对象:
// Initialize textures
// (I'll spare you the code since I've done that without issues)
// Initialize the FBO
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenRenderbuffers(1, &depthBuff);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuff);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuff);
// -snip-
// Bind each texture we want to use to the FBO at rtNum
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + rtNum,
GL_TEXTURE_2D, tex->getID(), 0);
// Check to make sure we're good to go
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
throw Exceptions::GLException("Frame buffer object is not complete.", …Run Code Online (Sandbox Code Playgroud) 最终编辑:
已解决...只需深入了解 alpha 混合如何工作。我应该有: oBlendStateDesc.RenderTarget[a].DestBlendAlpha = D3D11_BLEND_ZERO; ...设置为 D3D11_BLEND_ONE 以保留 Alpha。
当渲染到后台缓冲区时,问题不会被注意到,因为颜色混合正常,这就是最终输出。当渲染到纹理时,同样的情况也适用,然后将纹理渲染到后缓冲区,不正确的 alpha 会导致错误地将纹理混合到后缓冲区。
然后我遇到了另一个问题,阿尔法似乎在减少。这是因为颜色混合了两次,例如......
Source.RBGA = 1.0f, 0.0f, 0.0f, 0.5f
Dest.RGBA = 0.0f, 0.0f, 0.0f, 0.0f
Run Code Online (Sandbox Code Playgroud)
渲染成纹理...
Result.RGB = Source.RBG * Source.A + Dest.RGB * (1 - Source.A) = 0.5f, 0.0f, 0.0f
Result.A = Source.A * 1 + Dest.A * 1 = 0.5f
Run Code Online (Sandbox Code Playgroud)
现在...
Source.RBGA = 0.5f, 0.0f, 0.0f, 0.5f
Dest.RGBA = 0.0f, 0.0f, 0.0f, 0.0f
Run Code Online (Sandbox Code Playgroud)
渲染到后台缓冲区...
Result.RGB = Source.RBG * Source.A + Dest.RGB * (1 - Source.A) = …Run Code Online (Sandbox Code Playgroud) 现在,这是一种非常奇怪的行为。
TL;DR——在渲染到纹理设置中,在调整窗口(帧缓冲区 0)大小时,只有下一次调用glClear(GL_COLOR_BUFFER_BIT)绑定帧缓冲区 0(窗口的客户区)会给出GL_OUT_OF_MEMORY,仅在两个中的一个GPU,但是渲染仍然正确且正确地进行。
现在,所有重要的细节:
所以这是在带有两个 GPU 的 Vaio Z 上(可以通过机器上的物理切换按钮切换到):
OpenGL 4.2.0 @ NVIDIA Corporation GeForce GT 640M LE/PCIe/SSE2(GLSL:4.20 NVIDIA 通过 Cg 编译器)
OpenGL 4.0.0 - Build 9.17.10.2867 @ Intel Intel(R) HD Graphics 4000 (GLSL: 4.00 - Build 9.17.10.2867)
我的程序在使用 GLFW 64 位的 Win 7 64 位下的 Go 1.0.3 64 位。
我有一个相当简单直接的渲染到纹理“迷你管道”。首先,普通 3D 几何体使用最简单的着色器(没有照明,什么都没有,只有纹理三角形网格,它们只是一些立方体和平面)渲染到具有深度/模板渲染缓冲区作为深度/模板附件和texture2D 作为颜色附件。对于纹理,所有过滤都被禁用,mip-maps 也是如此。
然后我渲染一个全屏四边形(实际上是一个“超大”全屏三边形),只是从带有 texelFetch(tex, gl_FragCoord.xy, 0) 的所述帧缓冲区纹理(颜色附件)中采样,因此不使用包装。
两个 GPU 都可以很好地呈现这一点,无论是在我强制执行核心配置文件还是不执行核心配置文件时。没有为此报告任何 GL 错误,所有渲染也按预期进行。除非我在使用 Intel HD 4000 GPU 的 GL 4.0 渲染器(在 Core …
这是我对渲染多个纹理的基本步骤的理解。
1) 绑定要渲染的着色器位置
m_uihDiffuseMap = glGetUniformLocation( m_iShaderProgramHandle, "diffuseMap" );
if( m_uihDiffuseMap != -1 )
glUniform1i( m_uihDiffuseMap, 0 );
m_uihNormalMap = glGetUniformLocation( m_iShaderProgramHandle, "normalMap" );
if( m_uihNormalMap != -1 )
glUniform1i( m_uihNormalMap, 1 );
Run Code Online (Sandbox Code Playgroud)
2)绑定到你想要渲染的内容
glBindFramebuffer( GL_FRAMEBUFFER, m_uifboHandle );
//diffuse texture binding
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_uiTextureHandle1, 0);
//normal texture binding
(or GL_COLOR_ATTACHMENT1)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+1, m_uiTextureHandle2, 0);
Run Code Online (Sandbox Code Playgroud)
3)清除缓冲区并指定要绘制到的缓冲区
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
Run Code Online (Sandbox Code Playgroud)
4) 设置着色器程序进行渲染
glUseProgram( m_uiShaderProgramHandle ); …Run Code Online (Sandbox Code Playgroud) 我正在尝试实现两个不同的,CAMetalLayers并使用一个MTLRenderCommandEncoder将相同的场景渲染到两个层(OS X 的金属)。
为此,我尝试创建一个MTLRenderPassDescriptor并将两个图层的纹理附加到其颜色附件。我的渲染方法如下所示:
- (void)render {
dispatch_semaphore_wait(_inflight_semaphore, DISPATCH_TIME_FOREVER);
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
__block dispatch_semaphore_t block_sema = _inflight_semaphore;
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
dispatch_semaphore_signal(block_sema);
}];
MTLRenderPassDescriptor *renderPass = [MTLRenderPassDescriptor renderPassDescriptor];
for (int i = 0; i < [_metalLayers count]; i++) {
_metalDrawables[i] = [_metalLayers[i] nextDrawable];
renderPass.colorAttachments[i].texture = _metalDrawables[[_metalDrawables count] - 1].texture;
renderPass.colorAttachments[i].clearColor = MTLClearColorMake(0.5, 0.5, (float)i / (float)[_metalLayers count], 1);
renderPass.colorAttachments[i].storeAction = MTLStoreActionStore;
renderPass.colorAttachments[i].loadAction = MTLLoadActionClear;
}
id<MTLRenderCommandEncoder> commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPass];
[commandEncoder setRenderPipelineState:_pipeline]; …Run Code Online (Sandbox Code Playgroud) 我正在开发一个绘画程序,通过 MTKView 绘制交互式笔画。如果我将 renderPassDescriptor loadAction 设置为“clear”:
renderPassDescriptor?.colorAttachments[0].loadAction = .clear
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,帧缓冲区显示 的最新内容renderCommandEncoder?.drawPrimitives,在本例中是笔触的前缘。
如果我将 loadAction 设置为“加载”:
renderPassDescriptor?.colorAttachments[0].loadAction = .load
Run Code Online (Sandbox Code Playgroud)
帧缓冲区疯狂地闪烁,并显示出我刚刚绘制的斑驳痕迹。我现在明白闪烁可能是由 MTKView 的默认三重缓冲造成的。因此,每次写入 currentDrawable 时,我可能会写入 3 个循环缓冲区之一。如果我错了,请纠正我。
我的问题是,我需要做什么才能绘制干净的笔触而不像现在那样帧缓冲区闪烁?换句话说,有没有办法让主缓冲区使用 commandEncoder 的最新内容进行更新?
在交换链中绘制几何图形的现有渲染器中,我需要在纹理中渲染该几何图形的某些部分,其他部分必须保留在屏幕上。所有几何图形都记录到一个命令缓冲区中。我不需要每次都渲染这个纹理。我创建了目标图像、图像视图和帧缓冲区,但我不知道现在该怎么办。我认为我不需要特定的管道,也不需要新的特定描述符集,因为所有内容都正确呈现在屏幕上。我是否需要另一个渲染通道、子通道或其他任何东西?
framebuffer ×3
metal ×3
opengl ×3
c++ ×2
metalkit ×2
swift ×2
2d ×1
android ×1
buffer ×1
cg ×1
cocoa ×1
directx-11 ×1
glsl ×1
go ×1
iphone ×1
objective-c ×1
opengl-es ×1
rendertarget ×1
shader ×1
uiimageview ×1
vulkan ×1