////////////////////////////////////////////////////////
// filename: C2DEffect.cpp
// author: Chafumi Touji
// version: 1.0.0
// date: 2020/09/02
////////////////////////////////////////////////////////

#include "defcha3dcore.h"
#include "C2DEffect.h"

C2DEffect::C2DEffect(){

	EffectPosNum = 0;
	EffectPos = NULL;
	m_pEffectTexture = NULL;
	m_pEffectRenderTargetView = NULL;
	m_pEffectShaderResourceView = NULL;
	EffectBuffer = NULL;
	m_pConstantBufferEffect = NULL;
	Time = 0.0f;
	EffectParam = NULL;
}

C2DEffect::~C2DEffect(){

	if (EffectPos != NULL)
		delete[] EffectPos;
	if (EffectParam != NULL)
		delete[] EffectParam;

	SAFE_RELEASE( m_pEffectTexture );
	SAFE_RELEASE(m_pEffectRenderTargetView );
	SAFE_RELEASE(m_pEffectShaderResourceView );
	SAFE_RELEASE(EffectBuffer );
	SAFE_RELEASE(m_pConstantBufferEffect );
}

bool C2DEffect::CreateResource(CCommonDevice *device, float size){

	//////////////////////////////////////////////////////////
	//effect作成

	D3D11_TEXTURE2D_DESC desc_texture_2d;
	ZeroMemory(&desc_texture_2d, sizeof(D3D11_TEXTURE2D_DESC));
	desc_texture_2d.Width = EFFECT_TEXTURE_SIZE;
	desc_texture_2d.Height = EFFECT_TEXTURE_SIZE;
	desc_texture_2d.MipLevels = 1;
	desc_texture_2d.ArraySize = 1;
	desc_texture_2d.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	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;

	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->CreateTexture2D(&desc_texture_2d, NULL, &m_pEffectTexture);
	device->m_pDevice->CreateShaderResourceView(m_pEffectTexture, &desc_shader_resource, &m_pEffectShaderResourceView);
	device->m_pDevice->CreateRenderTargetView(m_pEffectTexture, NULL, &m_pEffectRenderTargetView);

	CVertex *VtxData = new CVertex[4];
	SetVertex(&VtxData[0], size, 0, size, 0, 0, 0, 0, 0, 0, 0, -1, -1);
	SetVertex(&VtxData[1], size, 0, -size, 0, 0, 0, 0, 0, 0, 0, -1, 1);
	SetVertex(&VtxData[2], -size, 0, size, 0, 0, 0, 0, 0, 0, 0, 1, -1);
	SetVertex(&VtxData[3], -size, 0, -size, 0, 0, 0, 0, 0, 0, 0, 1, 1);

	D3D11_BUFFER_DESC desc_buffer;
	ZeroMemory(&desc_buffer, sizeof(D3D11_BUFFER_DESC));
	desc_buffer.ByteWidth = sizeof(CVertex)* 4;
	desc_buffer.Usage = D3D11_USAGE_DYNAMIC;
	desc_buffer.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	desc_buffer.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	desc_buffer.MiscFlags = 0;
	desc_buffer.StructureByteStride = sizeof(CVertex);
	D3D11_SUBRESOURCE_DATA msr;
	msr.pSysMem = VtxData;
	device->m_pDevice->CreateBuffer(&desc_buffer, &msr, &EffectBuffer);

	delete[] VtxData;

	/////////////////////////////////////////////////////
	//コンスタントバッファ作成

	m_pConstantBufferEffect = NULL;
	ZeroMemory(&desc_buffer, sizeof(D3D11_BUFFER_DESC));
	desc_buffer.ByteWidth = sizeof(ConstantBufferEffect);
	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_pConstantBufferEffect);

	return true;
}

bool C2DEffect::Update(){

	Time += 0.05f;
	if (Time > 3.14159265f * 2.0f)
		Time -= 3.14159265f * 2.0f;

	if (EffectParam != NULL){
		for (int i = EffectParamNum-2; i >= 0; i--){
			bool finished = EffectParamUpdate(i);
			if (finished == true)
				EffectParamInit(i);
		}
	}

	return true;
}

bool C2DEffect::CreateEffectParam(){

	EffectParam = new XMFLOAT4[SIZE_EFFECT_PARAM2];
	EffectParamNum = SIZE_EFFECT_PARAM2;
	for (int i = 0; i <= EffectParamNum - 1; i++){
		EffectParam[i] = XMFLOAT4(0, 0, 0, 0);
		EffectParamInit(i);
		EffectParam[i].y = ((float)(rand() % 10000 - 5000) / 5000.0f);
	}

	return true;
}

