Gonzo
Contents
Sl. No. Title Page Numbers
1 Abstract 2
2 Introduction 3
3 Requirement Specifications 4
4 Project Implementation 5-7
5 Source Code 8 - 29
6 Snapshots 30
7 Conclusion 31
8 Bibliography 32
Abstract
Dept of CSE 2018-19 Page | 1
Gonzo
Computer Graphics is a vast field that encompasses almost any graphical aspect.
Although the main interest in Computer Graphics is mainly in the 3D development world, the
importance and uses of 2D Graphics is still relevant till today. Here, in our project, the
Graphical User Interface is developed using the C Language making use of its graphical
capabilities. The aim of this project is to enable the user to interact with the graphical
elements, which are generated using the C Language.
‘Gonzo’ is a collision detection game which scores the user based on the number of
collisions with the obstacles. As the number of the collisions increase, the difficulty of the
game increases. This game aims to test the reflexes of the user and thus, can be used to
sharpen the reflexive senses of the user. The game ‘Gonzo’ consists of a ‘paddle’, a ‘ball’ and
a bunch of obstacles called ‘bricks’. The player gets to control only the ‘paddle’.
The main features of this project include the most basic components of graphical
routines followed by different methods used to demonstrate the drawings. This project makes
use of various well known algorithms to draw spheres, rectangles and certain irregular
shapes. It also implements mouse and keyboard functions to enable the user to interact with
the graphical elements by making use of the mouse and keyboard .This project also
implements a graphical menu to change the various settings of the game such as the colours
of the brick, the paddle and the ball. It also provides options to change the difficulty of the
game and the size of the paddle.
Introduction
Dept of CSE 2018-19 Page | 2
Gonzo
A game is a structured form of play, usually undertaken for enjoyment and sometimes
used an educational tool. This project ‘Gonzo’ incorporates this concept to present a single
player game to the user.
This project ‘Gonzo’ has been designed to implement an interactive Graphical User
Interface using various OpenGL functions and methods. This game makes use of an uncanny
collision detection algorithm to detect the collisions between the ‘a brick and the ball’ and
‘the paddle and the ball’. This project also implements certain game physics like the law of
reflection.
The game ‘Gonzo’ scores the user based on the number of collisions with the
obstacles called ‘bricks’. There are 2 different types of bricks in each scenario, one which
gives a score of 1 when collided with, and one which gives a score of 2 when collided with.
This game also keeps track of the maximum score attained in any session of the game. The
game also offers a ‘life system’ where a user is given 3 chances to win the game.
The game is ‘won’ when the user manages to collide the ball with all the bricks on the
screen. The game is ‘lost’ when the user fails to do the above task within 3 tries. A game
‘failure’ is the scenario when the ball fails to collide with the paddle and reflect back towards
the bricks. Any such ‘failure’ will lead to a loss of ‘life’. Every user is granted 3 such ‘lives’
at the start of every game session.
This game is thus designed to help the user refine his/her reflexes. It is aimed to
promote hand and visual coordination.
Requirement Specifications
Dept of CSE 2018-19 Page | 3
Gonzo
The requirement specifications of this project are not perfectly optimized. However,
the following hardware and software specifications are specified in the best interest, i.e. to
make sure the game ‘Gonzo’ executes smoothly in the provided environment.
The hardware and software requirements specified here are the minimum
requirements for the project to run, even though the project can run smoothly on almost all
i386 based machines.
Hardware Requirements
1. Processor Speed : 300 MHz or above
2. RAM Size : 64 MB or above
3. Storage Space : 3 MB or above
Software Requirements
1. Operating System : MS DOS and the Windows
family
2. Compiler : GNU GCC
3. Graphics Library : OpenGL
Project Implementation
Dept of CSE 2018-19 Page | 4
Gonzo
This project, ‘Gonzo’, makes of the C Language, along with the OpenGL library, to
provide a Graphical User Interface to the user to interact with the Graphical Elements present
on the screen. This enables us to use many built in predefined functions such as
GlutMainLoop(), glBegin(), glutAddMenu(), glMatrixMode() and many more. All these
functions are perfectly incorporated with the C Language to provide a wide array of graphical
capabilities to the programmer. In addition to this, this project also has various user defined
functions such as:-
1. draw_paddle(), draw_ball(), draw_bricks(), draw_boundary()
These functions are used to draw the corresponding Graphical Elements, such as the
ball, the paddle, the boundary and the bricks, on the screen.
2. change_brick_color(), change_ball_color(), change_text_color(), change_paddle_color()
These functions are used to change the colours of the respective Graphical Elements.
3. change_difficulty()
This function is used to change the difficulty of the game (by increasing the speed of
the ball).
4. change_paddle_size()
This function is used to change the size of the paddle.
5. lightsOn()
This function is used to turn on the ‘customized lighting’ for added graphical effects.
6. display()
This function is passed as the ‘Display Function’ to the OpenGL function
‘glutDisplayFunc()’ which keeps executing in a loop to enable the refreshing of data
present on the screen.
7. reshape()
Dept of CSE 2018-19 Page | 5
Gonzo
This function is used as a parameter to the OpenGL function ‘glutReshapeFunc()’.
8. mousemotion(), keyboard()
These two functions are used to provide support for interfacing between the mouse,
keyboard and the running program. These functions are passed as parameters to the
OpenGL functions ‘glutPassiveMotionFunc()’ and ‘glutKeyboardFunc()’.
9. idle()
This function is used to provide the ‘idle functionality’ of the game when no keyboard
or mouse interaction exists. This function is passed as a parameter to the OpenGL
function ‘glutIdleFunc()’.
10. hit()
This function is used to provide the main ‘collision detection’ functionality of the
game. This function checks if the current position of the ball is in any forbidden
position (such as ‘out of boundary’, ‘within a brick’ or ‘within the paddle’). If it is,
then the function makes changes to the Graphical Elements accordingly and changes
the ball’s direction (or position). On the whole, this function is very crucial to
determine the ‘success’ state or the ‘failure’ state of the game.
All the functions mentioned above work flawlessly together to bring life to a fancy and
minimalistic game. This project provides a scoring mechanism in order to keep track of the
number of collisions. This helps in keeping the user engaged for a prolonged period of time.
This project also implements certain laws of physics (such as the law of reflection),
with the help of certain user-defined logic, to provide minimal physics to the game.
Just like any other game, this game has various stages, namely ‘Initial Stage’,
‘Running Stage’ and ‘Final Stage’. Each stage of the game has a set of distinct characteristics
which are determined by the various parameters and variables in the program.
The various stages of the game are:-
Dept of CSE 2018-19 Page | 6
Gonzo
Initial Stage
The game opens with the ball placed on the paddle. The game doesn’t start interacting
until the user presses the key ‘S’ to start the game.
Running Stage
When the game is in the running state, the ball moves linearly along the screen,
following the laws of reflection as it collides with the obstacles and boundaries, and the
number of bricks reduce after every successful collision with the corresponding brick.
Final Stage
The game resets to the ‘Initial State’ when the player has successfully removed all the
bricks or when the player ‘loses’ the game (When the paddle fails to reflect the ball back
towards the obstacles and the number of ‘lives’ left is zero). The main screen then displays the
score of the very previous instance of the game and the maximum score.
The game incorporates all these stages to present a fully interactive game which keeps
the users engaged. All this is done with the help of the C Language along with the OpenGL
functions.
Source Code
Dept of CSE 2018-19 Page | 7
Gonzo
#include <stdlib.h>
#include <GL/glut.h>
#include<stdio.h>
#include<string.h>
#include <math.h>
int score = 0;
int max_score = 0;
int life = 3;
int disp_flag = 0;
int brick_color = 1,ball_color = 3,level = 0,paddle_color = 2,text_color = 5,size = 2;
GLfloat twoModel[]={GL_TRUE};
int game_level[] = {20,15,10};
float rate = game_level[level];
int brick_count = 0;
GLfloat brick_color_array[][3] = {{1,0,0},{0,0,1},{0,1,0},{1,0,1},{1,1,0},{0,1,1}};
GLfloat paddle_color_array[][3] = {{1,0,0},{0,0,1},{0,1,0},{1,0,1},{1,1,0},{0,1,1}};
GLfloat text_color_array[][4] = {{1,0,0,1},{0,0,1,1},{0,1,0,1},{1,0,1,1},{1,1,0,1},
{0,1,1,1}};
GLfloat paddle_size[] = {2,4,6};
//The grid parameters for the bricks
int rows = 4;
int columns = 10;
Dept of CSE 2018-19 Page | 8
Gonzo
// Structure to store the coordinates of each brick
struct brick_coords{
GLfloat x;
GLfloat y;
GLint type;
};
//Array to store the bricks
brick_coords brick_array[50][50];
GLfloat px,bx = 0,by = -12.8 ,speed = 0,dirx=0,diry=0,start = 0;
// Function to draw the paddle
void draw_paddle()
glDisable(GL_LIGHTING);
glColor3fv(paddle_color_array[paddle_color]);
glBegin(GL_POLYGON);
glVertex3f(-paddle_size[size]+px,0-15,0);
glVertex3f(paddle_size[size]+px,0-15,0);
glVertex3f(paddle_size[size]+px,1-15,0);
glVertex3f(-paddle_size[size]+px,1-15,0);
glEnd();
glEnable(GL_LIGHTING);
//Function to draw a single brick
void brick(GLfloat x,GLfloat y, GLfloat z, GLint type)
Dept of CSE 2018-19 Page | 9
Gonzo
glDisable(GL_LIGHTING);
if(type == 0)
glColor3fv(brick_color_array[brick_color]);
else
glColor3fv(brick_color_array[(brick_color + 1)%6]);
glBegin(GL_QUADS);
glVertex3f(x,y,z);
glVertex3f(x+3,y,z);
glVertex3f(x+3,y+1,z);
glVertex3f(x,y+1,z);
glEnd();
glEnable(GL_LIGHTING);
// Function to draw hearts
void draw_hearts()
int hx = -15;
int hy = 12;
for(int i = 0; i<life; i++)
glDisable(GL_LIGHTING);
glColor3fv(brick_color_array[0]); // Color Red
Dept of CSE 2018-19 Page | 10
Gonzo
glBegin(GL_POLYGON);
glVertex2f(hx, hy-0.2);
glVertex2f(hx-0.6, hy+0.5);
//glVertex2f(hx-0.3, hy+0.4);
glVertex2f(hx-0.3, hy+1);
glVertex2f(hx-0.1, hy+0.8);
glVertex2f(hx, hy+0.6);
glVertex2f(hx+0.1, hy+0.8);
glVertex2f(hx+0.3, hy+1);
//glVertex2f(hx+0.3, hy+0.4);
glVertex2f(hx+0.6, hy+0.5);
glEnd();
glEnable(GL_LIGHTING);
hx+=2;
// Function to draw the grid of bricks
void draw_bricks()
int i,j;
if(start == 0 && life==3)
for(i = 1;i<=rows;i++)
Dept of CSE 2018-19 Page | 11
Gonzo
for(j = 1;j<=columns;j++)
brick_array[i][j].x = (GLfloat)(j*4*0.84);
brick_array[i][j].y = (GLfloat)(i*2*0.6) ;
brick_array[i][j].type = (GLint) (rand()%2);
glPushMatrix();
glTranslatef(-19.5,5,0);
for(i = 1;i<=rows;i+=1)
for(j = 1;j<=columns;j+=1)
if(brick_array[i][j].x==0 || brick_array[i][j].y ==0)
continue;
brick(brick_array[i][j].x,brick_array[i][j].y,0, brick_array[i][j].type);
Dept of CSE 2018-19 Page | 12
Gonzo
glPopMatrix();
//Function to draw the spherical ball
void draw_ball()
GLfloat ambient1[] = {1,1,1};
GLfloat diffuse1[] = {0.4,0.4,0.4};
GLfloat specular1[] = {1,1,1};
GLfloat position[] = {0,0,-50,1};
GLfloat ambient2[] = {0,0,0};
GLfloat diffuse2[] = {1,1,1};
GLfloat specular2[] = {0,1,1};
float materialColours[][3]={{1,0,0},{0,0,1},{0,1,0},{1,0,1},{1,1,0},{0,1,1}};
GLfloat matAmbient1[] = {1,1,1};
GLfloat matDiffuse1[] = {1,1,1};
GLfloat matSpecular1[] = {1,1,1};
GLfloat shininess[] = {1000};
glLightfv(GL_LIGHT0,GL_SPECULAR,specular1);
glLightfv(GL_LIGHT0,GL_AMBIENT,ambient1);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse1);
Dept of CSE 2018-19 Page | 13
Gonzo
glLightfv(GL_LIGHT1,GL_POSITION,position);
glLightfv(GL_LIGHT1,GL_SPECULAR,specular2);
glLightfv(GL_LIGHT1,GL_AMBIENT,ambient2);
glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuse2);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,materialColours[ball_color]);
glPushMatrix();
glTranslatef(bx,by,0);
glScalef(1.0, 1.0, 0.5);
//glScalef(size[i], size[], size[]);
glutSolidSphere(1.0, 52, 52);
glPopMatrix();
//Mouse function
void mousemotion(int x,int y)
if(start == 1)
px=(x-glutGet(GLUT_WINDOW_WIDTH)/2)/20;
if(px>16)
px=16;
if(px<-15)
Dept of CSE 2018-19 Page | 14
Gonzo
px=-15;
else
glutSetCursor(GLUT_CURSOR_INHERIT);
//Handle brick color
void change_brick_color(int action)
brick_color=action-1;
//Handle ball color
void change_ball_color(int action)
ball_color=action-1;
//Handle level
void change_difficulty(int action)
level=action-1;
//Handle menu
void handle_menu(int action)
Dept of CSE 2018-19 Page | 15
Gonzo
//Handle paddle color
void change_paddle_color(int action)
paddle_color = action -1;
//Handle text color
void change_text_color(int action)
text_color = action -1;
//Handle paddle size
void change_paddle_size(int action)
size = action-1;
//add menu
void addMenu()
int submenu1 = glutCreateMenu(change_brick_color);
glutAddMenuEntry("Red",1);
glutAddMenuEntry("Blue",2);
glutAddMenuEntry("Green",3);
Dept of CSE 2018-19 Page | 16
Gonzo
glutAddMenuEntry("Purple",4);
glutAddMenuEntry("Yellow",5);
glutAddMenuEntry("Cyan",6);
int submenu2 = glutCreateMenu(change_ball_color);
glutAddMenuEntry("Red",1);
glutAddMenuEntry("Blue",2);
glutAddMenuEntry("Green",3);
glutAddMenuEntry("Purple",4);
glutAddMenuEntry("Yellow",5);
glutAddMenuEntry("Cyan",6);
int submenu4 = glutCreateMenu(change_paddle_color);
glutAddMenuEntry("Red",1);
glutAddMenuEntry("Blue",2);
glutAddMenuEntry("Green",3);
glutAddMenuEntry("Purple",4);
glutAddMenuEntry("Yellow",5);
glutAddMenuEntry("Cyan",6);
int submenu3 = glutCreateMenu(change_difficulty);
glutAddMenuEntry("Easy",1);
glutAddMenuEntry("Medium",2);
glutAddMenuEntry("Hard",3);
int submenu5 = glutCreateMenu(change_text_color);
glutAddMenuEntry("Red",1);
glutAddMenuEntry("Blue",2);
Dept of CSE 2018-19 Page | 17
Gonzo
glutAddMenuEntry("Green",3);
glutAddMenuEntry("Purple",4);
glutAddMenuEntry("Yellow",5);
glutAddMenuEntry("Cyan",6);
int submenu6 = glutCreateMenu(change_paddle_size);
glutAddMenuEntry("Small",1);
glutAddMenuEntry("Medium",2);
glutAddMenuEntry("Large",3);
glutCreateMenu(handle_menu);
glutAddSubMenu("Bricks Color",submenu1);
glutAddSubMenu("Ball Color",submenu2);
glutAddSubMenu("Paddle Color",submenu4);
glutAddSubMenu("Text Color",submenu5);
glutAddSubMenu("Difficulty",submenu3);
glutAddSubMenu("Paddle Size",submenu6);
glutAttachMenu(GLUT_RIGHT_BUTTON);
//Function to draw boundary
void draw_boundary()
glDisable(GL_LIGHTING);
glColor3fv(brick_color_array[4]);
glBegin(GL_LINE_LOOP);
glVertex2f(-17, -14.4);
Dept of CSE 2018-19 Page | 18
Gonzo
glVertex2f(18, -14.4);
glVertex2f(18, 14.3);
glVertex2f(-17, 14.3);
glEnd();
glEnable(GL_LIGHTING);
//Function to print the score on the screen
void text(int brick_count, int sc)
glDisable(GL_LIGHTING);
char text[50];
char difficulty[10];
char max_string[20];
char start_hint[20];
sprintf(max_string, "Maximum Score: %d", max_score);
if(level == 0)
sprintf(difficulty,"Easy");
if(level == 1)
sprintf(difficulty,"Medium");
Dept of CSE 2018-19 Page | 19
Gonzo
if(level == 2)
sprintf(difficulty,"Hard");
if(brick_count<40 && disp_flag==1) {
sprintf(text," Sorry, you lost!");
else if(brick_count<40 && life!=0)
sprintf(text,"Difficulty: %s Your Score: %d",difficulty, sc);
else
sprintf(text," You have won!");
start = 0;
by = -12.8;
bx = 0;
dirx = 0;
diry = 0;
px = 0;
life = 3;
// The color
glColor4fv(text_color_array[text_color]);
// Position of the text to be printer
glPushMatrix();
Dept of CSE 2018-19 Page | 20
Gonzo
glTranslatef(-1,0,0);
glRasterPos3f(0, 0, 20);
for(int i = 0; text[i] != '\0'; i++)
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, text[i]);
glRasterPos3f(0.4, -0.5, 20);
for(int i = 0; max_string[i] != '\0'; i++)
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, max_string[i]);
if(start==0) {
glRasterPos3f(0.2, -1, 20);
sprintf(start_hint, "Press \'S\' to start the game!");
for(int i = 0; start_hint[i] != '\0'; i++)
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, start_hint[i]);
glEnable(GL_LIGHTING);
glPopMatrix();
//The main display function
void display (void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0,0,0,0,0,-25,0,1,0);
glTranslatef(0,0,-25);
draw_boundary();
Dept of CSE 2018-19 Page | 21
Gonzo
draw_paddle();
draw_bricks();
draw_ball();
draw_hearts();
text(brick_count, score);
glutSwapBuffers();
//function to turn on lights
void lightsOn()
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
void reshape (int w, int h) {
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 1000.0);
glMatrixMode (GL_MODELVIEW);
//function to take in keyboard entries
void keyboard (unsigned char key, int x, int y)
Dept of CSE 2018-19 Page | 22
Gonzo
switch(key)
case 'd': px+=3; break;
case 'a': px-=3; break;
case 'q': exit(0); break;
case 's':
if(!start)
if(rand()%2)
dirx = 1;
else
dirx = -1;
diry = 1;
rate = game_level[level];
start = 1;
disp_flag = 0;
if(life==3) {
score = 0;
brick_count = 0;
glutSetCursor(GLUT_CURSOR_NONE);
break;
Dept of CSE 2018-19 Page | 23
Gonzo
if(px>15)
px=15;
if(px<-15)
px=-15;
if(start== 0)
px=0;
glutPostRedisplay();
//Function to handle the case when the ball strikes the bricks
void hit()
int i,j;
for(i = 1;i<=rows;i++)
for(j=1;j<=columns;j++)
if((bx>=brick_array[i][j].x-19.5-0.1 )&&( bx<=brick_array[i][j].x + 3-
19.5+ 0.1))
Dept of CSE 2018-19 Page | 24
Gonzo
if(by >=brick_array[i][j].y+5-0.1 && by <=brick_array[i]
[j].y+5 +1.2 +0.1)
brick_array[i][j].x = 0;
brick_array[i][j].y = 0;
diry= diry*-1;
if(brick_array[i][j].type == 0)
score++;
else
score+=2;
brick_count++;
max_score = (max_score>score)?max_score:score;
//cout<<bx<<" "<<by<<"\t"<<brick_array[i][j].x<<"
"<<brick_array[i][j].y;
else if(by >=brick_array[i][j].y+5 -0.1 && by <=brick_array[i][j].y+5
+1.2+0.1)
if((bx>=brick_array[i][j].x-19.5-0.1) && (bx<=brick_array[i]
[j].x + 3-19.5 + 0.1 ))
brick_array[i][j].x = 0;
brick_array[i][j].y = 0;
dirx= dirx*-1;
Dept of CSE 2018-19 Page | 25
Gonzo
if(brick_array[i][j].type == 0)
score++;
else
score+=2;
brick_count++;
max_score = (max_score>score)?max_score:score;
//The idle function. Handles the motion of the ball along with rebounding from various
surfaces
void idle()
hit();
if(bx<-16 || bx>17 && start == 1)
dirx = dirx*-1;
if(by<-15 || by>14 && start == 1)
diry = diry*-1;
bx+=dirx/(rate);
by+=diry/(rate);
Dept of CSE 2018-19 Page | 26
Gonzo
rate-=0.001; // Rate at which the speed of ball increases
float x = paddle_size[size];
//Make changes here for the different position of ball after rebounded by paddle
if( by<=-12.8 && bx<(px+x*2/3) && bx>(px+x/3)&& start == 1 )
dirx = 1;
diry = 1;
else if(by <=-12.8 && bx<(px-x/3) && bx>(px-x*2/3) && start == 1 )
dirx = -1;
diry = 1;
else if( by<=-12.8 && bx<(px+x/3) &&bx>(px-x/3) && start == 1)
dirx = dirx;
diry = 1;
else if(by <=-12.8 && bx<(px-(x*2/3)) && bx>(px-(x+0.3)) && start == 1 )
dirx = -1.5;
diry = 0.8;
Dept of CSE 2018-19 Page | 27
Gonzo
else if(by<=-12.8 && bx<(px+(x+0.3)) && bx>(px+x/3)&& start == 1 )
dirx = 1.5;
diry = 0.8;
else if(by<-13)
life = life-1;
start = 0;
by = -12.8;
bx = 0;
dirx = 0;
diry = 0;
px = 0;
if(life==0) {
disp_flag = 1;
life=3;
glutPostRedisplay();
int main (int argc,char **argv) {
glutInit(&argc,argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);
Dept of CSE 2018-19 Page | 28
Gonzo
glutInitWindowSize (900, 900);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Gonzo");
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glEnable(GL_DEPTH_TEST);
glutIdleFunc (idle);
glutPassiveMotionFunc(mousemotion);
glutKeyboardFunc(keyboard);
lightsOn();
addMenu();
glutMainLoop ();
return 0;
Dept of CSE 2018-19 Page | 29
Gonzo
Snapshots
The following figures are the snapshots taken during the various stages of the
program execution.
Initial Stage Running Stage
Final Stage Game Menu
Dept of CSE 2018-19 Page | 30
Gonzo
Conclusion
The project titled ‘Gonzo’ is developed with the best of my efforts within a limited
period of time. Due to the time constraint, the complexity of this project has not been fully
furnished to attain perfection.
The graphics creation and manipulation algorithms in the OpenGL package and
libraries have been implemented and tested to ensure the efficiency of operation and they
were found to be quite satisfactory. The game ‘Gonzo’ has a good and intuitive user interface
which can enable the users to have better and easier interactions with the software.
After the completion of the development and study of the project, I came to the
conclusion that Computer Graphics using C Language and OpenGL libraries can be used to
develop much better and complex softwares or games that include 2D and 3D image
processing.
Dept of CSE 2018-19 Page | 31
Gonzo
Bibliography
1. Interactive Computer Graphics by Edward Angel
2. Graphics Under C by Yashavant Kanetkar
3. Computer Graphics by A. P. Godse
4. Let us C by Yashavant Kanetkar
5. Computer Graphics World ([Link])
6. Learn OpenGL ([Link])
Dept of CSE 2018-19 Page | 32