////////////////////////////////////////////////////////
// filename: CVolumeLight.cpp
// author: Chafumi Touji
// version: 1.0.0
// date: 2020/08/01
////////////////////////////////////////////////////////

#include "defcha3dcore.h"
#include "CLight.h"
#include "CVolumeLight.h"

CVolumeLight::CVolumeLight(){

	Width = 0.0f;
	Height = 0.0f;
	PixelInterval = 1;
	Resolution = VOLUME_LIGHT_RESOLUTION;
	m_pTextureVolumeLightOrg = NULL;
	m_pVolumeLightOrgRenderTargetView = NULL;
	m_pVolumeLightOrgShaderResourceView = NULL;
}

CVolumeLight::~CVolumeLight(){

	SAFE_RELEASE(m_pTextureVolumeLightOrg);
	SAFE_RELEASE(m_pVolumeLightOrgRenderTargetView);
	SAFE_RELEASE(m_pVolumeLightOrgShaderResourceView);
}

bool CVolumeLight::CreateResource(CCommonDevice *device, float resolution ){

	if (device == NULL)
		return false;

	Width = (float) device->Width;
	Height = (float) device->Height;
	Resolution = resolution;

	D3D11_TEXTURE2D_DESC desc_texture_2d;
	ZeroMemory(&desc_texture_2d, sizeof(D3D11_TEXTURE2D_DESC));
	desc_texture_2d.Width = Width * Resolution;
	desc_texture_2d.Height = Height * Resolution;
	desc_texture_2d.MipLevels = 1;
	desc_texture_2d.ArraySize = 1;
	desc_texture_2d.SampleDesc.Count = 1;
	desc_texture_2d.SampleDesc.Quality = 0;
	desc_texture_2d.Usage = D3D11_USAGE_DEFAULT;
	desc_texture_2d.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
	desc_texture_2d.CPUAccessFlags = 0;
	desc_texture_2d.MiscFlags = 0;
	desc_texture_2d.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;

	device->m_pDevice->CreateTexture2D(&desc_texture_2d, NULL, &m_pTextureVolumeLightOrg);

//	desc_texture_2d.Width = Width;
//	desc_texture_2d.Height = Height;
//	device->m_pDevice->CreateTexture2D(&desc_texture_2d, NULL, &m_pTextureVolumeLight);

	D3D11_SHADER_RESOURCE_VIEW_DESC desc_shader_resource;
	ZeroMemory(&desc_shader_resource, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
	desc_shader_resource.Format = desc_texture_2d.Format;
	desc_shader_resource.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	desc_shader_resource.Texture2D.MipLevels = desc_texture_2d.MipLevels;
	desc_shader_resource.Texture2D.MostDetailedMip = 0;

//	device->m_pDevice->CreateShaderResourceView(m_pTextureVolumeLight, &desc_shader_resource, &m_pVolumeLightShaderResourceView);
//	device->m_pDevice->CreateRenderTargetView(m_pTextureVolumeLight, NULL, &m_pVolumeLightRenderTargetView);
	device->m_pDevice->CreateShaderResourceView(m_pTextureVolumeLightOrg, &desc_shader_resource, &m_pVolumeLightOrgShaderResourceView);
	device->m_pDevice->CreateRenderTargetView(m_pTextureVolumeLightOrg, NULL, &m_pVolumeLightOrgRenderTargetView);

	//////////////////////////////////////////////////////////////////
	// ConstantBuffer

	D3D11_BUFFER_DESC desc_buffer;
	m_pConstantBufferVolumeLight = NULL;
	ZeroMemory(&desc_buffer, sizeof(D3D11_BUFFER_DESC));
	desc_buffer.ByteWidth = sizeof(ConstantBufferVolumeLight);
	desc_buffer.Usage = D3D11_USAGE_DYNAMIC;
	desc_buffer.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	desc_buffer.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	desc_buffer.MiscFlags = 0;
	desc_buffer.StructureByteStride = sizeof(float);
	device->m_pDevice->CreateBuffer(&desc_buffer, NULL, &m_pConstantBufferVolumeLight);

	return true;
}

bool CVolumeLight::DrawVolumeLight(CCommonDevice *device, CPointLight *light ){

	UINT Num = 1;
	D3D11_VIEWPORT back_vp;
	device->m_pDeviceContext->RSGetViewports(&Num, &back_vp);

	D3D11_VIEWPORT vp;
	vp.Width = (FLOAT)Width * Resolution;
	vp.Height = (FLOAT)Height * Resolution;
	vp.TopLeftX = 0;
	vp.TopLeftY = 0;
	vp.MinDepth = 0.0f;
	vp.MaxDepth = 1.0f;
	device->m_pDeviceContext->RSSetViewports(1, &vp);

	///////////////////////////////////////////////////////////////////////////////
	//ポイントライト設定

	light->SetParam(device);
	device->m_pDeviceContext->PSSetShaderResources(2, 1, &light->m_pShadowMapShaderResourceView[0]);
	device->m_pDeviceContext->PSSetShaderResources(3, 1, &light->m_pShadowMapShaderResourceView[1]);
	device->m_pDeviceContext->PSSetShaderResources(4, 1, &light->m_pShadowMapShaderResourceView[2]);
	device->m_pDeviceContext->PSSetShaderResources(5, 1, &light->m_pShadowMapShaderResourceView[3]);
	device->m_pDeviceContext->PSSetShaderResources(6, 1, &light->m_pShadowMapShaderResourceView[4]);
	device->m_pDeviceContext->PSSetShaderResources(7, 1, &light->m_pShadowMapShaderResourceView[5]);
	device->m_pDeviceContext->PSSetSamplers(2, 1, &device->m_pSampleState);
	device->m_pDeviceContext->PSSetSamplers(3, 1, &device->m_pSampleState);
	device->m_pDeviceContext->PSSetSamplers(4, 1, &device->m_pSampleState);
	device->m_pDeviceContext->PSSetSamplers(5, 1, &device->m_pSampleState);
	device->m_pDeviceContext->PSSetSamplers(6, 1, &device->m_pSampleState);
	device->m_pDeviceContext->PSSetSamplers(7, 1, &device->m_pSampleState);

	///////////////////////////////////////////////////////////////////////////////////////////

	device->m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	device->m_pDeviceContext->OMSetBlendState(device->m_pBlendState1, NULL, 0xffffffff);
	device->m_pDeviceContext->RSSetState(device->m_pRasterizeState);
	UINT stride = sizeof(CVertex);
	UINT offset = 0;
	device->m_pDeviceContext->IASetVertexBuffers(0, 1, &device->VertexBuffer, &stride, &offset);

	float clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

	////////////////////////////////////////////
	//パラメータ設定

	XMVECTOR at = XMVectorSet(device->At.x, device->At.y, device->At.z, 1.0f);
	XMVECTOR up = XMVectorSet(0, 0, 1, 1.0f);
	XMVECTOR eye = XMVectorSet(device->Eye.x, device->Eye.y, device->Eye.z, 1.0f);
	XMMATRIX view = XMMatrixLookAtLH(eye, at, up);

	float radian = 3.14159265f / 4.0f;
	XMMATRIX proj = XMMatrixPerspectiveFovLH(radian, 1.0f, 0.01f, 5000.0f);
	XMMATRIX world = XMMatrixIdentity();

	constant_buffer_vl.EyeVL = XMFLOAT4( device->Eye.x - device->At.x, device->Eye.y - device->At.y, device->Eye.z - device->At.z, 1.0f);
	constant_buffer_vl.EyePosVL = XMFLOAT4(device->Eye.x, device->Eye.y, device->Eye.z, 1.0f);
	constant_buffer_vl.MoveVL = XMFLOAT4(device->Move.x, device->Move.y, device->Move.z, 1.0f);

	XMStoreFloat4x4(&constant_buffer_vl.MatWorldVL, XMMatrixTranspose(world));
	XMStoreFloat4x4(&constant_buffer_vl.MatViewVL, XMMatrixTranspose(view));
	XMStoreFloat4x4(&constant_buffer_vl.MatProjVL, XMMatrixTranspose(proj));

	float screen_w = (float)((int)(Width * Resolution));
	float screen_h = (float)((int)(Height * Resolution));

	float quality = 0.8f;

	constant_buffer_vl.VolumeLightParam1 = XMFLOAT4((float) screen_w, (float) screen_h, (float) Resolution, (float) PixelInterval );
	constant_buffer_vl.VolumeLightParam2 = XMFLOAT4((float) quality, (float) light->TextureSize, 0, 0 );

	///////////////////////////////////////////////////

	D3D11_MAPPED_SUBRESOURCE resource;
	device->m_pDeviceContext->Map(m_pConstantBufferVolumeLight, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
	memcpy(resource.pData, &constant_buffer_vl, sizeof(ConstantBufferVolumeLight));
	device->m_pDeviceContext->Unmap(m_pConstantBufferVolumeLight, 0);

	device->m_pDeviceContext->VSSetConstantBuffers(4, 1, &m_pConstantBufferVolumeLight);
	device->m_pDeviceContext->PSSetConstantBuffers(4, 1, &m_pConstantBufferVolumeLight);
	device->m_pDeviceContext->IASetInputLayout(device->m_pLayout1);
	device->m_pDeviceContext->ClearRenderTargetView(m_pVolumeLightOrgRenderTargetView, clear_color);

	ID3D11RenderTargetView *rtview[] = { m_pVolumeLightOrgRenderTargetView };
	device->m_pDeviceContext->OMSetRenderTargets(1, rtview, NULL);
	device->m_pDeviceContext->VSSetShader(device->m_pVtxShader2, NULL, 0);
	device->m_pDeviceContext->PSSetShader(device->m_pPxShader9, NULL, 0);
	device->m_pDeviceContext->PSSetShaderResources(1, 1, &device->m_pDepthShaderResourceView);
	device->m_pDeviceContext->Draw(4, 0);

	/////////////////////////////////////////////////////////////////////
	//ピクセル補完
	
	device->m_pDeviceContext->RSSetViewports(1, &back_vp);

	device->m_pDeviceContext->ClearRenderTargetView(light->m_pVolumeLightRenderTargetView, clear_color);
	ID3D11RenderTargetView *rtview2[] = { light->m_pVolumeLightRenderTargetView };
	device->m_pDeviceContext->OMSetRenderTargets(1, rtview2, NULL);
	device->m_pDeviceContext->PSSetShaderResources(1, 1, &m_pVolumeLightOrgShaderResourceView);
	device->m_pDeviceContext->VSSetShader(device->m_pVtxShader2, NULL, 0);
	device->m_pDeviceContext->PSSetShader(device->m_pPxShader10, NULL, 0);
	device->m_pDeviceContext->Draw(4, 0);

	return true;
}
