pizzaboy150
Posts: 18
Joined: Sat Sep 05, 2015 11:03 am

Where's my Triangle??

Sat Sep 28, 2019 10:36 am

Hi All,

Done this code a few times and never had this problem before. I know I am overlooking something simple but been messing with the code for 3 days and can't seem to make it work?

Feels to me like the shader is not loading the source code and i am getting no errors?

All ideas welcome!

Code: Select all

#include <iostream>
#include <bcm_host.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>

int main(int argc, char *argv[]) {

	/////////////// 
	// BCM SETUP //
	///////////////
	EGL_DISPMANX_WINDOW_T nativewindow;
	uint32_t display_width;
	uint32_t display_height;

	//get the bcm setup
	bcm_host_init();

	//the variables
	DISPMANX_ELEMENT_HANDLE_T dispman_element;
	DISPMANX_DISPLAY_HANDLE_T dispman_display;
	DISPMANX_UPDATE_HANDLE_T dispman_update;
	DISPMANX_TRANSFORM_T dispman_trans;
	VC_RECT_T dst_rect;
	VC_RECT_T src_rect;

	//create an EGL window surface, passing context width/height
	int success = graphics_get_display_size(0 /* LCD */,
                        &display_width, &display_height);
	if ( success < 0 )
	{
		return 1;
	}

	//You can hardcode the resolution here:
	//display_width = 640;
	//display_height = 480;

	dst_rect.x = 0;
	dst_rect.y = 0;
	dst_rect.width = display_width;
	dst_rect.height = display_height;

	src_rect.x = 0;
	src_rect.y = 0;
	src_rect.width = display_width << 16;
	src_rect.height = display_height << 16;

	dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
	dispman_update = vc_dispmanx_update_start( 0 );

	dispman_element = vc_dispmanx_element_add ( dispman_update,
	dispman_display, 0/*layer*/, &dst_rect, 0/*src*/,
			&src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/,
			0/*clamp*/, dispman_trans/*transform*/);

	nativewindow.element = dispman_element;
	nativewindow.width = display_width;
	nativewindow.height = display_height;
	vc_dispmanx_update_submit_sync( dispman_update );

	///////////////
	// EGL SETUP //
	///////////////
	
	EGLDisplay eglDisplay;
	EGLSurface eglSurface;
	EGLContext eglContext;

	eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	if(eglDisplay == EGL_NO_DISPLAY) {
		return 2;
	}

	//initialise EGL
	if(eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE) {
		return 3;
	}

	//Create an EGL config for what we want
	EGLConfig config;
	EGLint numConfigs;
	EGLint configs[] = {
		EGL_RED_SIZE, 8,
		EGL_GREEN_SIZE, 8,
		EGL_BLUE_SIZE, 8,
		EGL_ALPHA_SIZE, 8,
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
		EGL_NONE
	};

	//Choose the config to use
	if(eglChooseConfig(eglDisplay, configs, &config, 1, &numConfigs) == EGL_FALSE) {
		return 4;
	}

	//tell EGL we are using OpenVG / OpenGL ES / OpenGL
	//IMPORTANT THIS MUST BE DONE BEFORE CREATING THE CONTEXT!
	if(eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) {
		return 5;
	}

	//Now lets create the rendering context
	eglContext = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, NULL);
	if(eglContext == EGL_NO_CONTEXT) {
		return 6;
	}

	//Create the window surface
	eglSurface = eglCreateWindowSurface(eglDisplay, config, &nativewindow, NULL);
	if(eglSurface == EGL_NO_CONTEXT) {
		return 7;
	}

	//make context current
	if(eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE) {
		return 8;
	}

	////////////////////
	// CREATE SHADERS //
	////////////////////
	
	//create the shader objects
	GLuint VShader = glCreateShader(GL_VERTEX_SHADER);
	GLuint FShader = glCreateShader(GL_FRAGMENT_SHADER);

	//our shader code later we will load this from a file
	const GLchar *VCode = {"attribute vec2 position;void main() {gl_Positon = position;}"};
	const GLchar *FCode = {"void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}"};

	//load shader source code
	glShaderSource(VShader, 1, &VCode, NULL);
	glShaderSource(FShader, 1, &FCode, NULL);

	//debug print shader code to see it loaded?
	GLchar *VSource = NULL;
	GLchar *FSource = NULL;
	glGetShaderSource(VShader, 1024, NULL, VSource);
	glGetShaderSource(FShader, 1024, NULL, FSource);
	std::cout << VSource << std::endl;
	std::cout << FSource << std::endl;

	//compile the shaders
	glCompileShader(VShader);
	glCompileShader(FShader);

	//check for errors in both shaders
	GLint status;
	GLint logSize;
	GLchar *log = NULL;
	GLint size;
	glGetShaderiv(VShader, GL_COMPILE_STATUS, &status);
	if(status == GL_FALSE) {
		std::cout << "Vertex Shader ERROR!" << std::endl;
		glGetShaderiv(VShader, GL_INFO_LOG_LENGTH, &logSize);
		std::cout << logSize << std::endl;
		glGetShaderInfoLog(VShader, logSize, &size, log);
		if(logSize > 1) {
			std::cout << log << std::endl;
		}
	}
	glGetShaderiv(FShader, GL_COMPILE_STATUS, &status);
	if(status == GL_FALSE) {
		std::cout << "Fragment Shader ERROR!" << std::endl;
		glGetShaderiv(FShader, GL_INFO_LOG_LENGTH, &logSize);
		log = new char[logSize];
		glGetShaderInfoLog(FShader, logSize, &size, log);
		if(logSize > 1) {
			std::cout << log << std::endl;
		}
	}
	//create shader program
	GLuint program = glCreateProgram();

	//attach the shaders
	glAttachShader(program, VShader);
	glAttachShader(program, FShader);

	//now link the program
	glLinkProgram(program);

	//check program linked correctly
	GLint proLog = 0;
	glGetProgramiv(program, GL_LINK_STATUS, &proLog);
	if(proLog == GL_FALSE) {
		std::cout << "Error linking shader program!" << std::endl;
		GLint logLen = 0;
		GLchar *logInfo = NULL;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLen);
		glGetProgramInfoLog(program, logLen, &logLen, logInfo);
		if(logLen > 0) {
			std::cout << logInfo << std::endl;
		}
	}

	//set the program to be used
	glUseProgram(program);

	//finished with shades so now we can delete
	glDeleteShader(VShader);
	glDeleteShader(FShader);

	///////////////////
	// TRIANGLE DATA //
	///////////////////
	
	//the vertex data
	GLfloat triangle[] = {-0.5, -0.5, 0.0, 0.5, 0.5, -0.5};

	//create a buffer to store the data in GPU memory
	GLuint triBuffer;
	glGenBuffers(1, &triBuffer);
	
	//tell GL which buffer we would like to work with?
	glBindBuffer(GL_ARRAY_BUFFER, triBuffer);

	//assign the data to the buffer
	glBufferData(GL_ARRAY_BUFFER, 6*sizeof(GLfloat), triangle, GL_STATIC_DRAW);

	//bind the attribute in vertex shader to index 0
	glBindAttribLocation(program, 0, "position");

	//tell GL how the data is stored?
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangle);
	
	//tell GL which attrib we would like to use
	glEnableVertexAttribArray(0);
	
	////////////////////
	// DRAWING & LOOP //
	////////////////////
	
	//Program loop
	int count = 0;

	//set the clear color
	glClearColor(0.5, 0.5, 0.5, 1.0);

	//assuming a vsync of 60hz here
	while(count < 600) {
			
		//clear the screen
		glClear(GL_COLOR_BUFFER_BIT);
	
		//lets draw our triangle
		glDrawArrays(GL_TRIANGLES, 0, 3);

		//swap the buffers
		eglSwapBuffers(eglDisplay, eglSurface);

		//Increment timer thinking 60hz refresh here
		count++;
	}
	


	//////////////
	// CLEAN UP //
	//////////////
	
	eglDestroySurface(eglDisplay, eglSurface);
	eglDestroyContext(eglDisplay, eglContext);
	eglTerminate(eglDisplay);

	return 0;
}
Thanks in advance! :)

