Problem: I've been trying to figure out this error in OpenGL that I keep getting with glTexSubImage3D. VS2010 throws the error: glTexSubImage3D: identifier not found
Usage: I am trying to create a 3D texture with ten slices (images) placed along the z-dimension. It is similar to the question in this post: C++ - place multiple images in an array pointer
However, I have been trying to use glTexSubImage3D in order to avoid these access violation errors.
I have included glext.h in my project and since, glTexImage3D is not part of OpenGL libraries yet, I have used the function pointer PFNGLTEXIMAGE3DPROC glTexImage3D as provided for use here: http://content.gpwiki.org/index.php/OpenGL:Tutorials:3D_Textures
Code:
I have been following NeHe's Texture Mapping tutorial and volume rendering tutorial present here: http://www.codeproject.com/Articles/352270/Getting-started-with-Volume-Rendering?msg=4729498
GLuint m_nTexId;
unsigned char *tex;
int h = 1024;
int w = 256;
int slices = 10;
PFNGLTEXIMAGE3DPROC glTexImage3D = (PFNGLTEXIMAGE3DPROC) wglGetProcAddress("glTexImage3D");
int LoadGLTextures()
{
glGenTextures(1,(GLuint*)&m_nTexId );
if(m_nTexId == 0)
return false;
glBindTexture( GL_TEXTURE_3D, m_nTexId );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, w, h , slices, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
tex = (unsigned char *)SOIL_load_image("Data/PA_170090.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char*) SOIL_load_image("Data/PA_170091.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char *)SOIL_load_image("Data/PA_170092.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char *)SOIL_load_image("Data/PA_170093.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 3, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char *)SOIL_load_image("Data/PA_170094.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 4, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char *)SOIL_load_image("Data/PA_170095.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 5, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char*) SOIL_load_image("Data/PA_170096.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 6, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char*) SOIL_load_image("Data/PA_170097.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 7, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char*) SOIL_load_image("Data/PA_170098.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 8, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
tex = (unsigned char*) SOIL_load_image("Data/PA_170099.png", &w, &h, NULL, 0);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 9, h, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
//glBindTexture( GL_TEXTURE_3D, 0 );
return true;
}
The problem is the same as you had when you originally tried to use glTexImage3D (...). Namely, 3D textures are a feature of OpenGL 1.2 and Windows only gives you OpenGL 1.1 without run-time extension.
You need to load the glTexSubImage3D (...) function the same as you did glTexImage3D (...).
PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D =
(PFNGLTEXSUBIMAGE3DPROC) wglGetProcAddress("glTexSubImage3D");
Related
I'm having problems with my OpenGL rendering. The RAM memory grows absurdly up to the point the entire system freezes. I've identified that if I comment the entire render function, no memory grows at all. Therefore the problem is that my OpenGL render function might be allocating memory for something and I'm not releasing it.
Can you identify what is the problem?
PS: the thing inside the if actually runs one single time, so the allocation of memory it does, occur only one time
This is my OpenGL render function:
void OpenGlVideoQtQuickRenderer::render()
{
if (this->firstRun) {
std::cout << "Creating QOpenGLShaderProgram " << std::endl;
this->firstRun = false;
program = new QOpenGLShaderProgram();
initializeOpenGLFunctions();
//this->m_F = QOpenGLContext::currentContext()->functions();
datas[0] = new unsigned char[width*height]; //Y
datas[1] = new unsigned char[width*height/4]; //U
datas[2] = new unsigned char[width*height/4]; //V
std::cout << program->addShaderFromSourceCode(QOpenGLShader::Fragment, tString2) << std::endl;
std::cout << program->addShaderFromSourceCode(QOpenGLShader::Vertex, vString2) << std::endl;
program->bindAttributeLocation("vertexIn",A_VER);
program->bindAttributeLocation("textureIn",T_VER);
std::cout << "program->link() = " << program->link() << std::endl;
}
program->bind();
glVertexAttribPointer(A_VER, 2, GL_FLOAT, 0, 0, ver);
glEnableVertexAttribArray(A_VER);
glVertexAttribPointer(T_VER, 2, GL_FLOAT, 0, 0, tex);
glEnableVertexAttribArray(T_VER);
unis[0] = program->uniformLocation("tex_y");
unis[1] = program->uniformLocation("tex_u");
unis[2] = program->uniformLocation("tex_v");
glGenTextures(3, texs);
//Y
glBindTexture(GL_TEXTURE_2D, texs[0]);
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_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
//U
glBindTexture(GL_TEXTURE_2D, texs[1]);
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_RED, width/2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
//V
glBindTexture(GL_TEXTURE_2D, texs[2]);
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_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texs[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, datas[0]);
glUniform1i(unis[0], 0);
glActiveTexture(GL_TEXTURE0+1);
glBindTexture(GL_TEXTURE_2D, texs[1]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width/2, height / 2, GL_RED, GL_UNSIGNED_BYTE, datas[1]);
glUniform1i(unis[1],1);
glActiveTexture(GL_TEXTURE0+2);
glBindTexture(GL_TEXTURE_2D, texs[2]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, datas[2]);
glUniform1i(unis[2], 2);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
program->disableAttributeArray(A_VER);
program->disableAttributeArray(T_VER);
program->release();
}
The code is creating three new textures in each frame (glGenTextures) without ever releasing them (glDeleteTextures). Either you delete them at the end of the render method, or even better: You only create the textures once in the first block and then only upload new data to them.
Just for the records: Drawing from CPU memory by specifying the address in glVertexAttribPointer is only valid in OpenGL before Core profile. I highly suggest to use Vertex Buffer Objects instead.
I started learning OpenGL recently and I've been messing with texture. I updated my texture using glTexImage2D but I've learned that it's better to use glTexSubImage2D, so I tried to change my code but i doesn't work.
Working code
void GLWidget::updateTextures(){
QImage t = img.mirrored();
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits());
glBindTexture( GL_TEXTURE_2D, 0);
}
Not working code
void GLWidget::updateTextures(){
QImage t = img.mirrored();
glBindTexture(GL_TEXTURE_2D, tex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, t.width(), t.height(), GL_RGBA, GL_UNSIGNED_BYTE, t.bits());
glBindTexture( GL_TEXTURE_2D, 0);
}
All I have is a black screen.
Thanks.
EDIT :
Here is the initialization of my texture :
void GLWidget::initializeGL(){
...
LoadGLTextures();
...
}
void GLWidget::LoadGLTextures(){
QImage t = img.mirrored();
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits());
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);
}
img is a QImage variable containing the pixel data.
glGetError() Returns code 1281.
glTexSubImage2D updates the content of a previously allocated texture. glTexImage2D has to be called at least once to trigger the allocation:
void GLWidget::initializeGL(){
//...
QImage t = img.mirrored();
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(
GL_TEXTURE_2D,
0,
3,
t.width(),
t.height(),
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
t.bits()
);
glBindTexture( GL_TEXTURE_2D, 0);
// ...
}
Update with glTexSubImage2D:
void GLWidget::updateTextures(){
QImage t = img.mirrored();
glBindTexture(GL_TEXTURE_2D, tex);
glTexSubImage2D(
GL_TEXTURE_2D,
0,
0,
0,
t.width(),
t.height(),
GL_RGBA,
GL_UNSIGNED_BYTE,
t.bits()
);
glBindTexture( GL_TEXTURE_2D, 0);
}
EDIT: the problem was glTexImage2D and glTexSubImage2D were called with different image sizes, generating the error GL_INVALID_VALUE (1281, 0x501) on glTexSubImage2D call.
Below code uploads my texture memory that's described in the passed parameters. When 'vPixelData' only holds 1 item/texture it is rendered properly, but once there's 2 or more nothing shows up.
glTexSubImage3D() is returning 'GL_INVALID_OPERATION' when I call glGetError() after it only when vPixelData.size() is greater than 1.
/*virtual*/ uint32 HyOpenGL::AddTextureArray(uint32 uiNumColorChannels, uint32 uiWidth, uint32 uiHeight, vector<unsigned char *> &vPixelData)
{
GLenum eInternalFormat = uiNumColorChannels == 4 ? GL_RGBA8 : (uiNumColorChannels == 3 ? GL_RGB8 : GL_R8);
GLenum eFormat = uiNumColorChannels == 4 ? GL_RGBA : (uiNumColorChannels == 3 ? GL_RGB : GL_RED);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, eInternalFormat, uiWidth, uiHeight, static_cast<uint32>(vPixelData.size()), 0, eFormat, GL_UNSIGNED_BYTE, NULL);
GLuint hGLTextureArray;
glGenTextures(1, &hGLTextureArray);
//glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, hGLTextureArray);
// Create storage for the texture
glTexStorage3D(GL_TEXTURE_2D_ARRAY,
1, // Number of mipmaps
eInternalFormat, // Internal format
uiWidth, uiHeight, // width, height
static_cast<uint32>(vPixelData.size()));
for(unsigned int i = 0; i != vPixelData.size(); ++i)
{
// Write each texture into storage
glTexSubImage3D(GL_TEXTURE_2D_ARRAY,
0, // Mipmap number
0, 0, i, // xoffset, yoffset, zoffset
uiWidth, uiHeight, 1, // width, height, depth (of texture you're copying in)
eFormat, // format
GL_UNSIGNED_BYTE, // type
vPixelData[i]); // pointer to pixel data
GLenum eError = glGetError(); // Getting 'GL_INVALID_OPERATION' when > 1 texture depth. It's 'GL_NO_ERROR' otherwise
}
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return hGLTextureArray;
}
(My current passed parameters are uiNumColorChannels == 4)
(uiWidth and uiHeight are both 512)
Apparently everything works if I use:
glTexImage3D(GL_TEXTURE_2D_ARRAY,
0,
eFormat,
uiWidth, uiHeight,
uiNumTextures,
0,
eFormat,
GL_UNSIGNED_BYTE,
NULL);
instead of:
glTexStorage3D(GL_TEXTURE_2D_ARRAY,
1, // Number of mipmaps
eInternalFormat, // Internal format
uiWidth, uiHeight, // width, height
static_cast<uint32>(vPixelData.size()));
Idea:
I have been trying to develop code which can take several (ten) slices of 2D images and render them as a 3D texture. I have so far used glTexImage3D and glTexSubImage3D upon suggestions from my previous post here: OpenGL - 'glTexSubImage3D': identifier not found
I have been based my work off of NeHe's texture mapping tutorial here: http://nehe.gamedev.net/tutorial/lesson_06_texturing_update/47002/
The flow of function calls in the NeHe's tutorial in main() proceeds like this: CreateGLWindow(), InitGL(), LoadGLTextures(), DrawGLScene(). I have only made changes to the code commencing upwards from DrawGLScene() while, everything below that function is the same as in my code.
Problem:
Everything in the code seemingly looks right but, there is nothing being rendered on the screen. I have spent two days on this trying to get it to work to no avail. What am I missing? Is there something that I am doing incorrectly?
EDITED CODE
#include "windows.h"
#include "stdio.h"
#include "gl\gl.h"
#include "gl\glu.h"
#include "GLext.h"
#include "SOIL.h"
HDC hDC=NULL;
HGLRC hRC=NULL;
HWND hWnd=NULL;
HINSTANCE hInstance;
bool keys[256];
bool active=TRUE;
bool fullscreen=TRUE;
GLfloat xrot;
GLfloat yrot;
GLfloat zrot;
GLuint m_nTexId;
unsigned char tex;
int h = 1024;
int w = 256;
int slices = 10;
GLfloat dOrthoSize = 1.0f;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// EDIT HERE
PFNGLTEXIMAGE3DPROC TexImage3D;
PFNGLTEXSUBIMAGE3DPROC TexSubImage3D;
PFNGLCOPYTEXSUBIMAGE3DPROC CopyTexSubImage3D;
int LoadGLTextures()
{
glGenTextures(1,(GLuint*)&m_nTexId );
if(m_nTexId == 0)
return false;
glBindTexture( GL_TEXTURE_3D, m_nTexId );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
return true;
}
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
if (height==0)
{
height=1;
}
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int InitGL(GLvoid)
{
if (!LoadGLTextures())
{
return FALSE;
}
glEnable(GL_TEXTURE_3D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// EDIT HERE
TexImage3D = (PFNGLTEXIMAGE3DPROC) wglGetProcAddress("glTexImage3D");
TexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) wglGetProcAddress("glTexSubImage3D");
CopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) wglGetProcAddress("glCopyTexSubImage3D");
return TRUE;
}
#define MAP_3DTEXT( TexIndex ) \
glTexCoord3f(0.0f, 0.0f, ((float)TexIndex+1.0f)/2.0f); \
glVertex3f(-dOrthoSize,-dOrthoSize,TexIndex);\
glTexCoord3f(1.0f, 0.0f, ((float)TexIndex+1.0f)/2.0f); \
glVertex3f(dOrthoSize,-dOrthoSize,TexIndex);\
glTexCoord3f(1.0f, 1.0f, ((float)TexIndex+1.0f)/2.0f); \
glVertex3f(dOrthoSize,dOrthoSize,TexIndex);\
glTexCoord3f(0.0f, 1.0f, ((float)TexIndex+1.0f)/2.0f); \
glVertex3f(-dOrthoSize,dOrthoSize,TexIndex);
int DrawGLScene(GLvoid)
{
PFNGLTEXIMAGE3DPROC glTexImage3D = (PFNGLTEXIMAGE3DPROC) wglGetProcAddress("glTexImage3D");
PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) wglGetProcAddress("glTexSubImage3D");
PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) wglGetProcAddress("glCopyTexSubImage3D");
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//glEnable( GL_ALPHA_TEST );
//glAlphaFunc( GL_GREATER, 0.2f );
//glEnable(GL_BLEND);
//glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt(0,0,-300,0,0,1,0,1,0);
glEnable(GL_TEXTURE_3D);
glBindTexture( GL_TEXTURE_3D, m_nTexId );
TexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, w, h , slices, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTranslatef( 0.0f, 0.0f, 100.0f );
glBegin(GL_QUADS);
tex = (unsigned char)SOIL_load_image("Data/PA_170090.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.0f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char) SOIL_load_image("Data/PA_170091.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.1f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char)SOIL_load_image("Data/PA_170092.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 3, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.2f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char)SOIL_load_image("Data/PA_170093.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 4, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.3f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char)SOIL_load_image("Data/PA_170094.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 5, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.4f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char)SOIL_load_image("Data/PA_170095.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 6, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.5f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char) SOIL_load_image("Data/PA_170096.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 7, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.6f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char) SOIL_load_image("Data/PA_170097.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 8, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.7f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char) SOIL_load_image("Data/PA_170098.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 9, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.8f );
glEnd();
glBegin(GL_QUADS);
tex = (unsigned char) SOIL_load_image("Data/PA_170099.png", &w, &h, NULL, 0);
TexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 10, w, h, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) tex);
MAP_3DTEXT( 0.9f );
glEnd();
return TRUE;
}
Look at the function call TexSubImage3D, the argument depth is always 1, and you are incrementing only zoffset. Please keep the zoffset 0 and provide the depth/layer values from 8th argument (depth).
TexSubImage3D( enum target, int level, int xoffset,
int yoffset, int zoffset, sizei width, sizei height,
sizei depth, enum format, enum type, const
void *data );
I'm creating a QGLWidget subclass with initializeGL. resizeGL and paintGL. Everything is fine, i can draw 2D graphivcs with gluOrtho2D and 3D too. Everything is fine.
Now I need to draw some text, no text rotation, no text deformations, no particular fonts. The first trial was with glut engine but the program kept on crashing so I thought with QGLWidget glut does not work in that context.
I've tried with QPainter, remember to use end() method and swapBuffers too, but.. nothing, the text is rendered but the opengl stuff no..
What is the easiest way to draw some text on a QGLWidget?
I usually do this by first rendering the text into a QImage which contents I then copy into a texture using glTexSubImage2D. Then I draw a textured quad.
Code from actual project
void displayText(QString const &text, bool render_text)
{
if(!text_texture) {
glGenTextures(1, &text_texture);
}
glActiveTexture(GL_TEXTURE0); gltPrintMultiError("glActiveTexture");
glBindTexture(GL_TEXTURE_2D, text_texture); gltPrintMultiError("glBindTexture");
int tex_width, tex_height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_width); gltPrintMultiError("glGetTexLevelParameteriv GL_TEXTURE_WIDTH");
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_height); gltPrintMultiError("glGetTexLevelParameter GL_TEXTURE_HEIGHT");
if(tex_width != text_width || tex_height != text_height ) {
render_text = true;
tex_width = text_width;
tex_height = text_height;
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB8,
tex_width, tex_height, 0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
gltPrintMultiError("glTexImage2D");
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);
}
if(render_text) {
QImage textimg(tex_width, tex_height, QImage::Format_RGB888);
{
QPainter painter(&textimg);
painter.fillRect(0, 0, tex_width, tex_height, QColor(0,0,0));
painter.setBrush(QColor(255, 255, 255));
painter.setPen(QColor(255, 255, 255));
painter.setFont(QFont("Sans", 15));
painter.drawText(5, 20, text);
}
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexSubImage2D(
GL_TEXTURE_2D, 0,
0, 0,
tex_width, tex_height,
GL_RGB, GL_UNSIGNED_BYTE, textimg.constBits() );
}
static GLfloat const pos[] = {
0, 1,
1, 1,
1, 0,
0, 0
};
static GLfloat const tex[] = {
0, 0,
1, 0,
1, 1,
0, 1
};
glUseProgram(frame2d.program);
/* frame2d is a program consisting of the
following vertex and fragment shaders:
// Vertex Shader
#version 330
in vec2 position;
in vec2 texcoord;
out vec2 vert_tex;
void main()
{
vert_tex = texcoord;
gl_Position = vec4(position*2 - 1., 0, 1);
}
// Fragment Shader
#version 330
uniform sampler2D frame;
in vec2 vert_tex;
void main()
{
gl_FragColor = texture(frame, vert_tex);
}
*/
glEnableVertexAttribArray(frame2d.attrib_position);
glEnableVertexAttribArray(frame2d.attrib_texcoord);
glVertexAttribPointer(frame2d.attrib_position, 2, GL_FLOAT, GL_FALSE, 0, pos);
gltPrintMultiError("glVertexAttribPointer(attrib_position, ...)");
glVertexAttribPointer(frame2d.attrib_texcoord, 2, GL_FLOAT, GL_FALSE, 0, tex);
gltPrintMultiError("glVertexAttribPointer(attrib_texcoord, ...)");
glUniform1i(frame2d.uniform_sampler_frame, 0);
gltPrintMultiError("glUniform1i(frame2d.uniform_sampler_frame)");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
glViewport(0, 0, tex_width, tex_height);
glDisable(GL_DEPTH_TEST);
glDepthMask(0);
glColorMask(1,1,1,1);
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(frame2d.attrib_position);
glDisableVertexAttribArray(frame2d.attrib_texcoord);
glUseProgram(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
I didn't know but there is also renderText method builtin in QGLWidget class.