I am trying to use multiple textures in the same scene but no matter what I try the same texture is loaded for each object. So this what I am doing at the moment, I initialise each shader:
rightWall.SendShaders("wall.vert","wall.frag","brick3.bmp", "wallTex", 0);
demoFloor.SendShaders("floor.vert","floor.frag","dirt1.bmp", "floorTex", 1);
The code in SendShaders is:
GLuint vert,frag;
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
char *vs = NULL,*fs = NULL;
vert = glCreateShader(GL_VERTEX_SHADER);
frag = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead(vertFile);
fs = textFileRead(fragFile);
const char * ff = fs;
const char * vv = vs;
glShaderSource(vert, 1, &vv, NULL);
glShaderSource(frag, 1, &ff, NULL);
free(vs); free(fs);
glCompileShader(vert);
glCompileShader(frag);
program = glCreateProgram();
glAttachShader(program, frag);
glAttachShader(program, vert);
glLinkProgram(program);
glUseProgram(program);
LoadGLTexture(textureImage, texture);
And then in the main loop:
rightWall.UseShader("wallTex");
rightWall.Draw();
demoFloor.UseShader("floorTex");
demoFloor.Draw();
The code in UseShader:
void GraphicsObject::UseShader(char textureName []){
glUseProgram(program);
GLint location = glGetUniformLocation(program, textureName);
glUniform1i(location, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
}
And finally, the texture load methods:
int GraphicsObject::LoadGLTexture(const char fileName []){
AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
int arraySize = strlen(fileName);
arraySize += 1;
if (TextureImage[0]=LoadBMP(fileName, arraySize))
{
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TextureImage[0]->sizeX,
TextureImage[0]->sizeY, 0, GL_RGB,
GL_UNSIGNED_BYTE, TextureImage[0]->data);
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_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
}
if (TextureImage[0])
{
if (TextureImage[0]->data)
{
free(TextureImage[0]->data);
}
free(TextureImage[0]);
}
return 1;
}
AUX_RGBImageRec* GraphicsObject::LoadBMP(const char fileName[], int arraySize){
FILE *File=NULL;
LPWSTR pwszFileName;
int lenW;
BSTR unicodestr;
lenW = MultiByteToWideChar(CP_ACP, 0, fileName, arraySize, 0,0);
DWORD bottom = GetLastError();
unicodestr = SysAllocStringLen(0, lenW);
MultiByteToWideChar(CP_ACP,0, fileName, arraySize,
unicodestr,lenW);
SysFreeString(unicodestr);
DWORD tit = GetLastError();
if (!fileName)
{
return NULL;
}
File=fopen(fileName,"r");
if (File)
{
fclose(File);
return auxDIBImageLoad((LPCWSTR)unicodestr);
}
return NULL;
}
Which ever shader is initialised last is the texture which is used for both objects. Thank you for your time and I appreciate any comments.
Like you have to call glUseProgram(program) before using the shader for rendering, you also have to bind the right texture directly before rendering.
The code should look like this:
glUseProgram(program1);
glBindTexture(GL_TEXTURE_2D, texture1);
// render calls for object 1
glUseProgram(program2);
glBindTexture(GL_TEXTURE_2D, texture2);
// render calls for object 2
Moreover also Uniforms must be set directly before rendering, and not at shader intialization.
So in your case the part
GLint location = glGetUniformLocation(program, textureName);
glUniform1i(location, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
does not belong in the function SendShaders, but in UseShader!
I'm going to point out the obvious just to make sure you can rule it out.
Is your texture image data actually different? Have you checked your texture loading code to make sure you are getting different files for the texture?
Related
On my 2nd project I work with opengl and SDL2. I want to render the text to a surface with SDL2 and then convert it.
I am already loading textures from files with SDL so I have a function that can convert Surfaces. Still when I supply a surface generated by the TTF_Render function the result is this:
Now I dont know why this is happening so some support would be appreciated.
I am using the SDL_ttf libary to load the file.
I am using visual studio 2015 as the ide.
Here is my convert function:
GLuint JUMA_Texture::loadFromSurface(SDL_Surface *img, GLenum target, GLenum filtering) {
GLuint TextureID = 0;
glGenTextures(1, &TextureID);
glBindTexture(GL_TEXTURE_2D, TextureID);
std::cout << " got " << img;
if (target == GL_TEXTURE_2D)
{
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
int Mode = GL_RGB;
if (img->format->BytesPerPixel == 4) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
transparent = true;
Mode = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, Mode, img->w, img->h, 0, Mode, GL_UNSIGNED_BYTE, img->pixels);
glGenerateMipmap(target);
return TextureID;
}
I printed the address of the surface pointers before and after it has been send to the function and they seem identical.
Also I am writing the surface to a file using SDL_SaveBmp and it seems fine aswell.
Edit:
Due to request I will now post the code for the use functions as well as the constructors of my shader and texture classes.
Shader constructor/loader
printf("Loading shader");
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
strcpy_s(Fragpath, fragmentPath);
strcpy_s(Vertexpath, vertexPath);
printf(".");
// ensures ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
try
{
// Open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// Convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
printf(".");
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar * fShaderCode = fragmentCode.c_str();
// 2. Compile shaders
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
// Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// Print compile errors if any
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
printf(".");
if (!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// Print compile errors if any
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
printf(".");
// Shader Program
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
// Print linking errors if any
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
printf(".");
// Delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader(vertex);
glDeleteShader(fragment);
printf("done\n");
Shader use function
void JUMA_Shader::Use()
{
glUseProgram(this->Program);
}
Texture constructor
printf("loading Texture");
int pos;
pos = filePath.find(".");
if (filePath.substr(pos) == ".png") {
IMG_Init(IMG_INIT_PNG);
}
else if (filePath.substr(pos) == ".jpg")
IMG_Init(IMG_INIT_JPG);
SDL_Surface *img = IMG_Load(filePath.c_str());
id = loadFromSurface(img,target,filtering);
Texture::loadFromSurface (NOTE: I HAVE NOT YET IMPLEMENTED CHECKING FOR GL_BGR AND GL_BGRA HOWEVER I HAVE MANUALLY ATTEMPTED BOTH OF THESE MODES WITH NO DIFFERENT EFFECT AT THIS MOMENT.)
GLuint JUMA_Texture::loadFromSurface(SDL_Surface *img, GLenum target, GLenum filtering) {
GLuint TextureID = 0;
glGenTextures(1, &TextureID);
glBindTexture(GL_TEXTURE_2D, TextureID);
std::cout << " got " << img;
if (target == GL_TEXTURE_2D)
{
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
int Mode = GL_RGB;
if (img->format->BytesPerPixel == 4) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
transparent = true;
Mode = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, Mode, img->w, img->h, 0, Mode, GL_UNSIGNED_BYTE, img->pixels);
glGenerateMipmap(target);
return TextureID;
}
Texture::USE
int JUMA_Texture::use(GLenum Channel) {
glActiveTexture(Channel); // Activate the texture unit first before binding texture
glBindTexture(GL_TEXTURE_2D, id);
if (transparent)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
return 1;
}
Also here is what I am seeing right now (Note that I have checked again and this is not the color I set for my font as I previously stated. I dont know where this blue color is coming from. I am currently trying to figure this out)
Lastly here is my vertex shader:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 texcoords;
out vec2 texCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec4 pos;
void main()
{
pos=gl_Position = projection*view*model*vec4(position,1.0f);
texCoords=vec2(texcoords.xy);
};
And my fragment shader:
#version 330 core
out vec4 color;
in vec2 texCoords;
in vec4 pos;
uniform sampler2D ourTexture;
uniform vec4 mixCol;
void main()
{
vec4 texColor = texture(ourTexture, texCoords);
if(texColor.a < 0.1f)
discard;
color = texColor;
};
My font constructor
JUMA_Font::JUMA_Font(char *path, int size, SDL_Color color, char* text, char *uniform) {
TTF_Init();
font = TTF_OpenFont(path, 40);
sourceSurface = TTF_RenderText_Blended(font, text, color);
printf("%d %d %d %d", color.r, color.g, color.b, color.a);
};
convert font to texture
JUMA_Texture convertToTexture() {
JUMA_Texture _this;
SDL_SaveBMP(sourceSurface, "out.bmp"); //outputs font correctly
std::cout << "Expected " << sourceSurface;
_this.id = _this.loadFromSurface(sourceSurface,GL_TEXTURE_2D,GL_NEAREST);
return _this;
}
This looks like you generated the surface with TTF_Render*_Solid() or TTF_Render*_Shaded().
However, these functions return an 8-bit palettized surface,
which OpenGL does not understand.
This is not detected in your function, where you set the source format (Mode) either to GL_RGB or GL_RGBA, which both are incorrect in that case.
As a solution, make sure to render the text in the blended mode, using one of the TTF_Render*_Blended() functions.
These will create a full BGRA surface, which can then be used with glTexImage2D().
Also note that it is recommended
to use a specific internal format with glTexImage2D(), so the function call should look like this:
glTexImage2D(GL_TEXTURE_2D, 0,
GL_RGBA8,
img->w, img->h, 0,
GL_BGRA,
GL_UNSIGNED_BYTE, img->pixels);
I can't find my mistake, why text has not been created? When using texture instead of text I get nothing or black background with colored points, please help
GLuint texture;
SDL_Surface *text = NULL;
TTF_Font *font = NULL;
SDL_Color color = {0, 0, 0};
font = TTF_OpenFont("../test.ttf", 20);
text = TTF_RenderText_Solid(font, "Hello, SDL !!!", color);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, text->w, text->h, 0, GL_RGB, GL_UNSIGNED_BYTE, text->pixels);
SDL_FreeSurface(text);
One thing you could add is to specify texture filters, e.g.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Few things you have to check first
is the font loaded properly? check if "font == NULL", maybe your
font path is wrong
is the shader (if you use a shader) setup properly?
My guess is that you set the wrong pixel format type in glTexImage2D cause random color dots apear on your texture
Below is my code that load image via SDL_image for OpenGL use, I think it would be a good start to figure out what step you missed or forgot.
BTW, this code is not perfect. The types of pixel format is more than four (like index color) and I only handle some of them.
/*
* object_, originalWidth_ and originalHeight_ are private variables in
* this class, don't panic.
*/
void
Texture::Load(string filePath, GLint minMagFilter, GLint wrapMode)
{
SDL_Surface* image;
GLenum textureFormat;
GLint bpp; //Byte Per Pixel
/* Load image file */
image = IMG_Load(filePath.c_str());
if (image == nullptr) {
string msg("IMG error: ");
msg += IMG_GetError();
throw runtime_error(msg.c_str());
}
/* Find out pixel format type */
bpp = image->format->BytesPerPixel;
if (bpp == 4) {
if (image->format->Rmask == 0x000000ff)
textureFormat = GL_RGBA;
else
textureFormat = GL_BGRA;
} else if (bpp == 3) {
if (image->format->Rmask == 0x000000ff)
textureFormat = GL_RGB;
else
textureFormat = GL_BGR;
} else {
string msg("IMG error: Unknow pixel format, bpp = ");
msg += bpp;
throw runtime_error(msg.c_str());
}
/* Store widht and height */
originalWidth_ = image->w;
originalHeight_ = image->h;
/* Make OpenGL texture */
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &object_);
glBindTexture(GL_TEXTURE_2D, object_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minMagFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, minMagFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(
GL_TEXTURE_2D, // texture type
0, // level
bpp, // internal format
image->w, // width
image->h, // height
0, // border
textureFormat, // format(in this texture?)
GL_UNSIGNED_BYTE, // data type
image->pixels // pointer to data
);
/* Clean these mess up */
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
SDL_FreeSurface(image);
}
For more information, you should check out SDL wiki or deep into it's source code to fully understand the architecture of SDL_Surface.
My textures wont change and i'm not sure why. This my Texture Loader.h
class TextureLoader
{
private:
GLuint* Texture;
std::map<std::string, GLuint*> TextureMap;
public:
TextureLoader(){};
~TextureLoader()
{
delete Texture;
}
bool LoadTexture(std::string Source);
GLuint* GetImage(std::string TextureID);
bool CheckTextureExsist(std::string TextureID);
};
This is the CPP.
bool TextureLoader::LoadTexture(std::string Source)
{
//Bind the texture to load in.
Texture = new GLuint;
glGenTextures (1, Texture);
glBindTexture (GL_TEXTURE_CUBE_MAP, *Texture);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
//Width, Height and Components of the image.
int x, y, n;
//Set pixel format
int force_channels = 4;
//Load data into the char.
unsigned char* image_data = stbi_load (
Source.c_str(), &x, &y, &n, force_channels);
//Check too see if the image loaded.
if (!image_data) {
fprintf (stderr, "ERROR: could not load %s\n", Source);
return false;
}
//Copy the image data to the selected target.
glTexImage2D (
GL_TEXTURE_2D,
0,
GL_RGBA,
x,
y,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
image_data
);
free (image_data);
TextureMap.insert(std::pair<std::string, GLuint*>(Source,Texture));
return true;
}
GLuint* TextureLoader::GetImage(std::string TextureID)
{
return TextureMap.find(TextureID)->second;
}
bool TextureLoader::CheckTextureExsist(std::string TextureID)
{
if(TextureMap.find(TextureID) == TextureMap.end())
{
return false;
}
else
return true;
}
This is how i am drawing.
glBindTexture(GL_TEXTURE_2D, *TextureID);
glMaterialfv(GL_FRONT , GL_AMBIENT, Ambient);
glMaterialfv(GL_FRONT , GL_DIFFUSE, Diffuse);
glMaterialfv(GL_FRONT , GL_SPECULAR, Specular);
glMaterialf(GL_FRONT , GL_SHININESS, Shininess);
glVertexPointer(3,GL_FLOAT,0,&Vertices[0]);
glNormalPointer(GL_FLOAT,0,&Normals[0]);
glTexCoordPointer(2,GL_FLOAT,0,&TextureCoords[0]);
glPushMatrix();
glScalef(Scale[0],Scale[1],Scale[2]);
glTranslatef(Translate[0],Translate[1],Translate[2]);
glRotatef(Rotate[0],Rotate[1],Rotate[2],Rotate[3]);
glDrawArrays(GL_TRIANGLES, 0,(GLsizei)(Vertices.size()/3));
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, NULL);
The TextureID gets passed the pointer, of the texture handle . The handle does change during run time to the different handles but it does draws the last texture that i loaded in, regardless of texture handle.
The problem is binding to GL_TEXTURE_CUBE_MAP in your LoadTexture function:
glBindTexture (GL_TEXTURE_CUBE_MAP, *Texture);
Change that to
glBindTexture(GL_TEXTURE_2D, *Texture);
I would also suggest to use GLuint instead of a GLuint* and store that into the map. The only reason glGenTextures takes a pointer is because it can also output to an array of GLuint.
Trying to colour terrain points based on texture colour (currently hard coded to vec2(0.5, 0.5) for test purposes - which should be light blue) but all the points are grey. glGetError returns 0 throughout the whole process. I think I might be doing the render process wrong or have a problem with my shaders(?)
Vertex Shader:
void main(){
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
Fragment Shader:
uniform sampler2D myTextureSampler;
void main(){
gl_FragColor = texture2D(myTextureSampler, vec2(0.5, 0.5));
}
Terrain Class:
class Terrain
{
public:
Terrain(GLuint pProgram, char* pHeightmap, char* pTexture){
if(!LoadTerrain(pHeightmap))
{
OutputDebugString("Loading terrain failed.\n");
}
if(!LoadTexture(pTexture))
{
OutputDebugString("Loading terrain texture failed.\n");
}
mProgram = pProgram;
mTextureLocation = glGetUniformLocation(pProgram, "myTextureSampler");
};
~Terrain(){};
void Draw()
{
glEnableClientState(GL_VERTEX_ARRAY); // Uncommenting this causes me to see nothing at all
glBindBuffer(GL_ARRAY_BUFFER, mVBO);
glVertexPointer(3, GL_FLOAT, 0, 0);
glEnable( GL_TEXTURE_2D );
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mBMP);
glProgramUniform1i(mProgram, mTextureLocation, 0);
GLenum a = glGetError();
glPointSize(5.0f);
glDrawArrays(GL_POINTS, 0, mNumberPoints);
a = glGetError();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisable( GL_TEXTURE_2D );
glDisableClientState(GL_VERTEX_ARRAY);
}
private:
GLuint mVBO, mBMP, mUV, mTextureLocation, mProgram;
int mWidth;
int mHeight;
int mNumberPoints;
bool LoadTerrain(char* pFile)
{
/* Definitely no problem here - Vertex data is fine and rendering nice and dandy */
}
// TEXTURES MUST BE POWER OF TWO!!
bool LoadTexture(char *pFile)
{
unsigned char header[54]; // Each BMP file begins by a 54-bytes header
unsigned int dataPos; // Position in the file where the actual data begins
unsigned int width, height;
unsigned int imageSize;
unsigned char * data;
FILE * file = fopen(pFile, "rb");
if(!file)
return false;
if(fread(header, 1, 54, file) != 54)
{
fclose(file);
return false;
}
if ( header[0]!='B' || header[1]!='M' )
{
fclose(file);
return false;
}
// Read ints from the byte array
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
// Some BMP files are misformatted, guess missing information
if (imageSize==0) imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component
if (dataPos==0) dataPos=54; // The BMP header is done that way
// Create a buffer
data = new unsigned char [imageSize];
// Read the actual data from the file into the buffer
fread(data,1,imageSize,file);
//Everything is in memory now, the file can be closed
fclose(file);
// Create one OpenGL texture
glGenTextures(1, &mBMP);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, mBMP);
// Give the image to OpenGL
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
delete [] data;
data = 0;
return true;
}
};
Answering own question incase anyone has a similar problem:
I had tested this with multiple images - but it turns out theres a bug in my graphics application of choice; which has been exporting 8-bit Bitmap's even though I explicitally told it to export 24-bit Bitmap's. So basically - reverting back to MS Paint solved my solution. 3 cheers for MS Paint.
i'm trying to texture a sphere with OpenGL programmable pipeline and dont know what goes wrong here.
Initialization:
earth = createSphere(1, 64, 32);
glEnable(GL_TEXTURE_2D);
earthTex = createTexture("textures/earth.jpg");
createTexture:
GLuint createTexture(const char* fileName)
{
GLuint texID;
int width, height, imgFormat, internalFormat;
float* imgData = getImage(fileName, &height, &width, &imgFormat);
switch (imgFormat)
{
case GL_RED: internalFormat = GL_R8; break;
case GL_RG: internalFormat = GL_RG8; break;
case GL_RGB: internalFormat = GL_RGB8; break;
case GL_RGBA: internalFormat = GL_RGBA8; break;
default: fprintf(stderr, "\n Cannot get ImgType \n"); break;
}
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, imgFormat, GL_FLOAT, (void*) imgData);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
return texID;
}
RenderLoop:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, earthTex);
glUniform1i(glGetUniformLocation(programID, "colorTex"), 0);
earth->draw();
glBindTexture(GL_TEXTURE_2D, 0);
In vertexShader I'm passing texCoords to FragmentShader and there i just call something like fs_out_color = texture(colorTex, fs_in_texCoords);
where colorTex is uniform sampler2D.
As soon as I comment this out, everything works fine (except vertex coloring obviously).
Anyone got a a clue?
Thanks!
Edit:
Thats my FragmentShader. As you can see, nothing too special.
#version 150 core
uniform sampler2D colorTex;
in vec3 fs_in_color;
in vec2 fs_in_texCoods;
out vec4 fs_out_color;
void main(void) {
fs_out_color = texture(colorTex, fs_in_texCoords);
}
Edit2: If I change fs_out_color to fs_in_color (which are currently normals), everything works fine. Otherwise OpenGL states INVALID_OPERATION after drawElements call.