在本次的系列文章中,我们将阐述如何使用PowerVR框架创建跨平台跨API的图形应用程序——所有均来自一组源代码文件!
本系列文章将分为以下几个部分:
? PowerVR框架: PVRApi Vulkan和OpenGL ES抽象层
? PowerVR框架:使用PVRApi编写可移植的Vulkan和OpenGL ES 3.0/3.1
? PowerVR框架:使用PVRAssets加载场景、纹理和着色器
? PowerVR框架:了解图像渲染纹理效果的障碍
让我们先从第一部分开始。
第一部分的重点是已清除的屏幕,如下所示:
虽然不是最高级的示例,但其引入了编写框架程序所需的第一个概念。
首先,让我们谈谈PowerVR框架的主旨及使用此框架的原因。
新框架设计的主旨是:
? 支持新的显式API,如Vulkan——展示其强大功率的同时又隐藏了其冗长性
? 继续支持OpenGL ES 3.x ——允许使用快速路径来尽可能地模拟显式API
? 一个源基地支持所有主要的平台——Android、iOS、Windows、Linux和OS X
最重要的是,这个框架使我们得以尽可能多地使用样本化代码来进行高层次的消除设计。
请关注“新PowerVR架构综述”一文获取更多信息,若不熟悉Vulkan请关注“Vulkan API的详细解读”一文。
现在,我们将创建第一个示例——Intro1ClearApi。
创建Intro1ClearApi将需要git、CMake 3.1 +和可以支持的IDE /平台。
以下平台已使用CMake 3.3.1进行测试,并使用了比较合适的SDK 16.1发行版PVRVFrame库:
? Visual Studio 14
? XCode – iOS 和OS X
? Android Ninja 和Visual Studio 14
? Ubuntu 14.04 Make
所有示例和CMake文件都托管在以下资源库的GitHub上:
PVRApiIntro
请参见GitHub页面,了解如何在支持平台上构建及运行Intro1ClearApi。GitHub页面还详细描述了CMake的构建过程。CMake文件是基于您自身项目框架的数据库。若您在创建示例中有任何疑问请在 PowerVR Support或PowerVR Forum上与我们联系。
让我们回顾下第一个概念,即通过Intro1ClearApi编写框架应用程序。所有的源代码均涵括在ClearAPI.cpp中。
编写框架应用程序,我们可以扩展pvr::Shell并实现以下切入点:
class MyApp : public pvr
{
public:
virtual pvr::Result::Enum initApplication(); // Perform non-graphics set-up - audio initialization etc
virtual pvr::Result::Enum initView(); // Graphics set-up - load textures, create command buffers etc
virtual pvr::Result::Enum renderFrame(); // Render frame called at VSync rate - submit command buffers etc
virtual pvr::Result::Enum releaseView(); // Graphics tear down - delete textures, command buffers etc
virtual pvr::Result::Enum quitApplication(); // Non-graphics tear down - close audio devices etc
};
initApplication()和quitApplication()——对于Intro1ClearAPI,我们可以在这两个函数时返回至pvr::Result::Success。这里没有非图像设置。
initView()——形成了Intro1ClearAPI的核心。在现代API如Vulkan中,我们想在主要渲染线程(renderFrame()函数)之外创建命令缓冲区。这时我们便可以使用第二个线程或者根据命令缓冲区的静态要求在initView()上完成。对于Intro1ClearAPI,我们在initView() 时准备所有命令缓冲区,即在交换链中为每一帧缓冲创建一个命令缓冲区。在renderFrame()中提交所有命令缓冲区。
pvr::Result::Enum OGLESIntroducingPVRApi::initView() {
onscreenFB = getGraphicsContext()->createOnScreenFboSet(); // This returns an array of our on-screen frame buffers. In OpenGL ES we just receive one.
// We then create a command buffer for each frame buffer
for (int i = 0 ; i < getSwapChainLength(); i++){
onscreenCBArray.add(getGraphicsContext()->createCommandBufferOnDefaultPool());
auto & cb = onscreenCBArray[i];
auto & frameBuffer = onscreenFB[i];
// We record a command buffer with a render pass that clears the screen for each frame buffer
cb->beginRecording();
cb->beginRenderPass(frameBuffer, pvr::Rectanglei(0, 0, getWidth(), getHeight()),false,
glm::vec4(123.0 / 255.0, 172.0 / 255.0, 189.0 / 255.0, 1.0));
cb->endRenderPass();
cb->endRecording();
}
return pvr::Result::Success;
};
renderFrame()——在这里,我们通过initView()为每个帧缓冲创建了一个命令缓冲区。renderFrame()以initView()命名,以VSync…率渲染框架。通过调用getSwapChainIndex(),可以确定交换链中接下来是哪些帧缓冲。然后再为帧缓冲提交相应的命令缓冲区——将我们的框架渲染至屏幕中。
pvr::Result::Enum OGLESIntroducingPVRApi::renderFrame(){
onscreenCBArray[getSwapChainIndex()]->submit();
return pvr::Result::Success;
}
评论
查看更多