bool C2DEffect::EffectParamUpdate(int num){

	if (num < 0 || num > EffectParamNum)
		return false;

	if ( num % 16 != 0)
		EffectParam[num] = EffectParam[num-1];
	else{
		int random = (num * 2774 + 276) % 10000;
		EffectParam[num].x += sin(Time + ((float) random / 10000.0f) * 3.14159265f * 2.0f ) / 100.0f;
		EffectParam[num].y -= 0.03f;
		EffectParam[num].z += sin(Time + ((float)random / 10000.0f) * 3.14159265f * 2.0f) / 500.0f;
		EffectParam[num].w = cos(EffectParam[num].y * 3.14159265f * 0.3f);
	}

	if (EffectParam[num].y < -1.0f)
		return true;

	return false;
}

bool C2DEffect::EffectParamInit(int num){

	if (num % 16 == 0){
		EffectParam[num].x = ((float)(rand() % 10000 - 5000) / 40000.0f);
		EffectParam[num].y = 1.0f;
		EffectParam[num].z = 0.1f;
		EffectParam[num].w = 0.0f;
	}

	return true;
}

bool C2DEffect::Draw(CCommonDevice *device){

	device->m_pDeviceContext->VSSetShader(device->m_pVtxShader1_5, NULL, 0);

	ConstantBufferEffect		constant_buffer_effect;

	Update();
	if (EffectParam != NULL){
		for (int i = 0; i <= EffectParamNum - 1; i++)
			constant_buffer_effect.EffectParam2[i] = EffectParam[i];
	}

	//ソート
	int *Num = new int[EffectPosNum];
	float *Dist = new float[EffectPosNum];
	for (int i = 0; i <= EffectPosNum - 1; i++){
		Num[i] = i;
		Dist[i] = sqrt(pow(device->Eye.x - EffectPos[i].x, 2.0f) + pow(device->Eye.y - EffectPos[i].y, 2.0f) + pow(device->Eye.z - EffectPos[i].z, 2.0f));
	}
	for (int i = 0; i <= EffectPosNum - 1; i++){
		for (int j = i; j <= EffectPosNum - 1; j++){
			if (Dist[j] > Dist[i]){
				int num = Num[j];
				float dist = Dist[j];
				Num[j] = Num[i];
				Dist[j] = Dist[i];
				Num[i] = num;
				Dist[i] = dist;
			}
		}
	}
	for (int i = 0; i <= EffectPosNum - 1; i++){

		XMMATRIX matrix = XMMatrixRotationZ( device->CameraRotationZ ) * XMMatrixTranslation(EffectPos[Num[i]].x, EffectPos[Num[i]].y, EffectPos[Num[i]].z);

		XMStoreFloat4x4(&constant_buffer_effect.MatEffect, XMMatrixTranspose(matrix));
		constant_buffer_effect.EffectColor = EffectColor;
		constant_buffer_effect.EffectParam1 = XMFLOAT4(Time, Num[i] + 54, 0, 0);

		//コンスタントバッファ設定
		D3D11_MAPPED_SUBRESOURCE resource;
		device->m_pDeviceContext->Map(m_pConstantBufferEffect, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
		memcpy(resource.pData, &constant_buffer_effect, sizeof(ConstantBufferEffect));
		device->m_pDeviceContext->Unmap(m_pConstantBufferEffect, 0);

		UINT stride = sizeof(CVertex);
		UINT offset = 0;

		device->m_pDeviceContext->VSSetConstantBuffers(3, 1, &m_pConstantBufferEffect);
		device->m_pDeviceContext->PSSetConstantBuffers(3, 1, &m_pConstantBufferEffect);

		device->m_pDeviceContext->IASetInputLayout(device->m_pLayout2);
		device->m_pDeviceContext->RSSetState(device->m_pRasterizeState);
		device->m_pDeviceContext->OMSetBlendState(device->m_pBlendState2, NULL, 0xffffffff);
		device->m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

		device->m_pDeviceContext->IASetVertexBuffers(0, 1, &EffectBuffer, &stride, &offset);
		device->m_pDeviceContext->Draw(4, 0);
	}

	delete[] Num;
	delete[] Dist;

	return true;
}