I have two buffers with .rgb images loaded. Original image is stored in frame_buffer and second one is stored in temp_buffer. I want to switch between those two images in GLUT window, when user press a button, how can I extend my code to do this?
typedef struct pixel{
GLbyte r;
GLbyte g;
GLbyte b;
}Pixel;
Pixel frame_buffer[WIDTH][HEIGHT]; //original image
Pixel temp_buffer[WIDTH][HEIGHT]; //embossed image
GLuint texture;
int window_id;
void keyboardFunction(unsigned char button, int x, int y){
switch(button){
case 'S':
case 's':
// WHEN USER PRESS 'S', NEW IMAGE FROM temp_buffer IS
// LOADED, HOW CAN I DO THIS?
break;
default:
break;
}
glutPostRedisplay();
}
// Initialize OpenGL state
void init() {
// Texture setup
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// Other
glClearColor(0, 0, 0, 0);
gluOrtho2D(-1, 1, -1, 1);
glLoadIdentity();
glColor3f(1, 1, 1);
loadInputFromUser();
emboss();
}
void display() {
// Copy frame_buffer to texture memory
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, frame_buffer);
// Clear screen buffer
glClear(GL_COLOR_BUFFER_BIT);
// Render a quad
glBegin(GL_QUADS);
glTexCoord2f(1, 0); glVertex2f(1, 1);
glTexCoord2f(1, 1); glVertex2f(1, -1);
glTexCoord2f(0, 1); glVertex2f(-1, -1);
glTexCoord2f(0, 0); glVertex2f(-1, 1);
glEnd();
// Display result
glFlush();
//glutPostRedisplay();
glutSwapBuffers();
}
// Main entry function
int main(int argc, char **argv) {
// Init GLUT
glutInit(&argc, argv);
glutInitWindowPosition(-1, -1);
glutInitWindowSize(WIDTH, HEIGHT);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("Convolution Filter");
// Set up OpenGL state
init();
// Run the control loop
glutDisplayFunc(display);
glutKeyboardFunc(keyboardFunction);
glutReshapeFunc(changeViewPoint);
GLenum err = glewInit();
if (GLEW_OK != err){
fprintf(stderr, "GLEW error");
return 1;
}
glutMainLoop();
return EXIT_SUCCESS;
}
original image stored in frame_buffer
image filtered with emboss stored in temp_buffer (yeah I know its not perfect :D )
I want to switch between them with keybutton.
Edit the following snippets:
Pixel frame_buffer[WIDTH][HEIGHT]; //original image
Pixel temp_buffer[WIDTH][HEIGHT]; //embossed image
int which_image = 0;
...
case 'S':
case 's':
which_image ^= 1;
break;
...
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, which_image == 0 ? frame_buffer : temp_buffer);
...
glFlush();
glutPostRedisplay();
glutSwapBuffers();
That being said, you currently upload the texture (glTexImage2D) for each frame drawn. You should rather upload it only once during startup and each time it changes.
Related
I want to display a texture but the compiler (Visual Studio 2017) gives me this error:
Exception thrown at 0x69F1454A (nvoglv32.dll) in Playground.exe: 0xC0000005: Access violation reading location 0x0A08D000.
The loadBMP_custom function has been taken from this website:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/
Any help is going to be appreciated.
This is my code:
#include <GL\freeglut.h>
#include <stdio.h>
GLuint loadBMP_custom(const char * imagepath) {
unsigned char header[54];
unsigned int width, height;
unsigned int imageSize;
GLuint textureID;
unsigned char * data;
FILE * file;
file = fopen(imagepath, "rb");
printf("%s\n", imagepath);
if (!file) {
printf("Image could not be opened\n");
return 0;
}
if (fread(header, 1, 54, file) != 54) {
printf("Not a correct BMP file\n");
}
if (header[0] != 'B' || header[1] != 'M') {
printf("Not a correct BMP file\n");
}
imageSize = *(int*)&(header[0x22]); //34
width = *(int*)&(header[0x12]); //18
height = *(int*)&(header[0x16]); //22
if (imageSize == 0) imageSize = width*height * 3;
data = (unsigned char* )malloc(imageSize);
fread(data, 1, imageSize, file);
fclose(file);
for (int i = 0; i < width * height; ++i)
{
int index = i * 3;
unsigned char B, R;
B = data[index];
R = data[index + 2];
data[index] = R;
data[index + 2] = B;
}
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return textureID;
}
void displayMe(void) {
GLuint bmp;
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
bmp = loadBMP_custom("C:\\Dev\\Playground\\Release\\template.bmp");
glBindTexture(GL_TEXTURE_2D, bmp);
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 0.0);
glVertex2f(0.0, 0.0);
glTexCoord2f(0.1, 0.0);
glVertex2f(0.1, 0.0);
glTexCoord2f(0.1, 0.1);
glVertex2f(0.1, 0.1);
glTexCoord2f(0.0, 0.1);
glVertex2f(0.0, 0.1);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.6);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(800, 800);
glutCreateWindow("hi");
glutDisplayFunc(displayMe);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
if (imageSize == 0) imageSize = width*height * 3;
[...]
data = (unsigned char* )malloc(imageSize);
[...]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
You are telling OpenGL that it should interpret the data pointer as describing an image with RGBA components at each pixel, each as bytes, but you provide only RGB data, which means that the GL will access beyond the end of your buffer.
The last three parameters of glTexImage describe the image data in client memory: the numer and order of the channels, the data format for each channel, and the pointer to the first pixel. The GL_RGB you use as internalFormat just describes the format the GL shall internally store the texture at.
The correct code should be
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // use tightly-packed data buffer with no padding between image rows
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
I'm trying my hand at making a chip8 emulator using just plain C. I got most of the opcodes set so I just need to work on the display. I decided on using GLUT for the display since it appeared quick setup. The main idea is to display the chip8 sprites onto the 2D texture. I got it to display some digits though some opcode execution but it's flickering. I'm using double buffering since from what I read it's the best way to make sure something is ready to be displayed but I'm still getting flickering. Any ideas on what can cause it?
Here's all the code for OpenGL and GLUT for the display.
int main(int argc, char * argv[]) {
// if(argc < 2){
// printf("Usage: %s <bin file>\n", argv[0]);
// exit(0);
// }
//initialize chip 8
chip8_Init();
//load file if exists
chip8_load("test6.bin");
//setup graphics
glutInit(&argc, argv);
glutInitWindowSize(display_width, display_height);
glutInitWindowPosition(320, 320);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
glutCreateWindow("Chip8 GL");
setupTexture();
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);
glutKeyboardFunc(chip8_keypad);
glutKeyboardUpFunc(chip8_keypadUp);
glutMainLoop();
return 0;
}
void setupTexture(){
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
//set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
//update texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH,
SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE,
screenData);
}
void updateTexture(){ //display()
//update pixels
for (int i = 0; i < SCREEN_HEIGHT; i++) {
for (int j = 0; j < SCREEN_WIDTH; j++) {
if(chip8.gfx[(i * SCREEN_WIDTH)+j] == 0){
screenData[i][j][0] = 0;
screenData[i][j][1] = 0;
screenData[i][j][2] = 0;
}
else{
screenData[i][j][0] = 255;
screenData[i][j][1] = 255;
screenData[i][j][2] = 255;
}
}
}
//update texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH,
SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE,
screenData);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texName);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2d(0.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex2d(display_width, 0.0);
glTexCoord2f(1.0, 1.0); glVertex2d(display_width, display_height);
glTexCoord2f(0.0, 1.0); glVertex2d(0.0, display_height);
glEnd();
glutSwapBuffers();
}
void renderScene(){
chip8_emulateCycle();
if(drawFlag == 1){
updateTexture();
drawFlag = 0;
}
}
void changeSize(int w, int h){
glClearColor(0.0f, 0.0f, 0.5f, 0.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, w, h);
// Resize quad
display_width = w;
display_height = h;
}
Edit: I might have figured it out. In the draw opcode, it uses XOR. So when the draw command for the first time the sprite is displayed and when called again it disappears and so on so forth.
My opengl is very dusty, but I saw some points in your code:
You should enable GL_TEXTURE_2D before initialize it:
void setupTexture()
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/* enable texturing */
glEnable(GL_TEXTURE_2D);
/* create texture */
glGenTextures(1, &texName);
/* select texture */
glBindTexture(GL_TEXTURE_2D, texName);
/* select behavior */
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
/* ... */
}
You should select the texture before modifying it
void updateTexture(){
/* update pixels */
/* ... */
/*select texture */
glBindTexture(GL_TEXTURE_2D, texName);
/*update texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH,
SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE,
screenData);
/* clear screen */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* draw texture */
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2d(0.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex2d(display_width, 0.0);
glTexCoord2f(1.0, 1.0); glVertex2d(display_width, display_height);
glTexCoord2f(0.0, 1.0); glVertex2d(0.0, display_height);
glEnd();
glutSwapBuffers();
}
Moreover, you may test for the result of called functions, by using glGetError():
void check_for_error(void)
{
GLenum err = glGetError();
if (GL_NO_ERROR != err)
{
fprintf("Error %d\n", err);
exit(EXIT_FAILURE);
}
}
Said that, I don't know the data inside chip8.gfx[], may be they are not as you expect.
Here is the error message I am recieving from VS2010:
Unhandled exception at 0x77358dc9 in AzimuthalEqui.exe:
0xC0000005: Access violation writing location 0x00000014.
The line of code generating this error is:
texture[1] = SOIL_load_OGL_texture
(
texture_filename,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID, // create ID automatically
SOIL_flags
);
before entering this function:
texture_filename = "Data/texture.jpg"
SOIL_LOAD_AUTO (= 0)
SOIL_CREATE_NEW_ID (=0)
SOIL_flags = 16 (=SOIL_FLAG_INVERT_Y)
The problem is that when I include a file I have written to parse some information in a text file an error is generated, otherwise the texture loads and is displayed. The prob is most likely caused by one function as when this particular function is removed the code loads and displays the texture.
Here is the function that when added to my project makes the error occur:
[CODE]
void get_user_points(double *lats, double *longs){
char buffer[BUFFSIZE_PARSE];
char *p_buff = buffer;
FILE *fp;
const char *filename = "Points.txt";
double temp;
double *tmp_p = &temp;
fp = fopen(filename,"r+");
if (fp == NULL)
{
sprintf(buffer, "Can't Find File: %s", filename);
MessageBoxA(NULL, buffer, "ERROR", MB_OK|MB_ICONEXCLAMATION);
exit(0);
}
fgets(buffer, BUFFSIZE_PARSE, fp);
while (*(p_buff+1) != '\0'){
p_buff = get_next_letter(p_buff);
switch (tolower(*p_buff)){
case 'n':
putchar(*p_buff);
p_buff++;
p_buff=get_next_double(lats, p_buff);
printf(" = %f\n", *lats);
break;
case 's':
...
...
}
}
putchar('\n');
fclose(fp);
}
It has something to do with opening the file for reading... if I comment out these lines the texture loads correctly:
//fpr = fopen(filename2,"rb");
...
...
...
//fclose(fpr);
Here is my reduced code (i don't think this is the issue but just in case). [There may be some remanants of my full code]:
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
{
printf("Initialising...\n");
glutInitWindowSize(700, 700);
glutInitWindowPosition(0, 0);
glutCreateWindow ("SOIL Texture Test");
}
InitGL();
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
glutMainLoop();
return 0;
}
int InitGL(GLvoid) // Setup OpenGL
{
//Load textures
if (!LoadGLTextures()) // Jump To Texture Loading Routine ( NEW )
{
MessageBox(NULL,TEXT("Cannot Load Image for Texture Map"),TEXT("Error!"),MB_OK | MB_ICONINFORMATION);
//return false; // If Texture Didn't Load Return FALSE ( NEW )
}
else
glEnable(GL_TEXTURE_2D); // Enable texture mapping
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Set the background colour (to black)
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // Select testing type
//get_user_points(&user_lat[0], &user_long[0]);
return true; // Initialization went OK
}
void DrawGLScene(GLvoid) // OpenGL drawing function
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the Screen and the Depth Buffer
glLoadIdentity();
glTranslatef(0.0f,0.0f,z);
glBindTexture (GL_TEXTURE_2D, texture[filter]);
glBegin (GL_QUADS);
glNormal3f(0, 0, 1);
glTexCoord2f (0,0);
glVertex3f (-3,-3 ,0);
glTexCoord2f (1,0 );
glVertex3f (3,-3 , 0);
glTexCoord2f (1, 1);
glVertex3f (3,3 , 0);
glTexCoord2f (0,1 );
glVertex3f (-3,3 ,0 );
glEnd();
glFlush();
}
void ReSizeGLScene(int w, int h) // Code to resize (and initialise) the OpenGL scene (run once when in fullscreen mode)
{
// Set up perspective view matrix
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 0.1f, 100.0f);
//glOrtho(-50.0, 50.0, -50.0, 50.0, -50.0, 50.0);
// Set up modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int LoadGLTextures(void) // Load Bitmaps And Convert To Textures
{
unsigned int SOIL_flags;
GLint mag_param;
GLint min_param;
printf("Loading Textures... ");
SOIL_flags = SOIL_FLAG_INVERT_Y;
mag_param = GL_NEAREST;
min_param = GL_NEAREST;
texture[1] = SOIL_load_OGL_texture
(
texture_filename,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID, // create ID automatically
SOIL_flags
);
if(texture[1] == 0)
return false;
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,mag_param);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,min_param);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
printf("Textures Loaded\n");
return true;
}
Including the .c files in my project instead of the .lib file fixed the problem.
I am having some trouble in OpenGL, making a render to texture example work. At initialization, i generate a texture 'randtex' with random values of green and black. If i render this texture directly to the window (mapped into a quad) it works all well.
like this:
But if i render 'randtex' into another texture 'tex' which is attached to a framebuffer object, then rendering 'tex' on the screen just gives me a black image on the fbo's blue background and from what i know it should give me the original texture over the blue background. In other words, this is what i am getting
vertex shader for display only (display_shaderp).
#version 420
in vec4 pos;
in vec2 tex_coord;
out vec2 vtex_coord;
uniform mat4 projection;
uniform mat4 modelview;
void main(){
gl_Position = projection * modelview * pos;
vtex_coord = tex_coord;
}
fragment shader for display only (display_shaderp)
#version 420
in vec2 vtex_coord;
uniform sampler2D tex;
out vec4 color;
void main(){
color = texture2D(tex, vtex_coord);
//color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
shader program compiles and links ok, i get no gl errors and framebuffer is complete without errors too.
This is the rendering code:
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (GLfloat)win_width / (GLfloat) win_height, 0.1f, 50.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslate3f(0.0f, 0.0f, -3.0f)
// render to texture
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0,0, win_width, win_height);
glClearColor(0.0, 0.0, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(fbo_shaderp);
GLfloat m_matrix[16], p_matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, m_matrix);
glGetFloatv(GL_PROJECTION_MATRIX, p_matrix);
glUniformMatrix4fv(glGetUniformLocation(fbo_shaderp, "modelview"),1,GL_FALSE,m_matrix);
glUniformMatrix4fv(glGetUniformLocation(fbo_shaderp, "projection"),1,GL_FALSE,p_matrix);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, randtex);
glUniform1i(glGetUniformLocation(fbo_shaderp, "tex"), randtex);
GLuint _p = glGetAttribLocation(fbo_shaderp, "pos");
GLuint _t = glGetAttribLocation(fbo_shaderp, "tex_coord");
glVertexAttribPointer(_p, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
glVertexAttribPointer(_t, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(sizeof(float)*3));
glEnableVertexAttribArray(_p);
glEnableVertexAttribArray(_t);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
glUseProgram(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// render to the window
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0,0, win_width, win_height);
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(display_shaderp);
glUniformMatrix4fv(glGetUniformLocation(display_shaderp,"modelview"),1,GL_FALSE,m_matrix);
glUniformMatrix4fv(glGetUniformLocation(display_shaderp,"projection"),1,GL_FALSE,p_matrix);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(glGetUniformLocation(display_shaderp, "tex"), 0);
GLuint _p = glGetAttribLocation(display_shaderp, "pos");
GLuint _t = glGetAttribLocation(display_shaderp, "tex_coord");
glVertexAttribPointer ( _p, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0 );
glVertexAttribPointer ( _t, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*) (sizeof(float) * 3) );
glEnableVertexAttribArray(_p);
glEnableVertexAttribArray(_t);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
glUseProgram(0);
And the code to create textures and framebuffer
int i = 0;
// create a random texture 'randtex'
glGenTextures(1, &randtex);
glBindTexture(GL_TEXTURE_2D, randtex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// random data
GLubyte* data = (GLubyte *) malloc(width*height*4*sizeof(GLubyte));
GLubyte val;
for (i = 0; i < width * height * 4; i+=4){
if ((double)rand()/(double)RAND_MAX > 0.8)
val = 255;
else
val = 0;
data[i] = 0;
data[i+1] = val;
data[i+2] = 0;
data[i+3] = 255;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,GL_UNSIGNED_BYTE, data);
// create an empty texture 'tex'
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,GL_UNSIGNED_BYTE, 0);
// create framebuffer and attach 'tex'
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, tex, 0);
GLenum status;
if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE)
fprintf(stderr, "glCheckFramebufferStatus: error %p", status);
shaders for render to texture (fbo_shaderp)
render to texture vertex shader
in vec4 pos;
in vec2 tex_coord;
out vec2 vtex_coord;
uniform mat4 projection;
uniform mat4 modelview;
void main(){
gl_Position = projection * modelview * pos;
vtex_coord = tex_coord;
}
render to texture fragment shader
#version 420
in vec2 vtex_coord;
layout(location = 0) out vec4 color;
uniform sampler2D tex;
void main(){
color = texture2D(tex, vtex_coord);
//color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
In this last shader, if i use the commented line to paint all white and comment out the
texture one, i do get a white image but also opengl error right after rendering to texture "OpenGL Error: invalid value", so this actually confuses me more.
glUniform1i(glGetUniformLocation(fbo_shaderp, "tex"), randtex);
You must not give the ID of the texture, but the slot you bind the texture to. So in your case, that should be
glUniform1i(glGetUniformLocation(fbo_shaderp, "tex"), 0);
I'm having trouble getting a texture loaded with SOIL to show up properly on this quad. In case it's not clear, I'm just writing up a little 2D sprite engine, and this is the rendering portion (needs a bit of optimization without a doubt). I haven't done any OpenGL in a couple months, and I'm admittedly quite rusty.
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include "SOIL.h"
#include <stdio.h>
GLuint linktex;
void drawSprite(GLint left, GLint right, GLint bottom, GLint top, GLuint texture){
//Draw clockwise
glColor3f(1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2i(1,1); glVertex2i(right , top);
glTexCoord2i(1,0); glVertex2i(right , bottom);
glTexCoord2i(0,0); glVertex2i(left , bottom);
glTexCoord2i(0,1); glVertex2i(left , top);
glEnd();
}
void display(void){
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho(0.0, 240.0, 0.0, 160.0, -1.0, 1.0);
drawSprite(50, 82, 50, 82, linktex);
glFlush();
}
void reshape(int w, int h){
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
void init(){
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glFrontFace(GL_CW);
GLuint linktex = SOIL_load_OGL_texture(
"link.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
if( 0 == linktex )
{
printf( "SOIL loading error: '%s'\n", SOIL_last_result());
}
}
int main (int argc, char **argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE);
glutInitWindowSize (240, 160);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Test");
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutMainLoop();
init();
return 0;
}
It looks like when you are loading the texture, you are assigning the id to a local variable linktex instead of the global you declared at the beginning of the file.
When you reference linktex in the void display(void); method, the texture is un-initialized.
Try changing your call to load the texture to :
// comment out the type declaration, to assign to the global instead of a local
/*GLuint*/ linktex = SOIL_load_OGL_texture(
"link.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y
);