#include "StdAfx.h"
#include "IntegrateShader.h"

#include <LibTest/DebugStream.h>

#include "../ShaderUtil.h"

// IDEでのソース参照用. コンパイルには使わない.
#if 0
#include "..\Shader\integrate_shader.frag"
#include "..\Shader\integrate_shader.vert"
#endif


IntegrateShader::IntegrateShader(ShaderContext* context) :
	ShaderInterface(context)
{
}

bool IntegrateShader::Initialize(const std::string& shader_libdir)
{
	if( !InitializeShader(shader_libdir) )
		return false;

	return true;
}

bool IntegrateShader::InitializeShader(const std::string& shader_libdir)
{
	std::string vert_filename = shader_libdir + "integrate_shader.vert";
	std::string frag_filename = shader_libdir + "integrate_shader.frag";

	return ShaderUtil::InitShaderStd(m_Shader, frag_filename, vert_filename);
}


void IntegrateShader::BeginShader(void)
{
	m_Shader.BeginShader();

	SceneMain* scene = m_Context->m_Scene;
	Cursor3D& cursor = scene->m_Cursor3d;

	glUniform1i(GetLoc("tex_matcap"), 3);
	glUniform1i(GetLoc("enable_matcap"), false);

	glActiveTexture(GL_TEXTURE2);
	scene->m_EnvImg.BindTexture();
	glUniform1i(GetLoc("tex_envmap"), 2);
	glUniform1i(GetLoc("enable_envmap"), scene->m_EnvImg.m_IsEnableReflection);

	SetShadowmap(&m_Context->m_ShadowBuf);

	glActiveTexture(GL_TEXTURE0);

	glUniform1i(GetLoc("tex_color"), 0);

	lm::matrix4f mat;
	scene->m_WorldTransform.GetRotateMatrix(mat);
	glUniformMatrix4fv(GetLoc("scene_mat"), 1, GL_FALSE, &mat[0]);

	glUniform1f(GetLoc("env_reflection"), scene->m_EnvImg.m_EnvReflection);

	glUniform1f(GetLoc("color_shadow_ratio"), scene->m_ShadowConfig.m_ShadowDarkness);

	glUniform1i(GetLoc("enable_hole"), cursor.IsHoleActive());
	if (cursor.IsHoleActive())
	{
		float hole_range = scene->GetSceneBBox().max_length() * cursor.HoleRangeRatio;
		lm::vec3f cp = cursor.CursorPos;
		glUniform3f(GetLoc("hole_pos"), cp.x, cp.y, cp.z);
		glUniform1f(GetLoc("hole_range"), hole_range);
	}
}

void IntegrateShader::EndShader(void)
{
	m_Shader.EndShader();
}

GLint IntegrateShader::GetLoc(const GLchar* name)
{
	return m_Shader.GetUniformLocation(name);
}


void IntegrateShader::SetTextureEnabled(bool enabled)
{
	glUniform1i( m_Shader.GetUniformLocation( "enable_texture" ) , enabled ? 1 : 0 );
}

void IntegrateShader::SetDublesideEnabled(bool enabled)
{
	glUniform1i( m_Shader.GetUniformLocation( "enable_doubleside" ) , enabled ? 1 : 0 );
}

void IntegrateShader::SetLightingEnabled(bool enabled)
{
	glUniform1i( m_Shader.GetUniformLocation( "enable_lighting" ) , enabled ? 1 : 0 );
}

void IntegrateShader::SetFlatShade(bool enable_flat)
{
	glUniform1i( m_Shader.GetUniformLocation( "enable_flatshade" ) , enable_flat ? 1 : 0 );
}


void IntegrateShader::SetMatcap(gl::MatcapImage* matcap)
{
	if (matcap == NULL)
	{
		glUniform1i(m_Shader.GetUniformLocation("enable_matcap"), false);
		return;
	}

	glActiveTexture(GL_TEXTURE3);
	matcap->BindTexture();

	glUniform1i(GetLoc("tex_matcap"), 3);
	glUniform1i(GetLoc("enable_matcap"), matcap->HasImage());

	glActiveTexture(GL_TEXTURE0);
}

void IntegrateShader::SetShadowmap(ShadowBuffer* shadow)
{
	SceneMain* scene = m_Context->m_Scene;
	glActiveTexture(GL_TEXTURE1);
	shadow->m_ShadowBuffer.Bind();
	glUniform1i(GetLoc("shadow_buffer"), 1);
	glUniform1i(GetLoc("enable_shadow"), scene->m_ShadowConfig.m_EnableShadow);
	glUniform1i(GetLoc("enable_softshadow"), scene->m_ShadowConfig.m_EnableSoftShadow);
	glUniformMatrix4fv(GetLoc("shadow_mat"), 1, GL_FALSE, shadow->m_ShadowMatrix.v());
}
