体积阴影GPU实现--数据预处理

HRESULT CShadow::Create( LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXMESH pMesh )
{
  BASEMESHVERTEX*   pVertices;
  WORD*             pIndices;
  EdgeMap           edgeMap; //sharing edges
  EdgeMap::iterator edgeMapIter;
  DWORD             dwNumSavedEdges = 0L; // No of coplanar edges optimized
  DWORD             dwI;


  ShadowVertices    shadowVerticesVector;  //存放网格预处理之后,添加了退化四边形后的顶点数组
  ShadowIndices     shadowIndicesVector; //同上,索引数组


  // Copy pointer to d3d device
  if ( pd3dDevice )
m_pd3dDevice = pd3dDevice;
  else
return E_FAIL;


  // Lock the geometry buffers
  pMesh->LockVertexBuffer( D3DLOCK_READONLY, (VOID**)&pVertices );
  pMesh->LockIndexBuffer( D3DLOCK_READONLY, (VOID**)&pIndices );
  DWORD dwNumSourceVertices     = pMesh->GetNumVertices();
  DWORD dwNumFaces              = pMesh->GetNumFaces();
  
  // Step thru all faces
  for ( DWORD faceIndex=0; faceIndex<dwNumFaces; faceIndex++ )
  {
    WORD wIndex0 = pIndices[3*faceIndex+0];
    WORD wIndex1 = pIndices[3*faceIndex+1];
    WORD wIndex2 = pIndices[3*faceIndex+2];


    D3DXVECTOR3 v0 = pVertices[wIndex0].p;
    D3DXVECTOR3 v1 = pVertices[wIndex1].p;
    D3DXVECTOR3 v2 = pVertices[wIndex2].p;


    // Compute face normal
    D3DXVECTOR3 faceNormal;
    D3DXVec3Cross( &faceNormal, &( v2 - v0 ), &( v1 - v0 ) );
    D3DXVec3Normalize( &faceNormal, &faceNormal );


    // Create shadow mesh vertices for current face
    SHADOWMESHVERTEX shadowVertices[3];
    for ( DWORD vertIndex = 0; vertIndex < 3; vertIndex++ )
    {
shadowVertices[vertIndex].p = pVertices[pIndices[3*faceIndex+vertIndex]].p;
      // There was a time when a typo (.p instead of .n) caused me 6 hours...
shadowVertices[vertIndex].n = faceNormal;
    }


    // Search edgeMap for a possible partner edge to the current edge 
    // e.g. Equivalent positions
    EdgePositions edgePositions[3];
    EdgeData sharedEdgesData[3];
    EdgePositions edgeToFind;
    BOOL edgeFound[3];
    BOOL quadRequired[3];
//检查当前面的每一边,是否为共享边,如果是,检查法线是否平行,不平行的才需要插入退化四边形
    for ( DWORD edgeIndex = 0; edgeIndex < 3; edgeIndex++ )
    {
      edgePositions[edgeIndex].p0 = shadowVertices[edgeIndex].p;
      edgePositions[edgeIndex].p1 = shadowVertices[( edgeIndex + 1 ) % 3].p;


      // Find shared edge with reverse vertices
      edgeToFind.p0 = edgePositions[edgeIndex].p1;
      edgeToFind.p1 = edgePositions[edgeIndex].p0;
      edgeMapIter = edgeMap.find( edgeToFind );


      // Did we find it?
      if ( edgeMapIter != edgeMap.end() ) // Found!
      {
edgeFound[edgeIndex] = TRUE;
sharedEdgesData[edgeIndex] = edgeMapIter->second;
edgeMap.erase( edgeMapIter );


// We can optimize away coplanar shared edges. e.g. their normals are 
// almost parallel
if ( ( D3DXVec3Dot( &faceNormal, &sharedEdgesData[edgeIndex].n0 ) ) < 
              MERGE_COS_ANGLE_PROXIMITY )
{
quadRequired[edgeIndex] = TRUE;
}
else
{
quadRequired[edgeIndex] = FALSE;
dwNumSavedEdges++;
}
      }
      else  // New
 {
edgeFound[edgeIndex] = FALSE;
 }
    }


// Selected index of vertices
//如果当前边是共享边,已经被优化(不需要加入退化四边形),直接将它的顶点和索引数据放入shadowVerticesVector shadowIndicesVector
//如果当前边不是共享边(新发现的),或者需要加入退化四边形,添加新的顶点和索引数据
    WORD index[3]; 
    for ( DWORD vertIndex=0; vertIndex<3; vertIndex++ )
    {
// Vertex creation
DWORD edgeIndex0  = vertIndex;              // 0, 1, 2
DWORD edgeIndex1  = ( vertIndex + 2 ) % 3;  // 2, 0, 1
// We check whether the current edge had been optimized away
// If it is, we just need to copy the index from the shared edge since 
// the current vertex is gone
if ( ( edgeFound[edgeIndex0] ) && ( !quadRequired[edgeIndex0] ) )
{
index[vertIndex] = sharedEdgesData[edgeIndex0].i1;
}
else if ( ( edgeFound[edgeIndex1] ) && ( !quadRequired[edgeIndex1] ) )
{
index[vertIndex] = sharedEdgesData[edgeIndex1].i0;
}
else  // No optimization, new vertex OR degenerate quad required
{
// Current size = index
index[vertIndex] = (WORD)shadowVerticesVector.size();
// Store current vertex
shadowVerticesVector.push_back( shadowVertices[vertIndex] );
}


// Index creation
shadowIndicesVector.push_back( index[vertIndex] );
}


    // Time to create the degenerate quads
    for ( DWORD edgeIndex = 0; edgeIndex < 3; edgeIndex++ )
    {
EdgeData edgeData;
edgeData.i0   = index[edgeIndex];             // 0, 1, 2
edgeData.i1   = index[( edgeIndex + 1 ) % 3]; // 1, 2, 0
edgeData.n0   = faceNormal;
if ( edgeFound[edgeIndex] ) // Shared edge found
{
// Handle 3 cases: Insert full quad, insert left side tri or insert 
// right side tri
// If current edge had NOT been optimized away
if ( ( sharedEdgesData[edgeIndex].i0 != edgeData.i1 ) && 
( sharedEdgesData[edgeIndex].i1 != edgeData.i0 ) )
{
shadowIndicesVector.push_back( edgeData.i1 );
shadowIndicesVector.push_back( edgeData.i0 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i0 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i1 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i0 );
shadowIndicesVector.push_back( edgeData.i0 );
}
else if ( sharedEdgesData[edgeIndex].i1 != edgeData.i0 )
{
shadowIndicesVector.push_back( edgeData.i1 );
shadowIndicesVector.push_back( edgeData.i0 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i1 );
}
else if( sharedEdgesData[edgeIndex].i0 != edgeData.i1 )
{
shadowIndicesVector.push_back( edgeData.i1 );
shadowIndicesVector.push_back( edgeData.i0 );
shadowIndicesVector.push_back( sharedEdgesData[edgeIndex].i0 );
}
// All other cases meant that the current edge had been optimized away 
// and only the shared edge is left. The shared edge is left alone with 
// additional degenerate triangles added
}
else  // New edge
{
edgeMap[edgePositions[edgeIndex]] = edgeData;
}
}
  }


  // Gather some stats
  m_dwVertexBufferSize  = (DWORD)shadowVerticesVector.size();
  m_dwIndexBufferSize   = (DWORD)shadowIndicesVector.size();
  
  // ********** Create vertex and index buffers **********
  // Create index buffer
  if ( FAILED( m_pd3dDevice->CreateIndexBuffer( m_dwIndexBufferSize * 
        sizeof( WORD ), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, 
            &m_pIndexBuffer, NULL ) ) )
  {
    OutputDebugString( "Index buffer creation failed!\n" );
    return E_FAIL;
  }


  // Lock index buffer
  WORD* pLockedIndexBuffer;
  m_pIndexBuffer->Lock( 0, m_dwIndexBufferSize * sizeof( WORD ), 
        (VOID**)&pLockedIndexBuffer, 0 );


  // Fill locked index buffer with data
  IndexIter indexIter;
  for ( indexIter = shadowIndicesVector.begin(), dwI = 0; 
        indexIter != shadowIndicesVector.end(); ++indexIter, dwI++ )
  {
    pLockedIndexBuffer[dwI] = (WORD)*indexIter;
  }
  m_pIndexBuffer->Unlock();


  // Create vertex buffer
  if ( FAILED( m_pd3dDevice->CreateVertexBuffer( m_dwVertexBufferSize * 
        sizeof( SHADOWMESHVERTEX ), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, 
            &m_pVertexBuffer, NULL ) ) )
  {
    OutputDebugString( "Vertex buffer creation failed!\n" );
    return E_FAIL;
  }


  // Lock vertex buffer
  SHADOWMESHVERTEX* pLockedVertexBuffer;
  VertexIter vertexIter;
  m_pVertexBuffer->Lock( 0, m_dwVertexBufferSize * sizeof( SHADOWMESHVERTEX ), 
        (VOID**)&pLockedVertexBuffer, 0 );
  // Fill locked vertex buffer with data
  for ( vertexIter=shadowVerticesVector.begin(), dwI=0; 
        vertexIter != shadowVerticesVector.end(); ++vertexIter, dwI++ )
  {
    pLockedVertexBuffer[dwI] = *vertexIter;
  }

  m_pVertexBuffer->Unlock();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt是一个跨平台的应用程序开发框架,可以用于构建图形用户界面(GUI)和用于非GUI应用程序的扩展库。GPU是图形处理单元的缩写,用于加速图形和计算任务。而零拷贝(Zero-Copy)是一种内存管理技术,它可以减少数据在不同设备之间的复制次数来提高性能。 在Qt中,GPU的零拷贝主要用于加速图形渲染和处理。传统上,绘制和渲染GUI元素需要将数据从主机内存(CPU)复制到GPU内存,这会导致额外的数据传输时延和内存使用。而使用GPU的零拷贝技术,可以直接在主机内存和GPU内存之间共享数据,避免复制操作,从而减少了内存使用和数据传输的开销,提高了图形渲染的性能。 Qt提供了一些方法来实现零拷贝操作。例如,可以使用QOpenGLTexture类在Qt中创建和管理纹理对象,然后将数据直接传输到纹理对象中,而不需要进行额外的复制操作。此外,Qt还提供了与OpenGL集成的功能,可以在GPU上进行图形渲染和计算,进一步提高绘制和渲染性能。 总的来说,Qt GPU零拷贝是一种通过减少CPU和GPU之间的数据复制来提高图形渲染和处理性能的技术。通过在Qt中集成GPU和使用零拷贝技术,可以更高效地利用图形处理能力,提供更流畅和响应快速的用户界面体验。 ### 回答2: Qt的GPU零拷贝是指在使用Qt框架进行图形处理时,通过充分利用现代GPU的功能,实现在CPU和GPU之间进行无拷贝传输数据的技术。 在传统的图形处理流程中,CPU负责将图形数据从内存中复制到GPU的显存中,再由GPU进行处理和渲染。这种方式在大规模图形数据处理时会产生大量的数据复制,造成性能上的浪费。而Qt的GPU零拷贝技术则能够避免这种浪费,提高图形处理的效率。 Qt的GPU零拷贝技术通过利用现代GPU的高速内存访问能力,将数据直接从CPU内存传输到GPU内存,而不需要进行数据拷贝。这样可以减少数据的复制次数,节省了时间和资源。 通过Qt的GPU零拷贝技术,可以在图形数据传输和处理过程中减少内存带宽消耗,提高系统的响应速度和性能,特别是在大规模数据处理和复杂图形场景下。这对于实时图形处理、游戏开发、虚拟现实等领域都具有重要意义。 总之,Qt的GPU零拷贝技术通过充分利用GPU的特性,实现了在CPU和GPU之间进行图形数据传输的无拷贝处理,提高了系统的图形处理效率和性能。 ### 回答3: qt gpu zero-copy是一种用于在Qt图形用户界面框架中实现零拷贝(Zero-copy)的技术。零拷贝是指在数据传输过程中避免对数据进行不必要的复制或移动,以提高数据传输的效率。 在使用Qt进行图形渲染时,通常需要将图像数据从CPU传输到GPU进行处理。传统的方式是通过拷贝数据到GPU的内存空间中,然后再进行处理。而使用Qt gpu zero-copy技术,可以直接将数据从CPU内存中传输到GPU内存中,避免了不必要的数据拷贝操作,提高了图像处理的效率。 Qt gpu zero-copy技术通过使用QOpenGLTexture将图像数据直接映射到GPU内存中实现零拷贝。通过这种方式,可以避免将数据从CPU内存复制到GPU内存的过程,减少了数据传输的延迟和带宽占用。 使用Qt gpu zero-copy技术可以在一定程度上提高图形渲染的性能和效率,特别是对于需要频繁传输大量图像数据的应用程序,如图形编辑器、游戏等。同时,这项技术还能减少内存的占用,提高系统的整体性能和响应速度。 总之,Qt gpu zero-copy是一种通过直接将图像数据从CPU传输到GPU内存来实现零拷贝的技术。它可以提高图形渲染的效率和性能,减少数据传输的延迟和带宽占用,同时降低内存占用,提高系统的整体性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值