コード例 #1
0
ファイル: scene.cpp プロジェクト: bajabob/OpenGL-Ray-Tracing
scene::scene( const vec &camera ) :
		camera_width( 3 ), camera_height( 3 ), camera_center( 3 ), camera_slope(
				3 ) {
	camera_center = camera;

	float x = 0.9285;
	float y = 0;
	float z = -0.3714;
	float angle = 1.5;

	camera_slope( 0 ) = x;
	camera_slope( 1 ) = y;
	camera_slope( 2 ) = z;

	vec camera_up( 3 );
	camera_up( 0 ) = -z;
	camera_up( 1 ) = y;
	camera_up( 2 ) = x;

	vec y_cross( 3 );
	y_cross( 0 ) = 0;
	y_cross( 1 ) = -1;
	y_cross( 2 ) = 0;

	camera_width = (rotation_matrix( camera_up, -angle / 2.0 ) * camera_slope)
			- (rotation_matrix( camera_up, angle / 2.0 ) * camera_slope);
	camera_height = (rotation_matrix( y_cross, -angle / 2.0 ) * camera_slope)
			- (rotation_matrix( y_cross, angle / 2.0 ) * camera_slope);
}
コード例 #2
0
ファイル: bump.cpp プロジェクト: ishikawash/glfw-example
int main(int argc, char **args)
{
  const char *ctm_filepath = (argc > 1) ? args[1] : "teapot.ctm";

	trackback_state_initialize(camera_rotation);
	trackback_state_initialize(light_rotation);
	current_trackball_state = &camera_rotation;

  if (!glfwInit()) {
    std::cerr << "Failed to initialize GLFW" << std::endl;
    exit(EXIT_FAILURE);
  }

  int depth_bits = 16;
  if (!glfwOpenWindow(640, 480, 0, 0, 0, 0, depth_bits, 0, GLFW_WINDOW)) {
    std::cerr << "Failed to open GLFW window" << std::endl;
    glfwTerminate();
    exit(EXIT_FAILURE);
  }
  glfwGetWindowSize(&screen_width, &screen_height);
  glfwSetWindowSizeCallback(resize);
  glfwSetKeyCallback(keyboard);
  glfwSetMouseButtonCallback(mouse);
  glfwSetMousePosCallback(motion);
  glfwSetWindowTitle("Spinning Teapot");
  glfwEnable(GLFW_STICKY_KEYS);
  glfwSwapInterval(1);

	// Shaders
	shader_program_t phong_shader;
	build_shader_program(phong_shader, "phong.vs", "phong.fs");
	shader_program_t rect_shader;
	build_shader_program(rect_shader, "rect.vs", "rect.fs");
	shader_program_t render_buffer_shader;
	build_shader_program(render_buffer_shader, "render_buffer.vs", "render_buffer.fs");
	shader_program_t bump_shader;
	build_shader_program(bump_shader, "bump.vs", "bump.fs");

	//--- Mesh Objects
	mesh_t mesh_floor;
	load_mesh_cube(mesh_floor);
  mesh_object_t floor;
  if (! build_mesh_object(mesh_floor, floor) ) {
    glfwTerminate();
    exit(EXIT_FAILURE);	
	}

	mesh_t mesh_plane;
	load_mesh_plane(mesh_plane);
  mesh_object_t plane;
  if (! build_mesh_object(mesh_plane, plane) ) {
    glfwTerminate();
    exit(EXIT_FAILURE);	
	}

	mesh_t mesh_teapot;
	if (! load_mesh_from_file(ctm_filepath, mesh_teapot) ) {
	  glfwTerminate();
    exit(EXIT_FAILURE);		
	}
	compute_tangent_vectors(mesh_teapot);
  mesh_object_t teapot;
  if (! build_mesh_object(mesh_teapot, teapot) ) {
	  glfwTerminate();
    exit(EXIT_FAILURE);
	}

  //--- Texture
	const char *texture_filepath = "checker.tga";
	texture_t tex;
	tex.unit_id = 1;
	if (! build_texutre_from_file(texture_filepath, tex)) {
		std::cout << "Failed to load texture: " << texture_filepath << std::endl;
	  glfwTerminate();
	  exit(EXIT_FAILURE);		
	}

	//--- FBO
	texture_t depth_tex_buffer;
	int depth_tex_width = 2 * screen_width;
	int depth_tex_height = 2 * screen_height;
	depth_tex_buffer.unit_id = 2;
	GLuint fb_handle;
	create_framebuffer_and_depth_texture(depth_tex_width, depth_tex_height, depth_tex_buffer, &fb_handle);

	// Scene settings
  glm::vec3 camera_position(0.0f, 0.0f, 5.0f);
  glm::vec3 camera_center(0.0f, 0.0f, 0.0f);
  glm::vec3 camera_up(0.0f, 1.0f, 0.0f);
  glm::mat4 view_matrix = glm::lookAt(camera_position, camera_center, camera_up); // from world to camera

	glm::mat4 light_pov_matrix;	
	glm::mat4 bias(
		0.5f, 0.0f, 0.0f, 0.0f,
		0.0f, 0.5f, 0.0f, 0.0f,
		0.0f, 0.0f, 0.5f, 0.0f,
		0.5f, 0.5f, 0.5f, 1.0f
		);

	teapot.material.diffuse = glm::vec3(0.0f, 1.0f, 1.0f);
	teapot.material.specular = glm::vec3(0.8f);
	teapot.material.shininess = 128.0f;	
	teapot.textures.push_back(tex);	
	teapot.textures.push_back(depth_tex_buffer);
	
	floor.material.diffuse = glm::vec3(1.0f, 1.0f, 1.0f);
	floor.material.specular = glm::vec3(0.8f);
	floor.material.shininess = 2.0f;
	floor.textures.push_back(depth_tex_buffer);
	
	plane.textures.push_back(depth_tex_buffer);

	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

  do {
		//--- Transform
		glm::vec3 light_position = glm::mat3_cast(light_rotation.orientation) * glm::vec3(0.0f, 5.0f, 0.0f);
		glm::vec3 light_center(0.0f, 0.0f, 0.0f);
		glm::vec3 light_up(0.0f, 0.0f, 1.0f);
		glm::mat4 light_view_matrix = glm::lookAt(light_position, light_center, light_up);
		
		teapot.matrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.5f, 0.0f));
		floor.matrix = glm::scale(glm::mat4(1.0f), glm::vec3(2.0f, 0.05f, 2.0f));
		plane.matrix = glm::scale(glm::mat4(1.0f), glm::vec3(screen_width, screen_height, 1.0f));
		
		//--- Render
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_handle);
		{
	    __projection_matrix = glm::perspective(30.0f, (float) screen_width / (float) screen_height, 0.5f, 30.0f);
			__view_matrix = light_view_matrix;
			light_pov_matrix = bias * __projection_matrix * light_view_matrix;
			
			glClear(GL_DEPTH_BUFFER_BIT);
			glClearDepth(1.0f);
			glViewport(0, 0, depth_tex_width, depth_tex_height);
			teapot.shader_program = &render_buffer_shader;
			teapot.shader_program->bind();
			render_object(teapot);
			teapot.shader_program->release();
			floor.shader_program = &render_buffer_shader;
			floor.shader_program->bind();
    	render_object(floor);
			floor.shader_program->release();		
		}
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);		
	