User avatar
PeterO
Posts: 5066
Joined: Sun Jul 22, 2012 4:14 pm

Re: Where's my Triangle??

Sat Sep 28, 2019 10:49 am

Lots of things have changed on Buster and Pi4s :-)

No need to use PI specific code anymore, generic GL and GLES code should work.

Try this.... https://wiki.maemo.org/SimpleGL_example

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

pizzaboy150
Posts: 18
Joined: Sat Sep 05, 2015 11:03 am

Re: Where's my Triangle??

Sat Sep 28, 2019 11:00 am

Oh blimey, been a while since I picked up the PI, it seems a lot has changed. Does that now mean I can create a context using GLEW and GLFW instead of X11 or the funcky BCM stuff?

User avatar
PeterO
Posts: 5066
Joined: Sun Jul 22, 2012 4:14 pm

Re: Where's my Triangle??

Sat Sep 28, 2019 11:09 am

pizzaboy150 wrote:
Sat Sep 28, 2019 11:00 am
Oh blimey, been a while since I picked up the PI, it seems a lot has changed. Does that now mean I can create a context using GLEW and GLFW instead of X11 or the funcky BCM stuff?
All I know is that you can't use the "funky BCM stuff" for sure as it is no longer supported. TBH the changes have not been well communicated and the whole alphabet soup of acronyms and abbreviations around 3D graphics is now even more confusing !

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

