I found a wonderful volume rendering tutorial on the internet:
volume rendering tutorial
. The sample code is written in Windows and since I am working on a Mac, I tried to write my own code according to my understanding. For now, my program just arranges the 2D frame from -1 to 1 in Z axis without applying alpha and blend. So if everything goes well, I should be able to see the first slice. However, when I run the program, I get something weird.
My code:
//
// VolumeRendering.cpp
// Volume_Rendering
//
// Created by HOBBY on 4/5/14.
// Copyright (c) 2014 Yihao Jiang. All rights reserved.
//
#include <GLTools.h>
#include <GL/glew.h>
#include <Opengl/gl.h>
#include <glut/glut.h>
#include <fstream>
#include "VolumeRendering.h"
#include <GLMatrixStack.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
int m_uImageCount;
int m_uImageWidth;
int m_uImageHeight;
GLuint* m_puTextureIDs;
GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLFrame cameraFrame;
GLFrustum viewFrustum;
GLBatch myBatch;
GLGeometryTransform transformPipeline;
GLShaderManager shaderManager;
void ChangeSize(int w, int h)
{
glViewport(0, 0, w, h);
GLdouble aspectRatio = (GLdouble)(w)/(GLdouble)(h);
if (w <= h)
{
viewFrustum.SetOrthographic(-1.0f, 1.0f, -(1.0f/aspectRatio), 1.0f/aspectRatio, -1.0f, 1.0f);
}
else
{
viewFrustum.SetOrthographic(-1.0f, 1.0f, -(1.0f * aspectRatio), 1.0f * aspectRatio, -1.0f, 1.0f);
}
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
void SetupRC()
{
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
shaderManager.InitializeStockShaders();
glEnable(GL_DEPTH_TEST);
const char* filePath = "/Users/WensarHobby/Documents/Codes/workspace/Volume_Rendering/Volume_Rendering/head256x256x109";
if(!InitTextures2D(filePath))
{
printf("InitTexture error");
}
}
bool InitTextures2D(const char* filePath)
{
std::fstream myFile;
myFile.open(filePath, std::ios::in | std::ios::binary);
m_uImageCount = 109;
m_uImageWidth = 256;
m_uImageHeight = 256;
// Holds the texuture IDs
m_puTextureIDs = new GLuint[m_uImageCount];
// Holds the luminance buffer
char* chBuffer = new char[m_uImageWidth * m_uImageHeight];
char* chRGBABuffer = new char[m_uImageWidth * m_uImageHeight * 4];
glGenTextures(m_uImageCount, (GLuint*)m_puTextureIDs);
// Read each frames and construct the texture
for( int nIndx = 0; nIndx < m_uImageCount; ++nIndx )
{
// Read the frame
myFile.read(chBuffer, m_uImageWidth*m_uImageHeight);
// Set the properties of the texture.
glBindTexture( GL_TEXTURE_2D, m_puTextureIDs[nIndx] );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_uImageWidth, m_uImageHeight , 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE,(GLvoid *) chBuffer);
glBindTexture( GL_TEXTURE_2D, 0 );
}
delete[] chBuffer;
delete[] chRGBABuffer;
return true;
}
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
{}
if (key == GLUT_KEY_DOWN)
{
}
if (key == GLUT_KEY_LEFT)
{
}
if (key == GLUT_KEY_RIGHT)
{
}
glutPostRedisplay();
}
void RenderScene(void)
{
static GLfloat vLightPos [] = { 1.0f, 1.0f, 0.0f };
static GLfloat vWhite [] = { 1.0f, 1.0f, 1.0f, 1.0f };
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
modelViewMatrix.PushMatrix();
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
for(int nIndx=0; nIndx <m_uImageCount;++nIndx)
{
glBindTexture(GL_TEXTURE_2D, m_puTextureIDs[nIndx]);
MakeQuads(nIndx);
glBindTexture(GL_TEXTURE_2D, m_puTextureIDs[nIndx]);
}
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos, vWhite, 0);
myBatch.Draw();
modelViewMatrix.PopMatrix();
glutSwapBuffers();
}
void MakeQuads(int quads_index)
{
myBatch.Begin(GL_QUADS, 4, 1);
myBatch.Normal3f(0.0f, 0.0f, -1.0f);
myBatch.MultiTexCoord2f(quads_index, 0.0f, 0.0f);
myBatch.Vertex3f(-1.0f, -1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
myBatch.Normal3f(0.0f, 0.0f, -1.0f);
myBatch.MultiTexCoord2f(quads_index, 1.0f, 0.0f);
myBatch.Vertex3f(1.0f, -1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
myBatch.Normal3f(0.0f, 0.0f, -1.0f);
myBatch.MultiTexCoord2f(quads_index, 0.0f, 1.0f);
myBatch.Vertex3f(-1.0f, 1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
myBatch.Normal3f(0.0f, 0.0f, -1.0f);
myBatch.MultiTexCoord2f(quads_index, 1.0f, 1.0f);
myBatch.Vertex3f(1.0f, 1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
myBatch.End();
}
void ShutdownRC(void)
{
glDeleteTextures(m_uImageCount, (GLuint*)m_puTextureIDs);
}
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowSize(400, 400);
glutCreateWindow("Volume_Rendering");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
SetupRC();
glutMainLoop();
ShutdownRC();
return 0;
}
And this is my weird result:
I am new to OpenGL and volume rendering, in my opinion, there should be something wrong with my use of the shader manager. But I am not so sure. Anyone can tell me where the problem is? Thank you very much.
Finally, I figure it out! I was right and the problem lies in function MultiTexCoord2f(). The first parameter of this function here should always be 0 rather than quads_index. No multitextures here!! The new code looks like this:
#include <GLTools.h>
#include <GL/glew.h>
#include <Opengl/gl.h>
#include <glut/glut.h>
#include <fstream>
#include "VolumeRendering.h"
#include <GLMatrixStack.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
int m_uImageCount;
int m_uImageWidth;
int m_uImageHeight;
GLuint* m_puTextureIDs;
GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLFrame cameraFrame;
GLFrame objectFrame;
GLFrustum viewFrustum;
GLBatch myBatch;
GLGeometryTransform transformPipeline;
GLShaderManager shaderManager;
void ChangeSize(int w, int h)
{
glViewport(0, 0, w, h);
viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
void SetupRC()
{
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
shaderManager.InitializeStockShaders();
glEnable(GL_DEPTH_TEST);
const char* filePath = "/Users/WensarHobby/Documents/Codes/workspace/Volume_Rendering/Volume_Rendering/head256x256x109";
if(!InitTextures2D(filePath))
{
printf("InitTexture error");
}
cameraFrame.MoveForward(-7.0f);
}
bool InitTextures2D(const char* filePath)
{
std::fstream myFile;
myFile.open(filePath, std::ios::in | std::ios::binary);
m_uImageCount = 109;
m_uImageWidth = 256;
m_uImageHeight = 256;
// Holds the texuture IDs
m_puTextureIDs = new GLuint[m_uImageCount];
// Holds the luminance buffer
char* chBuffer = new char[m_uImageWidth * m_uImageHeight];
//char* chRGBABuffer = new char[m_uImageWidth * m_uImageHeight * 4];
glGenTextures(m_uImageCount, m_puTextureIDs);
// Read each frames and construct the texture
for( int nIndx = 0; nIndx < m_uImageCount; ++nIndx )
{
// Read the frame
myFile.read(chBuffer, m_uImageWidth*m_uImageHeight);
// Set the properties of the texture.
glBindTexture( GL_TEXTURE_2D, m_puTextureIDs[nIndx] );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_uImageWidth, m_uImageHeight , 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE,(GLvoid *) chBuffer);
glBindTexture( GL_TEXTURE_2D, 0 );
}
delete[] chBuffer;
// delete[] chRGBABuffer;
return true;
}
void SpecialKeys(int key, int x, int y)
{
glutPostRedisplay();
}
void RenderScene(void)
{
static GLfloat vLightPos [] = { 1.0f, 1.0f, 0.0f };
static GLfloat vWhite [] = { 1.0f, 1.0f, 1.0f, 1.0f };
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
modelViewMatrix.PushMatrix();
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
M3DMatrix44f mObjectFrame;
objectFrame.GetMatrix(mObjectFrame);
modelViewMatrix.MultMatrix(mObjectFrame);
for(int nIndx=0; nIndx <m_uImageCount;++nIndx)
{
glBindTexture(GL_TEXTURE_2D, m_puTextureIDs[nIndx]);
MakeQuads(nIndx);
glBindTexture(GL_TEXTURE_2D, m_puTextureIDs[nIndx]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos, vWhite, 0);
myBatch.Draw();
}
modelViewMatrix.PopMatrix();
glutSwapBuffers();
}
void MakeQuads(int quads_index)
{
myBatch.Begin(GL_QUADS, 4, 1);
myBatch.Normal3f(0.0f, 0.0f, -1.0f);
myBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
myBatch.Vertex3f(-1.0f, -1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
//myBatch.Vertex3f(-1.0f, -1.0f, 1.0f);
myBatch.Normal3f(0.0f, 0.0f, -1.0f);
myBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
myBatch.Vertex3f(1.0f, -1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
//myBatch.Vertex3f(1.0f, -1.0f, 1.0f);
myBatch.Normal3f(0.0f, 0.0f, -1.0f);
myBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
myBatch.Vertex3f(1.0f, 1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
//myBatch.Vertex3f(1.0f, 1.0f, 1.0f);
myBatch.Normal3f(0.0f, 0.0f, -1.0f);
myBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
myBatch.Vertex3f(-1.0f, 1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
//myBatch.Vertex3f(-1.0f, 1.0f, 1.0f);
myBatch.End();
}
void ShutdownRC(void)
{
glDeleteTextures(m_uImageCount, (GLuint*)m_puTextureIDs);
}
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowSize(400, 400);
glutCreateWindow("Volume_Rendering");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
SetupRC();
glutMainLoop();
ShutdownRC();
return 0;
}
Related
I'm trying to display a spinning cube with 6 different textures (all jpg and jpeg) using SDL library. But the program only shows white squares only. Anyone can please explain what happened to these textures?
each function behavior
opengl_init(): init opengl settings
init(): init SDL settings including opengl_init()
clean_up(): runs right before program ends
RenewTexture(): here I want to map texture with this function
main(): about drawing vertexes and playing each frame with spinning function
const int window_width = 1024;
const int window_height = 1024;
const int SCREEN_BPP = 32;
SDL_Event event;
SDL_Window* win = NULL;
SDL_Renderer* renderer = NULL;
GLuint texId[6];
SDL_GLContext context;
/****** Name Space for Game Variables ******/
namespace var
{
int frame_start_time = 0;
int frame_current_time = 0;
int frame_count = 0;
}
/****** Initializes Core OpenGL Features ******/
bool opengl_init()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glClearColor(0, 0, 0, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (640.0 / 480.0), 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
std::cout << glGetError << std::endl;
if (glGetError() != GL_NO_ERROR)
{
return false;
}
return true;
}
/****** Initializes SDL, OpenGL and Video and Window ******/
bool init()
{
//if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
return false;
}
win = SDL_CreateWindow("WINDOW", 100, 100, window_width, window_height, SDL_WINDOW_OPENGL);
renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
context = SDL_GL_CreateContext(win);
if (opengl_init() == false)
{
return false;
}
}
/* Removes objects before game closes */
void clean_up()
{
SDL_Quit();
}
void RenewTexture(SDL_Surface* tmpimg, int index) {
GLubyte* map = (GLubyte*)tmpimg->pixels;
glBindTexture(GL_TEXTURE_2D, texId[index]);
int w, h;
w = tmpimg->w;
h = tmpimg->h;
/*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);*/
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB,
w, h, 0,
GL_RGB, GL_UNSIGNED_BYTE,
map
);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glBindTexture(GL_TEXTURE_2D, texId[index]);
}
int main(int argc, char* args[])
{
std::vector<SDL_Surface*> image;
GLfloat rotation = 0.0f;
bool quit = false;
if (init() == false)
{
return 1;
}
const char* ImageNames[6] = { "res/KGU-logo.jpg", "res/Me.jpeg", "res/beach-1838501.jpg", "res/bench-560435.jpg", "res/wolf-1341881_1920.jpg", "res/spring-bird-2295434.jpg" };
for (int i = 0; i < 6; i++) {
SDL_RWops* tmprwop = SDL_RWFromFile(ImageNames[i], "rb");
SDL_Surface* tmpimg = IMG_LoadJPG_RW(tmprwop);
image.push_back(tmpimg);
}
for(int i=0;i<6;i++)
glGenTextures(1, &texId[i]);
/*SDL_Rect position;
position.x = 1;
position.y = 1;
position.h = 10;
position.w = 10;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, SDL_CreateTextureFromSurface(renderer, image.at(0)), NULL, &position);
SDL_RenderPresent(renderer);*/
/****** Main Game Loop ******/
while (quit == false)
{
/****** Get Most Current Time ******/
var::frame_start_time = SDL_GetTicks();
/****** Draw Rectangle ******/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -6.0f);
glRotatef(rotation, 1.0f, 1.0f, 0.0f);
RenewTexture(image.at(0), 0);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(0, 0);
glTexCoord2f(1.0, 0.0); glVertex2f(550, 0);
glTexCoord2f(1.0, 1.0); glVertex2f(550, 550);
glTexCoord2f(0.0, 1.0); glVertex2f(0, 550);
glEnd();
RenewTexture(image.at(0), 0);
glBegin(GL_QUADS);
/* Cube Top */
//glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
RenewTexture(image.at(1), 1);
/* Cube Bottom */
//glColor4f(1.0f, 0.5f, 0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
RenewTexture(image.at(2), 2);
/* Cube Front */
//glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
RenewTexture(image.at(3), 3);
/* Cube Back */
//glColor4f(0.0f, 1.0f, 0.5f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
RenewTexture(image.at(4), 4);
/* Cube Left Side */
//glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
RenewTexture(image.at(5), 5);
/* Cube Right Side */
//glColor4f(0.15f, 0.25f, 0.75f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd();
rotation -= 0.5f;
/****** Check for Key & System input ******/
while (SDL_PollEvent(&event))
{
/****** Application Quit Event ******/
if (event.type == SDL_QUIT)
{
quit = true;
}
}
/****** Update Screen And Frame Counts ******/
SDL_GL_SwapWindow(win);
var::frame_count++;
var::frame_current_time = SDL_GetTicks();
/****** Frame Rate Handle ******/
if ((var::frame_current_time - var::frame_start_time) < (1000 / 60))
{
var::frame_count = 0;
SDL_Delay((1000 / 60) - (var::frame_current_time - var::frame_start_time));
}
}
clean_up();
return 0;
}
Edit
Solved via changing all glTexCoord3f() to glTexCoord2f() and it worked... my fault :D
additionaly, I misunterstood glEnable(GL_TEXTURE_3D) so changed to glEnable(GL_TEXTURE_2D), and checked all opengl errors via error check function
void errorcheck() {
int errormsg;
if ((errormsg = glGetError()) != GL_NO_ERROR)
{
std::cout << "glerror: " << errormsg << std::endl;
exit(0);
}
}
I found a useful post at this site, where some code is used to load a BMP
This code should load the header, read out infos, go further, read data, generate texture and bin it. But it doesnt work. What am I doing wrong ?
Texture Declaration :
GLuint texture[1];
BMP Loading :
void LoadTexture(char *filename)
{
FILE * file = fopen(filename,"rb");
unsigned char header[54];
unsigned int dataPos;
unsigned int imageSize;
unsigned int width, height;
fread(header,1,54,file);
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if (imageSize==0) {
imageSize=width*height*3;
}
if (dataPos==0) {
dataPos=54;
}
unsigned char data[imageSize];
fseek(file, SEEK_SET, 53);
fread(data,1,imageSize,file);
fclose(file);
glActiveTexture(GL_TEXTURE1);
glGenTextures(1, texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[0]);
}
EDIT : I printed out some values read from the header. The header seems to be read properly.
Drawing :
int DrawGLScene(GLvoid)
{
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glTranslatef(0.0f,0.0f,-5.0f);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
glFlush();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return 1;
}
Finally, after browsing the internet quite a lot, I found this working example :
#include <stdlib.h>
#include <string.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdio.h>
#include <math.h>
GLuint texture[2];
struct Image {
unsigned long sizeX;
unsigned long sizeY;
char *data;
};
typedef struct Image Image;
#define checkImageWidth 64
#define checkImageHeight 64
GLubyte checkImage[checkImageWidth][checkImageHeight][3];
void makeCheckImage(void){
int i, j, c;
for (i = 0; i < checkImageWidth; i++) {
for (j = 0; j < checkImageHeight; j++) {
c = ((((i&0x8)==0)^((j&0x8)==0)))*255;
checkImage[i][j][0] = (GLubyte) c;
checkImage[i][j][1] = (GLubyte) c;
checkImage[i][j][2] = (GLubyte) c;
}
}
}
int ImageLoad(char *filename, Image *image) {
FILE *file;
unsigned long size; // size of the image in bytes.
unsigned long i; // standard counter.
unsigned short int planes; // number of planes in image (must be 1)
unsigned short int bpp; // number of bits per pixel (must be 24)
char temp; // temporary color storage for bgr-rgb conversion.
// make sure the file is there.
if ((file = fopen(filename, "rb"))==NULL){
printf("File Not Found : %s\n",filename);
return 0;
}
// seek through the bmp header, up to the width/height:
fseek(file, 18, SEEK_CUR);
// read the width
if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
printf("Error reading width from %s.\n", filename);
return 0;
}
//printf("Width of %s: %lu\n", filename, image->sizeX);
// read the height
if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
printf("Error reading height from %s.\n", filename);
return 0;
}
//printf("Height of %s: %lu\n", filename, image->sizeY);
// calculate the size (assuming 24 bits or 3 bytes per pixel).
size = image->sizeX * image->sizeY * 3;
// read the planes
if ((fread(&planes, 2, 1, file)) != 1) {
printf("Error reading planes from %s.\n", filename);
return 0;
}
if (planes != 1) {
printf("Planes from %s is not 1: %u\n", filename, planes);
return 0;
}
// read the bitsperpixel
if ((i = fread(&bpp, 2, 1, file)) != 1) {
printf("Error reading bpp from %s.\n", filename);
return 0;
}
if (bpp != 24) {
printf("Bpp from %s is not 24: %u\n", filename, bpp);
return 0;
}
// seek past the rest of the bitmap header.
fseek(file, 24, SEEK_CUR);
// read the data.
image->data = (char *) malloc(size);
if (image->data == NULL) {
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1) {
printf("Error reading image data from %s.\n", filename);
return 0;
}
for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
// we're done.
return 1;
}
Image * loadTexture(){
Image *image1;
// allocate space for texture
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
exit(0);
}
if (!ImageLoad("NeHe.bmp", image1)) {
exit(1);
}
return image1;
}
void myinit(void)
{
glClearColor (0.5, 0.5, 0.5, 0.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
Image *image1 = loadTexture();
if(image1 == NULL){
printf("Image was not returned from loadTexture\n");
exit(0);
}
makeCheckImage();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Create Texture
glGenTextures(2, texture);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //scale linearly when image smalled than texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0,
GL_RGB, GL_UNSIGNED_BYTE, image1->data);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth,
checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,&checkImage[0][0][0]);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_FLAT);
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glutSolidTeapot(1.0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(2.41421, 1.0, -1.41421);
glTexCoord2f(0.0, 1.0);
glVertex3f(2.41421, -1.0, -1.41421);
glEnd();
glutSwapBuffers();
}
void myReshape(int w, int h){
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, 1.0*(GLfloat)w/(GLfloat)h, 1.0, 30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.6);
}
void keyboard (unsigned char key, int x, int y){
switch (key) {
case 27: // “esc” on keyboard
exit(0);
break;
default: // “a” on keyboard
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("Texture Mapping - Programming Techniques");
myinit();
glutReshapeFunc (myReshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Review how you read data. dataPos, size and others may be set after reading the BMP. It's a relative position defined in the header of the image file.
And then review glTexImage2D(). Your are passing datainstead of dataPos.
Here is the code. Please help guys
#include <GL/glut.h>
#include <iostream>
#include <math.h>
#include "SOIL.h"
using namespace std;
GLuint texture[1];
int LoadGLTextures()
{
texture[0] = SOIL_load_OGL_texture
(
"NeHe.bmp",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y
);
if(texture[0] == 0)
return false;
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
return true;
}
void ChangeSize(int w, int h)
{
if(h == 0)
{
h = 1;
}
float ratio = 1.0f * w/h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,w,h);
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,6.0,
0.0,0.0,0.0,
0.0f,1.0f,0.0f);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glFlush();
}
void idle(void)
{
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
glutCreateWindow("ZC");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(display);
glutIdleFunc(idle);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}
I dont get errors, but not loading the texture.
You forgot to call LoadGLTextures in your main program. I ran your program with this change:
glEnable(GL_DEPTH_TEST);
LoadGLTextures(); //<-- added this
glutMainLoop();
}
and things worked fine.
I provided my own NeHe.bmp file, since you didn't link to one. It could also fail if your .bmp file is bad in some way.
This is part of my coding, a simple balloon clicking game. I have a background image and another image for balloon, the code seems to replace all my previous loaded image. Helppppp
GLuint tex_2d;
GLuint tex_bg;
int main (int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(800, 800);
glutInitWindowPosition(100, 100);
glutCreateWindow("Lab Assignment");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutMouseFunc(mouse);
glutMainLoop();
return EXIT_SUCCESS;
}
This is where I put the coding for image loading, tex_bg is background.bmp for background, and tex_2d is for balloon image. Image loaded for tex_2d replaced the background image which is loaded earlier than it.
void init()
{
tex_bg = SOIL_load_OGL_texture
(
"background.bmp",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
tex_2d = SOIL_load_OGL_texture
(
"balloonImage.bmp",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
if (tex_2d == 0 || tex_bg == 0)
{
printf( "SOIL loading error: '%s'\n", SOIL_last_result() );
exit(0);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
void drawQuadOutline()
{
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glBindTexture(GL_TEXTURE_2D, tex_bg);
glNormal3f(0, 1, 0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
drawQuadOutline();
drawCircleOutline(balloon[balloonBurst]);
glutSwapBuffers();
}
void drawCircleOutline(Circle o)
{
float angle;
glEnable(GL_TEXTURE_2D);
glBegin(GL_POLYGON);
glBindTexture(GL_TEXTURE_2D, tex_2d);
for(angle=0.0f; angle<360.0f; angle+=2.0f)
{
float radian = angle * (pi/180.0f);
float xcos = (float)cos(radian);
float ysin = (float)sin(radian);
float x = xcos * o.r + o.pos.x;
float y = ysin * o.r + o.pos.y;
float tx = xcos * 0.5f + 0.5f;
float ty = ysin * 0.5f + 0.5f;
glTexCoord2f(tx, ty);
glVertex2f(x, y);
}
glEnd();
glDisable(GL_TEXTURE_2D);
}
Is it problem with my coding? or misuse of SOIL function?
The problem with your coding is that you call glBindTexture(...) in-between glBegin (...) and glEnd (...).
That is invalid; if you checked glGetError (...) you would know this.
You need to re-write this code:
glBegin(GL_POLYGON);
glBindTexture(GL_TEXTURE_2D, tex_2d);
...
glBegin(GL_QUADS);
glBindTexture(GL_TEXTURE_2D, tex_bg);
To this:
glBindTexture(GL_TEXTURE_2D, tex_2d);
glBegin(GL_POLYGON);
...
glBindTexture(GL_TEXTURE_2D, tex_bg);
glBegin(GL_QUADS);
I am stuck in this texturing problem. I have a created a quad as the ground and I want to fill its texture with a grass image. But, when I try to set MultiTexCoord2f values, I get Segmentation Fault error. I couldn't find the reason. What am I doing wrong here?
SetupRC(){
floorBatch.Begin(GL_QUADS, 4);
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Vertex3f(-50.0f, 0.0f, -50.0f);
floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
floorBatch.Vertex3f(50.0f, 0.0f, -50.0f);
floorBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
floorBatch.Vertex3f(-50.0f, 0.0f, 50.0f);
floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
floorBatch.Vertex3f(50.0f, 0.0f, 50.0f);
floorBatch.End();
glGenTextures(1, textures);
// Grass floor
pBytes = gltReadTGABits("Grass.tga", &nWidth, &nHeight, &nComponents, &format);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth, nHeight, 0,
format, GL_UNSIGNED_BYTE, pBytes);
glGenerateMipmap(GL_TEXTURE_2D);
free(pBytes);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
RenderScene(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f};
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
mModelview.PushMatrix(mCamera);
mModelview.Translate( 0.0f, -0.3f, -2.5f);
mModelview.PushMatrix();
mModelview.Translate( 0.0f, -0.3f, 0.0f);
mModelview.PushMatrix();
glBindTexture(GL_TEXTURE_2D, textures[0]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor, 0);
floorBatch.Draw();
mModelview.PopMatrix();
mModelview.PopMatrix();
mModelview.PushMatrix();
}
main()
{
gltSetWorkingDirectory(argv[0]); //
glutInit(&argc, argv); //opengl initialization
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL); //display mode set
glutInitWindowSize(800, 600); //window size
glutCreateWindow("Neighbourhood"); // title ile pencereyi yarattik
glutReshapeFunc(ChangeSize); // pencere boyutu degisince cagrilan fonksiyonun adi
glutDisplayFunc(RenderScene); // her bir frame icin cagrilan fonksiyonun adi
glutSpecialFunc(SpecialKeys);
// Add menu entries to change filter
glutCreateMenu(ProcessMenu);
glutAddMenuEntry("GL_NEAREST",0);
glutAddMenuEntry("GL_LINEAR",1);
glutAddMenuEntry("GL_NEAREST_MIPMAP_NEAREST",2);
glutAddMenuEntry("GL_NEAREST_MIPMAP_LINEAR", 3);
glutAddMenuEntry("GL_LINEAR_MIPMAP_NEAREST", 4);
glutAddMenuEntry("GL_LINEAR_MIPMAP_LINEAR", 5);
glutAttachMenu(GLUT_RIGHT_BUTTON);
GLenum err = glewInit(); // bu ne a.q.
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
SetupRC(); // opengle ozel kendimizce ayarlari initialize edecegimiz fonksiyon
glutMainLoop(); // opengl calisiyor
ShutdownRC();
return 0;
}
In glBatch.Begin() function, you should tell the function the number of textures you want to use. The third parameter here is the number of textures.
I don't know why but changing that part to this solved the problem;
floorBatch.Begin(GL_TRIANGLE_STRIP, 4, 2);
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Vertex3f(-50.0f, 0.0f, -50.0f);
floorBatch.MultiTexCoord2f(0 , 1.0f, 0.0f);
floorBatch.Vertex3f(50.0f, 0.0f, -50.0f);
floorBatch.MultiTexCoord2f(0 , 0.0f, 1.0f);
floorBatch.Vertex3f(-50.0f, 0.0f, 50.0f);
floorBatch.MultiTexCoord2f(0 , 1.0f, 1.0f);
floorBatch.Vertex3f(50.0f, 0.0f, 50.0f);
floorBatch.End();