Here is the code I am trying to use to set up a Cube Map in LWJGL.
public static int setUpCubeMap(String filename, int anisotropyLevel, boolean clamp, boolean pixelated, boolean mipmapped) {
IntBuffer tmp = BufferUtils.createIntBuffer(1);
glGenTextures(tmp);
tmp.rewind();
try {
InputStream in = new FileInputStream(filename);
PNGDecoder decoder = new PNGDecoder(in);
glEnable(GL_TEXTURE_CUBE_MAP);
ByteBuffer buf = ByteBuffer.allocateDirect(4 * decoder.getWidth() * decoder.getHeight());
decoder.decode(buf, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
buf.flip();
glBindTexture(GL_TEXTURE_CUBE_MAP, tmp.get(0));
org.lwjgl.opengl.ARBTextureStorage.glTexStorage2D(GL_TEXTURE_CUBE_MAP, (int)(Math.log(Math.max(decoder.getHeight(), decoder.getWidth()))/Math.log(2))+1, GL_RGBA8, decoder.getWidth(), decoder.getHeight());
glTexSubImage2D(GL_TEXTURE_CUBE_MAP, 0, 0, 0, decoder.getWidth(), decoder.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, buf);
if(mipmapped)
org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
if(clamp) {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_S);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_T);
}
if(pixelated) {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
} else {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if(mipmapped)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
else
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if(anisotropyLevel > 1)
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropyLevel);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
System.out.println("Loaded texture successfully from: " + filename + " with dimensions of " + decoder.getWidth() + "x" + decoder.getHeight());
} catch (java.io.FileNotFoundException ex) {
System.err.println("Error " + filename + " not found");
} catch (java.io.IOException e) {
System.err.println("Error decoding " + filename);
}
tmp.rewind();
return tmp.get(0);
}
I then pass the texture to a samplerCube in a shader and call textureCube() to display it. Sadly, the screen shows up black, and when I call glGetError() I get GL_INVALID_OPERATION and GL_INVALID_ENUM. What am I doing wrong here?
There are several problems, none of these definitely prevent the code from working, I list them anyway.
The glTexSubImage2D call at the beginning is is superfluous.
calling it with GL_TEXTURE_CUBE_MAP causes an error glTexSubImage2D.
you are filling in the data the correct way down below
Also related to this, the call to glGenerateMipmap should happen after those other six glTexSubImage2D calls.
And in this section, in the else clause, the third parameter to both function calls is wrong.
if(clamp) {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_S);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_T);
}
I suggest you use gDEBugger; it gives a very understandable description of the problem and exactly when it occurs.
Related
This is the code for a ground object that gets rendered every frame in a game I'm making with c++ and openGl.
Ground::Ground() {
this->loadedObject = loadObject("ground.obj");
this->vertices = getVerticesFromLoadedObject(this->loadedObject);
this->textureCoords = getTextureCoordsFromLoadedObject(this->loadedObject);
this->textureData = loadTexture("ground.jpg");
glGenTextures(1, &this->textureId);
glBindTexture(GL_TEXTURE_2D, this->textureId);
}
void Ground::draw() {
glEnable(GL_TEXTURE_2D);
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_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, this->textureData.width, this->textureData.height, 0, GL_RGB, GL_UNSIGNED_BYTE, this->textureData.data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
tinyobj::shape_t shape = this->loadedObject.shape;
unsigned int vertexCount = shape.mesh.num_face_vertices.size() * 3;
glTexCoordPointer(2, GL_FLOAT, 0, this->textureCoords);
glVertexPointer(3, GL_FLOAT, 0, this->vertices);
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
glDisable(GL_TEXTURE_2D);
}
Even though this works, calling glTexImage2D every frame causes a memory leak, but I can't get the texture to show otherwise, I tried doing the call in Ground's constructor but it doesn't load the image at all. How do I load the image just once to avoid the memory leak?
Update: with glTexImage2D in the constructor
Ground::Ground() {
this->loadedObject = loadObject("ground.obj");
this->vertices = getVerticesFromLoadedObject(this->loadedObject);
this->textureCoords = getTextureCoordsFromLoadedObject(this->loadedObject);
this->textureData = loadTexture("ground.jpg");
glGenTextures(1, &this->textureId);
glBindTexture(GL_TEXTURE_2D, this->textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, this->textureData.width, this->textureData.height, 0, GL_RGB, GL_UNSIGNED_BYTE, this->textureData.data);
}
void Ground::draw() {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, this->textureId);
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_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
tinyobj::shape_t shape = this->loadedObject.shape;
unsigned int vertexCount = shape.mesh.num_face_vertices.size() * 3;
glTexCoordPointer(2, GL_FLOAT, 0, this->textureCoords);
glVertexPointer(3, GL_FLOAT, 0, this->vertices);
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY_EXT);
glDisable(GL_TEXTURE_2D);
}
I'm attempting to use the newer DSA functions to show textures but it's not working at all.
Here is the code for using the older approach.
unsigned int containerTexture = 0;
glGenTextures(1, &containerTexture);
glBindTexture(GL_TEXTURE_2D, containerTexture);
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_LINEAR);
int width = 0, height = 0, channelCount = 0;
stbi_set_flip_vertically_on_load(true);
unsigned char* pixels = stbi_load("res/textures/container.jpg", &width, &height, &channelCount, 0);
if (pixels) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
cerr << "Failed to load texture! \n";
}
stbi_image_free(pixels);
Here is the DSA version.
unsigned int containerTexture = 0;
int width = 0, height = 0, channelCount = 0;
stbi_set_flip_vertically_on_load(true);
unsigned char* pixels = stbi_load("res/textures/container.jpg", &width, &height, &channelCount, 0);
if (pixels) {
glCreateTextures(GL_TEXTURE_2D, 1, &containerTexture);
glTextureParameteri(containerTexture, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(containerTexture, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTextureParameteri(containerTexture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(containerTexture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureStorage2D(containerTexture, 1, GL_RGB8, width, height);
glTextureSubImage2D(containerTexture, 1, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
glGenerateTextureMipmap(containerTexture);
glBindTextureUnit(0, containerTexture);
} else {
cerr << "Failed to load texture! \n";
}
stbi_image_free(pixels);
The 2nd parameter to glTextureSubImage2D is the level to be set. Mipmap levels are zero-based, therefore the base level is 0 and not 1 as in your code:
glTextureSubImage2D(containerTexture, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
i have tried to load stack of .png image files into glTexImage3D for volume rendering purpose. However, i just cant make it work as it keeps crashing. BTW, the problem seems to be related with pData.
Below is the code for your reference:
GLubyte * pData = new GLubyte[XDIM*YDIM*ZDIM];
ifstream volumeData;
getFileNameWithSpecificExtension(dir_path);
sort(begin(fileIndex), end(fileIndex));
for (int i = 0; i < 201; i ++)
{
volumeData.open(FrontPart + to_string(fileIndex[i]) + ".png", ios::binary);
}
volumeData.read(reinterpret_cast<char*>(pData), XDIM*YDIM*ZDIM*sizeof(GLubyte));
volumeData.close();
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_3D, textureID);
// set the texture parameters
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
//set the mipmap levels (base and max)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 4);
//allocate data with internal format and foramt as (GL_RED)
glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, XDIM, YDIM, ZDIM, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
GL_CHECK_ERRORS
//generate mipmaps
glGenerateMipmap(GL_TEXTURE_3D);
//delete the volume data allocated on heap
delete[] pData;
Non-Power-of-2 is no issue since OpenGL-2.0 removed that constraint. For reading each image slice into the texture use glTexImage3D with a NULL pointer to initialize the texture, then in the loop iterating over the files, read each file, decode it and load it into the right slice using glTexSubImage3D. Also don't use explicit new and delete[] but a std::vector.
Properly implementing the "foreach file" loop and the "ImageFileReader" are left as an exercise for the reader. I suggest looking into the Generic Image library for one particular candidate (http://sourceforge.net/adobe/genimglib/home/Home/). Also keep in mind that it's a very bad idea to hardcode any image dimensions into your code.
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_3D, textureID);
// set the texture parameters
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
//set the mipmap levels (base and max)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 4);
//allocate data with internal format and foramt as (GL_RED)
glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, XDIM, YDIM, ZDIM, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
GL_CHECK_ERRORS
GLubyte * pData = new GLubyte[XDIM*YDIM*ZDIM];
std::vector<GLubyte> vData(XDIM*YDIM*ZDIM);
foreach file in filenames (...)
{
ImageFileReader ifr(FrontPart + to_string(fileIndex[i]) + ".png")
ifr.decode(vData);
glTexSubImage3D(GL_TEXTURE_3D, 0,
0 /* x offset */,
0 /* y offset */,
z,
XDIM, YDIM, 1,
GL_RED, GL_UNSIGNED_BYTE,
&vData[0] );
}
//generate mipmaps
glGenerateMipmap(GL_TEXTURE_3D);
I'm trying to use awesomium with opengl (glut and cpp) and I'm having trouble rendering the webpages to textures. The textures are randomly (different every time I run the program) shifted in the x and y axis. Picture:
I thought GL_CLAMP_TO_EDGE would take care of that problem but it did not. What am I doing wrong?
The Awesomiumpart:
web_core = WebCore::Initialize(WebConfig());
view = web_core->CreateWebView(WIDTH, HEIGHT);
WebURL url(WSLit(URL));
view->LoadURL(url);
BindMethods(view);
while (view->IsLoading())
web_core->Update();
Sleep(300);
web_core->Update();
surface = (BitmapSurface*)view->surface();
The part loading the texture:
glBindTexture(GL_TEXTURE_2D, 13);
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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, surface);
This is what I did. I know you solved the problem, but it might help someone in the future.
int w = surface->width();
int h = surface->height();
unsigned char *buffer = new unsigned char[w * h * 4];
surface->CopyTo(buffer, w * 4, 4, false, false);
glBindTexture(GL_TEXTURE_2D, 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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer);
delete[] buffer;
I am trying to display some textures, while most of the times it works, sometimes the application freezes. I found exactly the point where the application hangs, the code is this one and I marked with a comment where it stops working.
glGenFramebuffers(1, &id);
glGenTextures(1, &texture);
glGenRenderbuffers(1, &render_buffer_id);
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_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// Here it freezes, also while using 'glBindRenderbuffer'
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_buffer_id);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, render_buffer_id);
Any ideas?