pizzaboy150
Posts: 18
Joined: Sat Sep 05, 2015 11:03 am

Re: Where's my Triangle??

Sat Sep 28, 2019 11:46 am

Thanks for the info I will loose bcm and add xlib then see where that takes me.

pizzaboy150
Posts: 18
Joined: Sat Sep 05, 2015 11:03 am

Re: Where's my Triangle??

Sun Sep 29, 2019 11:08 am

Okay so dumped the BCM stuff and added Xlib, code now compiles but crashes when creating the EGL window surface but compiles okay.

I have dummed down my Xlib code so am worried that EGL may need a window attribute set in Xlib to function correctly.

Though while playing I get a different response depending on which libs i use.

/opt/vc/lib/libEGL.so gives no feedback and just crashes while using;
eglSurface = eglCreateWindowSurface(eglDisplay, config, &win, NULL);

when using the /usr/lib/arm-linux-gnueabihf/libEGL.so with the code
eglSurface = eglCreateWindowSurface(eglDisplay, config, win, NULL);
gives me the error;

Code: Select all

pi@raspberrypi:~/OpenGL-ES2 $ ./program 
libEGL warning: DRI2: failed to authenticate
Segmentation fault
So I am using a Raspberry Pi3 not the 4, which lib should i be using and what am i missing in my code below?

Code: Select all

#include <iostream>
#include <X11/Xlib.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>

