Thursday, July 14, 2022

Lesson03:Indexed Cube with interpolated colors

 


In Lesson02 we saw that VBO were used to draw the single colored cube. In this post we  will discuss how to draw an Indexed cube using EBO with interpolated colors. It looks as shown above.

Drawing a cube with VBO requires binding VBO of 12 vertices containing position and optionally  normal vector, color, Texture coordinate data. Whereas an  Indexed draw requires binding VBO of 8 vertices containing position, normal vector, color, Texture coordinate data and bind an EBO containing 12 indices. 
To draw a VBO cube glDrawArrays API is used where as for EBO or Indexed, glDrawElements is used. Here the EBO contains indices data.
Color interpolation means a triangle's fragment's color is computed by interpolating colors of the vertices. 

Implementation
IndexedCube class is implemented as below. It's located in VOGLLib\Geometry\Cube\IndexedCube .h.
       
#pragma once
#include "..\BaseGeometry.h"
#include "CubeMesh.h"

//implements EBO Indexed cube
class IndexedCube :public BaseGeometry
{
public:

	void Init()
	{
		//initialize
		BaseGeometry::Init(new CubeMesh());
		//update VBO data of the vertices
		mesh->GenerateVerticesData(true, VAOUtil::POS | VAOUtil::CLR, vaoutl);
		//setup vertex for Position
		vaoutl.SetupVBO(0, VAOUtil::POS);
		//setup vertex for Color
		vaoutl.SetupVBO(1, VAOUtil::CLR);
		//populate EBO indices
		kount = mesh->GenerateIndicesData(vaoutl);
		//bind VBO
		vaoutl.SetupEBO();

		vaoutl.unbindVAO();
	}

	//draw
	void Draw()
	{
		BaseGeometry::Draw(true);
	}

	//override
	virtual string vertexShaderSource()
	{
		return R"(
		#version 330 core
		layout (location = 0) in vec3 vVertex;
		layout (location = 1) in vec3 vColor;
		out vec3 fcolor;

		uniform mat4 transform;

		void main()
		{
		   gl_Position =  transform * vec4(vVertex, 1.0);
		   fcolor = vColor;
		};
		)";
	}

	//override
	virtual string fragmentShaderSource()
	{
		return R"(
		#version 330 core
		in vec3 fcolor;
		out vec4 FragColor;
		void main()
		{
		   FragColor = vec4(fcolor,1.0);
		};
		)";
	}

};     
 
Lesson03 Project

This purpose of this Lesson03 project is to create a Window initialized with OpenGL context and draw a IndexedCube with interpolated colors.
As discussed in introduction create tutorial lesson project Lesson03 under Lessons folder.
Add a header file Scene.h as shown below. The class itself is self explanatory. 
The WM_CLOSE  event is  handled in OnCloseWindow function and the window is destroyed and  application is shutdown. 
The Init method calls BaseScene's Init to create hosting window and OpenGL Context. It also attaches BaseCameraInputHandler to rotate the cube either by keyboard or mouse inputs.
The DrawScene method draws the cube with interpolated colors and rotates as per keyboard or mouse inputs.
The Cleanup method release the resources.

The Scene class is implemented as below. It's located in Lessons\Lesson03\Scene.h file.
       
#include "Scene\BaseScene.h"
#include "Geometry\Cube\IndexedCube.h"

class Scene:public BaseScene
{
public:
	//message handler
	BEGIN_MSG_MAP(Scene0)
		MESSAGE_HANDLER(WM_CLOSE, OnCloseWindow)
		CHAIN_MSG_MAP(BaseScene)
	END_MSG_MAP()

	//override
	int Init(RECT rect, WCHAR *windowname)
	{
		//create host window and context
		BaseScene::Init(rect, windowname);
		//attach mouse keyboard input handler
		mskbd = new BaseCameraInputHandler(m_hWnd);

		//Create cube an set color
		cube.Init();
		
		return 0;
	}

	//release resources
	void Cleanup()
	{
		cube.Cleanup();
		delete mskbd;
		
	}
	
	//draw the scene
	void DrawScene()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		//get model view projection matrix. 
		//only model is modified
		//view and projection will be identity matrix
		mskbd->fetchCameraData(&cube.camera);
		cube.Draw();

	}

	//Close the window
	LRESULT OnCloseWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = TRUE;
		DestroyWindow();
		PostQuitMessage(0);
		return 0;
	}


private:
	IndexedCube cube;
};      
 
The main.cpp is located in Lessons\Lesson03\main.cpp file. It creates the scene object and calls its init method.
       
#include "Scene.h"

Scene scene;

int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd_line, int show)
{
	scene.Init(RECT{ 100, 100, 780, 500 }, L"Modern OpenGL-Tutorial - Lesson03");
	scene.ShowWindow(show);

	MSG msg;
	while (GetMessage(&msg, 0, 0, 0)) 
	{
		TranslateMessage(&msg);
		DispatchMessageA(&msg);
	}

	return 0;
}     
 
The output looks as shown in the top. The cube is rotated by 20 degrees pitch and 20 degrees yaw. The camera position at the origin looking down on -Z axis or the back face of the cube.
To rotate the cube X,Y and Z keys can be used. They rotate respectively pitch, yaw and roll the cube  by 10 degrees,
In the next post we shall create a textured cube.

No comments:

Post a Comment