我有一个2D照明引擎,可以将游戏场景渲染到后台缓冲区,将光照贴图渲染为纹理,然后将纹理渲染到具有混合状态的后台缓冲区 我遇到的问题是每次我在渲染光线时进行绘制调用以添加到光照贴图时,它会完全替换纹理中的所有数据,包括其宽度和高度 例如,假设我使用黑色填充整个光照贴图纹理的Draw调用,当我进行另一个Draw调用以向纹理渲染光精灵时,整个纹理将被该单个精灵替换,并且它也会调整大小 可能这实际上并不是正在发生的事情,但是来自相当多的测试的所有证据都表明了这一点
我想做的是将我的光照精灵渲染到我的光照贴图纹理,就像我将对象精灵渲染到后台缓冲区一样,每次连续的Draw调用只会在其他任何东西上添加新的精灵。在那里,只替换某些像素 我不相信这是一个混合状态问题,因为我使用相同的渲染到后台缓冲区和光照贴图,后台缓冲区渲染工作得很好 请提供一个解释,说明正在进行的操作以及如何使此过程功能正如我所描述的那样
以下是设置:
// Lighting
ZeroMemory( &blendDesc, sizeof( blendDesc ) );
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_DEST_COLOR;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
d3dDevice_->CreateBlendState( &blendDesc, &lightingBlendState_ );
float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
// Light map and render target view
DXGI_SAMPLE_DESC sampleDesc = {
1,
0
};
D3D11_TEXTURE2D_DESC texDesc = {
1024,
768,
1,
1,
DXGI_FORMAT_R32G32B32A32_FLOAT,
sampleDesc,
D3D11_USAGE_DEFAULT,
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
NULL,
NULL
};
d3dDevice_->CreateTexture2D( &texDesc, NULL, ( ID3D11Texture2D** )&lightMap_ );
D3D11_RENDER_TARGET_VIEW_DESC renderDesc = {
DXGI_FORMAT_R32G32B32A32_FLOAT,
D3D11_RTV_DIMENSION_TEXTURE2D,
{ 0 },
};
d3dDevice_->CreateRenderTargetView( lightMap_, &renderDesc, &lightMapTarget_ );
D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesc = {
DXGI_FORMAT_R32G32B32A32_FLOAT,
D3D11_SRV_DIMENSION_TEXTURE2D,
0,
1
};
d3dDevice_->CreateShaderResourceView( lightMap_, &resourceDesc, &lightMapResource_ );
这是渲染:
d3dContext_->OMSetRenderTargets( 1, &lightMapTarget_, NULL );
colorMap = dxiSprites_[kBlackSprite].GetShaderResourceView( );
d3dContext_->PSSetShaderResources( 0, 1, &colorMap );
spritePtr = 0;
HRESULT d3dResult = d3dContext_->Map( vertexBufferText_, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapResource );
spritePtr = ( VertexPos* )mapResource.pData;
spritePtr[0].pos = XMFLOAT3( 1, -1, 0 );
spritePtr[1].pos = XMFLOAT3( -1, -1, 0 );
spritePtr[2].pos = XMFLOAT3( -1, 1, 0 );
spritePtr[3].pos = XMFLOAT3( -1, 1, 0 );
spritePtr[4].pos = XMFLOAT3( 1, 1, 0 );
spritePtr[5].pos = XMFLOAT3( 1, -1, 0 );
spritePtr[0].tex0 = XMFLOAT2( 1, 0 );
spritePtr[1].tex0 = XMFLOAT2( 0, 0 );
spritePtr[2].tex0 = XMFLOAT2( 0, 1 );
spritePtr[3].tex0 = XMFLOAT2( 0, 1 );
spritePtr[4].tex0 = XMFLOAT2( 1, 1 );
spritePtr[5].tex0 = XMFLOAT2( 1, 0 );
d3dContext_->Unmap( vertexBufferText_, 0 );
d3dContext_->Draw( 6, 0 );
stride = sizeof( VertexPos );
offset = 0;
d3dContext_->IASetInputLayout( inputLayout_ );
d3dContext_->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
d3dContext_->VSSetShader( solidColorVS_, 0, 0 );
d3dContext_->PSSetShader( solidColorPS_, 0, 0 );
d3dContext_->PSSetSamplers( 0, 1, &colorMapSampler_ );
for( int i = kNumberOfSprites; i < kNumberOfLights + kNumberOfSprites; i++ )
{
ID3D11Buffer* vertexBuffer = dxiSprites_[i].GetVertexBuffer( );
ID3D11ShaderResourceView* colorMap = dxiSprites_[i].GetShaderResourceView( );
d3dContext_->IASetVertexBuffers( 0, 1, &vertexBuffer, &stride, &offset );
d3dContext_->PSSetShaderResources( 0, 1, &colorMap );
if( i == kDarknessLight )
{
XMFLOAT2 pos = XMFLOAT2( 0.0f, 0.0f );
XMMATRIX world = dxiSprites_[i].CreateAWorldMatrix( pos, ( 360.0f - 0 ) * 0.0174532925f, XMFLOAT2( 1, 1 ) );
XMMATRIX mvp = XMMatrixMultiply( world, vpMatrix_ );
mvp = XMMatrixMultiply( mvp, XMMatrixTranslation( 512 / ( kWindowWidth / 2 ), 384 / ( kWindowHeight / 2 ), 0.0f ) );
mvp = XMMatrixTranspose( mvp );
d3dContext_->UpdateSubresource( mvpCB_, 0, 0, &mvp, 0, 0 );
d3dContext_->VSSetConstantBuffers( 0, 1, &mvpCB_ );
d3dContext_->Draw( 6, 0 );
}
for( int j = 0; j < drawData->spriteDataLength; j++ )
{
if( drawData->spriteData[j].index == kFlagshipSprite )
{
XMFLOAT2 pos = XMFLOAT2( 0.0f, 0.0f );
XMMATRIX world = dxiSprites_[i].CreateAWorldMatrix( pos, ( 360.0f - drawData->spriteData[j].rotation ) * 0.0174532925f, drawData->spriteData[j].scale );
XMMATRIX mvp = XMMatrixMultiply( world, vpMatrix_ );
mvp = XMMatrixMultiply( mvp, XMMatrixTranslation( drawData->spriteData[j].position.x / ( kWindowWidth / 2 ), drawData->spriteData[j].position.y / ( kWindowHeight / 2 ), 0.0f ) );
mvp = XMMatrixTranspose( mvp );
d3dContext_->UpdateSubresource( mvpCB_, 0, 0, &mvp, 0, 0 );
d3dContext_->VSSetConstantBuffers( 0, 1, &mvpCB_ );
d3dContext_->Draw( 6, 0 );
}
}
}
d3dContext_->OMSetRenderTargets( 1, &backBufferTarget_, NULL );
d3dContext_->OMSetBlendState( lightingBlendState_, blendfactor, 0xFFFFFFFF );
d3dContext_->PSSetShaderResources( 0, 1, &lightMapResource_ );
d3dContext_->Draw( 6, 0 );
第一块用黑暗填充纹理(黑色) 然后第二位绘制所有光照精灵(通常是白色圆圈)和黑暗精灵 出于调试原因,暗度被绘制两次,表明无论纹理中有什么,它都会在进行新的Draw调用时被替换。 最后一块将纹理绘制到具有正确混合状态的现有渲染帧
如果这太详细了,我很抱歉,但是我在GameDev.net上发布了这个并且还没有得到答案,所以我认为这个问题可能很复杂,需要它
谢谢