int main(int argc, char *argv[]) {

	/////////////// 
	// X11 STUFF //
	///////////////
	
	///create the display
	Display *display = XOpenDisplay(NULL);
	if(display == NULL) {
		std::cout << "Error creating X display!" << std::endl;
		return 1;
	}
	
	//get information about out display
	int screen_num = DefaultScreen(display);
	
	//now lets create the window
	Window win;
	int win_width = 640;
	int win_height = 480;
	int win_x = 0;
	int win_y = 0;

	win = XCreateSimpleWindow(display,
                          RootWindow(display, screen_num),
                          win_x, win_y,
                          win_width, win_height,
                          0, BlackPixel(display, screen_num),
                          WhitePixel(display, screen_num));                                           
	
	//Window name
	XStoreName(display, win, "Testing OpenGL ES 2.0");
	                         
	//make the window visable
	XMapWindow(display, win);
		
	///////////////
	// EGL SETUP //
	///////////////
	
	EGLDisplay eglDisplay;
	EGLSurface eglSurface;
	EGLContext eglContext;

	eglDisplay = eglGetDisplay((EGLNativeDisplayType)display);
	if(eglDisplay == EGL_NO_DISPLAY) {
		return 2;
	}

	//initialise EGL
	if(eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE) {
		return 3;
	}

	//Create an EGL config for what we want
	EGLConfig config;
	EGLint numConfigs;
	EGLint configs[] = {
		EGL_BUFFER_SIZE, 24,
		EGL_RENDERABLE_TYPE, 
		EGL_OPENGL_ES2_BIT,
		EGL_NONE
	};

	//Choose the config to use
	if(eglChooseConfig(eglDisplay, configs, &config, 1, &numConfigs) == EGL_FALSE) {
		return 4;
	}

	//Create the window surface
	eglSurface = eglCreateWindowSurface(eglDisplay, config, win, NULL);
	if(eglSurface == EGL_NO_SURFACE) {
		return 5;
	}
	
	//more attributes
	EGLint contextAttribs[] = {
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};	

	//Now lets create the rendering context
	eglContext = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, contextAttribs);
	if(eglContext == EGL_NO_CONTEXT) {
		return 6;
	}

	//make context current
	if(eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE) {
		return 7;
	}

	////////////////////
	// CREATE SHADERS //
	////////////////////
	
	//create the shader objects
	GLuint VShader = glCreateShader(GL_VERTEX_SHADER);
	GLuint FShader = glCreateShader(GL_FRAGMENT_SHADER);

	//our shader code later we will load this from a file
	const GLchar *VCode = {"attribute vec2 position;void main() {gl_Positon = position;}"};
	const GLchar *FCode = {"void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}"};

	//load shader source code
	glShaderSource(VShader, 1, &VCode, NULL);
	glShaderSource(FShader, 1, &FCode, NULL);

	//debug print shader code to see it loaded?
	GLchar *VSource = NULL;
	GLchar *FSource = NULL;
	glGetShaderSource(VShader, 1024, NULL, VSource);
	glGetShaderSource(FShader, 1024, NULL, FSource);
	std::cout << VSource << std::endl;
	std::cout << FSource << std::endl;

	//compile the shaders
	glCompileShader(VShader);
	glCompileShader(FShader);

	//check for errors in both shaders
	GLint status;
	GLint logSize;
	GLchar *log = NULL;
	GLint size;
	glGetShaderiv(VShader, GL_COMPILE_STATUS, &status);
	if(status == GL_FALSE) {
		std::cout << "Vertex Shader ERROR!" << std::endl;
		glGetShaderiv(VShader, GL_INFO_LOG_LENGTH, &logSize);
		std::cout << logSize << std::endl;
		glGetShaderInfoLog(VShader, logSize, &size, log);
		if(logSize > 1) {
			std::cout << log << std::endl;
		}
	}
	glGetShaderiv(FShader, GL_COMPILE_STATUS, &status);
	if(status == GL_FALSE) {
		std::cout << "Fragment Shader ERROR!" << std::endl;
		glGetShaderiv(FShader, GL_INFO_LOG_LENGTH, &logSize);
		log = new char[logSize];
		glGetShaderInfoLog(FShader, logSize, &size, log);
		if(logSize > 1) {
			std::cout << log << std::endl;
		}
	}
	//create shader program
	GLuint program = glCreateProgram();

	//attach the shaders
	glAttachShader(program, VShader);
	glAttachShader(program, FShader);

	//now link the program
	glLinkProgram(program);

	//check program linked correctly
	GLint proLog = 0;
	glGetProgramiv(program, GL_LINK_STATUS, &proLog);
	if(proLog == GL_FALSE) {
		std::cout << "Error linking shader program!" << std::endl;
		GLint logLen = 0;
		GLchar *logInfo = NULL;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLen);
		glGetProgramInfoLog(program, logLen, &logLen, logInfo);
		if(logLen > 0) {
			std::cout << logInfo << std::endl;
		}
	}

	//set the program to be used
	glUseProgram(program);

	//finished with shades so now we can delete
	glDeleteShader(VShader);
	glDeleteShader(FShader);

	///////////////////
	// TRIANGLE DATA //
	///////////////////
	
	//the vertex data
	GLfloat triangle[] = {-0.5, -0.5, 0.0, 0.5, 0.5, -0.5};

	//create a buffer to store the data in GPU memory
	GLuint triBuffer;
	glGenBuffers(1, &triBuffer);
	
	//tell GL which buffer we would like to work with?
	glBindBuffer(GL_ARRAY_BUFFER, triBuffer);

	//assign the data to the buffer
	glBufferData(GL_ARRAY_BUFFER, 6*sizeof(GLfloat), triangle, GL_STATIC_DRAW);

	//bind the attribute in vertex shader to index 0
	glBindAttribLocation(program, 0, "position");

	//tell GL how the data is stored?
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangle);
	
	//tell GL which attrib we would like to use
	glEnableVertexAttribArray(0);
	
	////////////////////
	// DRAWING & LOOP //
	////////////////////
	
	//set the clear color
	glClearColor(0.5, 0.5, 0.5, 1.0);
	
	//main program loop
	bool session = true;
	
	while(session) {
			
		//clear the screen
		glClear(GL_COLOR_BUFFER_BIT);
		
		//lets draw our triangle
		glDrawArrays(GL_TRIANGLES, 0, 3);

		//swap the buffers
		eglSwapBuffers(eglDisplay, eglSurface);
	}

	//////////////
	// CLEAN UP //
	//////////////
	
	eglDestroySurface(eglDisplay, eglSurface);
	eglDestroyContext(eglDisplay, eglContext);
	eglTerminate(eglDisplay);
	XDestroyWindow(display, win);
	XCloseDisplay(display);

	return 0;
}

