#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
GLuint pboID[2];
GLuint textureID;
const int IMAGE_WIDTH = 1024;
const int IMAGE_HEIGHT = 800;
const int CHANNEL_COUNT = 4;
const int DATA_SIZE = IMAGE_WIDTH * IMAGE_HEIGHT * CHANNEL_COUNT;
GLubyte * imageData = 0;
float cameraAngleX;
float cameraAngleY;
float cameraDistance = -5.0;
bool mouseLeftDown;
bool mouseRightDown;
float LastXPos;
float LastYPos;
void InitGL()
{
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0, 0.0, 0.0, 1.0);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, IMAGE_WIDTH, IMAGE_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)(imageData));
glBindTexture(GL_TEXTURE_2D, 0);
glGenBuffers(2, pboID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID[0]);
glBufferData(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE, 0, GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID[1]);
glBufferData(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE, 0, GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
void UpdatePixels(GLubyte* dst, int size)
{
static int color = 0;
if(!dst)
return;
int* ptr = (int*)dst;
for(int i = 0; i < IMAGE_HEIGHT; ++i)
{
for(int j = 0; j < IMAGE_WIDTH; ++j)
{
*ptr = color;
ptr++;
}
color += 257;
}
++color;
}
void PaintGL()
{
static int index = 0;
int nextIndex = 0;
index = (index + 1) % 2;
nextIndex = (index + 1) % 2;
glBindTexture(GL_TEXTURE_2D, textureID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID[index]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID[nextIndex]);
glBufferData(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE, 0, GL_STREAM_DRAW);
GLubyte * ptr = (GLubyte *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
if (ptr)
{
UpdatePixels(ptr, DATA_SIZE);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0, 0, cameraDistance);
glRotatef(cameraAngleX, 1, 0, 0);
glRotatef(cameraAngleY, 0, 1, 0);
glBindTexture(GL_TEXTURE_2D, textureID);
glColor4f(1, 1, 1, 1);
glBegin(GL_QUADS);
glNormal3f(0, 0, 1);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
glutSwapBuffers();
}
void ResizeGL(int w, int h)
{
if (h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, w/h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
mouseLeftDown = true;
LastXPos = x;
LastYPos = y;
}
if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
{
mouseRightDown = true;
}
}
void mouseMotion(int x, int y)
{
if (mouseLeftDown)
{
cameraAngleX += GLfloat(y - LastYPos)/GLfloat(20.0);
cameraAngleY += GLfloat(x - LastXPos)/GLfloat(20.0);
LastYPos = y;
LastXPos = x;
}
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(1024, 800);
glutCreateWindow("PBO");
GLenum res = glewInit();
if (res != GLEW_OK)
{
std::cout << glewGetErrorString(res) << std::endl;
return EXIT_FAILURE;
}
InitGL();
glutDisplayFunc(PaintGL);
glutReshapeFunc(ResizeGL);
glutMouseFunc(mouse);
glutMotionFunc(mouseMotion);
glutMainLoop();
glDeleteBuffers(2, pboID);
glDeleteTextures(1, &textureID);
delete [] imageData;
return EXIT_SUCCESS;
}