Пример #1
0
//--------------------------------------------------------------------------------------
// Create any D3D11 resources that aren't dependant on the back buffer
//--------------------------------------------------------------------------------------
HRESULT SoftParticles::OnD3D11CreateDevice(ID3D11Device* pd3dDevice)
{
	HRESULT hr;

	V_RETURN( LoadEffectFromFile(pd3dDevice,  L"SoftParticles.hlsl", &g_pEffect11) );

	// Obtain the technique handles
	g_pRenderBillboardParticlesHard = g_pEffect11->GetTechniqueByName( "RenderBillboardParticles_Hard" );
	g_pRenderBillboardParticlesODepth = g_pEffect11->GetTechniqueByName( "RenderBillboardParticles_ODepth" );
	g_pRenderBillboardParticlesSoft = g_pEffect11->GetTechniqueByName( "RenderBillboardParticles_Soft" );
	g_pRenderBillboardParticlesODepthSoft = g_pEffect11->GetTechniqueByName( "RenderBillboardParticles_ODepthSoft" );
	g_pRenderVolumeParticlesHard = g_pEffect11->GetTechniqueByName( "RenderVolumeParticles_Hard" );
	g_pRenderVolumeParticlesSoft = g_pEffect11->GetTechniqueByName( "RenderVolumeParticles_Soft" );
	g_pRenderVolumeParticlesSoftMSAA = g_pEffect11->GetTechniqueByName( "RenderVolumeParticles_Soft_MSAA" );
	g_pRenderVolumeParticlesHardMSAA = g_pEffect11->GetTechniqueByName( "RenderVolumeParticles_Hard_MSAA" );
	g_pRenderBillboardParticlesSoftMSAA = g_pEffect11->GetTechniqueByName( "RenderBillboardParticles_Soft_MSAA" );
	g_pRenderBillboardParticlesODepthSoftMSAA = g_pEffect11->GetTechniqueByName( "RenderBillboardParticles_ODepthSoft_MSAA" );
  
	// Obtain the parameter handles
	g_pmWorldViewProj = g_pEffect11->GetVariableByName( "g_mWorldViewProj" )->AsMatrix();
	g_pmWorldView = g_pEffect11->GetVariableByName( "g_mWorldView" )->AsMatrix();
	g_pmWorld = g_pEffect11->GetVariableByName( "g_mWorld" )->AsMatrix();
	g_pmInvView = g_pEffect11->GetVariableByName( "g_mInvView" )->AsMatrix();
	g_pmInvProj = g_pEffect11->GetVariableByName( "g_mInvProj" )->AsMatrix();
	g_pfFadeDistance = g_pEffect11->GetVariableByName( "g_fFadeDistance" )->AsScalar();
	g_pfSizeZScale = g_pEffect11->GetVariableByName( "g_fSizeZScale" )->AsScalar();
	g_pvViewLightDir1 = g_pEffect11->GetVariableByName( "g_vViewLightDir1" )->AsVector();
	g_pvViewLightDir2 = g_pEffect11->GetVariableByName( "g_vViewLightDir2" )->AsVector();
	g_pvWorldLightDir1 = g_pEffect11->GetVariableByName( "g_vWorldLightDir1" )->AsVector();
	g_pvWorldLightDir2 = g_pEffect11->GetVariableByName( "g_vWorldLightDir2" )->AsVector();
	g_pvEyePt = g_pEffect11->GetVariableByName( "g_vEyePt" )->AsVector();
	g_pvViewDir = g_pEffect11->GetVariableByName( "g_vViewDir" )->AsVector();
	g_pvOctaveOffsets = g_pEffect11->GetVariableByName( "g_OctaveOffsets" )->AsVector();
	g_pvScreenSize = g_pEffect11->GetVariableByName( "g_vScreenSize" )->AsVector();
	g_pDiffuseTex = g_pEffect11->GetVariableByName( "g_txDiffuse" )->AsShaderResource();
	g_pNormalTex = g_pEffect11->GetVariableByName( "g_txNormal" )->AsShaderResource();
	g_pColorGradient = g_pEffect11->GetVariableByName( "g_txColorGradient" )->AsShaderResource();
	g_pVolumeDiffTex = g_pEffect11->GetVariableByName( "g_txVolumeDiff" )->AsShaderResource();
	g_pVolumeNormTex = g_pEffect11->GetVariableByName( "g_txVolumeNorm" )->AsShaderResource();
	g_pDepthTex = g_pEffect11->GetVariableByName( "g_txDepth" )->AsShaderResource();
	g_pDepthMSAATex = g_pEffect11->GetVariableByName( "g_txDepthMSAA" )->AsShaderResource();

	// Create our vertex input layouts
	D3DX11_PASS_DESC PassDesc;
	const D3D11_INPUT_ELEMENT_DESC particlelayout[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "VELOCITY", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "LIFE",     0, DXGI_FORMAT_R32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "SIZE",     0, DXGI_FORMAT_R32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};
	g_pRenderBillboardParticlesHard->GetPassByIndex( 0 )->GetDesc( &PassDesc );
	V_RETURN( pd3dDevice->CreateInputLayout( particlelayout, sizeof(particlelayout)/sizeof(particlelayout[0]), PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pParticleVertexLayout ) );

	// Create the particles
	V_RETURN( CreateParticleBuffers( pd3dDevice ) );

	// Create the noise volume
	V_RETURN( CreateNoiseVolume( pd3dDevice, 32 ) );

	// Load the Particle Texture
	V_RETURN( D3DX11CreateShaderResourceViewFromFile( pd3dDevice, L"Resource\\SmokeTexture\\smokevol1.dds", NULL, NULL, &g_pParticleTexRV, NULL ) );
	V_RETURN( D3DX11CreateShaderResourceViewFromFile( pd3dDevice, L"Resource\\SmokeTexture\\colorgradient.dds", NULL, NULL, &g_pColorGradTexRV, NULL ) );

	g_pfFadeDistance->SetFloat( g_fFadeDistance );

	//---------------------------------
	//resize swap chain
	//---------------------------------

	// Create a new Depth-Stencil texture to replace the DXUT created one
	D3D11_TEXTURE2D_DESC descDepth;
	descDepth.Width = 800;
	descDepth.Height = 600;
	descDepth.MipLevels = 1;
	descDepth.ArraySize = 1;
	descDepth.Format = DXGI_FORMAT_R32_TYPELESS; // Use a typeless type here so that it can be both depth-stencil and shader resource.
	// This will fail if we try a format like D32_FLOAT
	descDepth.SampleDesc.Count = 1;
	descDepth.SampleDesc.Quality = 0;
	descDepth.Usage = D3D11_USAGE_DEFAULT;
	descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
	descDepth.CPUAccessFlags = 0;
	descDepth.MiscFlags = 0;
	V_RETURN( pd3dDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencilTexture ) );

	// Create the depth stencil view
	D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
	if( 1 == descDepth.SampleDesc.Count ) {
		descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
	} else {
		descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
	}
	descDSV.Flags = 0;
	descDSV.Format = DXGI_FORMAT_D32_FLOAT;	// Make the view see this as D32_FLOAT instead of typeless
	descDSV.Texture2D.MipSlice = 0;
	V_RETURN( pd3dDevice->CreateDepthStencilView( g_pDepthStencilTexture, &descDSV, &g_pDepthStencilDSV ) );

	// Create the shader resource view
	if( 1 == descDepth.SampleDesc.Count ) {

		D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;
		descSRV.Format = DXGI_FORMAT_R32_FLOAT;	// Make the shaders see this as R32_FLOAT instead of typeless
		descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
		descSRV.Texture2D.MipLevels = 1;
		descSRV.Texture2D.MostDetailedMip = 0;
		V_RETURN( pd3dDevice->CreateShaderResourceView( g_pDepthStencilTexture, &descSRV, &g_pDepthStencilSRV ) );
	}
			
	g_iWidth = 800;
	g_iHeight = 600;
	g_iSampleCount = 1;

	//----------------------------------
	// frame move
	//----------------------------------

	return S_OK;
}
// Load the sample assets.
void D3D12nBodyGravity::LoadAssets()
{
	// Create the root signatures.
	{
		CD3DX12_DESCRIPTOR_RANGE ranges[2];
		ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
		ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0);

		CD3DX12_ROOT_PARAMETER rootParameters[RootParametersCount];
		rootParameters[RootParameterCB].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL);
		rootParameters[RootParameterSRV].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_VERTEX);
		rootParameters[RootParameterUAV].InitAsDescriptorTable(1, &ranges[1], D3D12_SHADER_VISIBILITY_ALL);

		// The rendering pipeline does not need the UAV parameter.
		CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
		rootSignatureDesc.Init(_countof(rootParameters) - 1, rootParameters, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

		ComPtr<ID3DBlob> signature;
		ComPtr<ID3DBlob> error;
		ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
		ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));

		// Create compute signature. Must change visibility for the SRV.
		rootParameters[RootParameterSRV].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;

		CD3DX12_ROOT_SIGNATURE_DESC computeRootSignatureDesc(_countof(rootParameters), rootParameters, 0, nullptr);
		ThrowIfFailed(D3D12SerializeRootSignature(&computeRootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));

		ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_computeRootSignature)));
	}

	// Create the pipeline states, which includes compiling and loading shaders.
	{
		ComPtr<ID3DBlob> vertexShader;
		ComPtr<ID3DBlob> geometryShader;
		ComPtr<ID3DBlob> pixelShader;
		ComPtr<ID3DBlob> computeShader;

#ifdef _DEBUG
		// Enable better shader debugging with the graphics debugging tools.
		UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
		UINT compileFlags = 0;
#endif

		// Load and compile shaders.
		ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"ParticleDraw.hlsl").c_str(), nullptr, nullptr, "VSParticleDraw", "vs_5_0", compileFlags, 0, &vertexShader, nullptr));
		ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"ParticleDraw.hlsl").c_str(), nullptr, nullptr, "GSParticleDraw", "gs_5_0", compileFlags, 0, &geometryShader, nullptr));
		ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"ParticleDraw.hlsl").c_str(), nullptr, nullptr, "PSParticleDraw", "ps_5_0", compileFlags, 0, &pixelShader, nullptr));
		ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"NBodyGravityCS.hlsl").c_str(), nullptr, nullptr, "CSMain", "cs_5_0", compileFlags, 0, &computeShader, nullptr));

		D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
		{
			{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
		};

		// Describe the blend and depth states.
		CD3DX12_BLEND_DESC blendDesc(D3D12_DEFAULT);
		blendDesc.RenderTarget[0].BlendEnable = TRUE;
		blendDesc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
		blendDesc.RenderTarget[0].DestBlend = D3D12_BLEND_ONE;
		blendDesc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ZERO;
		blendDesc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;

		CD3DX12_DEPTH_STENCIL_DESC depthStencilDesc(D3D12_DEFAULT);
		depthStencilDesc.DepthEnable = FALSE;
		depthStencilDesc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;

		// Describe and create the graphics pipeline state object (PSO).
		D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
		psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
		psoDesc.pRootSignature = m_rootSignature.Get();
		psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() };
		psoDesc.GS = { reinterpret_cast<UINT8*>(geometryShader->GetBufferPointer()), geometryShader->GetBufferSize() };
		psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() };
		psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
		psoDesc.BlendState = blendDesc;
		psoDesc.DepthStencilState = depthStencilDesc;
		psoDesc.SampleMask = UINT_MAX;
		psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
		psoDesc.NumRenderTargets = 1;
		psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
		psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
		psoDesc.SampleDesc.Count = 1;

		ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)));

		// Describe and create the compute pipeline state object (PSO).
		D3D12_COMPUTE_PIPELINE_STATE_DESC computePsoDesc = {};
		computePsoDesc.pRootSignature = m_computeRootSignature.Get();
		computePsoDesc.CS = { reinterpret_cast<UINT8*>(computeShader->GetBufferPointer()), computeShader->GetBufferSize() };

		ThrowIfFailed(m_device->CreateComputePipelineState(&computePsoDesc, IID_PPV_ARGS(&m_computeState)));
	}

	// Create the command list.
	ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get(), IID_PPV_ARGS(&m_commandList)));

	CreateVertexBuffer();
	CreateParticleBuffers();

	ComPtr<ID3D12Resource> constantBufferCSUpload;

	// Create the compute shader's constant buffer.
	{
		const UINT bufferSize = sizeof(ConstantBufferCS);

		ThrowIfFailed(m_device->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
			D3D12_HEAP_FLAG_NONE,
			&CD3DX12_RESOURCE_DESC::Buffer(bufferSize),
			D3D12_RESOURCE_STATE_COPY_DEST,
			nullptr,
			IID_PPV_ARGS(&m_constantBufferCS)));

		ThrowIfFailed(m_device->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
			D3D12_HEAP_FLAG_NONE,
			&CD3DX12_RESOURCE_DESC::Buffer(bufferSize),
			D3D12_RESOURCE_STATE_GENERIC_READ,
			nullptr,
			IID_PPV_ARGS(&constantBufferCSUpload)));

		ConstantBufferCS constantBufferCS = {};
		constantBufferCS.param[0] = ParticleCount;
		constantBufferCS.param[1] = int(ceil(ParticleCount / 128.0f));
		constantBufferCS.paramf[0] = 0.1f;
		constantBufferCS.paramf[1] = 1.0f;

		D3D12_SUBRESOURCE_DATA computeCBData = {};
		computeCBData.pData = reinterpret_cast<UINT8*>(&constantBufferCS);
		computeCBData.RowPitch = bufferSize;
		computeCBData.SlicePitch = computeCBData.RowPitch;

		UpdateSubresources<1>(m_commandList.Get(), m_constantBufferCS.Get(), constantBufferCSUpload.Get(), 0, 0, 1, &computeCBData);
		m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_constantBufferCS.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER));
	}

	// Create the geometry shader's constant buffer.
	{
		const UINT constantBufferGSSize = sizeof(ConstantBufferGS) * FrameCount;

		ThrowIfFailed(m_device->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
			D3D12_HEAP_FLAG_NONE,
			&CD3DX12_RESOURCE_DESC::Buffer(constantBufferGSSize),
			D3D12_RESOURCE_STATE_GENERIC_READ,
			nullptr,
			IID_PPV_ARGS(&m_constantBufferGS)
			));

		ThrowIfFailed(m_constantBufferGS->Map(0, nullptr, reinterpret_cast<void**>(&m_pConstantBufferGSData)));
		ZeroMemory(m_pConstantBufferGSData, constantBufferGSSize);
	}

	// Close the command list and execute it to begin the initial GPU setup.
	ThrowIfFailed(m_commandList->Close());
	ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
	m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);

	// Create synchronization objects and wait until assets have been uploaded to the GPU.
	{
		ThrowIfFailed(m_device->CreateFence(m_renderContextFenceValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_renderContextFence)));
		m_renderContextFenceValue++;

		m_renderContextFenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
		if (m_renderContextFenceEvent == nullptr)
		{
			ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
		}

		WaitForRenderContext();
	}
}