Adreno GPU SDK例程分析(2)

一、简介
在上节中,我们介绍了与NDK和着色器相关的内容,SDK中对此提供了很多的便利,我们只要熟悉了SDK的框架流程,就可以很轻易的实现图案绘制。

二、例程分析
在Initialize函数中,此例程加载了Font、resource、texture等资源,同时调用Shader初始化函数对Shader进行了初始化。资源的加载过程中,我们这里主要分析一下它的流程:
首先在Scene.cpp中,调用了FrmFontGLES.cpp中的Create函数,来实现它的字体创建,首先他传入的为:m_Font.Create( “Samples/Fonts/Tuffy12.pak” );之后在Create函数中首先调用到的是FrmPackedResource.cpp中的LoadFromFile函数,如下:
m_ResourceGLES.LoadFromFile( strFontFileName );
之后通过GetData函数获取到font data:
FRM_FONT_FILE_HEADER_GLES* pFontData;
pFontData = (FRM_FONT_FILE_HEADER_GLES*)m_ResourceGLES.GetData( “FontData” );
接下来当然就是检查font data是否可用,并加载字体相关的Shader等:

m_nGlyphHeight = pFontData->nGlyphHeight;
m_pGlyphsGLES = pFontData->pGlyphs;

// Create the font texture
m_pTexture = m_ResourceGLES.GetTexture( “FontTexture” );
if( NULL == m_pTexture )
{
FrmLogMessage( “ERROR: CFrmFontGLES::Create( const CHAR* strFontFileName ) failed. - if( NULL == m_pTexture )”);
return FALSE;
}

// Compile the font shaders
if( FALSE == FrmCompileShaderProgram( g_strFontVertexShader, g_strFontFragmentShader, &m_hShader ) )
{
FrmLogMessage( “ERROR: CFrmFontGLES::Create( const CHAR* strFontFileName ) failed. - if( FALSE == FrmCompileShaderProgram( g_strFontVertexShader, g_strFontFragmentShader, &m_hShader ) )”);
return FALSE;
}

m_locVertexPos = glGetAttribLocation( m_hShader, “g_vVertexPos” );
m_locVertexColor = glGetAttribLocation( m_hShader, “g_vVertexColor” );
m_locVertexTex = glGetAttribLocation( m_hShader, “g_vVertexTex” );

m_locScale = glGetUniformLocation( m_hShader, “g_vScale” );
m_locOffset = glGetUniformLocation( m_hShader, “g_vOffset” );

这里的FrmCompileShaderProgram使用的是FrmShader.cpp中定义到的,这里的Shader是FrmFontGLES.cpp中实现的,如下:
const CHAR* g_strFontVertexShader =
“#version 300 es\n”
“uniform vec4 g_vScale; \n”
“uniform vec4 g_vOffset; \n”
“in vec2 g_vVertexPos; \n”
“in vec4 g_vVertexColor; \n”
“in vec2 g_vVertexTex; \n”
“out vec4 g_vColor; \n”
“out vec2 g_vTexCoord; \n”
" \n"
“void main() \n”
“{ \n”
" // Transform the position \n"
" vec2 vVertex = g_vVertexPos * g_vScale.xy + g_vOffset.xy; \n"
" gl_Position = vec4( vVertex, 0.0, 1.0 ); \n"
" \n"
" // Pass through color and texture coordinates \n"
" g_vColor = g_vVertexColor; \n"
" g_vTexCoord = g_vVertexTex * g_vScale.zw + g_vOffset.zw; \n"
“} \n”;

然后在FrmShader.cpp中设置着色器程序。到这里,这些与字体相关的资源加载就已经完成了。

接下来就是图像的绘制工作了,这里我们需要绑定Buffer:
FrmSetVertexBuffer( pMesh->m_hVertexBuffer );
FrmSetVertexLayout( pMesh->m_VertexLayout, pMesh->m_nVertexSize );
FrmSetIndexBuffer( pMesh->m_hIndexBuffer );
然后是设置Shader中的变量,以及纹理等,最后是Draw:
FrmDrawIndexedVertices( pSubset->m_nPrimType, pSubset->m_nNumIndices,
pMesh->m_nIndexSize, pSubset->m_nIndexOffset );

这些实现统统都在FrmResourceGLES.h中,当然我们也可以自己动手来实现都是可以的。这里就有问题了,设置buffer的函数我们直接放在了Draw函数里面,而它有肯定是要被循环调用的,我们是否可以把它提取出来,那么我们接着往下走。
在Render函数中:
VOID CSample::Render()
{
// Set default states
glEnable( GL_DEPTH_TEST );
glEnable( GL_CULL_FACE );

// Clear the backbuffer and depth-buffer
glClearColor( 0.2f, 0.2f, 0.6f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );

// Draw the skinned mesh
DrawSkinnedMesh( m_Mesh[m_nActiveMesh].m_pFrames[0].m_pMesh,
m_hSkinningShader, &m_SkinningConstants,
m_matView, m_matProj );

// Update the timer
m_Timer.MarkFrame();

// Render the user interface
m_UserInterface.Render( m_Timer.GetFrameRate() );
}

我们可以看到最后有一个UserInterface.Render函数,这里有这样一个调用关系。在这个Render函数里面,它会绘制Background和Font,而这些都拥有自己独立的着色器程序,那么我们就可以发现,在最后这里,其实也就是整个框架最后的绘制部分,存在多个着色器程序的同时,也会存在着其相应的buffer。因此,为了便于理解,背景和字体绘制这块,它们也都是每绘制一次便初始化一次其对应的buffer。
最终将会在我们的测试手机上呈现出绘制出来的图案及Logo等。

三、总结
好了,到这里大家应该都对这个框架有了简单的了解了。从始至终,我们只是调用了一下SDK提供的内容,完全不需要去实现复杂的着色器程序,最终却能够绘制出大量复杂多变的图像出来,这就是它的魅力所在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值