I have a project in C++ using opengl. I have main.cpp working with openGL initialization, creating window and stuff like that.
I would like to create a class, where I can outsource loading some texture into Shader.
But when I am trying to use shader.h or glad.h headers as include in any other class-headers, I got error:
fatal error C1189: #error: OpenGL header already included, remove
this include, glad already provides it
If I do all logic inside main.cpp everything is fine, problem raised only if trying to use openGL functions anywhere except main.cpp
main.cpp:
#include <glad/glad.h> // generated from https://glad.dav1d.de
#include "shader.h"
int main()
{
... //Do OpenGL Staff
}
shader.h:
#ifndef SHADER_H
#define SHADER_H
#include <glad/glad.h>
#include <glm/glm.hpp>
class Shader
{
public:
unsigned int ID;
...//some Shader definition staff
}
#endif
and now I want external class "Maze.h" to load it's map inside opengl texture, something like That:
class Maze
{
public:
...//some maze-relate staff
void LoadMazeToGL(Shader* shader)
{
// load and create a texture
// -------------------------
glGenTextures(1, &screenTex1);
glBindTexture(GL_TEXTURE_1D, screenTex1);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLint curMapId = glGetUniformLocation(shader->ID, "shaderInternalVarName");
glUniform1i(curMapId, 2); // Texture unit 2 is for current map.
... //define and fill tex1data using Maze private information
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_1D, screenTex1);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, MazeIntegerSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex1data);
}
}
To check for problems like this use the -E flag of GCC/g++ or an alternative for your compiler. This outputs the result of the pre-processor (so the includes etc). You can then have a look at the files produced and look for the double include. You may have just forgotten an include guard somewhere :)
Related
In our own 3d application I'm loading multiple textures, using devil library. When attempting to load one texture, I'm calling ilutRenderer( ILUT_OPENGL );, which in a turn perform following function calls:
ILboolean ilutGLInit()
{
// Use PROXY_TEXTURE_2D with glTexImage2D() to test more accurately...
glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&MaxTexW);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&MaxTexH);
if (MaxTexW == 0 || MaxTexH == 0)
MaxTexW = MaxTexH = 256; // Trying this because of the VooDoo series of cards...
// Should we really be setting all this ourselves? Seems too much like a glu(t) approach...
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
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_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
#ifdef _MSC_VER
if (IsExtensionSupported("GL_ARB_texture_compression") &&
IsExtensionSupported("GL_EXT_texture_compression_s3tc")) {
ilGLCompressed2D = (ILGLCOMPRESSEDTEXIMAGE2DARBPROC)
wglGetProcAddress("glCompressedTexImage2DARB");
}
#endif
if (IsExtensionSupported("GL_ARB_texture_cube_map"))
HasCubemapHardware = IL_TRUE;
return IL_TRUE;
}
ilutRenderer( ILUT_OPENGL ); needs to be called only once (for each newly created window), but while experimenting I've called same function multiple times. (one call for each loaded texture)
If same function were called multiple times - loaded openGl texture was looking with poorer quality than if called once. (I have multiple textures, but most of them with poorer quality, not sure about first image).
I was stumbled about it - since from my perspective that call did not do anything special - why it cannot tolerate multiple similar calls ?
Well, I've started to filter out which functions can be called multiple times and which cannot be - and concluded that it was glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); which triggered odd behavior. So wrapping function like this:
if( !bInitDone )
{
bInitDone = TRUE;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
after that ilutRenderer( ILUT_OPENGL ) can be called as many times as needed.
I have also tried to centralize opengl initialization like this:
...
InitGL( OnWindowReady )
...
void OnWindowReady( void )
{
ilInit();
ilutRenderer( ILUT_OPENGL );
}
... may be some rendering code ...
void LoadModel( const wchar_t* file )
{
... load texture 1 ...
... load texture 2 ...
}
But textures are still appearing "as corrupted". Maybe window should be rendered at least once before starting to load textures, but I want to know what functions in OpenGL are reflecting texture corruption / looking nice kind of state.
I have "NVidia Quadro K2100M", driver version 375.86.
Is this display driver bug ?
How do you typically report bugs to NVidia ?
I can load a texture just fine in SOIL/OpenGL normally. No errors, everything works fine:
// this is inside my texture loading code in my texture class
// that i normally use for loading textures
image = SOIL_load_OGL_texture
(
file,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
NULL
);
However, using that same code and calling it from an std::thread, at the line image = SOIL_load_OGL_texture I get unhandled exception Integer Division by Zero:
void loadMe() {
Texture* abc = new Texture("res/img/office.png");
}
void loadStuff() {
Texture* loading = new Texture("res/img/head.png"); // < always works
loadMe() // < always works
std::thread textures(loadMe); // < always "integer division by zero"
Here's some relevant code from my Texture class:
// inside the class
private:
GLint w, h;
GLuint image;
// loading the texture (called by constructor if filename is given)
void Texture::loadImage(const char* file)
{
image = SOIL_load_OGL_texture
(
file,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
NULL
);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, image);
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_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
glBindTexture(GL_TEXTURE_2D, 0);
if (image <= 0)
std::cout << file << " failed to load!\n";
else
std::cout << file << " loaded.\n";
glDisable(GL_TEXTURE_2D);
}
It raises the exception exactly at image = SOIL_load_OGL_texture, and when I go into the debugger, I see things like w = -816294792 and w = -816294792, but I guess that just means it hasn't been set yet, as it also shows that in the debugger for loading the other textures.
Also, the SOIL_load_OGL_texture part of the code works fine by itself, outside of the Texture class, even in a std::thread.
Any idea what's going on here?
This is how you do it. Note that, as others have mentioned in the comments, a context needs to be maintained current for every thread that uses GL. What this means is practically there cannot be a GL API call made in multiple threads without making one thread the owner of the GL context. Hence if the intention is to separate the Image loading overhead it is recommended to load the image file into a buffer using a library in a separate thread, then use that buffer to glTexImage2D in the main thread. Till the image is loaded, a dummy texture can be displayed.
I tried checking what platform you are on (see comment above), since I did not see a response, I am assuming Linux for below.
/* Regular GL context creation foo */
/* Regular attribute, uniform, shader creation foo */
/* Create a thread that does loading with SOIL in function SOIL_loader */
std::thread textureloader(SOIL_loader);
/* Wait for loader thread to finish,
thus defeating the purpose of a thread. Ideally,
only the image file read/decode should happen in separate thread */
textureloader.join();
/* Make the GL context current back again in the main thread
for other actions */
glfwMakeContextCurrent((GLFWwindow*)window);
/* Some other foo */
======
And this is the loader thread function:
void SOIL_loader()
{
glfwMakeContextCurrent((GLFWwindow*)window);
SOIL_load_OGL_texture
(
"./img_test.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID /* or passed ID */,
NULL
);
GL_CHECK(SOIL);
}
Tested on Ubuntu 14.04, Mesa, and glfw3.
Ok, before anyone marks this question as a duplicate, I have looked at What is an undefined reference/unresolved external symbol error and how do I fix it? and many other online posts. I've tried every solution I've come acoss but I still can't fix these errors:
1>SOIL.lib(stb_image_aug.o) : error LNK2019: unresolved external symbol __alloca referenced in function _stbi_zlib_decode_noheader_buffer
1>SOIL.lib(image_helper.o) : error LNK2019: unresolved external symbol _sqrtf referenced in function _RGBE_to_RGBdivA2
I'm using Visual Studio 2012 on Windows 8. I've tried rebuilding the library and I have quintuple checked all my includes and directories.Here are the SOIL includes/directory I have:
>Configuration Properties->VC++ Directories->Include Directories: "C:\SOIL\Simple OpenGL Image Library\src
>Configuration Properties->VC++ Directories->Library Directories: "C:\SOIL\Simple OpenGL Image Library\lib
>Congiguration Properties->Linker->Input->Additional Dependencies: "SOIL.lib"
And here's my code. The SOIL_load_image function is what's causing the errors:
#include <Windows.h>
#include <GL/glut.h>
#include "glext.h"
#include <SOIL.h>
void glEnable2D( void );
void display();
void glDisable2D( void );
GLuint tex;
/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutInitWindowSize(320, 320); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
//Texture
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float color[] = { 1.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height;
unsigned char* image = SOIL_load_image("Resources/Sprites/playerCharacter.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
//Texture
glutDisplayFunc(display); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the infinitely event-processing loop
return 0;
}
I've been working on this all day and I haven't been able to figure out what I'm doing wrong, and it's been extremely frustrating. Note: I know the original name of SOIL.lib is "libSOIL.a." I tried working with it with that name and got the same errors.
You can build the VC8 or VC9 solution files yourself in VS2012/13. Just make sure you are Win32 configuration if you are building a 32bit application. Change the configuration properties to x64 if you are building a 64bit application. Once the projects are built, link your openGL project to your these generated SOIL.lib files and you will be good to go.
I'm having problems trying to load textures in an OpenGL GLUT project using classes.
Here's some code that includes the texturing stuff:
Declaring a Textured Model from a subclass of a model class.
TextureModel * title = new TextureModel("Box.obj", "title.raw");
Constructor method of TextureModel subclass:
TextureModel(string fName, string tName) : Model(fName), textureFile(tName)
{
material newMat = {{0.63,0.52,0.1,1.0},{0.63,0.52,0.1,1.0},{0.2,0.2,0.05,0.5},10};
Material = newMat;
// enable texturing
glEnable(GL_TEXTURE_2D);
loadcolTexture(textureFile);
glGenTextures(1, &textureRef);
// specify the filtering method
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_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// associate the image read in to the texture to be applied
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, image_array);
}
Texture loading function to read in data in RAW file:
int loadcolTexture(const string fileName) {
ifstream inFile;
inFile.open(fileName.c_str(), ios::binary );
if (!inFile.good())
{
cerr << "Can't open texture file " << fileName << endl;
return 1;
}
inFile.seekg (0, ios::end);
int size = inFile.tellg();
image_array = new char [size];
inFile.seekg (0, ios::beg);
inFile.read (image_array, size);
inFile.close();
return 0;}
Method to draw the triangles:
virtual void drawTriangle(int f1, int f2, int f3, int t1, int t2, int t3, int n1, int n2, int n3)
{
glColor3f(1.0,1.0,1.0);
glBegin(GL_TRIANGLES);
glBindTexture(GL_TEXTURE_2D, textureRef);
glNormal3fv(&normals[n1].x);
glTexCoord2f(textures[t1].u, textures[t1].v);
glVertex3fv(&Model::vertices[f1].x);
glNormal3fv(&normals[n2].x);
glTexCoord2f(textures[t2].u, textures[t2].v);
glVertex3fv(&Model::vertices[f2].x);
glNormal3fv(&normals[n3].x);
glTexCoord2f(textures[t3].u, textures[t3].v);
glVertex3fv(&Model::vertices[f3].x);
glEnd();
}
I also have Lighting, Depth Testing and Double Buffering enabled.
Models and Lighting work fine, but the textures don't appear. Any reasons why it won't work will be great.
To add to the comment, I see a few things here:
As mentioned in the comment, you need to bind a texture before you can upload data to it. Once you generate the texture with glGenTextures, you need to set it to be the active texture before you try to load data or set set parameters with glTexParameteri
You're building mipmaps, but not using them. Either set the GL_TEXTURE_MIN_FILTER to GL_NEAREST_MIPMAP_LINEAR to utilize the mipmaps, or don't build them in the first place. As is you're just wasting texture memory.
It's not legal to bind a texture inbetween glBegin/glEnd as you have done in drawTriangle. Bind it before the glBegin.
Please, please, please start using glGetError in your code. This will tell you if you are doing wrong things before you have to come and ask to find your mistakes. (you would have found 2/3 of the mistakes here if you had been using it).
When I use GL3W, I cannot load textures. They appear blank or messed up.
I wanted an OpenGL 4.2 context in SDL 1.3 and so I decided to use GL3W, as GLEW used deprecated functions. Everything seems to work fine, however, when I try to load a texture, it either gets messed up (randomly colored lines) or simply ends up blank (black without alpha, transparent with). Everything else I've tried so far has worked (shaders, VAO's, VBO's, etc.)
I wrote the most simple example I could come up with to illustrate:
#include <SDL.h>
#include <SDL_image.h>
#include <GL3/gl3w.h>
#include <gl/gl.h>
#include <gl/glu.h>
int main(int argc, char* argv[]) {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_WindowID mainWindow = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GLContext mainContext = SDL_GL_CreateContext(mainWindow);
SDL_GL_MakeCurrent(mainWindow, mainContext);
gl3wInit();
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
SDL_Surface* test2 = IMG_Load("test.png");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, test2->w, test2->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, test2->pixels);
// Loop to keep the window open while debugging in gDEBugger
while (1) {
SDL_GL_SwapWindow(mainWindow);
}
return 0;
}
I don't know how relevant it is, but since gl3w is generated by a python script I'll include it (external links because of length):
gl3w.c: http://pastebin.com/T5GNdJL8
gl3w.h: http://pastebin.com/yU2EzBZP
gl3.h: http://pastebin.com/0uCgB8d1
If I remove #include <GL3/gl3w.h> and glewInit(); the texture is successfully loaded.