User avatar
PeterO
Posts: 5066
Joined: Sun Jul 22, 2012 4:14 pm

Re: Where's my Triangle??

Sun Sep 29, 2019 12:13 pm

I've never seen a clear explanation of what to use on Pi3 vs Pi4.
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

pizzaboy150
Posts: 18
Joined: Sat Sep 05, 2015 11:03 am

Re: Where's my Triangle??

Sun Sep 29, 2019 2:31 pm

Well i just compiled the example in the post you linked and that runs using the /usr/lib/arm-linux-gnueabihf/libEGL.so but with the DRI2: failed to authenticate error still being present.

Running it with the /opt/vc/lib/libEGL.so ends in no compilation and an egl bad surface exception.

So thinking I am getting closer.

May try using the OpenGL driver and seeing what difference that makes but still not sure my source is correct.

pizzaboy150
Posts: 18
Joined: Sat Sep 05, 2015 11:03 am

Re: Where's my Triangle??

Sun Sep 29, 2019 3:20 pm

Okay all sorted!!

I finally have my triangle. I am putting it down to a naff driver or an error in the EGL library I am using for the DRI2 error.

Here is the code thats working...

UPDATED 29/09/19 19:38

Code: Select all

#include <iostream>
#include <fstream>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>

int main(int argc, char *argv[]) {

	/////////////// 
	// X11 STUFF //
	///////////////
	
	///create the display
	Display *display = XOpenDisplay(NULL);
	if(display == NULL) {
		std::cout << "Error creating X display!" << std::endl;
		return 1;
	}
	
	//get information about out display
	int screen_num = DefaultScreen(display);
	
	//now lets create the window
	Window win;
	int win_width = 640;
	int win_height = 480;
	int win_x = 0;
	int win_y = 0;

	win = XCreateSimpleWindow(display,
                          RootWindow(display, screen_num),
                          win_x, win_y,
                          win_width, win_height,
                          0, BlackPixel(display, screen_num),
                          WhitePixel(display, screen_num));                                           
	
	//Window name
	XStoreName(display, win, "Testing OpenGL ES 2.0");
	
	//register for events
	XSelectInput(display, win, ExposureMask | KeyPressMask);
	                         
	//make the window visable
	XMapWindow(display, win);
		
	///////////////
	// EGL SETUP //
	///////////////
	
	EGLDisplay eglDisplay;
	EGLSurface eglSurface;
	EGLContext eglContext;

	eglDisplay = eglGetDisplay((EGLNativeDisplayType)display);
	if(eglDisplay == EGL_NO_DISPLAY) {
		return 2;
	}

	//initialise EGL
	if(eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE) {
		return 3;
	}

	//Create an EGL config for what we want
	EGLConfig config;
	EGLint numConfigs;
	EGLint configs[] = {
		EGL_BUFFER_SIZE, 32,
		EGL_RENDERABLE_TYPE, 
		EGL_OPENGL_ES2_BIT,
		EGL_NONE
	};
	//Choose the config to use
	if(eglChooseConfig(eglDisplay, configs, &config, 1, 
					   &numConfigs) == EGL_FALSE) {
		return 4;
	}

	//Create the window surface
	eglSurface = eglCreateWindowSurface(eglDisplay, config, win, NULL);
	if(eglSurface == EGL_NO_SURFACE) {
		return 5;
	}
	
	//more attributes
	EGLint contextAttribs[] = {
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};	

	//Now lets create the rendering context
	eglContext = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT,
								  contextAttribs);
	if(eglContext == EGL_NO_CONTEXT) {
		return 6;
	}

	//make context current
	if(eglMakeCurrent(eglDisplay, eglSurface, eglSurface, 
					  eglContext) != EGL_TRUE) {
		return 7;
	}
	
	////////////////////
	// CREATE SHADERS //
	////////////////////
	
	//open shader files and read contents
	
	std::fstream vFile;
	std::fstream fFile;
	
	vFile.open("vShader", std::fstream::in);
	fFile.open("fShader", std::fstream::in);
	
	//check files opened
	if(!vFile.is_open()) {
		std::cout << "Unable to open vertex shader file!" << std::endl;
	}
	if(!fFile.is_open()) {
		std::cout << "Unable to open fragment shader file!" << std::endl;
	}
	
	//find file lengths
	long unsigned int vLen, fLen;
	
	vFile.seekg(0, vFile.end);
	vLen = vFile.tellg();
	vFile.seekg(0, vFile.beg);
	
	fFile.seekg(0, fFile.end);
	fLen = fFile.tellg();
	fFile.seekg(0, fFile.beg);
	
	//now read the data into a buffer
	GLchar *vSrc = new GLchar[vLen];
	GLchar *fSrc = new GLchar[fLen];
	vFile.read(vSrc, vLen);
	fFile.read(fSrc, fLen);
	
	//close files when finished
	vFile.close();
	fFile.close();
	
	//create the shader objects
	GLuint VShader = glCreateShader(GL_VERTEX_SHADER);
	GLuint FShader = glCreateShader(GL_FRAGMENT_SHADER);

	//load shader source code
	glShaderSource(VShader, 1, &vSrc, NULL);
	glShaderSource(FShader, 1, &fSrc, NULL);

	//compile the shaders
	glCompileShader(VShader);
	glCompileShader(FShader);

	//check for errors in both shaders
	GLint status;
	GLint logSize;
	GLchar *log = NULL;
	GLint size;
	glGetShaderiv(VShader, GL_COMPILE_STATUS, &status);
	if(status == GL_FALSE) {
		std::cout << "Vertex Shader ERROR!" << std::endl;
		glGetShaderiv(VShader, GL_INFO_LOG_LENGTH, &logSize);
		log = new char[logSize];
		glGetShaderInfoLog(VShader, logSize, &size, log);
		if(logSize > 1) {
			std::cout << log << std::endl;
		}
	}
	glGetShaderiv(FShader, GL_COMPILE_STATUS, &status);
	if(status == GL_FALSE) {
		std::cout << "Fragment Shader ERROR!" << std::endl;
		glGetShaderiv(FShader, GL_INFO_LOG_LENGTH, &logSize);
		log = new char[logSize];
		glGetShaderInfoLog(FShader, logSize, &size, log);
		if(logSize > 1) {
			std::cout << log << std::endl;
		}
	}
	//create shader program
	GLuint program = glCreateProgram();

	//attach the shaders
	glAttachShader(program, VShader);
	glAttachShader(program, FShader);

	//now link the program
	glLinkProgram(program);

	//check program linked correctly
	GLint proLog = 0;
	glGetProgramiv(program, GL_LINK_STATUS, &proLog);
	if(proLog == GL_FALSE) {
		std::cout << "Error linking shader program!" << std::endl;
		GLint logLen = 0;
		GLchar *logInfo = NULL;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLen);
		logInfo = new char[logLen];
		glGetProgramInfoLog(program, logLen, &logLen, logInfo);
		if(logLen > 0) {
			std::cout << logInfo << std::endl;
		}
	}

	//set the program to be used
	glUseProgram(program);

	//finished with shades so now we can delete
	glDeleteShader(VShader);
	glDeleteShader(FShader);

	///////////////////
	// TRIANGLE DATA //
	///////////////////
	
	//the vertex coordinates
	GLfloat verticies[] = {-0.5, -0.5, 0.0, 
						   0.0,  0.5, 0.0, 
						   0.5, -0.5, 0.0};
						   
	//the index for the vertices to make triangles						
	GLushort index[] = {0, 1, 2};

	//create a buffer to store the data in GPU memory
	GLuint vertBuffer;
	GLuint indxBuffer;
	glGenBuffers(1, &vertBuffer);
	glGenBuffers(1, &indxBuffer);
	
	//now bind to the elements buffer for the index's
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indxBuffer);
	
	//assign index data to the buffer
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3*sizeof(GLushort),
				 index, GL_STATIC_DRAW);
	
	//tell GL which buffer we would like to work with?
	glBindBuffer(GL_ARRAY_BUFFER, vertBuffer);

	//assign the data to the buffer
	glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat),
				 verticies, GL_STATIC_DRAW);

	//bind the attribute in vertex shader to index 0
	glBindAttribLocation(program, 0, "position");

	//tell GL how the data is stored?
	//carefull NULL to use bound buffer or pointer to data not on gpu!!!
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
	
	//tell GL which attrib we would like to use
	glEnableVertexAttribArray(0);
	
	////////////////////
	// DRAWING & LOOP //
	////////////////////
	
	//set the clear color
	glClearColor(0.1, 0.1, 0.1, 1.0);
	
	//events
	XEvent event;
	
	//main program loop
	bool session = true;
	
	while(session) {
		
		XNextEvent(display, &event);
		
		//draws to the screen when we need too
		if(event.type == Expose) {
			//clear the screen
			glClear(GL_COLOR_BUFFER_BIT);
			
			//lets draw our triangle
			glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void*)0);

			//swap the buffers
			eglSwapBuffers(eglDisplay, eglSurface);
		}
		
		//check for Button presses
		if(event.type == KeyPress) {
			//okay which button?
			KeySym ks = XkbKeycodeToKeysym(display, event.xkey.keycode,
										   0, 0);
			
			//go through keys
			switch(ks) {
				//escape key exits loop
				case XK_Escape:
					session = false;
					break;
			}
		}	
	}

	//////////////
	// CLEAN UP //
	//////////////
	
	eglDestroySurface(eglDisplay, eglSurface);
	eglDestroyContext(eglDisplay, eglContext);
	eglTerminate(eglDisplay);
	XDestroyWindow(display, win);
	XCloseDisplay(display);

	return 0;
}

Return to “OpenGLES”