|
|
发表于 2007-5-18 10:56:00
|
显示全部楼层
Re: 如何让CPU与GPU同步?
并不是Lock愈小愈好,应当根据不同的硬件测试获得一个最佳的buffer大小,具体可以进一步参考Nvidia上相关性能的讨论部分,
某位兄弟提问要什么样的机器才能支持大规模的比如万级别,十万级别粒子数?
说明他并没有真正了解为什么要采用这种渲染的内在意义,
在很普通的vs 1.0 ps1.1的显卡上我都能渲染好几万级别的粒子那
下面的代码出至Introduction to 3D Game Programming with DirectX 9.0
供大家学习
_vbSize—The number of particles that our vertex buffer can hold
at a given time. This value is independent of the number of particles
in the actual particle system.
_vbOffset—This variable marks the offset (measured in particles,
not bytes) into the vertex buffer into which we should begin
copying the next batch of particles. For instance, if batch one
resides in entries 0 to 499 of the vertex buffer, the offset to start
copying batch two would be 500.
_vbBatchSize—The number of particles that we define to be in a
batch.
void PSystem::render()
{
if( !_particles.empty() )
{
// set render states
preRender();
device->SetTexture(0, _tex);
_device->SetFVF(Particle::FVF);
_device->SetStreamSource(0, _vb, 0, sizeof(Particle));
// start at beginning if we're at the end of the vb
if(_vbOffset >= _vbSize)
_vbOffset = 0;
Particle* v = 0;
_vb->Lock(
_vbOffset * sizeof( Particle ),
_vbBatchSize * sizeof( Particle ),
(void**)&v,
_vbOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
DWORD numParticlesInBatch = 0;
//
// Until all particles have been rendered.
//
std::list<Attribute>::iterator i;
for(i = _particles.begin(); i != _particles.end(); i++)
{
if( i->_isAlive )
{
//
// Copy a batch of the living particles to the
// next vertex buffer segment
//
v->_position = i->_position;
v->_color = (D3DCOLOR)i->_color;
v++; // next element;
numParticlesInBatch++; //increase batch counter
// is this batch full?
if(numParticlesInBatch == _vbBatchSize)
{
//
// Draw the last batch of particles that was
// copied to the vertex buffer.
//
_vb->Unlock();
_device->DrawPrimitive(
D3DPT_POINTLIST,
_vbOffset,
_vbBatchSize);
//
// While that batch is drawing, start filling the
// next batch with particles.
//
// move the offset to the start of the next batch
_vbOffset += _vbBatchSize;
// don't offset into memory thats outside the vb's
// range. If we're at the end, start at the beginning.
if(_vbOffset >= _vbSize)
_vbOffset = 0;
_vb->Lock(
_vbOffset * sizeof( Particle ),
_vbBatchSize * sizeof( Particle ),
(void**)&v,
_vbOffset ? D3DLOCK_NOOVERWRITE :
D3DLOCK_DISCARD);
numParticlesInBatch = 0; // reset for new batch
}//end if
}//end if
}//end for
_vb->Unlock();
// it’s possible that the LAST batch being filled never
// got rendered because the condition
// (numParticlesInBatch == _vbBatchSize) would not have
// been satisfied. We draw the last partially filled batch now.
if( numParticlesInBatch )
{
_device->DrawPrimitive(
D3DPT_POINTLIST,
_vbOffset,
numParticlesInBatch);
}
// next block
_vbOffset += _vbBatchSize;
postRender();
}//end if
}// end render() |
|