When I am trying to display images on a square, they are not mapping properly to corners.
These are the original images and the outputs -
I had downloaded original images from the net, and then converted them to bmp using online converter to use them in the code.
here is the code -
#include <stdio.h>
#include <GL/glut.h>
GLuint LoadBMP(const char *fileName)
{
FILE *file;
unsigned char header[54],*data;
unsigned int dataPos,size,width, height;
file = fopen(fileName, "rb");
fread(header, 1, 54, file);
dataPos = *(int*)&(header[0x0A]);
size = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if (size == 0) size = width * height * 3;
if (dataPos == 0) dataPos = 54;
data = new unsigned char[size];
fread(data, 1, size, file);
fclose(file);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, data);
return texture;
}
GLint texture;
void display(void)
{
glClear( GL_COLOR_BUFFER_BIT);
// glColor3f(0.0, 1.0, 0.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5, -0.5, 0.0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5, 0.5, 0.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5, 0.5, 0.0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5, -0.5, 0.0);
glEnd();
glDisable(GL_TEXTURE_2D);
glFlush();
}
int main(int argc, char **argv)
{
printf("hello world\n");
glutInit(&argc, argv);
glutInitDisplayMode ( GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glViewport(0, 0, 500, 500);
glutCreateWindow ("square");
glClearColor(0.0, 0.0, 0.0, 0.0); // black background
glMatrixMode(GL_PROJECTION); // setup viewing projection
glLoadIdentity(); // start with identity matrix
glutDisplayFunc(display);
texture = LoadBMP("wall.bmp");
glutMainLoop();
return 0;
}
Your code uses a static header size, thus it looks like it could be a problem due to the differences in the BMP header changes due to OS changes by Microsoft.
If you are using Linux, try using the file command, to find out which type of BMP you are using:
Your code looks like it works well for Window 3.x format, and you should try converting into that format and check again. You can use ffmpeg for that purpose:
Related
I have created a rotating wired sphere. I have done textures to a cube but sphere seems to be a problem.
I want to add world map as a texture to this sphere. Any suggestions?
#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <thread>
#include <chrono>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
using namespace std;
GLuint texture;
int start = 1;
GLfloat xRotated, yRotated, zRotated;
GLdouble radius = 1;
void init() {
glOrtho(-1000 / 2, 1000 / 2, -1000 / 2, 1000 / 2, -500, 500);
}
GLuint glInitTexture(char* filename)
{
GLuint t = 0;
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
unsigned char* data = stbi_load(filename, &width, &height, &nrChannels, 0);
glGenTextures(1, &t);
glBindTexture(GL_TEXTURE_2D, t);
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);
//unsigned char data[] = { 255, 0, 0, 255 };
if (data)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
else
std::cout << "fail";
return t;
}
void drawImage(GLuint file, float x, float y, float w, float h)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glPushMatrix();
//glTranslatef(x, y, 0.0);
//glRotatef(angle, 0.0, 0.0, 1.0);
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, file);
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -4.5);
glRotatef(yRotated, 0.0, 1.0, 0.0);
glEnable(GL_TEXTURE_2D);
GLUquadric *qobj = gluNewQuadric();
gluQuadricTexture(qobj, GL_TRUE);
gluSphere(qobj, radius, 20, 20);
gluDeleteQuadric(qobj);
glDisable(GL_TEXTURE_2D);
glFlush();
yRotated += 0.01;
//glBindTexture(GL_TEXTURE_2D, 0);
glFlush();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
//Plots points of both graphs together
//Displays map on screen
void drawMap() {
std::cout << "\nDraw map\n";
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
const double w = glutGet(GLUT_WINDOW_WIDTH);
const double h = glutGet(GLUT_WINDOW_HEIGHT);
gluPerspective(90.0, w / h, 0.1, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -15);
for (int i = 0; i < 10000; i++) {
glClear(GL_DEPTH_BUFFER_BIT);
drawImage(texture, 0, 0, 100, 200);
//std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
glutSwapBuffers();
glEnd();
glFlush();
}
void render()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//glFlush();
glPointSize(5);
glColor3f(1, 1, 1);
glBegin(GL_LINES);
glVertex3f(-450, -450, 10);
glVertex3f(-450, -250, 10);
glEnd();
glBegin(GL_LINES);
glVertex3f(-450, -450, 10);
glVertex3f(-250, -450, 10);
glEnd();
drawMap();
//plotPoints();
glFlush();
}
void Kbevent(unsigned char key, int x, int y) {
if (key == 's') {
start = start % 2;
glutPostRedisplay();
}
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1560, 810);
glutCreateWindow("Applying Textures");
init();
xRotated = yRotated = zRotated = 30.0;
xRotated = 33;
yRotated = 40;
char fn[] = "map.jpg";
texture = glInitTexture(fn);
glutDisplayFunc(render);
//glutReshapeFunc(reshapeFunc);
//glutIdleFunc(idleFunc);
glutKeyboardFunc(Kbevent);
glutMainLoop();
return 0;
}
The problem with applying a 2D texture is that when you wrap a 2D texture onto a sphere, the top and bottom area of the sphere, the texture looks squeezed.
I suggest to use gluSphere and gluQuadricTexture rather than glutSolidSphere. e.g:
glEnable(GL_TEXTURE_2D);
GLUquadric *qobj = gluNewQuadric();
gluQuadricTexture(qobj, GL_TRUE);
gluSphere(qobj, radius, 20, 20);
gluDeleteQuadric(qobj);
glDisable(GL_TEXTURE_2D);
For an continuously rotation, you have increment the rotation angle and to continuously update the window (glutPostRedisplay). e.g.:
void redisplayFunc(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -4.5);
glRotatef(yRotated, 0.0, 1.0, 0.0);
glEnable(GL_TEXTURE_2D);
GLUquadric *qobj = gluNewQuadric();
gluQuadricTexture(qobj, GL_TRUE);
gluSphere(qobj, radius, 20, 20);
gluDeleteQuadric(qobj);
glDisable(GL_TEXTURE_2D);
glFlush();
yRotated += 1;
glutPostRedisplay();
}
I tried to apply textures to squares with the following code, but they didn't apply.
Is there a problem with the code above?
"dd" is printed on the console window.
I think it is read the bmp file.
but I only see white square like the following pictures.
Bitmap files are located in the project folder.
LoadBMP() is a function that opens the bmp file.
LoadGLTextures() is a function to load textures.
ps. I am not good at English. I'm sorry.
#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <GL/GLAUX.H>
#pragma comment (lib,"glaux.lib")
unsigned int MyTextureObiect[1];
AUX_RGBImageRec *pTextureImage[1];
AUX_RGBImageRec *LoadBMP(char *szFilename) {
FILE * pFile = NULL;
if (!szFilename) {
return NULL;
}
pFile = fopen(szFilename, "r");
if (pFile) {
fclose(pFile);
return auxDIBImageLoad(szFilename);
}
return NULL;
}
int LoadGLTextures() {
int Status = FALSE;
memset(pTextureImage, 0, sizeof(void *) * 1);
if (pTextureImage[0] = LoadBMP("butterflyans.bmp")) {
printf("dd");
Status = TRUE;
glGenTextures(1, &MyTextureObiect[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, pTextureImage[0]->sizeX, pTextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, pTextureImage[0]->data);
glEnable(GL_TEXTURE_2D);
}
if (pTextureImage[0]) {
if (pTextureImage[0]->data) {
free(pTextureImage[0]->data);
}
free(pTextureImage[0]);
}
return Status;
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, MyTextureObiect[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-0.5, -0.5, 0.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(0.5, -0.5, 0.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(0.5, 0.5, 0.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-0.5, 0.5, 0.0);
glEnd();
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutCreateWindow("OpenGL Drawing Example");
glutDisplayFunc(myDisplay);
if (LoadGLTextures()) {
glEnable(GL_TEXTURE_2D);
}
glutMainLoop();
return 0;
}
You missed to bind glBindTexture the texture object, before setting the texture parameters and specifying the texture.
Note, glTexParameter and glTexImage2D apply to the currently bound texture:
glGenTextures(1, &MyTextureObiect[0]);
glBindTexture(GL_TEXTURE_2D, MyTextureObiect[0]); // <---- bind the texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D( .... );
By the way, you set GL_TEXTURE_MIN_FILTER twice, but you never set GL_TEXTURE_MAG_FILTER.
I am struggling with loading src/up.bmp and showing it in 2D overlaid on my 3D environment.
But nothing does appear. Where is my mistake?
#define SDL_MAIN_HANDLED
#include <math.h>
#include <SDL.h>
#include <iostream>
#include <GL/freeglut.h>
using namespace std;
int w_width = 800;
int w_height = 500;
string w_title = "Model viewer";
float line_width = 2.0f;
float camera_radius = 100.0f;
float axis_size = 20.0;
SDL_Surface* button1;
GLuint TextureID;
void draw_button(SDL_Surface* button)
{
glGenTextures(1, &TextureID);
glBindTexture(GL_TEXTURE_2D, TextureID);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, button->w, button->h, GL_RGB, GL_UNSIGNED_BYTE, button->pixels);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
const float ratio = (float)glutGet(GLUT_SCREEN_WIDTH) / (float)glutGet(GLUT_SCREEN_HEIGHT);
static double t = 0.0;
const float deg2rad = 3.1415926f / 180.0f;
float cam_x = camera_radius*float(cos(20.0f*deg2rad))*float(cos(0.5235*deg2rad));
float cam_y = camera_radius*float(sin(20.f*deg2rad))*float(cos(0.5235*deg2rad));
float cam_z = camera_radius*float(sin(0.5235*deg2rad));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, ratio, 0.01, 10000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cam_x, cam_y, cam_z, 0, 0, 0, 0, 0, 1);
// sphere
glPushMatrix();
glColor3ub(255, 0, 0);
glTranslated(
0,
0,
0);
glutSolidSphere(1, 20, 20);
glPopMatrix();
draw_button(button1);
glFlush();
glutSwapBuffers();
}
void timer_event(int value)
{
glutPostRedisplay();
glutTimerFunc(100, timer_event, value);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutSetOption(GLUT_MULTISAMPLE, 8);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);
glutTimerFunc(30, timer_event, 1);
glutInitWindowSize(w_width, w_height);
glutInitWindowPosition(10, 10);
glutCreateWindow(argv[0]);
glutSetWindowTitle(w_title.c_str());
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glutDisplayFunc(display);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_TEXTURE_2D);
button1 = SDL_LoadBMP("src/up.bmp");
if (button1 == NULL)
{
cout << "Image not found" << endl;
exit(1);
}
glutMainLoop();
SDL_FreeSurface(button1);
return 0;
}
Here is a minimal example I can come up with:
#define SDL_MAIN_HANDLED
#include <math.h>
#include <SDL.h>
#include <iostream>
#include <GL/gl.h>
#include <GL/freeglut.h>
using namespace std;
int w_width = 800;
int w_height = 500;
string w_title = "Model viewer";
float line_width = 2.0f;
float camera_radius = 100.0f;
float axis_size = 20.0;
SDL_Surface* button1;
GLuint TextureID;
static void prepare_texture(SDL_Surface *button)
{
glGenTextures(1, &TextureID);
glBindTexture(GL_TEXTURE_2D, TextureID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// convert surface to RGB8
SDL_Surface *rgb = SDL_CreateRGBSurface(0, button->w, button->h, 24, 0xff, 0xff00, 0xff0000, 0);
SDL_BlitSurface(button, NULL, rgb, NULL);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, button->w, button->h, GL_RGB, GL_UNSIGNED_BYTE, rgb->pixels);
SDL_FreeSurface(rgb);
}
static void draw_button()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glBindTexture(GL_TEXTURE_2D, TextureID);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0.1f, 0.1f);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0.1f, 0.2f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(0.2f, 0.2f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(0.2f, 0.1f);
glEnd();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
const float ratio = (float)glutGet(GLUT_SCREEN_WIDTH) / (float)glutGet(GLUT_SCREEN_HEIGHT);
static double t = 0.0;
const float deg2rad = 3.1415926f / 180.0f;
float cam_x = camera_radius*float(cos(20.0f*deg2rad))*float(cos(0.5235*deg2rad));
float cam_y = camera_radius*float(sin(20.f*deg2rad))*float(cos(0.5235*deg2rad));
float cam_z = camera_radius*float(sin(0.5235*deg2rad));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, ratio, 0.01, 10000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cam_x, cam_y, cam_z, 0, 0, 0, 0, 0, 1);
// sphere
glPushMatrix();
glColor3ub(255, 0, 0);
glTranslated(
0,
0,
0);
glutSolidSphere(1, 20, 20);
glPopMatrix();
draw_button();
glFlush();
glutSwapBuffers();
}
void timer_event(int value)
{
glutPostRedisplay();
glutTimerFunc(100, timer_event, value);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutSetOption(GLUT_MULTISAMPLE, 8);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);
glutTimerFunc(30, timer_event, 1);
glutInitWindowSize(w_width, w_height);
glutInitWindowPosition(10, 10);
glutCreateWindow(argv[0]);
glutSetWindowTitle(w_title.c_str());
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glutDisplayFunc(display);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_TEXTURE_2D);
button1 = SDL_LoadBMP("up.bmp");
if (button1 == NULL)
{
cout << "Image not found" << endl;
exit(1);
}
prepare_texture(button1);
SDL_FreeSurface(button1);
glutMainLoop();
return 0;
}
Note identity projection, which maps screen to [-1,1] range; you may want something more like gluOrtho2D.
I am trying to wrap a texture on a quad.
All I see is a white rectangle:
To load the texture I used freeimage.
I need help in order to fix this very simple demo:
#include <GL/glut.h>
#include <GL/gl.h>
#include <FreeImage.h>
#include <stdio.h>
GLfloat coordinates[] =
{
-0.5, 0.5, 1,
-0.5, -0.5, 0,
0.5, -0.5, 0,
0.5, 0.5, 0
};
GLfloat texCoords[] =
{
0, 1,
0, 0,
1, 0,
1, 1
};
BYTE* data;
FIBITMAP* bitmap;
GLuint texture;
void initGlutCallbacks();
void initGL();
void onReshape(int w, int h);
void display();
FIBITMAP* loadTexture(const char* fileName);
int main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(512, 512);
glutInitWindowPosition(64, 64);
glutCreateWindow("arrays");
initGlutCallbacks();
initGL();
// texture
bitmap = loadTexture("rufol.png");
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
data = FreeImage_GetBits(bitmap);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
GL_RGBA8, GL_UNSIGNED_BYTE,
data
);
// enable arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// specifying data for the arrays
glVertexPointer
(
3, GL_FLOAT, 0, coordinates
);
glTexCoordPointer
(
2, GL_FLOAT, 0, texCoords
);
glutMainLoop();
}
void initGlutCallbacks(){
glutReshapeFunc(onReshape);
glutDisplayFunc(display);
}
void initGL(){
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0);
glEnable ( GL_TEXTURE_2D );
}
void onReshape(int w, int h){
}
void display(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTexEnvf(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDrawArrays(GL_QUADS, 0, 4);
glFlush();
glutSwapBuffers();
}
FIBITMAP* loadTexture(const char* fileName){
FIBITMAP *bitmap = FreeImage_Load(FIF_PNG, "rufol.png");
if(bitmap == 0) printf("error loading the image\n");
FIBITMAP *fbitmap = FreeImage_ConvertTo32Bits(bitmap);
FreeImage_Unload(bitmap);
return fbitmap;
}
As you can see I am not even using perspective. Also lighting is not enabled(I don't know if it is required to display textures). I have tested a very similar code but using colors for each vertex instead of texture coordinates and it worked. So I think it might be something wrong when loading the image.
Have you tried using GL_RGBA instead of GL_RGBA8 as second parameter (format)?
I'm currently trying to implement in OpenGL image processing algorithms.
I would like to successively use several shaders in order to perform several filters (Sobel Gaussian,...).
I understood that to do this I had to render to texture thanks to a FBO. I read a lot of things about that, and wrote a code. But I'm not getting the result I expected.
For the moment, I'm just trying to use two shaders. So, I have an original image which is the input of my first shader. Then, I want to render the output of the shader to a texture which will then be the input of my second shader (ping-pong technique). And finally, I want to display the output of the second shader.
But as result, I'm getting the original image.
My code is the following:
/******************** Shaders Function *******************************/
void setupShaders(char *vert, char *frag, GLuint p) {
GLuint v, f;
char *vs = NULL,*fs = NULL;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead(vert);
fs = textFileRead(frag);
const char * ff = fs;
const char * vv = vs;
glShaderSource(v, 1, &vv, NULL);
glShaderSource(f, 1, &ff, NULL);
free(vs);free(fs);
glCompileShader(v);
glCompileShader(f);
p = glCreateProgram();
glAttachShader(p,f);
glAttachShader(p,v);
glLinkProgram(p);
glUseProgram(p);
}
/******************** Texture Function ***********************************/
void setupTexture(void) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
/******************** Quad Drawing Function ******************************/
void ShaderDraw(void){
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(0.0, height, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(width, height, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(width, height, 0.0);
glEnd();
}
/******************** Initialization Function ***************************/
void init(void)
{
//Checking GLSL
glewInit();
if (glewIsSupported("GL_VERSION_2_0"))
printf("Ready for OpenGL 2.0\n");
else {
printf("OpenGL 2.0 not supported\n");
exit(1);
}
// Init
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
}
/******************** Display Function **********************************/
void display(void)
{
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-4.0, -4.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-4.0, 4.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(4.0, 4.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(4.0, -4.0, 0.0);
glEnd();
glFlush();
glDisable(GL_TEXTURE_2D);
}
/******************** Reshape Function *********************************/
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, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -7.0);
}
/******************** Main Function *************************************/
int main(int argc, char** argv)
{
// Glut Initialisation
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
// Window Generation
glutInitWindowSize(1000,800);
glutInitWindowPosition(100, 100);
glutCreateWindow("Night Vision");
// Initialisation Function
init();
// Downloading Image
data = cLoadBitmap("lena.bmp", &height, &width);
checkGLErrors ("Downloading Image");
int read_tex = 0;
int write_tex = 1;
// Generating Texture
glEnable(GL_TEXTURE_2D);
glGenTextures(2, texImg);
// Init Texture0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texImg[read_tex]);
setupTexture();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
checkGLErrors ("InitTexture0");
// Init Texture1
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texImg[write_tex]);
setupTexture();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
checkGLErrors ("InitTexture1");
// Setup Framebuffer Object
GLuint fb;
glGenFramebuffersEXT(1, &fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
checkGLErrors ("Framebuffer->fb");
GLenum att_point[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
glBindTexture(GL_TEXTURE_2D, texImg[read_tex]);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, att_point[read_tex], GL_TEXTURE_2D, texImg[read_tex], 0);
glBindTexture(GL_TEXTURE_2D, texImg[write_tex]);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, att_point[write_tex], GL_TEXTURE_2D, texImg[write_tex], 0);
checkFramebufferStatus();
//set the write texture as output buffer for the shader
glDrawBuffer(att_point[write_tex]);
// create, init and enable the shader
setupShaders("filter.vert", "sobel_filter_3.frag", p1);
checkGLErrors ("Shaders 1");
// attach the input texture(read texture) to the first texture unit
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texImg[read_tex]);
GLuint texLoc;
texLoc = glGetUniformLocation(p1,"tex");
glUniform1i(texLoc, 0);
// draw a square with the texture on it so to perform the computation
ShaderDraw();
// swap the buffers
read_tex = 1;
write_tex = 0;
// Delete program 1
glDeleteProgram(p1);
// set the write texture as output buffer for the shader
glDrawBuffer(att_point[write_tex]);
// create, init and enable the shaders
setupShaders("filter.vert", "gaussian7.frag", p2);
checkGLErrors ("Shaders 2");
// attach the input texture(read texture) to the first texture unit
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texImg[read_tex]);
texLoc = glGetUniformLocation(p2,"tex");
glUniform1i(texLoc, 0);
// draw a square with the texture on it so to perform the computation
ShaderDraw();
// Delete program 2 & disable the FBO
glDeleteProgram(p2);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glUseProgram(0);
// Bind the texture to display
glBindTexture(GL_TEXTURE_2D,texImg[0]);
// Glut Functions: Display, Reshape, Keyboard
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
// Calling Main
glutMainLoop();
return 0;
}
Does someone have an idea of what is wrong???
You are trying to simultaneously use the FBO as render source and render target. Afaik you cannot do that - if you want to use a texture bound to an FBO as render source, you need to unbind the FBO (either by calling glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); or by binding another FBO).
It looks like you are trying to save memory that way by using your start texture as the FBO's color buffer there. I am not sure whether this is possible as well.
So you may want try to create two FBOs, each with a single color buffer, and swap the entire FBOs, and start with rendering your texture to the first FBO. Also, don't use your start texture as a color buffer for an FBO, but create a separate color buffer for each FBO instead.
You also don't need to bind a texture to a texture unit before attaching it to an FBO.