示例#1
0
int main()
{
	////////////////////
	// ionEngine Init //
	////////////////////

	Log::AddDefaultOutputs();

	SingletonPointer<CGraphicsAPI> GraphicsAPI;
	SingletonPointer<CWindowManager> WindowManager;
	SingletonPointer<CTimeManager> TimeManager;
	SingletonPointer<CSceneManager> SceneManager;
	SingletonPointer<CAssetManager> AssetManager;
	SingletonPointer<CGUIManager> GUIManager;

	GraphicsAPI->Init(new Graphics::COpenGLImplementation());
	WindowManager->Init(GraphicsAPI);
	TimeManager->Init(WindowManager);
	SceneManager->Init(GraphicsAPI);
	AssetManager->Init(GraphicsAPI);

	//CWindow * Window = WindowManager->CreateWindow(vec2i(1600, 900), "DemoApplication", EWindowType::Windowed);
	CWindow * Window = WindowManager->CreateWindowOnMonitor(2, "SSAO");

	GUIManager->Init(Window);
	Window->AddListener(GUIManager);

	AssetManager->AddAssetPath("Assets/");
	AssetManager->SetShaderPath("Shaders/");
	AssetManager->SetTexturePath("Images/");

	SharedPointer<IGraphicsContext> Context = GraphicsAPI->GetWindowContext(Window);
	SharedPointer<IRenderTarget> BackBuffer = Context->GetBackBuffer();
	BackBuffer->SetClearColor(color3f(0.3f));

	SharedPointer<IFrameBuffer> SceneFrameBuffer = Context->CreateFrameBuffer();

	SharedPointer<ITexture2D> SceneColor = GraphicsAPI->CreateTexture2D(Window->GetSize(), ITexture::EMipMaps::False, ITexture::EFormatComponents::RGB, ITexture::EInternalFormatType::Fix8);
	SceneColor->SetMinFilter(ITexture::EFilter::Nearest);
	SceneColor->SetMagFilter(ITexture::EFilter::Nearest);
	SceneColor->SetWrapMode(ITexture::EWrapMode::Clamp);
	SharedPointer<ITexture2D> SceneNormal = GraphicsAPI->CreateTexture2D(Window->GetSize(), ITexture::EMipMaps::False, ITexture::EFormatComponents::RGB, ITexture::EInternalFormatType::Fix8);
	SceneNormal->SetMinFilter(ITexture::EFilter::Nearest);
	SceneNormal->SetMagFilter(ITexture::EFilter::Nearest);
	SceneNormal->SetWrapMode(ITexture::EWrapMode::Clamp);
	SharedPointer<ITexture2D> SceneDepth = GraphicsAPI->CreateTexture2D(Window->GetSize(), ITexture::EMipMaps::False, ITexture::EFormatComponents::R, ITexture::EInternalFormatType::Depth);
	SceneFrameBuffer->AttachColorTexture(SceneColor, 0);
	SceneFrameBuffer->AttachColorTexture(SceneNormal, 1);
	SceneFrameBuffer->AttachDepthTexture(SceneDepth);
	if (! SceneFrameBuffer->CheckCorrectness())
	{
		Log::Error("Frame buffer not valid!");
	}

	SharedPointer<IFrameBuffer> PingFrameBuffer = Context->CreateFrameBuffer();

	SharedPointer<ITexture2D> PingColor = GraphicsAPI->CreateTexture2D(Window->GetSize(), ITexture::EMipMaps::False, ITexture::EFormatComponents::RGB, ITexture::EInternalFormatType::Fix8);
	PingColor->SetMinFilter(ITexture::EFilter::Nearest);
	PingColor->SetMagFilter(ITexture::EFilter::Nearest);
	PingColor->SetWrapMode(ITexture::EWrapMode::Clamp);
	PingFrameBuffer->AttachColorTexture(PingColor, 0);
	if (! PingFrameBuffer->CheckCorrectness())
	{
		Log::Error("Frame buffer not valid!");
	}

	SharedPointer<IFrameBuffer> PongFrameBuffer = Context->CreateFrameBuffer();

	SharedPointer<ITexture2D> PongColor = GraphicsAPI->CreateTexture2D(Window->GetSize(), ITexture::EMipMaps::False, ITexture::EFormatComponents::RGB, ITexture::EInternalFormatType::Fix8);
	PongColor->SetMinFilter(ITexture::EFilter::Nearest);
	PongColor->SetMagFilter(ITexture::EFilter::Nearest);
	PongColor->SetWrapMode(ITexture::EWrapMode::Clamp);
	PongFrameBuffer->AttachColorTexture(PongColor, 0);
	if (! PongFrameBuffer->CheckCorrectness())
	{
		Log::Error("Frame buffer not valid!");
	}

	/////////////////
	// Load Assets //
	/////////////////

	CSimpleMesh * SphereMesh = CGeometryCreator::CreateSphere();
	CSimpleMesh * PlaneMesh = CGeometryCreator::CreatePlane(vec2f(100.f));

	SharedPointer<IShader> GeometryShader = AssetManager->LoadShader("Geometry");
	SharedPointer<IShader> SSAOShader = AssetManager->LoadShader("SSAO");
	SharedPointer<IShader> BlurHShader = AssetManager->LoadShader("BlurH");
	SharedPointer<IShader> BlurVShader = AssetManager->LoadShader("BlurV");


	std::uniform_real_distribution<float> randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0
	std::default_random_engine generator;

	// Sample kernel
	int const numSamples = 64;
	std::vector<vec3f> ssaoKernel;
	for (uint i = 0; i < numSamples; ++i)
	{
		float const VerticalBias = 0.1f;

		bool random = true;

		int const sampleRegionWidth = (int) sqrt((float) numSamples);

		float const a = random ? randomFloats(generator) : (float) (i / sampleRegionWidth) / (float) (sampleRegionWidth - 1);
		float const b = random ? randomFloats(generator) : (float) (i % sampleRegionWidth) / (float) (sampleRegionWidth - 1);
		float const c = random ? randomFloats(generator) : (float) (i % 3) / 2.f;

		vec3f sample = vec3f(a * 2 - 1, b * 2 - 1, c * (1.f - VerticalBias) + VerticalBias);
		sample.Normalize();
		sample *= randomFloats(generator);
		float scale = float(i) / numSamples;

		// Scale samples s.t. they're more aligned to center of kernel
		scale = lerp(0.1f, 1.0f, scale * scale);
		sample *= scale;
		ssaoKernel.push_back(sample);
	}

	// Noise texture
	std::vector<float> NoiseData;
	uint const NoiseTexSize = 4;
	for (uint i = 0; i < NoiseTexSize * NoiseTexSize; i++)
	{
		NoiseData.push_back(randomFloats(generator) * 2 - 1);
		NoiseData.push_back(randomFloats(generator) * 2 - 1);
		NoiseData.push_back(0.0);
	}
	SharedPointer<ITexture2D> SSAONoise = GraphicsAPI->CreateTexture2D(vec2i(NoiseTexSize), ITexture::EMipMaps::False, ITexture::EFormatComponents::RGB, ITexture::EInternalFormatType::Float16);
	SSAONoise->Upload(NoiseData.data(), vec2i(NoiseTexSize), ITexture::EFormatComponents::RGB, EScalarType::Float);
	SSAONoise->SetMinFilter(ITexture::EFilter::Nearest);
	SSAONoise->SetMagFilter(ITexture::EFilter::Nearest);


	////////////////////
	// ionScene Setup //
	////////////////////

	CRenderPass * RenderPass = new CRenderPass(Context);
	RenderPass->SetRenderTarget(SceneFrameBuffer);
	SceneManager->AddRenderPass(RenderPass);

	CRenderPass * SSAOPass = new CRenderPass(Context);
	SSAOPass->SetRenderTarget(PingFrameBuffer);
	SceneManager->AddRenderPass(SSAOPass);

	int const BlurPasses = 2;

	CRenderPass * BlurHPasses[BlurPasses] =  { nullptr };
	CRenderPass * BlurVPasses[BlurPasses] =  { nullptr };

	for (int i = 0; i < BlurPasses; ++ i)
	{
		BlurHPasses[i] = new CRenderPass(Context);
		BlurHPasses[i]->SetRenderTarget(PongFrameBuffer);
		SceneManager->AddRenderPass(BlurHPasses[i]);

		BlurVPasses[i] = new CRenderPass(Context);
		BlurVPasses[i]->SetRenderTarget(i + 1 == BlurPasses ? BackBuffer : PingFrameBuffer);
		SceneManager->AddRenderPass(BlurVPasses[i]);
	}
	

	CPerspectiveCamera * Camera = new CPerspectiveCamera(Window->GetAspectRatio());
	Camera->SetPosition(vec3f(-1.7f, 2.8f, 3.4f));
	Camera->SetFocalLength(0.4f);
	Camera->SetNearPlane(0.1f);
	Camera->SetFarPlane(50.f);
	RenderPass->SetActiveCamera(Camera);
	SSAOPass->SetActiveCamera(Camera);

	CCameraController * Controller = new CCameraController(Camera);
	Controller->SetTheta(-0.08f);
	Controller->SetPhi(-0.26f);
	Window->AddListener(Controller);
	TimeManager->MakeUpdateTick(0.02)->AddListener(Controller);


	/////////////////
	// Add Objects //
	/////////////////

	CSimpleMeshSceneObject * Sphere1 = new CSimpleMeshSceneObject();
	Sphere1->SetMesh(SphereMesh);
	Sphere1->SetShader(GeometryShader);
	Sphere1->SetPosition(vec3f(0, 0, 0));
	Sphere1->SetScale(2.f);
	Sphere1->GetMaterial().Diffuse *= color3f(1.0, 0.8f, 0.8f);
	RenderPass->AddSceneObject(Sphere1);

	CSimpleMeshSceneObject * Sphere2 = new CSimpleMeshSceneObject();
	Sphere2->SetMesh(SphereMesh);
	Sphere2->SetShader(GeometryShader);
	Sphere2->SetPosition(vec3f(4, 0, 0));
	Sphere2->SetScale(3.f);
	Sphere2->GetMaterial().Diffuse *= color3f(0.8f, 1, 0.8f);
	RenderPass->AddSceneObject(Sphere2);

	CSimpleMeshSceneObject * Sphere3 = new CSimpleMeshSceneObject();
	Sphere3->SetMesh(SphereMesh);
	Sphere3->SetShader(GeometryShader);
	Sphere3->SetPosition(vec3f(12, 0, 0));
	Sphere3->SetScale(4.f);
	Sphere3->GetMaterial().Diffuse *= color3f(0.8f, 0.9f, 1);
	RenderPass->AddSceneObject(Sphere3);

	CSimpleMeshSceneObject * Sphere4 = new CSimpleMeshSceneObject();
	Sphere4->SetMesh(SphereMesh);
	Sphere4->SetShader(GeometryShader);
	Sphere4->SetPosition(vec3f(3, 0, 6));
	Sphere4->GetMaterial().Diffuse *= color3f(0.9f, 1, 1);
	RenderPass->AddSceneObject(Sphere4);

	CSimpleMeshSceneObject * PlaneObject = new CSimpleMeshSceneObject();
	PlaneObject->SetMesh(PlaneMesh);
	PlaneObject->SetShader(GeometryShader);
	RenderPass->AddSceneObject(PlaneObject);

	CSimpleMesh * DragonMesh = AssetManager->LoadMeshMerged("dragon10k.obj");
	CSimpleMeshSceneObject * DragonObject = new CSimpleMeshSceneObject();
	DragonObject->SetMesh(DragonMesh);
	DragonObject->SetShader(GeometryShader);
	DragonObject->SetPosition(vec3f(6.f, 1.1f, 4.f));
	DragonObject->SetScale(4.f);
	RenderPass->AddSceneObject(DragonObject);

	CSimpleMesh * StairMesh = AssetManager->LoadMeshMerged("SM_StairCase_02.obj");
	CSimpleMeshSceneObject * StairObject = new CSimpleMeshSceneObject();
	StairObject->SetMesh(StairMesh);
	StairObject->SetShader(GeometryShader);
	StairObject->SetPosition(vec3f(12.f, 0.f, 5.f));
	StairObject->SetScale(1.f);
	StairObject->SetRotation(vec3f(0.f, DegToRad(90.f), 0.f));
	RenderPass->AddSceneObject(StairObject);

	float SSAORadius = 1.0f;

	CSimpleMeshSceneObject * PostProcessObject = new CSimpleMeshSceneObject();
	PostProcessObject->SetMesh(CGeometryCreator::CreateScreenTriangle());
	PostProcessObject->SetShader(SSAOShader);
	PostProcessObject->SetTexture("tSceneNormals", SceneNormal);
	PostProcessObject->SetTexture("tSceneDepth", SceneDepth);
	PostProcessObject->SetTexture("texNoise", SSAONoise);
	PostProcessObject->SetUniform("samples[0]", CUniform<vector<vec3f>>(ssaoKernel));
	PostProcessObject->SetUniform("radius", std::make_shared<CUniformReference<float>>(&SSAORadius));
	SSAOPass->AddSceneObject(PostProcessObject);

	CUniform<bool> uDoBlur = true;
	CUniform<bool> uUnconstrained = false;
	CUniform<float> uNormalThreshold = 0.5f;

	for (int i = 0; i < BlurPasses; ++ i)
	{
		CSimpleMeshSceneObject * BlurHObject = new CSimpleMeshSceneObject();
		BlurHObject->SetMesh(CGeometryCreator::CreateScreenTriangle());
		BlurHObject->SetShader(BlurHShader);
		BlurHObject->SetTexture("uTexture", PingColor);
		BlurHObject->SetTexture("tSceneNormals", SceneNormal);
		BlurHObject->SetUniform("uDoBlur", uDoBlur);
		BlurHObject->SetUniform("uUnconstrained", uUnconstrained);
		BlurHObject->SetUniform("uNormalThreshold", uNormalThreshold);
		BlurHPasses[i]->AddSceneObject(BlurHObject);

		CSimpleMeshSceneObject * BlurVObject = new CSimpleMeshSceneObject();
		BlurVObject->SetMesh(CGeometryCreator::CreateScreenTriangle());
		BlurVObject->SetShader(BlurVShader);
		BlurVObject->SetTexture("uTexture", PongColor);
		BlurVObject->SetTexture("tSceneNormals", SceneNormal);
		BlurVObject->SetUniform("uDoBlur", uDoBlur);
		BlurVObject->SetUniform("uUnconstrained", uUnconstrained);
		BlurVObject->SetUniform("uNormalThreshold", uNormalThreshold);
		BlurVPasses[i]->AddSceneObject(BlurVObject);
	}

	CPointLight * Light1 = new CPointLight();
	Light1->SetPosition(vec3f(0, 6, 0));
	RenderPass->AddLight(Light1);


	///////////////
	// Main Loop //
	///////////////

	TimeManager->Init(WindowManager);
	while (WindowManager->Run())
	{
		TimeManager->Update();

		GUIManager->NewFrame();
		ImGui::SetNextWindowPos(ImVec2(10, 10), ImGuiSetCond_Once);
		if (ImGui::Begin("Settings"))
		{
			ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
			ImGui::Text("Camera position: %.3f %.3f %.3f", Camera->GetPosition().X, Camera->GetPosition().Y, Camera->GetPosition().Z);
			ImGui::Text("Camera rotation: %.3f %.3f", Controller->GetTheta(), Controller->GetPhi());

			ImGui::Separator();

			ImGui::SliderFloat("SSAO Radius", &SSAORadius, 0.1f, 20.f);
			ImGui::Checkbox("Do Blur", &uDoBlur.Get());
			ImGui::SameLine();
			ImGui::Checkbox("Unconstrained", &uUnconstrained.Get());
			ImGui::SliderFloat("Normal Threshold", &uNormalThreshold.Get(), -1.f, 1.f);

			ImGui::End();
		}

		SceneFrameBuffer->ClearColorAndDepth();
		BackBuffer->ClearColorAndDepth();
		SceneManager->DrawAll();
		GUIManager->Draw();
		Window->SwapBuffers();
	}

	return 0;
}
int main()
{
	////////////////////
	// ionEngine Init //
	////////////////////

	Log::AddDefaultOutputs();

	SingletonPointer<CGraphicsAPI> GraphicsAPI;
	SingletonPointer<CWindowManager> WindowManager;
	SingletonPointer<CTimeManager> TimeManager;
	SingletonPointer<CSceneManager> SceneManager;
	SingletonPointer<CAssetManager> AssetManager;

	GraphicsAPI->Init(new Graphics::COpenGLImplementation());
	WindowManager->Init(GraphicsAPI);
	TimeManager->Init(WindowManager);
	SceneManager->Init(GraphicsAPI);
	AssetManager->Init(GraphicsAPI);

	CWindow * Window = WindowManager->CreateWindow(vec2i(1600, 900), "DemoApplication", EWindowType::Windowed);

	AssetManager->SetAssetPath("Assets/");
	AssetManager->SetShaderPath("Shaders/");
	AssetManager->SetTexturePath("Images/");

	SharedPointer<IGraphicsContext> Context = GraphicsAPI->GetWindowContext(Window);
	SharedPointer<IRenderTarget> RenderTarget = Context->GetBackBuffer();
	RenderTarget->SetClearColor(color3f(0.3f));


	/////////////////
	// Load Assets //
	/////////////////

	CSimpleMesh * SphereMesh = CGeometryCreator::CreateSphere();
	CSimpleMesh * SkySphereMesh = CGeometryCreator::CreateSkySphere();
	CSimpleMesh * PlaneMesh = CGeometryCreator::CreatePlane(vec2f(100.f));

	SharedPointer<IShaderProgram> DiffuseShader = AssetManager->LoadShader("Diffuse");
	SharedPointer<IShaderProgram> SimpleShader = AssetManager->LoadShader("Simple");
	SharedPointer<IShaderProgram> SpecularShader = AssetManager->LoadShader("Specular");
	SharedPointer<IShaderProgram> SkySphereShader = AssetManager->LoadShader("SkySphere");

	SharedPointer<ITexture2D> SkyMap = AssetManager->LoadTexture("SkyMap.jpg");
	SkyMap->SetMagFilter(ITexture::EFilter::Nearest);


	////////////////////
	// ionScene Setup //
	////////////////////

	CRenderPass * RenderPass = new CRenderPass(Context);
	RenderPass->SetRenderTarget(RenderTarget);
	SceneManager->AddRenderPass(RenderPass);

	CPerspectiveCamera * Camera = new CPerspectiveCamera(Window->GetAspectRatio());
	Camera->SetPosition(vec3f(0, 3, -5));
	Camera->SetFocalLength(0.4f);
	RenderPass->SetActiveCamera(Camera);

	CCameraController * Controller = new CCameraController(Camera);
	Controller->SetTheta(15.f * Constants32::Pi / 48.f);
	Controller->SetPhi(-Constants32::Pi / 16.f);
	Window->AddListener(Controller);
	TimeManager->MakeUpdateTick(0.02)->AddListener(Controller);


	/////////////////
	// Add Objects //
	/////////////////

	CSimpleMeshSceneObject * LightSphere1 = new CSimpleMeshSceneObject();
	LightSphere1->SetMesh(SphereMesh);
	LightSphere1->SetShader(SimpleShader);
	LightSphere1->SetPosition(vec3f(0, 1, 0));
	RenderPass->AddSceneObject(LightSphere1);

	CSimpleMeshSceneObject * LightSphere2 = new CSimpleMeshSceneObject();
	LightSphere2->SetMesh(SphereMesh);
	LightSphere2->SetShader(SimpleShader);
	LightSphere2->SetPosition(vec3f(4, 2, 0));
	RenderPass->AddSceneObject(LightSphere2);

	CSimpleMeshSceneObject * LightSphere3 = new CSimpleMeshSceneObject();
	LightSphere3->SetMesh(SphereMesh);
	LightSphere3->SetShader(SimpleShader);
	LightSphere3->SetPosition(vec3f(12, 3, 0));
	RenderPass->AddSceneObject(LightSphere3);

	CSimpleMeshSceneObject * SpecularSphere = new CSimpleMeshSceneObject();
	SpecularSphere->SetMesh(SphereMesh);
	SpecularSphere->SetShader(SpecularShader);
	SpecularSphere->SetPosition(vec3f(3, 3, 6));
	SpecularSphere->GetMaterial().Ambient = vec3f(0.05f);
	RenderPass->AddSceneObject(SpecularSphere);

	CSimpleMeshSceneObject * PlaneObject = new CSimpleMeshSceneObject();
	PlaneObject->SetMesh(PlaneMesh);
	PlaneObject->SetShader(DiffuseShader);
	PlaneObject->GetMaterial().Ambient = vec3f(0.05f);
	RenderPass->AddSceneObject(PlaneObject);

	CSimpleMeshSceneObject * SkySphereObject = new CSimpleMeshSceneObject();
	SkySphereObject->SetMesh(SkySphereMesh);
	SkySphereObject->SetShader(SkySphereShader);
	SkySphereObject->SetTexture("uTexture", SkyMap);
	RenderPass->AddSceneObject(SkySphereObject);

	CPointLight * Light1 = new CPointLight();
	Light1->SetPosition(vec3f(0, 1, 0));
	Light1->SetColor(Colors::Red);
	RenderPass->AddLight(Light1);

	CPointLight * Light2 = new CPointLight();
	Light2->SetPosition(vec3f(4, 2, 0));
	Light2->SetColor(Colors::Green);
	RenderPass->AddLight(Light2);

	CPointLight * Light3 = new CPointLight();
	Light3->SetPosition(vec3f(12, 3, 0));
	Light3->SetColor(Colors::Blue);
	RenderPass->AddLight(Light3);


	///////////////
	// Main Loop //
	///////////////

	TimeManager->Init(WindowManager);
	while (WindowManager->Run())
	{
		TimeManager->Update();

		float const MinimumBrightness = 0.2f;
		float const MaximumBrightness = 1.f - MinimumBrightness;
		float const Brightness = (Sin<float>((float) TimeManager->GetRunTime()) / 2.f + 0.5f) * MaximumBrightness + MinimumBrightness;
		float const Radius = Brightness * 10.f;
		Light1->SetRadius(Radius);
		Light2->SetRadius(Radius);
		Light3->SetRadius(Radius);

		float const Bright = 1;
		float const Dim = 0.5f;
		LightSphere1->GetMaterial().Diffuse = color3f(Bright, Dim, Dim) * Brightness;
		LightSphere2->GetMaterial().Diffuse = color3f(Dim, Bright, Dim) * Brightness;
		LightSphere3->GetMaterial().Diffuse = color3f(Dim, Dim, Bright) * Brightness;
		LightSphere1->SetScale(Brightness);
		LightSphere2->SetScale(Brightness);
		LightSphere3->SetScale(Brightness);

		SkySphereObject->SetPosition(Camera->GetPosition());

		RenderTarget->ClearColorAndDepth();
		SceneManager->DrawAll();
		Window->SwapBuffers();
	}

	return 0;
}