#ifdef DEPTH_BUFFER_DEBUG
		{
			__projection_matrix = glm::ortho(0.0f, (float)screen_width, 0.0f, (float)screen_height, 0.5f, 1.0f);
			__view_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -1.0f));
			
			glDisable(GL_DEPTH_TEST);
			glClear(GL_COLOR_BUFFER_BIT);		
    	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    	glViewport(0, 0, screen_width, screen_height);	
			plane.shader_program = &rect_shader;
			plane.shader_program->bind();	
			plane.shader_program->set_uniform_value("texture2", depth_tex_buffer.unit_id); 
	  	render_object(plane);
			plane.shader_program->release();
			glEnable(GL_DEPTH_TEST);
		}
#endif

#ifndef DEPTH_BUFFER_DEBUG
		{			
			glCullFace(GL_BACK);
			glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
			glClearDepth(1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			glViewport(0, 0, screen_width, screen_height);

	    __projection_matrix = glm::perspective(camera_fovy, (float) screen_width / (float) screen_height, 1.0f, 30.0f);
			__view_matrix = view_matrix * glm::mat4_cast(camera_rotation.orientation);

#ifdef USE_BUMP_MAPPING
			teapot.shader_program = &bump_shader;
			teapot.shader_program->bind();		
			teapot.shader_program->set_uniform_value("light_world_position", light_position);
			teapot.shader_program->set_uniform_value("surface_color", glm::vec3(0.7f, 0.6f, 0.18f));
			teapot.shader_program->set_uniform_value("bump_density", 16.0f);
			teapot.shader_program->set_uniform_value("bump_size", 0.15f);
			teapot.shader_program->set_uniform_value("specular_factor", 0.5f);
			render_object(teapot);
			teapot.shader_program->release();
#else
			teapot.shader_program = &phong_shader;
			teapot.shader_program->bind();		
			teapot.shader_program->set_uniform_value("light_world_position", light_position);
			teapot.shader_program->set_uniform_value("light_pov_matrix", light_pov_matrix);
			teapot.shader_program->set_uniform_value("texture1", tex.unit_id); 
			teapot.shader_program->set_uniform_value("texture2", depth_tex_buffer.unit_id); 
			render_object(teapot);
			teapot.shader_program->release();
#endif

			floor.shader_program = &phong_shader;
			floor.shader_program->bind();	
			floor.shader_program->set_uniform_value("light_world_position", light_position);
			floor.shader_program->set_uniform_value("light_pov_matrix", light_pov_matrix);
			floor.shader_program->set_uniform_value("texture2", depth_tex_buffer.unit_id); 
	    render_object(floor);
			floor.shader_program->release();	
		}
#endif

    glfwSwapBuffers();

  }
  while (glfwGetKey(GLFW_KEY_ESC) != GLFW_PRESS && glfwGetWindowParam(GLFW_OPENED));

  glfwTerminate();

  return 0;
}
コード例 #3
0
ファイル: render_dx10.cpp プロジェクト: as2120/ZNginx
void RenderFrameDX10(void)
{
	Vector4 vClearColor(0.4f, 0.4f, 0.4f, 1.0f);

	// frame buffer
	ID3D10RenderTargetView *pRenderTargetView = GutGetDX10RenderTargetView(); 
	// depth/stencil buffer
	ID3D10DepthStencilView *pDepthStencilView = GutGetDX10DepthStencilView(); 
	// front/back buffer
	IDXGISwapChain *pSwapChain = GutGetDX10SwapChain(); 

	// `清除顏色`
	g_pDevice->ClearRenderTargetView(pRenderTargetView, (float *)&vClearColor);
	// `清除`Depth/Stencil buffer
	g_pDevice->ClearDepthStencilView(pDepthStencilView, D3D10_CLEAR_DEPTH | D3D10_CLEAR_STENCIL, 1.0f, 0);

	Vector4 camera_lookat(0.0f, 0.0f, 0.0f);
	int w, h;
	GutGetWindowSize(w, h);

	Matrix4x4 view_matrix;
	Matrix4x4 ortho_proj = GutMatrixOrthoRH_DirectX(20.0f, 20.0f, 0.1f, 100.0f);

	// `前視圖`
	{
		D3D10_VIEWPORT vp = {0, 0, w/2, h/2, 0.0f, 1.0f};
		g_pDevice->RSSetViewports(1, &vp);
		// view matrix
		Vector4 camera_pos(0.0f, -20.0f, 0.0f);
		Vector4 camera_up(0.0f, 0.0f, 1.0f);
		view_matrix = GutMatrixLookAtRH(camera_pos, camera_lookat, camera_up);
		// render objects
		RenderSolarSystemDX10(view_matrix, ortho_proj);
	}
	// `上視圖`
	{
		D3D10_VIEWPORT vp = {w/2, 0, w/2, h/2, 0.0f, 1.0f};
		g_pDevice->RSSetViewports(1, &vp);
		// view matrix
		Vector4 camera_pos(0.0f, 0.0f, 20.0f);
		Vector4 camera_up(0.0f, 1.0f, 0.0f);
		view_matrix = GutMatrixLookAtRH(camera_pos, camera_lookat, camera_up);
		// render objects
		RenderSolarSystemDX10(view_matrix, ortho_proj);
	}
	// `右視圖`
	{
		D3D10_VIEWPORT vp = {0, h/2, w/2, h/2, 0.0f, 1.0f};
		g_pDevice->RSSetViewports(1, &vp);
		// view matrix
		Vector4 camera_pos(20.0f, 0.0f, 0.0f);
		Vector4 camera_up(0.0f, 0.0f, 1.0f);
		view_matrix = GutMatrixLookAtRH(camera_pos, camera_lookat, camera_up);
		// render objects
		RenderSolarSystemDX10(view_matrix, ortho_proj);
	}
	// `使用者視角`
	{
		D3D10_VIEWPORT vp = {w/2, h/2, w/2, h/2, 0.0f, 1.0f};
		g_pDevice->RSSetViewports(1, &vp);
		// view matrix
		Matrix4x4 view_matrix = g_Control.GetViewMatrix();
		Matrix4x4 object_matrix = g_Control.GetObjectMatrix();
		view_matrix = object_matrix * view_matrix;
		// render objects
		RenderSolarSystemDX10(view_matrix, g_proj_matrix);
	}
	// `畫邊線`
	{
		UINT stride = sizeof(Vertex_VC);
		UINT offset = 0;

		D3D10_VIEWPORT vp = {0, 0, w, h, 0.0f, 1.0f};
		g_pDevice->RSSetViewports(1, &vp);

		// `設定`vertex shader
		g_pDevice->VSSetShader(g_pVertexShader);
		// `設定`pixel shader
		g_pDevice->PSSetShader(g_pPixelShader);
		// `設定vertex shader讀取參數的記憶體位置`
		g_pDevice->VSSetConstantBuffers(0, 1, &g_pConstantBuffer);

		Matrix4x4 *pConstData;
		g_pConstantBuffer->Map( D3D10_MAP_WRITE_DISCARD, NULL, (void **) &pConstData );
		pConstData->Identity();
		g_pConstantBuffer->Unmap();

		g_pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINELIST);
		g_pDevice->IASetVertexBuffers(0, 1, &g_pBorderVertexBuffer, &stride, &offset);
		g_pDevice->Draw(4, 0);
	}
	// `等待硬體掃結束, 然後才更新畫面.`
	pSwapChain->Present(1, 0);
}
コード例 #4
0
ファイル: main.cpp プロジェクト: DiogoDantas/GraphicPipeline
//-----------------------------------------------------------------------------
void MyGlDraw(void)
{

	clearScreen();
	//*************************************************************************
	// Chame aqui as funções do mygl.h
	//*************************************************************************

	objData = new objLoader();			// cria o objeto que carrega o modelo
	objData->load("models/monkey_head2.obj");	// a carga do modelo é indicada atraves do nome do arquivo.
						// Neste caso, deve ser sempre do tipo OBJ.

	/**************creating the list of all vertexs**********************/
	std::vector<glm::vec4> vertex_list;
	std::vector<Vertex> my_list;
	obj_vector* vector;
	obj_face* faces;

	//std::cout<<"object vertex list"<<std::endl;
	for (int i = 0; i < objData->vertexCount; ++i)
	{
		vector =  objData->vertexList[i];
		glm::vec4 aux(vector->e[0], vector->e[1], vector->e[2], 1.0);
		//PrintVec4(aux);
		vertex_list.push_back(aux);
	}

	/******OBJECT SPACE TO UNIVERSE SPACE******/
	glm::mat4 Scale = glm::mat4(2.0);
	Scale[3].w = 1.0;

	glm::mat4 Trans = glm::mat4(1.0);
	glm::vec4 v(1.0,1.0, 1.0, 1.0);
	Trans[3] = v;

	glm::mat4 Rotate = glm::mat4(1.0);
    Rotate[0].x = cos(angle +=1 * PI/180.0);
    Rotate[2].x = sin(angle +=1 * PI/180.0);
    Rotate[0].z = - sin(angle +=1 * PI/180.0);
    Rotate[2].z = cos(angle +=1 * PI/180.0);
    Rotate[3].w = 1.0;

	glm::mat4 M_Model = Rotate * Scale;

	/******OBJECT SPACE TO UNIVERSE SPACE******/

	/******UNIVERSE SPACE TO CAMERA SPACE******/

	glm::vec3 camera_pos(0.0,0.0,5.0);
	glm::vec3 look_at(0.0,0.0,0.0);
	glm::vec3 camera_up(0.0,1.0,0.0);

	glm::vec3 camera_dir = look_at - camera_pos;


	glm::vec3 z_camera = -normalize(camera_dir);
	glm::vec3 x_camera = normalize(cross(camera_up, z_camera));
	glm::vec3 y_camera = normalize(cross(z_camera, x_camera));


	glm::vec4 homog(0.0,0.0,0.0,1.0);

	glm::mat4 B = glm::mat4(1.0);

	B[0]= glm::vec4 (x_camera,0.0);
	B[1]= glm::vec4 (y_camera,0.0);
	B[2]= glm::vec4 (z_camera,0.0);
	B[3]=homog;

	glm::mat4 trans = glm::mat4(1.0);
	trans[3] = glm::vec4 (-camera_pos, 1.0);

	glm::mat4 M_View = transpose(B) * trans;

	glm::mat4 Model_View = M_View * M_Model;

	/******UNIVERSE SPACE TO CAMERA SPACE******/

	/******CAMERA SPACE TO PROJECTION SPACE (CLIPPING)******/

	double d=1.0;

	glm::mat4 M_Projection = glm::mat4(1.0);
	M_Projection[2] = glm::vec4(0.0, 0.0, 1.0, -1.0/d);
	M_Projection[3] = glm::vec4(0.0, 0.0, d, 0.0);


	glm::mat4 M_ModelViewProjection = M_Projection * Model_View;



	/******CAMERA SPACE TO PROJECTION SPACE (CLIPPING)******/

	/******PROJECTION SPACE (CLIPPING) TO CANONICAL SPACE******/
	//std::cout<<"PRINTING"<<std::endl;

	for (int i = 0; i < objData->vertexCount; ++i)
	{
		vertex_list[i]=M_ModelViewProjection*vertex_list[i];
		vertex_list[i].x=vertex_list[i].x/vertex_list[i].w;
		vertex_list[i].y=vertex_list[i].y/vertex_list[i].w;
		vertex_list[i].z=vertex_list[i].z/vertex_list[i].w;
		vertex_list[i].w=vertex_list[i].w/vertex_list[i].w;
	}

	/******PROJECTION SPACE (CLIPPING) TO CANONICAL SPACE******/

	/******CANONICAL SPACE TO SCREEN SPACE******/
	glm::mat4 Translation_Screen = glm::mat4(1.0);
	Translation_Screen[3] = glm::vec4((IMAGE_WIDTH -1)/2, (IMAGE_HEIGHT -1)/2, 0.0, 1.0);

	glm::mat4 Scale_Screen = glm::mat4(1.0);
	Scale_Screen[0].x = IMAGE_WIDTH/2;
	Scale_Screen[1].y = IMAGE_HEIGHT/2;

	glm::mat4 InvertY_Screen = glm::mat4(1.0);
	InvertY_Screen[1].y = -1.0;

	glm::mat4 Final_Matrix = glm::mat4(1.0);
	//Final_Matrix = InvertY_Screen * Scale_Screen * Translation_Screen;
	Final_Matrix = Translation_Screen * Scale_Screen * InvertY_Screen;
	//PrintMatrix(Final_Matrix);

	for (int i = 0; i < objData->vertexCount; ++i)
	{
		vertex_list[i] = Final_Matrix * vertex_list[i];
		//PrintVec4(vertex_list[i]);
	}

	/******CANONICAL SPACE TO SCREEN SPACE******/


	//std::cout<<"object vertex list"<<std::endl;
	for (int i = 0; i < objData->vertexCount; ++i)
	{
		Vertex tmp;

		tmp.setX(round(vertex_list[i].x));
		tmp.setY(round(vertex_list[i].y));
		tmp.setZ(round(vertex_list[i].z));
		tmp.setW(round(vertex_list[i].w));

		my_list.push_back(tmp);
	}


	for (int i = 0; i < objData->faceCount; ++i)
	{
		faces = objData->faceList[i];
		my_list[faces->vertex_index[0]].DrawTriangle(my_list[faces->vertex_index[1]], my_list[faces->vertex_index[2]]);
	}






}
コード例 #5
0
ファイル: render_opengl.cpp プロジェクト: chenbk85/3dlearn
// 使用OpenGL來繪圖
void RenderFrameOpenGL(void)
{
	// `取得視窗大小`
	int w, h;
	GutGetWindowSize(w, h);
	// `清除畫面`
	glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	Vector4 camera_lookat(0.0f, 0.0f, 0.0f);
	Matrix4x4 ortho_proj = GutMatrixOrthoRH_OpenGL(20.0f, 20.0f, 0.1f, 100.0f);

	{
		// `前視圖`
		glViewport(0, h/2, w/2, h/2);
		// view matrix
		Vector4 camera_pos(0.0f, -20.0f, 0.0f);
		Vector4 camera_up(0.0f, 0.0f, 1.0f);
		g_view_matrix = GutMatrixLookAtRH(camera_pos, camera_lookat, camera_up);
		// projection matrix
		glMatrixMode(GL_PROJECTION);
		glLoadMatrixf(&ortho_proj[0][0]);
		// render objects
		RenderSolarSystemOpenGL();
	}
	{
		// `上視圖`
		glViewport(w/2, h/2, w/2, h/2);
		// view matrix
		Vector4 camera_pos(0.0f, 0.0f, 20.0f);
		Vector4 camera_up(0.0f, 1.0f, 0.0f);
		g_view_matrix = GutMatrixLookAtRH(camera_pos, camera_lookat, camera_up);
		// projection matrix
		glMatrixMode(GL_PROJECTION);
		glLoadMatrixf(&ortho_proj[0][0]);
		// render objects
		RenderSolarSystemOpenGL();
	}
	{
		// `右視圖`
		glViewport(0, 0, w/2, h/2);
		// view matrix
		Vector4 camera_pos(20.0f, 0.0f, 0.0f);
		Vector4 camera_up(0.0f, 0.0f, 1.0f);
		g_view_matrix = GutMatrixLookAtRH(camera_pos, camera_lookat, camera_up);
		// projection matrix
		glMatrixMode(GL_PROJECTION);
		glLoadMatrixf(&ortho_proj[0][0]);
		// render objects
		RenderSolarSystemOpenGL();
	}
	{
		// `使用者視角`
		glViewport(w/2, 0, w/2, h/2);
		// object * view matrix
		Matrix4x4 object_matrix = g_Control.GetObjectMatrix();
		Matrix4x4 view_matrix = g_Control.GetViewMatrix();
		g_view_matrix = object_matrix * view_matrix;
		// projection matrix
		glMatrixMode(GL_PROJECTION);
		glLoadMatrixf(&g_projection_matrix[0][0]);
		// render objects
		RenderSolarSystemOpenGL();
	}
	{
		// `畫出viewport的邊界`
		glViewport(0, 0, w, h);

		glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);

		glEnableClientState(GL_VERTEX_ARRAY);
		// projection matrix
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		// worldview matrix
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		// `畫邊界`
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
		glVertexPointer(3, GL_FLOAT, sizeof(Vertex_VC), g_Border);
		glDrawArrays(GL_LINES, 0, 4);

		glPopClientAttrib();
	}
	// `把背景backbuffer的畫面呈現出來`
	GutSwapBuffersOpenGL();
}
コード例 #6
0
int main(int argc, char **args)
{
  if (!glfwInit()) {
    std::cerr << "Failed to initialize GLFW" << std::endl;
    exit(EXIT_FAILURE);
  }

  int depth_bits = 16;
  if (!glfwOpenWindow(640, 480, 0, 0, 0, 0, depth_bits, 0, GLFW_WINDOW)) {
    std::cerr << "Failed to open GLFW window" << std::endl;
    glfwTerminate();
    exit(EXIT_FAILURE);
  }
  glfwGetWindowSize(&screen_width, &screen_height);
  glfwSetWindowTitle("Teapot");
  glfwEnable(GLFW_STICKY_KEYS);
  glfwSwapInterval(1);

	shader_program_t shader_program;
	shader_program_t::build(shader_program, "diffuse.vs", "diffuse.fs");

	mesh_t teapot;
	if (! mesh_t::read_from_file("teapot.ctm", teapot)) {
		std::cerr << "Failed to read ctm file" << std::endl;
	  glfwTerminate();
    exit(EXIT_FAILURE);		
	}
	teapot.load_to_buffers();
	
	projection_matrix = glm::perspective(camera_fovy, (float) screen_width / (float) screen_height, 1.0f, 30.0f);

  glm::vec3 camera_position(0.0f, 0.0f, 3.0f);
  glm::vec3 camera_center(0.0f, 0.0f, 0.0f);
  glm::vec3 camera_up(0.0f, 1.0f, 0.0f);
  view_matrix = glm::lookAt(camera_position, camera_center, camera_up); // from world to camera

	normal_matrix = glm::mat3(glm::transpose(glm::inverse(view_matrix)));

	light_direction = glm::vec3(0.0, -1.0, 0.0);

	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

  do {
		
		{			
			glCullFace(GL_BACK);
			glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
			glClearDepth(1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			glViewport(0, 0, screen_width, screen_height);

			shader_program.bind();
			shader_program.set_uniform_value("light_direction", light_direction);
			shader_program.set_uniform_value("projection_matrix", projection_matrix);
			shader_program.set_uniform_value("model_view_matrix", view_matrix);
			shader_program.set_uniform_value("normal_matrix", normal_matrix);
			teapot.render(shader_program);
			shader_program.release();
		}

    glfwSwapBuffers();

  }
  while (glfwGetKey(GLFW_KEY_ESC) != GLFW_PRESS && glfwGetWindowParam(GLFW_OPENED));

  glfwTerminate();

  return 0;
}