void gfx::BloomProgram::Render(){
	//Do brightpass
	ShaderProgram* prog = g_ShaderBank.GetProgramFromHandle(m_BrightPassShader);
	prog->Apply();
	const int WORK_GROUP_SIZE = 32;
	GLuint WorkGroupSizeX = GLuint((m_Width + WORK_GROUP_SIZE - 1) / float(WORK_GROUP_SIZE));
	GLuint WorkGroupSizeY = GLuint((m_Height + WORK_GROUP_SIZE - 1) / float(WORK_GROUP_SIZE));
	prog->SetUniformTextureHandle("g_Image", m_TargetTex, 1);
	prog->SetUniformVec2("g_ScreenSize", glm::vec2(m_Width, m_Height));
	prog->SetUniformFloat("g_Threshold", 0.4f);
	prog->SetUniformFloat("g_Smoothness", 0.8f);
	glBindImageTexture(0, m_BloomTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
	glDispatchCompute(WorkGroupSizeX, WorkGroupSizeY, 1);
	//blur result
	m_BlurProgram->Render();
	//add to final target
	prog = g_ShaderBank.GetProgramFromHandle(m_BloomShader);
	prog->Apply();
	prog->SetUniformTextureHandle("g_BluredBloomTex", m_BlurProgram->GetBluredTexture(), 1);
	prog->SetUniformTextureHandle("g_ColorBuffer", m_TargetTex, 2);
	prog->SetUniformVec2("g_ScreenSize", glm::vec2(m_Width, m_Height));
	glBindImageTexture(0, m_BloomTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
	glDispatchCompute(WorkGroupSizeX, WorkGroupSizeY, 1);

}
void gfx::GraphicsEngine::RenderLines(RenderQueue* drawQueue){
	//Fill vertex buffer
	int bufferSize = 0;
	for (auto& it : drawQueue->GetLineQueue()){
		bufferSize += it.Lines.size();
	}
	int i = 0;
	for (auto& it : drawQueue->GetLineQueue()){
		memcpy(m_LineBuffer + i * sizeof(glm::vec2), it.Lines.data(), it.Lines.size() * sizeof(glm::vec2));
		i += it.Lines.size();
	}
	glBindBuffer(GL_ARRAY_BUFFER, m_LineVBO);
	glBufferSubData(GL_ARRAY_BUFFER, 0, bufferSize * sizeof(glm::vec2), m_LineBuffer);
	glBindVertexArray(m_LineVAO);
	//set shader
	ShaderProgram* prog = g_ShaderBank.GetProgramFromHandle(m_LineProgram);
	prog->Apply();
	prog->SetUniformVec2("g_ScreenSize", glm::vec2(m_Width, m_Height));
	prog->SetUniformVec2("g_ScreenPos", glm::vec2(0, 0));
	//issue draw calls
	i = 0;
	glViewport(0, 0,m_Width,m_Height);
	for (auto& it : drawQueue->GetLineQueue()){
		prog->SetUniformVec4("g_Color", it.Color);
		glDrawArrays(GL_LINES, i, it.Lines.size());
		i += it.Lines.size();
	}
	
}
void gfx::BasicRenderProgram::Draw(DrawData* data)
{
	//draw
	int flag = data->ShaderFlags;
	g_ModelBank.ApplyBuffers( POS_NORMAL_TEX_TANGENT );
	ShaderProgram* prog = g_ShaderBank.GetProgramFromHandle(m_ProgramHandle);
	
	prog->Apply();
	m_RenderJobManager->BindBuffers(prog);
	GLint loc = -1;
	if(flag & FRAGMENT_DIFFUSEMAP)
	{
		Texture* diffuse = g_MaterialBank.GetTextureAtlasTex(Texture_Atlas_Type::Diffuse);
		loc = prog->FetchUniform("g_DiffuseTex");
		diffuse->Apply(loc, 0);
		prog->SetUniformBool("useDiffuse",true);
	}
	else
	{
		prog->SetUniformBool("useDiffuse",false);
	}
	if(flag & FRAGMENT_NORMALMAP)
	{
		Texture* normal = g_MaterialBank.GetTextureAtlasTex(Texture_Atlas_Type::Normal);
		loc = prog->FetchUniform("g_NormalTex");
		normal->Apply(loc, 1);
		prog->SetUniformBool("useNormal",true);
	}
	else
	{
		prog->SetUniformBool("useNormal",false);
	}
	if(flag & FRAGMENT_ROUGHNESSMAP)
	{
		Texture* roughness = g_MaterialBank.GetTextureAtlasTex(Texture_Atlas_Type::Roughness);
		loc = prog->FetchUniform("g_RoughnessTex");
		roughness->Apply(loc, 2);
		prog->SetUniformBool("useRoughness",true);
	}
	else
	{
		prog->SetUniformBool("useRoughness",false);
	}
	if(flag & FRAGMENT_METALMAP)
	{
		Texture* metal = g_MaterialBank.GetTextureAtlasTex(Texture_Atlas_Type::Metal);
		loc = prog->FetchUniform("g_MetalTex");
		metal->Apply(loc, 3);
		prog->SetUniformBool("useMetal",true);
	}
	else
	{
		prog->SetUniformBool("useMetal",false);
	}
	BasicData* frameData = (BasicData*)(data->ExtraData);
	prog->SetUniformInt("numPLights", frameData->PointLightCount);
	prog->SetUniformInt("numDLights", frameData->DirLightCount);
	prog->SetUniformUInt("BatchCounts",frameData->BatchOffset);
	prog->SetUniformVec2("g_WorldSize", frameData->WorldSize);
	prog->SetUniformMat4("ShadowMat",frameData->ShadowMat);
	loc = prog->FetchUniform("g_LightCubeTex");
	frameData->SkyTex->Apply(loc, 4);
	loc = prog->FetchUniform("g_IrradianceCube");
	frameData->IrradianceTex->Apply(loc, 5);

	//fog tex
	loc = prog->FetchUniform("g_FogOfWarTex");
	glUniform1i(loc,6);
	glActiveTexture(GL_TEXTURE6);
	glBindTexture(GL_TEXTURE_2D, frameData->FogTex);

	//fog tex
	loc = prog->FetchUniform("g_ShadowMap");
	glUniform1i(loc,7);
	glActiveTexture(GL_TEXTURE7);
	glBindTexture(GL_TEXTURE_2D, frameData->ShadowTex);

	
	if (m_HasDrawID)
	{
		GPU_PROFILE( AutoGPUProfiler gpMultiDraw( "BasicRenderProgramMultiDrawElementsIndirect" ); );
		glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (GLvoid*)(sizeof(IndirectDrawCall) * (frameData->BatchOffset)), frameData->BatchCount, 0);
		GPU_PROFILE( gpMultiDraw.Stop(); );