void TextRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, float zNear, float zFar, bool mode2D) { std::lock_guard<std::mutex> lock(mMutex); if(!mode2D) throw Exception("TextRender is only implemented for 2D at the moment"); if(mView == nullptr) throw Exception("TextRenderer need access to the view"); for(auto it : mDataToRender) { Text::pointer input = std::static_pointer_cast<Text>(it.second); uint inputNr = it.first; // Check if a texture has already been created for this text if (mTexturesToRender.count(inputNr) > 0 && mTextUsed[inputNr] == input) continue; // If it has already been created, skip it if (mTexturesToRender.count(inputNr) > 0) { // Delete old texture glDeleteTextures(1, &mTexturesToRender[inputNr]); mTexturesToRender.erase(inputNr); glDeleteVertexArrays(1, &mVAO[inputNr]); mVAO.erase(inputNr); } Text::access access = input->getAccess(ACCESS_READ); std::string text = access->getData(); // Font setup QColor color(mColor.getRedValue() * 255, mColor.getGreenValue() * 255, mColor.getBlueValue() * 255, 255); QFont font = QApplication::font(); font.setPointSize(mFontSize); if (mStyle == STYLE_BOLD) { font.setBold(true); } else if (mStyle == STYLE_ITALIC) { font.setItalic(true); } QFontMetrics metrics(font); const int width = metrics.boundingRect(QString(text.c_str())).width() + 10; const int height = mFontSize + 5; // create the QImage and draw txt into it QImage textimg(width, height, QImage::Format_RGBA8888); textimg.fill(QColor(0, 0, 0, 0)); { // Draw the text to the image QPainter painter(&textimg); painter.setBrush(color); painter.setPen(color); painter.setFont(font); painter.drawText(0, mFontSize, text.c_str()); } // Make texture of QImage GLuint textureID; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textimg.width(), textimg.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, textimg.bits()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Draw texture on a quad // Delete old VAO if(mVAO.count(inputNr) > 0) glDeleteVertexArrays(1, &mVAO[inputNr]); GLuint VAO_ID; glGenVertexArrays(1, &VAO_ID); mVAO[inputNr] = VAO_ID; glBindVertexArray(VAO_ID); float vertices[] = { // vertex: x, y, z; tex coordinates: x, y 0.0f, (float)height, 0.0f, 0.0f, 0.0f, (float)width, (float)height, 0.0f, 1.0f, 0.0f, (float)width, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; // Delete old VBO if(mVBO.count(inputNr) > 0) glDeleteBuffers(1, &mVBO[inputNr]); // Create VBO uint VBO; glGenBuffers(1, &VBO); mVBO[inputNr] = VBO; glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *) 0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *) (3 * sizeof(float))); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); // Delete old EBO if(mEBO.count(inputNr) > 0) glDeleteBuffers(1, &mEBO[inputNr]); // Create EBO uint EBO; glGenBuffers(1, &EBO); mEBO[inputNr] = EBO; uint indices[] = { // note that we start from 0! 0, 1, 3, // first triangle 1, 2, 3 // second triangle }; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glBindVertexArray(0); mTexturesToRender[inputNr] = textureID; mTextUsed[inputNr] = input; } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); activateShader(); for(auto it : mDataToRender) { const uint inputNr = it.first; Affine3f transform = Affine3f::Identity(); // Get width and height of texture glBindTexture(GL_TEXTURE_2D, mTexturesToRender[inputNr]); int width, height; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); const float scale = 1.0f / mView->width(); const float scale2 = 1.0f / mView->height(); const int padding = 15; Vector3f position; switch(mPosition) { case POSITION_CENTER: position = Vector3f(-width*scale/2.0f, -height*scale2/2.0f, 0); // Center break; case POSITION_TOP_CENTER: position = Vector3f(-width*scale/2.0f, 1 - (height + padding)*scale2, 0); // Top center break; case POSITION_BOTTOM_CENTER: position = Vector3f(-width*scale/2.0f, -1 + padding*scale2, 0); // Bottom center break; case POSITION_TOP_LEFT: position = Vector3f(-1 + padding*scale, 1 - (height + padding)*scale2, 0); // Top left corner break; case POSITION_TOP_RIGHT: position = Vector3f(1 - (width + padding)*scale, 1 - (height + padding)*scale2, 0); // Top right corner break; case POSITION_BOTTOM_LEFT: position = Vector3f(-1 + padding*scale, -1 + padding*scale2, 0); // Bottom left corner break; case POSITION_BOTTOM_RIGHT: position = Vector3f(1 - (width + padding)*scale, -1 + padding*scale2, 0); // Bottom right corner break; } transform.translate(position); transform.scale(Vector3f(scale, scale2, 0)); uint transformLoc = glGetUniformLocation(getShaderProgram(), "transform"); glUniformMatrix4fv(transformLoc, 1, GL_FALSE, transform.data()); transformLoc = glGetUniformLocation(getShaderProgram(), "perspectiveTransform"); glUniformMatrix4fv(transformLoc, 1, GL_FALSE, perspectiveMatrix.data()); transformLoc = glGetUniformLocation(getShaderProgram(), "viewTransform"); glUniformMatrix4fv(transformLoc, 1, GL_FALSE, viewingMatrix.data()); // Actual drawing glBindVertexArray(mVAO[inputNr]); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindVertexArray(0); } glDisable(GL_BLEND); deactivateShader(); }
static CoglBool allocate_from_gl_foreign (CoglTextureRectangle *tex_rect, CoglTextureLoader *loader, CoglError **error) { CoglTexture *tex = COGL_TEXTURE (tex_rect); CoglContext *ctx = tex->context; CoglPixelFormat format = loader->src.gl_foreign.format; GLenum gl_error = 0; GLint gl_compressed = GL_FALSE; GLenum gl_int_format = 0; if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_RECTANGLE_ARB)) { _cogl_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, "Foreign GL_TEXTURE_RECTANGLE textures are not " "supported by your system"); return FALSE; } /* Make sure binding succeeds */ while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR) ; _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, loader->src.gl_foreign.gl_handle, TRUE); if (ctx->glGetError () != GL_NO_ERROR) { _cogl_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, "Failed to bind foreign GL_TEXTURE_RECTANGLE texture"); return FALSE; } /* Obtain texture parameters */ #ifdef HAVE_COGL_GL if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS)) { GLint val; GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_COMPRESSED, &gl_compressed) ); GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_INTERNAL_FORMAT, &val) ); gl_int_format = val; /* If we can query GL for the actual pixel format then we'll ignore the passed in format and use that. */ if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx, gl_int_format, &format)) { _cogl_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, "Unsupported internal format for foreign texture"); return FALSE; } } else #endif { /* Otherwise we'll assume we can derive the GL format from the passed in format */ ctx->driver_vtable->pixel_format_to_gl (ctx, format, &gl_int_format, NULL, NULL); } /* Compressed texture images not supported */ if (gl_compressed == GL_TRUE) { _cogl_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, "Compressed foreign textures aren't currently supported"); return FALSE; } /* Setup bitmap info */ tex_rect->is_foreign = TRUE; tex_rect->gl_texture = loader->src.gl_foreign.gl_handle; tex_rect->gl_format = gl_int_format; /* Unknown filter */ tex_rect->gl_legacy_texobj_min_filter = GL_FALSE; tex_rect->gl_legacy_texobj_mag_filter = GL_FALSE; tex_rect->internal_format = format; _cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), format, loader->src.gl_foreign.width, loader->src.gl_foreign.height); return TRUE; }
static int initTextures(void) { struct TexSquare *tsq=0; GLfloat texpercx, texpercy; int s; int x=0, y=0; // textures smaller than 64x64 might not be supported s=64; while (s<image_width) s*=2; texture_width=s; s=64; while (s<image_height) s*=2; texture_height=s; if (!is_yuv) gl_internal_format = getInternalFormat(); /* Test the max texture size */ do { GLint w; glTexImage2D (GL_PROXY_TEXTURE_2D, 0, gl_internal_format, texture_width, texture_height, 0, gl_bitmap_format, gl_bitmap_type, NULL); glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); if (w >= texture_width) break; mp_msg (MSGT_VO, MSGL_V, "[gl_tiled] Needed texture [%dx%d] too big, trying ", texture_width, texture_height); if (texture_width > texture_height) texture_width /= 2; else texture_height /= 2; mp_msg (MSGT_VO, MSGL_V, "[%dx%d] !\n", texture_width, texture_height); if(texture_width < 64 || texture_height < 64) { mp_msg (MSGT_VO, MSGL_FATAL, "[gl_tiled] Give up .. usable texture size not available, or texture config error !\n"); return -1; } } while (texture_width > 1 && texture_height > 1); #ifdef TEXTURE_WIDTH texture_width = TEXTURE_WIDTH; #endif #ifdef TEXTURE_HEIGHT texture_height = TEXTURE_HEIGHT; #endif texnumx = image_width / texture_width; if ((image_width % texture_width) > 0) texnumx++; texnumy = image_height / texture_height; if ((image_height % texture_height) > 0) texnumy++; mp_msg(MSGT_VO, MSGL_V, "[gl_tiled] Creating %dx%d textures of size %dx%d ...\n", texnumx, texnumy, texture_width,texture_height); /* Allocate the texture memory */ texpercx = (GLfloat) texture_width / (GLfloat) image_width; texpercy = (GLfloat) texture_height / (GLfloat) image_height; free(texgrid); texgrid = calloc (texnumx * texnumy, sizeof (struct TexSquare)); raw_line_len = image_width * image_bytes; mp_msg (MSGT_VO, MSGL_DBG2, "[gl_tiled] texture-usage %d*width=%d, %d*height=%d\n", (int) texnumx, (int) texture_width, (int) texnumy, (int) texture_height); tsq = texgrid; for (y = 0; y < texnumy; y++) { for (x = 0; x < texnumx; x++) { tsq->fx = x * texpercx; tsq->fy = y * texpercy; tsq->fw = texpercx; tsq->fh = texpercy; tsq->texobj=0; tsq->uvtexobjs[0] = tsq->uvtexobjs[1] = 0; glGenTextures (1, &(tsq->texobj)); glBindTexture (GL_TEXTURE_2D, tsq->texobj); if (is_yuv) { glGenTextures(2, tsq->uvtexobjs); mpglActiveTexture(GL_TEXTURE1); glBindTexture (GL_TEXTURE_2D, tsq->uvtexobjs[0]); mpglActiveTexture(GL_TEXTURE2); glBindTexture (GL_TEXTURE_2D, tsq->uvtexobjs[1]); mpglActiveTexture(GL_TEXTURE0); } glCreateClearTex(GL_TEXTURE_2D, gl_internal_format, gl_bitmap_format, gl_bitmap_type, GL_LINEAR, texture_width, texture_height, 0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); if (is_yuv) { int xs, ys, depth; int chroma_clear_val = 128; mp_get_chroma_shift(image_format, &xs, &ys, &depth); chroma_clear_val >>= -depth & 7; mpglActiveTexture(GL_TEXTURE1); glCreateClearTex(GL_TEXTURE_2D, gl_internal_format, gl_bitmap_format, gl_bitmap_type, GL_LINEAR, texture_width >> xs, texture_height >> ys, chroma_clear_val); mpglActiveTexture(GL_TEXTURE2); glCreateClearTex(GL_TEXTURE_2D, gl_internal_format, gl_bitmap_format, gl_bitmap_type, GL_LINEAR, texture_width >> xs, texture_height >> ys, chroma_clear_val); mpglActiveTexture(GL_TEXTURE0); } tsq++; } /* for all texnumx */ } /* for all texnumy */ return 0; }
void DebugGraphics::Draw() { if (this->Mode == 1) { for (auto it = Texture::Textures.begin(); it != Texture::Textures.end(); ++it) { if ((it->X >= Filters[0].X1 && it->Y >= Filters[0].Y1 && it->X <= Filters[0].X2 && it->Y <= Filters[0].Y2) && it->BaseID != 0) { Renderer->Print(it->X, it->Y, 0.0f, 1.0f, 0.0f, "%", it->BaseID); } } } else if (this->Mode == 2) { for (auto it = Model::Models.begin(); it != Model::Models.end(); ++it) { if ((it->X >= Filters[1].X1 && it->Y >= Filters[1].Y1 && it->X <= Filters[1].X2 && it->Y <= Filters[1].Y2) && it->ID != 0) { Renderer->Print(it->X, it->Y, 0.0f, 1.0f, 0.0f, "%", it->ID); } } } else if (this->Mode == 3) { //auto HangingLetter = [](const char &C){return (C == 'f' || C == 'g' || C == 'j' || C == 'p' || C == 'q' || C == 'y' || C == '[' || C == ']' || C == '_' || C == '.');}; for (auto it = Font::RenderedFonts.begin(); it != Font::RenderedFonts.end(); ++it) { if ((it->X >= Filters[2].X1 && it->Y >= Filters[2].Y1 && it->X <= Filters[2].X2 && it->Y <= Filters[2].Y2)) { if ((it != Font::RenderedFonts.end() - 1) && (it->X - (it + 1)->X == 1)) ++it; Renderer->Print(it->Translate[0] + it->VX[0], it->Y + 3, 0.0f, 1.0f, 0.0f, "%", it->Letter); } } } else if (this->Mode == 4) { int HudX = 4, HudY = 75; int TextX = 10, TextY = 90, TextLn = 10; auto SimilarColours = [&](std::uint32_t ColourOne, std::uint32_t ColourTwo, int Tol) { static RGBA FirstCol = {0}; static RGBA SecondCol = {0}; FirstCol.Colour = ColourOne; SecondCol.Colour = ColourTwo; return ((FirstCol.R - SecondCol.R) * (FirstCol.R - SecondCol.R) + (FirstCol.G - SecondCol.G) * (FirstCol.G - SecondCol.G) + (FirstCol.B - SecondCol.B) * (FirstCol.B - SecondCol.B)) <= (Tol * Tol); }; auto it = std::find_if(Texture::Textures.begin(), Texture::Textures.end(), [&](const Texture &T) { return T.BaseID == this->HudID && (this->ColourID != 0 ? SimilarColours(T.ColourID, this->ColourID, this->Tolerance) : true) && (this->FullColourID != 0 ? SimilarColours(T.FullColourID, this->FullColourID, this->Tolerance) : true); }); if (it != Texture::Textures.end()) { glEnable(it->Target); glBindTexture(it->Target, it->ID); glGetTexLevelParameteriv(it->Target, 0, GL_TEXTURE_WIDTH, &it->Width); glGetTexLevelParameteriv(it->Target, 0, GL_TEXTURE_HEIGHT, &it->Height); glDisable(it->Target); int MaxWidth = 200; int MaxHeight = ((TextLn * 10) + it->Height) + 160; glColor4f(0.25f, 0.25f, 0.25f, 0.75f); Renderer->DrawRect(HudX, HudY, MaxWidth, MaxHeight); glColor4f(0.0f, 0.0f, 0.0f, 1.0f); Renderer->DrawRect(HudX, HudY, MaxWidth, MaxHeight, false); Renderer->Print(70, TextY, 1.0f, 1.0f, 1.0f, "GLX v3.5"); glColor4f(0.0f, 0.0f, 0.0f, 1.0f); TextY += (TextLn - 2); Renderer->DrawLine(HudX, TextY, MaxWidth, TextY); GLint ViewPort[4]; glGetIntegerv(GL_VIEWPORT, ViewPort); Renderer->Print(TextX, TextY += TextLn, 0.0f, 1.0f, 0.0f, "ViewPort: [%, %, %, %]", ViewPort[0], ViewPort[1], ViewPort[2], ViewPort[3]); Renderer->Print(TextX, TextY += (TextLn * 2) , 0.0f, 1.0f, 0.0f, "Target: %", it->Target == GL_TEXTURE_2D ? "TEXTURE-2D" : "TEXTURE-RECTANGLE"); Renderer->Print(TextX, TextY += TextLn, 0.0f, 1.0f, 0.0f, "GenID: %", it->ID); Renderer->Print(TextX, TextY += TextLn, 0.0f, 1.0f, 0.0f, "BaseID: %", it->BaseID); Renderer->Print(TextX, TextY += TextLn, 0.0f, 1.0f, 0.0f, "ColourID: %", it->ColourID); Renderer->Print(TextX, TextY += TextLn, 0.0f, 1.0f, 0.0f, "Location: (%, %)", it->X, it->Y); Renderer->Print(TextX, TextY += TextLn, 0.0f, 1.0f, 0.0f, "Width: %", it->Width); Renderer->Print(TextX, TextY += TextLn, 0.0f, 1.0f, 0.0f, "Height: %", it->Height); Renderer->Print(TextX, TextY += (TextLn * 2), 0.0f, 1.0f, 0.0f, "Image:"); glPushMatrix(); glColor4f(1, 1, 1, 1); glTranslated((MaxWidth - it->Width) / 2, TextY += TextLn, 0); DrawTexture(it->Target, it->ID, 0, 0, it->Width, it->Height, it->Width, it->Height); glPopMatrix(); glFlush(); } } }
void Image::readTexture(unsigned int id) { glBindTexture(GL_TEXTURE_2D, id); int nwidth, nheight; int internalFormat; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &nwidth); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &nheight); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat); int nchannels; bool depth = false; switch (internalFormat) { case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: depth = true; case GL_RED: case GL_R32F: case GL_LUMINANCE: nchannels = 1; break; case GL_LUMINANCE_ALPHA: nchannels = 2; break; case GL_BGR: case GL_RGB: case GL_RGB32F: nchannels = 3; break; case GL_BGRA: case GL_RGBA: case GL_RGBA32F: case GL_RGBA32I: case GL_RGBA32UI: case GL_DEPTH24_STENCIL8: nchannels = 4; break; default: printf("Error: Cannot read unknown texture format\n"); return; } if (nwidth != width || nheight != height || nchannels != channels) { width = nwidth; height = nheight; channels = nchannels; unsigned char* imageData = new unsigned char[width*height*channels]; data = RCByteArray(imageData); } int format; switch (channels) { case 1: format = GL_LUMINANCE; break; case 2: format = GL_LUMINANCE_ALPHA; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; default: printf("Error: invalid png channel count: %i\n", channels); return; } if (depth) format = GL_DEPTH_COMPONENT; glGetTexImage(GL_TEXTURE_2D, 0, format, GL_UNSIGNED_BYTE, data.get()); glBindTexture(GL_TEXTURE_2D, 0); }
void DGTexture::load() { FILE* fh; char magic[10]; // Used to identity file types GLint format = 0, internalFormat = 0; if (_isLoaded) return; if (!_hasResource) { log->error(DGModTexture, "%s: %s", DGMsg210004, this->name()); return; } fh = fopen(_resource, "rb"); if (fh != NULL) { if (fread(&magic, sizeof(magic), 1, fh) == 0) { // Couldn't read magic number log->error(DGModTexture, "%s: %s", DGMsg210002, _resource); } if (memcmp(TEXIdent, &magic, 7) == 0) { short numTextures = 0; TEXMainHeader header; TEXSubHeader subheader; GLint compressed, size; fseek(fh, 8, SEEK_SET); // Skip identifier if (!fread(&header, 1, sizeof(header), fh)) return; numTextures = header.numTextures; _width = (GLuint)header.width; _height = (GLuint)header.height; // Skip subheaders based on the index if (_indexInBundle) { unsigned int i; for (i = 0; i < _indexInBundle; i++) { if (!fread(&subheader, 1, sizeof(subheader), fh)) return; fseek(fh, sizeof(char) * subheader.size, SEEK_CUR); } } if (!fread(&subheader, 1, sizeof(subheader), fh)) return; _depth = (GLuint)subheader.depth; size = (GLint)subheader.size; internalFormat = (GLint)subheader.format; _bitmap = (GLubyte*)malloc(size * sizeof(GLubyte)); if (!fread(_bitmap, 1, sizeof(GLubyte) * size, fh)) return; glGenTextures(1, &_ident); glBindTexture(GL_TEXTURE_2D, _ident); if (header.compressionLevel) { glCompressedTexImage2D(GL_TEXTURE_2D, 0, internalFormat, _width, _height, 0, size, _bitmap); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &compressed); if (compressed == GL_TRUE) _isLoaded = true; else log->error(DGModTexture, "%s: %s", DGMsg210002, fh); } else { glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, _width, _height, 0, GL_RGB, GL_UNSIGNED_BYTE, _bitmap); // Only RGB is supported _isLoaded = true; } 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); free(_bitmap); } else { int x, y, comp; fseek(fh, 0, SEEK_SET); _bitmap = (GLubyte*)stbi_load_from_file(fh, &x, &y, &comp, STBI_default); if (_bitmap) { _width = x; _height = y; _depth = comp; switch (comp) { case STBI_grey: format = GL_LUMINANCE; if (_compressionLevel) internalFormat = GL_COMPRESSED_LUMINANCE; else internalFormat = GL_LUMINANCE; break; case STBI_grey_alpha: format = GL_LUMINANCE_ALPHA; if (_compressionLevel) internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA; else internalFormat = GL_LUMINANCE_ALPHA; break; case STBI_rgb: format = GL_RGB; if (_compressionLevel) internalFormat = GL_COMPRESSED_RGB; else internalFormat = GL_RGB; break; case STBI_rgb_alpha: format = GL_RGBA; if (_compressionLevel) internalFormat = GL_COMPRESSED_RGBA; else internalFormat = GL_RGBA; break; default: log->warning(DGModTexture, "%s: (%s) %d", DGMsg210003, _resource, comp); break; } glGenTextures(1, &_ident); glBindTexture(GL_TEXTURE_2D, _ident); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, _width, _height, 0, format, GL_UNSIGNED_BYTE, _bitmap); 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); free(_bitmap); _isLoaded = true; } else { // Nothing loaded log->error(DGModTexture, "%s: (%s) %s", DGMsg210001, _resource, stbi_failure_reason()); } } fclose(fh); } else { // File not found log->error(DGModTexture, "%s: %s", DGMsg210000, _resource); } }
PsychError SCREENTransformTexture(void) { PsychWindowRecordType *sourceRecord, *targetRecord, *proxyRecord, *sourceRecord2; int testarg, specialFlags, usefloatformat, d; // All subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if (PsychIsGiveHelp()) { PsychGiveHelp(); return(PsychError_none); }; PsychErrorExit(PsychCapNumInputArgs(5)); PsychErrorExit(PsychRequireNumInputArgs(2)); PsychErrorExit(PsychCapNumOutputArgs(1)); // OpenGL FBO's supported? Otherwise this is a no-go... if (glBindFramebufferEXT == NULL || glUseProgram == NULL) { // Game over! printf("PTB-ERROR: Sorry, your graphics driver & hardware does not support the required OpenGL framebuffer object extension or\n"); printf("PTB-ERROR: the OpenGL shading language for hardware accelerated fragment processing. This function is therefore disabled.\n"); printf("PTB-ERROR: You will need at least a NVidia GeforceFX-5200, a ATI Radeon 9600 or a Intel GMA-950 graphics card for this\n"); printf("PTB-ERROR: to work. If you have such a card (or a more recent one) then you'll need to update your graphics drivers.\n\n"); PsychErrorExitMsg(PsychError_user, "Screen('TransformTexture') command unsupported on your combination of graphics hardware & driver."); } // Get the window structure for the source texture. PsychAllocInWindowRecordArg(1, TRUE, &sourceRecord); if (!PsychIsTexture(sourceRecord)) PsychErrorExitMsg(PsychError_user, "'sourceTexture' argument must be a handle to a texture or offscreen window."); // Get the window structure for the proxy object. PsychAllocInWindowRecordArg(2, TRUE, &proxyRecord); if (proxyRecord->windowType != kPsychProxyWindow) PsychErrorExitMsg(PsychError_user, "'transformProxyPtr' argument must be a handle to a proxy object."); // Test if optional specialFlags are provided: specialFlags = 0; PsychCopyInIntegerArg(5, FALSE, &specialFlags); // Activate rendering context of the proxy object and soft-reset the drawing engine, // so we're in a well defined state. The value 1 means: Reset safely, ie. do any // framebuffer backups that might be needed before NULL-ing the binding: PsychSetDrawingTarget((PsychWindowRecordType*) 0x1); PsychSetGLContext(proxyRecord); // Save all state: glPushAttrib(GL_ALL_ATTRIB_BITS); // Disable alpha-blending: glDisable(GL_BLEND); // Reset color write mask to "all enabled" glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); // Disable any shaders: PsychSetShader(proxyRecord, 0); // Transform sourceRecord source texture into a normalized, upright texture if it isn't already in // that format. We require this standard orientation for simplified shader design. if (!(specialFlags & 1)) PsychNormalizeTextureOrientation(sourceRecord); // Test if optional 2nd source texture is provided: testarg = 0; PsychCopyInIntegerArg(3, FALSE, &testarg); if (testarg != 0) { // Tes. Get the window structure for the 2nd source texture. PsychAllocInWindowRecordArg(3, TRUE, &sourceRecord2); if (!PsychIsTexture(sourceRecord2)) PsychErrorExitMsg(PsychError_user, "'sourceTexture2' argument must be a handle to a texture or offscreen window."); // Transform sourceRecord2 source texture into a normalized, upright texture if it isn't already in // that format. We require this standard orientation for simplified shader design. if (!(specialFlags & 1)) PsychNormalizeTextureOrientation(sourceRecord2); } else { // No secondary source texture: sourceRecord2 = NULL; } // Restore proper rendering context: PsychSetGLContext(proxyRecord); // Test if optional target texture is provided: testarg = 0; PsychCopyInIntegerArg(4, FALSE, &testarg); // Do we need to create a new one from scratch? if (testarg == 0) { // No valid textureHandle provided. Create a new empty textureRecord which clones some // of the properties of the sourceRecord targetRecord = NULL; PsychCreateWindowRecord(&targetRecord); PsychInitWindowRecordTextureFields(targetRecord); targetRecord->windowType=kPsychTexture; targetRecord->screenNumber = sourceRecord->screenNumber; // Assign parent window and copy its inheritable properties: PsychAssignParentWindow(targetRecord, sourceRecord); targetRecord->depth = sourceRecord->depth; // Assume this texture has four channels. targetRecord->nrchannels = 4; PsychCopyRect(targetRecord->rect, sourceRecord->rect); PsychCopyRect(targetRecord->clientrect, targetRecord->rect); targetRecord->texturetarget = sourceRecord->texturetarget; // Orientation is set to 2 - like an upright Offscreen window texture: targetRecord->textureOrientation = 2; // Mark it valid and return handle to userspace: PsychSetWindowRecordValid(targetRecord); } else { // Get the window structure for the target texture. PsychAllocInWindowRecordArg(4, TRUE, &targetRecord); if (!PsychIsTexture(targetRecord)) PsychErrorExitMsg(PsychError_user, "'targetTexture' argument must be a handle to a texture or offscreen window."); } // Make sure our source textures have at least a pseudo FBO for read-access: PsychCreateShadowFBOForTexture(sourceRecord, FALSE, -1); if (sourceRecord2) PsychCreateShadowFBOForTexture(sourceRecord2, FALSE, -1); // Make sure the target texture is upright/normalized: if (!(specialFlags & 1)) PsychNormalizeTextureOrientation(targetRecord); // Make sure our target texture has a full-blown FBO attached as a rendertarget. // As our proxy object defines the image processing ops, it also defines the // required imagingMode properties for the target texture: PsychCreateShadowFBOForTexture(targetRecord, TRUE, proxyRecord->imagingMode); // Assign GLSL filter-/lookup-shaders if needed: usefloatformat is queried. // The 'userRequest' flag is set depending on specialFlags setting & 2. glBindTexture(targetRecord->texturetarget, targetRecord->textureNumber); glGetTexLevelParameteriv(targetRecord->texturetarget, 0, GL_TEXTURE_RED_SIZE, (GLint*) &d); if (d <= 0) glGetTexLevelParameteriv(targetRecord->texturetarget, 0, GL_TEXTURE_LUMINANCE_SIZE, (GLint*) &d); glBindTexture(targetRecord->texturetarget, 0); usefloatformat = 0; if (d == 16) usefloatformat = 1; if (d >= 32) usefloatformat = 2; PsychAssignHighPrecisionTextureShaders(targetRecord, sourceRecord, usefloatformat, (specialFlags & 2) ? 1 : 0); // Make sure our proxy has suitable bounce buffers if we need any: if (proxyRecord->imagingMode & (kPsychNeedDualPass | kPsychNeedMultiPass)) { // Needs multi-pass processing. Create bounce buffer if neccessary: PsychCopyRect(proxyRecord->rect, targetRecord->rect); PsychCopyRect(proxyRecord->clientrect, targetRecord->rect); // Build FBO for bounce-buffering. This will always be upright/normalized, // so no need to normalize "texture orientation" for proxyRecord bounce buffers: PsychCreateShadowFBOForTexture(proxyRecord, TRUE, proxyRecord->imagingMode); } // Make sure we don't have VRAM memory feedback loops: if ((sourceRecord->textureNumber == targetRecord->textureNumber) || (sourceRecord2 && (sourceRecord2->textureNumber == targetRecord->textureNumber))) PsychErrorExitMsg(PsychError_user, "Source texture and target texture must be different!"); // Apply image processing operation: Use ressources and OpenGL context of proxyRecord, run user defined blit chain, // Don't supply user specific data (NULL), don't supply override blitter (NULL), source is read-only (TRUE), no // swizzle allowed (FALSE), sourceRecord is source, targetRecord is destination, bounce buffers provided by proxyRecord, // no secondary FBO available (NULL). PsychPipelineExecuteHook(proxyRecord, kPsychUserDefinedBlit, NULL, NULL, TRUE, FALSE, &(sourceRecord->fboTable[sourceRecord->drawBufferFBO[0]]), (sourceRecord2) ? &(sourceRecord2->fboTable[sourceRecord2->drawBufferFBO[0]]) : NULL, &(targetRecord->fboTable[targetRecord->drawBufferFBO[0]]), (proxyRecord->drawBufferFBO[0]!=-1) ? &(proxyRecord->fboTable[proxyRecord->drawBufferFBO[0]]) : NULL); // Restore previous settings: glPopAttrib(); // Set "dirty" flag on texture: (Ab)used to trigger regeneration of mip-maps during texture drawing of mip-mapped textures. targetRecord->needsViewportSetup = TRUE; //Return the window index and the rect argument. PsychCopyOutDoubleArg(1, FALSE, targetRecord->windowIndex); // Done. return(PsychError_none); }
void deferred_renderer_end() { glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); /* Render out ssao */ glBindFramebuffer(GL_FRAMEBUFFER, ssao_fbo); glViewport(0, 0, graphics_viewport_width() / 2, graphics_viewport_height() / 2); GLuint ssao_handle = shader_program_handle(PROGRAM_SSAO); glUseProgram(ssao_handle); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glActiveTexture(GL_TEXTURE0 + 0 ); glBindTexture(GL_TEXTURE_2D, depth_texture); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(ssao_handle, "depth_texture"), 0); glActiveTexture(GL_TEXTURE0 + 1 ); glBindTexture(GL_TEXTURE_2D, texture_handle(RANDOM)); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(ssao_handle, "random_texture"), 1); float seed = CAMERA->position.x + CAMERA->position.y + CAMERA->position.z; glUniform1f(glGetUniformLocation(ssao_handle, "seed"), seed); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0, -1.0, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0, -1.0, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0, 1.0, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0, 1.0, 0.0f); glEnd(); glActiveTexture(GL_TEXTURE0 + 1 ); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0 + 0 ); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); /* End */ /* Render full screen quad to hdr fbo */ glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo); glViewport(0, 0, graphics_viewport_width(), graphics_viewport_height()); GLuint screen_handle = shader_program_handle(PROGRAM_COMPOSE); glUseProgram(screen_handle); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glActiveTexture(GL_TEXTURE0 + 0 ); glBindTexture(GL_TEXTURE_2D, diffuse_texture); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_handle, "diffuse_texture"), 0); glActiveTexture(GL_TEXTURE0 + 1 ); glBindTexture(GL_TEXTURE_2D, positions_texture); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_handle, "positions_texture"), 1); glActiveTexture(GL_TEXTURE0 + 2 ); glBindTexture(GL_TEXTURE_2D, normals_texture); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_handle, "normals_texture"), 2); glActiveTexture(GL_TEXTURE0 + 3 ); glBindTexture(GL_TEXTURE_2D, depth_texture); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_handle, "depth_texture"), 3); glActiveTexture(GL_TEXTURE0 + 4 ); glBindTexture(GL_TEXTURE_2D, texture_handle(SHADOW_TEX)); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_handle, "shadows_texture"), 4); glActiveTexture(GL_TEXTURE0 + 5 ); glBindTexture(GL_TEXTURE_2D, ssao_texture); glEnable(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_handle, "ssao_texture"), 5); glActiveTexture(GL_TEXTURE0 + 6 ); glBindTexture(GL_TEXTURE_2D, texture_handle(ENVIRONMENT)); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_handle, "env_texture"), 6); GLint cam_position = glGetUniformLocation(screen_handle, "camera_position"); glUniform3f(cam_position, CAMERA->position.x, CAMERA->position.y, CAMERA->position.z); GLint lproj_matrix_u = glGetUniformLocation(screen_handle, "light_proj"); glUniformMatrix4fv(lproj_matrix_u, 1, 0, LIGHT_PROJ_MATRIX); GLint lview_matrix_u = glGetUniformLocation(screen_handle, "light_view"); glUniformMatrix4fv(lview_matrix_u, 1, 0, LIGHT_VIEW_MATRIX); for(int i = 0; i < num_lights; i++) { light_power[i] = lights[i]->power; light_falloff[i] = lights[i]->falloff; light_position[i] = lights[i]->position; light_target[i] = lights[i]->target; light_diffuse[i] = lights[i]->diffuse_color; light_ambient[i] = lights[i]->ambient_color; light_specular[i] = lights[i]->specular_color; } glUniform1i(glGetUniformLocation(screen_handle, "num_lights"), num_lights); GLint light_power_u = glGetUniformLocation(screen_handle, "light_power"); GLint light_falloff_u = glGetUniformLocation(screen_handle, "light_falloff"); GLint light_position_u = glGetUniformLocation(screen_handle, "light_position"); GLint light_target_u = glGetUniformLocation(screen_handle, "light_target"); GLint light_diffuse_u = glGetUniformLocation(screen_handle, "light_diffuse"); GLint light_ambient_u = glGetUniformLocation(screen_handle, "light_ambient"); GLint light_specular_u = glGetUniformLocation(screen_handle, "light_specular"); glUniform1fv(light_power_u, num_lights, (const GLfloat*)light_power); glUniform1fv(light_falloff_u, num_lights, (const GLfloat*)light_falloff); glUniform3fv(light_position_u, num_lights, (const GLfloat*)light_position); glUniform3fv(light_target_u, num_lights, (const GLfloat*)light_target); glUniform3fv(light_diffuse_u, num_lights, (const GLfloat*)light_diffuse); glUniform3fv(light_ambient_u, num_lights, (const GLfloat*)light_ambient); glUniform3fv(light_specular_u, num_lights, (const GLfloat*)light_specular); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0, -1.0, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0, -1.0, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0, 1.0, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0, 1.0, 0.0f); glEnd(); glActiveTexture(GL_TEXTURE0 + 6 ); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0 + 5 ); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0 + 4 ); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0 + 3 ); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0 + 2 ); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0 + 1 ); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0 + 0 ); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glUseProgram(0); /* Render HDR to LDR buffer */ glBindFramebuffer(GL_FRAMEBUFFER, ldr_fbo); GLuint screen_tonemap_handle = shader_program_handle(PROGRAM_TONEMAP); glUseProgram(screen_tonemap_handle); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glActiveTexture(GL_TEXTURE0 + 0 ); glBindTexture(GL_TEXTURE_2D, hdr_texture); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_tonemap_handle, "hdr_texture"), 0); glUniform1f(glGetUniformLocation(screen_tonemap_handle, "exposure"), EXPOSURE); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0, -1.0, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0, -1.0, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0, 1.0, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0, 1.0, 0.0f); glEnd(); glActiveTexture(GL_TEXTURE0 + 0 ); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glUseProgram(0); /* Generate Mipmaps, adjust exposure */ unsigned char color[4] = {0,0,0,0}; int level = -1; int width = 0; int height = 0; glActiveTexture(GL_TEXTURE0 + 0 ); glBindTexture(GL_TEXTURE_2D, ldr_texture); glEnable(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D); do { level++; glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &height); if (level > 50) { error("Unable to find lowest mip level. Perhaps mipmaps were not generated"); } } while ((width > 1) || (height > 1)); glGetTexImage(GL_TEXTURE_2D, level, GL_RGBA, GL_UNSIGNED_BYTE, color); glActiveTexture(GL_TEXTURE0 + 0 ); glDisable(GL_TEXTURE_2D); float average = (float)(color[0] + color[1] + color[2]) / (3.0 * 255.0); EXPOSURE += (EXPOSURE_TARGET - average) * EXPOSURE_SPEED; /* Render final frame */ glBindFramebuffer(GL_FRAMEBUFFER, 0); GLuint screen_post_handle = shader_program_handle(PROGRAM_POST); glUseProgram(screen_post_handle); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glActiveTexture(GL_TEXTURE0 + 0 ); glBindTexture(GL_TEXTURE_2D, ldr_texture); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_post_handle, "diffuse_texture"), 0); glActiveTexture(GL_TEXTURE0 + 1 ); glBindTexture(GL_TEXTURE_2D, texture_handle(VIGNETTING)); glEnable(GL_TEXTURE_2D); glUniform1i(glGetUniformLocation(screen_post_handle, "vignetting_texture"), 1); glActiveTexture(GL_TEXTURE0 + 2 ); glBindTexture(GL_TEXTURE_3D, texture_handle(COLOR_CORRECTION)); glEnable(GL_TEXTURE_3D); glUniform1i(glGetUniformLocation(screen_post_handle, "lut"), 2); glUniform1i(glGetUniformLocation(screen_post_handle, "width"), graphics_viewport_width()); glUniform1i(glGetUniformLocation(screen_post_handle, "height"), graphics_viewport_height()); glUniform1i(glGetUniformLocation(screen_post_handle, "aa_type"), 1); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0, -1.0, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0, -1.0, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0, 1.0, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0, 1.0, 0.0f); glEnd(); glActiveTexture(GL_TEXTURE0 + 2 ); glDisable(GL_TEXTURE_3D); glActiveTexture(GL_TEXTURE0 + 1 ); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0 + 0 ); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glUseProgram(0); }
image* texture_get_image(texture* t) { int width, height, format; glBindTexture(GL_TEXTURE_2D, *t); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); if ((width == 0) || (height == 0)) { error("Texture has zero size width/height: (%i, %i)", width, height); } unsigned char* data = malloc(width * height * 4); if (format == GL_RGBA) { glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); } else if (format == GL_ALPHA16) { float* depth_data = malloc(sizeof(float) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_ALPHA, GL_FLOAT, depth_data); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { float depth = depth_data[(y*width) + x]; depth = pow(depth, 256.0); data[(y*4*width) + (x*4) + 0] = depth * 255; data[(y*4*width) + (x*4) + 1] = depth * 255; data[(y*4*width) + (x*4) + 2] = depth * 255; data[(y*4*width) + (x*4) + 3] = depth * 255; } free(depth_data); } else if (format == GL_RGBA32F) { float* pos_data = malloc(4 * sizeof(float) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, pos_data); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { data[(y*4*width) + (x*4) + 0] = clamp(pos_data[(y*4*width) + (x*4) + 0] * 255, 0, 255); data[(y*4*width) + (x*4) + 1] = clamp(pos_data[(y*4*width) + (x*4) + 1] * 255, 0, 255); data[(y*4*width) + (x*4) + 2] = clamp(pos_data[(y*4*width) + (x*4) + 2] * 255, 0, 255); data[(y*4*width) + (x*4) + 3] = clamp(pos_data[(y*4*width) + (x*4) + 3] * 255, 0, 255); } free(pos_data); } else if (format == GL_RGBA16F) { float* norm_data = malloc(4 * sizeof(float) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, norm_data); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { data[(y*4*width) + (x*4) + 0] = clamp(norm_data[(y*4*width) + (x*4) + 0] * 255, 0, 255); data[(y*4*width) + (x*4) + 1] = clamp(norm_data[(y*4*width) + (x*4) + 1] * 255, 0, 255); data[(y*4*width) + (x*4) + 2] = clamp(norm_data[(y*4*width) + (x*4) + 2] * 255, 0, 255); data[(y*4*width) + (x*4) + 3] = clamp(norm_data[(y*4*width) + (x*4) + 3] * 255, 0, 255); } free(norm_data); } else if (format == GL_DEPTH_COMPONENT) { unsigned int* depth_data = malloc(sizeof(unsigned int) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, depth_data); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { unsigned int depth = depth_data[(y*width) + x]; data[(y*4*width) + (x*4) + 0] = depth; data[(y*4*width) + (x*4) + 1] = depth; data[(y*4*width) + (x*4) + 2] = depth; data[(y*4*width) + (x*4) + 3] = depth; } free(depth_data); } else { error("Can't save that particular texture format to file."); } image* i = image_new(width, height, data); free(data); image_bgr_to_rgb(i); image_flip_vertical(i); return i; }
/** * gdk_cairo_draw_from_gl: * @cr: a cairo context * @window: The window we're rendering for (not necessarily into) * @source: The GL ID of the source buffer * @source_type: The type of the @source * @buffer_scale: The scale-factor that the @source buffer is allocated for * @x: The source x position in @source to start copying from in GL coordinates * @y: The source y position in @source to start copying from in GL coordinates * @width: The width of the region to draw * @height: The height of the region to draw * * This is the main way to draw GL content in GTK+. It takes a render buffer ID * (@source_type == #GL_RENDERBUFFER) or a texture id (@source_type == #GL_TEXTURE) * and draws it onto @cr with an OVER operation, respecting the current clip. * The top left corner of the rectangle specified by @x, @y, @width and @height * will be drawn at the current (0,0) position of the cairo_t. * * This will work for *all* cairo_t, as long as @window is realized, but the * fallback implementation that reads back the pixels from the buffer may be * used in the general case. In the case of direct drawing to a window with * no special effects applied to @cr it will however use a more efficient * approach. * * For #GL_RENDERBUFFER the code will always fall back to software for buffers * with alpha components, so make sure you use #GL_TEXTURE if using alpha. * * Calling this may change the current GL context. * * Since: 3.16 */ void gdk_cairo_draw_from_gl (cairo_t *cr, GdkWindow *window, int source, int source_type, int buffer_scale, int x, int y, int width, int height) { GdkGLContext *paint_context; cairo_surface_t *image; cairo_matrix_t matrix; int dx, dy, window_scale; gboolean trivial_transform; cairo_surface_t *group_target; GdkWindow *direct_window, *impl_window; guint framebuffer; int alpha_size = 0; cairo_region_t *clip_region; GdkGLContextPaintData *paint_data; impl_window = window->impl_window; window_scale = gdk_window_get_scale_factor (impl_window); paint_context = gdk_window_get_paint_gl_context (window, NULL); if (paint_context == NULL) { g_warning ("gdk_cairo_draw_gl_render_buffer failed - no paint context"); return; } clip_region = gdk_cairo_region_from_clip (cr); gdk_gl_context_make_current (paint_context); paint_data = gdk_gl_context_get_paint_data (paint_context); if (paint_data->tmp_framebuffer == 0) glGenFramebuffersEXT (1, &paint_data->tmp_framebuffer); if (source_type == GL_RENDERBUFFER) { glBindRenderbuffer (GL_RENDERBUFFER, source); glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_ALPHA_SIZE, &alpha_size); } else if (source_type == GL_TEXTURE) { glBindTexture (GL_TEXTURE_2D, source); glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size); } else { g_warning ("Unsupported gl source type %d\n", source_type); return; } group_target = cairo_get_group_target (cr); direct_window = cairo_surface_get_user_data (group_target, &direct_key); cairo_get_matrix (cr, &matrix); dx = matrix.x0; dy = matrix.y0; /* Trivial == integer-only translation */ trivial_transform = (double)dx == matrix.x0 && (double)dy == matrix.y0 && matrix.xx == 1.0 && matrix.xy == 0.0 && matrix.yx == 0.0 && matrix.yy == 1.0; /* For direct paint of non-alpha renderbuffer, we can just do a bitblit */ if ((_gdk_gl_flags & GDK_GL_SOFTWARE_DRAW_GL) == 0 && source_type == GL_RENDERBUFFER && alpha_size == 0 && direct_window != NULL && direct_window->current_paint.use_gl && trivial_transform && clip_region != NULL) { int unscaled_window_height; int i; /* Create a framebuffer with the source renderbuffer and make it the current target for reads */ framebuffer = paint_data->tmp_framebuffer; glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, framebuffer); glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, source); glBindFramebufferEXT (GL_DRAW_FRAMEBUFFER_EXT, 0); /* Translate to impl coords */ cairo_region_translate (clip_region, dx, dy); glEnable (GL_SCISSOR_TEST); gdk_window_get_unscaled_size (impl_window, NULL, &unscaled_window_height); glDrawBuffer (GL_BACK); #define FLIP_Y(_y) (unscaled_window_height - (_y)) for (i = 0; i < cairo_region_num_rectangles (clip_region); i++) { cairo_rectangle_int_t clip_rect, dest; cairo_region_get_rectangle (clip_region, i, &clip_rect); clip_rect.x *= window_scale; clip_rect.y *= window_scale; clip_rect.width *= window_scale; clip_rect.height *= window_scale; glScissor (clip_rect.x, FLIP_Y (clip_rect.y + clip_rect.height), clip_rect.width, clip_rect.height); dest.x = dx * window_scale; dest.y = dy * window_scale; dest.width = width * window_scale / buffer_scale; dest.height = height * window_scale / buffer_scale; if (gdk_rectangle_intersect (&clip_rect, &dest, &dest)) { int clipped_src_x = x + (dest.x - dx * window_scale); int clipped_src_y = y + (height - dest.height - (dest.y - dy * window_scale)); glBlitFramebufferEXT(clipped_src_x, clipped_src_y, (clipped_src_x + dest.width), (clipped_src_y + dest.height), dest.x, FLIP_Y(dest.y + dest.height), dest.x + dest.width, FLIP_Y(dest.y), GL_COLOR_BUFFER_BIT, GL_NEAREST); if (impl_window->current_paint.flushed_region) { cairo_rectangle_int_t flushed_rect; flushed_rect.x = dest.x / window_scale; flushed_rect.y = dest.y / window_scale; flushed_rect.width = (dest.x + dest.width + window_scale - 1) / window_scale - flushed_rect.x; flushed_rect.height = (dest.y + dest.height + window_scale - 1) / window_scale - flushed_rect.y; cairo_region_union_rectangle (impl_window->current_paint.flushed_region, &flushed_rect); cairo_region_subtract_rectangle (impl_window->current_paint.need_blend_region, &flushed_rect); } } } glDisable (GL_SCISSOR_TEST); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); #undef FLIP_Y } /* For direct paint of alpha or non-alpha textures we can use texturing */ else if ((_gdk_gl_flags & GDK_GL_SOFTWARE_DRAW_GL) == 0 && source_type == GL_TEXTURE && direct_window != NULL && direct_window->current_paint.use_gl && trivial_transform && clip_region != NULL) { int unscaled_window_height; GLint texture_width; GLint texture_height; int i, n_rects, n_quads; GdkTexturedQuad *quads; cairo_rectangle_int_t clip_rect; /* Translate to impl coords */ cairo_region_translate (clip_region, dx, dy); if (alpha_size != 0) { cairo_region_t *opaque_region, *blend_region; opaque_region = cairo_region_copy (clip_region); cairo_region_subtract (opaque_region, impl_window->current_paint.flushed_region); cairo_region_subtract (opaque_region, impl_window->current_paint.need_blend_region); if (!cairo_region_is_empty (opaque_region)) gdk_gl_texture_from_surface (impl_window->current_paint.surface, opaque_region); blend_region = cairo_region_copy (clip_region); cairo_region_intersect (blend_region, impl_window->current_paint.need_blend_region); glEnable (GL_BLEND); if (!cairo_region_is_empty (blend_region)) gdk_gl_texture_from_surface (impl_window->current_paint.surface, blend_region); cairo_region_destroy (opaque_region); cairo_region_destroy (blend_region); } glBindTexture (GL_TEXTURE_2D, source); glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texture_width); glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texture_height); 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); glEnable (GL_SCISSOR_TEST); gdk_window_get_unscaled_size (impl_window, NULL, &unscaled_window_height); #define FLIP_Y(_y) (unscaled_window_height - (_y)) cairo_region_get_extents (clip_region, &clip_rect); glScissor (clip_rect.x * window_scale, FLIP_Y ((clip_rect.y + clip_rect.height) * window_scale), clip_rect.width * window_scale, clip_rect.height * window_scale); n_quads = 0; n_rects = cairo_region_num_rectangles (clip_region); quads = g_new (GdkTexturedQuad, n_rects); for (i = 0; i < n_rects; i++) { cairo_rectangle_int_t dest; cairo_region_get_rectangle (clip_region, i, &clip_rect); clip_rect.x *= window_scale; clip_rect.y *= window_scale; clip_rect.width *= window_scale; clip_rect.height *= window_scale; dest.x = dx * window_scale; dest.y = dy * window_scale; dest.width = width * window_scale / buffer_scale; dest.height = height * window_scale / buffer_scale; if (gdk_rectangle_intersect (&clip_rect, &dest, &dest)) { int clipped_src_x = x + (dest.x - dx * window_scale); int clipped_src_y = y + (height - dest.height - (dest.y - dy * window_scale)); GdkTexturedQuad quad = { dest.x, FLIP_Y(dest.y), dest.x + dest.width, FLIP_Y(dest.y + dest.height), clipped_src_x / (float)texture_width, (clipped_src_y + dest.height) / (float)texture_height, (clipped_src_x + dest.width) / (float)texture_width, clipped_src_y / (float)texture_height, }; quads[n_quads++] = quad; if (impl_window->current_paint.flushed_region) { cairo_rectangle_int_t flushed_rect; flushed_rect.x = dest.x / window_scale; flushed_rect.y = dest.y / window_scale; flushed_rect.width = (dest.x + dest.width + window_scale - 1) / window_scale - flushed_rect.x; flushed_rect.height = (dest.y + dest.height + window_scale - 1) / window_scale - flushed_rect.y; cairo_region_union_rectangle (impl_window->current_paint.flushed_region, &flushed_rect); cairo_region_subtract_rectangle (impl_window->current_paint.need_blend_region, &flushed_rect); } } } if (n_quads > 0) gdk_gl_texture_quads (paint_context, GL_TEXTURE_2D, n_quads, quads); g_free (quads); if (alpha_size != 0) glDisable (GL_BLEND); #undef FLIP_Y } else { /* Software fallback */ /* TODO: avoid reading back non-required data due to dest clip */ image = cairo_surface_create_similar_image (cairo_get_target (cr), (alpha_size == 0) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32, width, height); cairo_surface_set_device_scale (image, buffer_scale, buffer_scale); framebuffer = paint_data->tmp_framebuffer; glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, framebuffer); if (source_type == GL_RENDERBUFFER) { /* Create a framebuffer with the source renderbuffer and make it the current target for reads */ glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, source); } else { glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, source, 0); } glPixelStorei (GL_PACK_ALIGNMENT, 4); glPixelStorei (GL_PACK_ROW_LENGTH, cairo_image_surface_get_stride (image) / 4); glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, cairo_image_surface_get_data (image)); glPixelStorei (GL_PACK_ROW_LENGTH, 0); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); cairo_surface_mark_dirty (image); /* Invert due to opengl having different origin */ cairo_scale (cr, 1, -1); cairo_translate (cr, 0, -height / buffer_scale); cairo_set_source_surface (cr, image, 0, 0); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_paint (cr); cairo_surface_destroy (image); } if (clip_region) cairo_region_destroy (clip_region); }
void DisplayScene() { // kolor tła - zawartość bufora koloru glClearColor(1.0, 1.0, 1.0, 1.0); // czyszczenie bufora koloru glClear(GL_COLOR_BUFFER_BIT); // wybór macierzy modelowania glMatrixMode(GL_MODELVIEW); // macierz modelowania = macierz jednostkowa glLoadIdentity(); // przesunięcie układu współrzędnych obiektów do środka bryły odcinania glTranslatef(0.0, -0.5, -(near + far) / 2); // przesunięcie obiektu z teksturą do góry okna glTranslatef(0.0, 0.5, 0.0); // włączenie teksturowania dwuwymiarowego glEnable(GL_TEXTURE_2D); // ustawienie parametów środowiska tekstur glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // dowiązanie stanu tekstury glBindTexture(GL_TEXTURE_2D, texture); // filtr powiàkszający glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // filtr pomniejszający glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // narysowanie kwadratu z teksturą glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2f(-1.5, -1.5); glTexCoord2f(0.0, 1.0); glVertex2f(-1.5, 1.5); glTexCoord2f(1.0, 1.0); glVertex2f(1.5, 1.5); glTexCoord2f(1.0, 0.0); glVertex2f(1.5, -1.5); glEnd(); // wyłączenie teksturowania dwuwymiarowego glDisable(GL_TEXTURE_2D); // wyświetlenie wybranych informacji char string[200]; GLint var; glColor3fv(Black); // informacja czy tekstura jest skompresowana glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &var); if (var == GL_FALSE) sprintf(string, "GL_TEXTURE_COMPRESSED = GL_FALSE"); else sprintf(string, "GL_TEXTURE_COMPRESSED = GL_TRUE"); DrawString(2, 2, string); // rozmiar danych tekstury glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &var); sprintf(string, "GL_TEXTURE_COMPRESSED_IMAGE_SIZE = %i", var); DrawString(2, 16, string); // wewnętrzny format tekstury glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &var); switch (var) { // formaty rozszerzenia EXT_texture_compression_s3tc case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_COMPRESSED_RGB_S3TC_DXT1_EXT"); break; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"); break; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"); break; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"); break; // formaty rozszerzenia 3DFX_texture_compression_FXT1 case GL_COMPRESSED_RGB_FXT1_3DFX: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_COMPRESSED_RGB_FXT1_3DFX"); break; case GL_COMPRESSED_RGBA_FXT1_3DFX: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_COMPRESSED_RGBA_FXT1_3DFX"); break; // format rozszerzenia ATI_texture_compression_3dc (nie występuje w pliku glext.h) case 0x8837: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_COMPRESSED_RGB_3DC_ATI"); break; // wybrane formaty nieskompresowane case GL_RED: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_RED"); break; case GL_GREEN: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_GREEN"); break; case GL_BLUE: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_BLUE"); break; case GL_ALPHA: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_ALPHA"); break; case GL_RGB: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_RGB"); break; case GL_RGBA: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_RGBA"); break; case GL_LUMINANCE: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_LUMINANCE"); break; case GL_LUMINANCE_ALPHA: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = GL_LUMINANCE_ALPHA"); break; // pozostałe formaty default: sprintf(string, "GL_TEXTURE_INTERNAL_FORMAT = nieznany"); break; } DrawString(2, 30, string); // informacja o wskazówkach do kompresji tekstur glGetIntegerv(GL_TEXTURE_COMPRESSION_HINT, &var); switch (var) { case GL_FASTEST: sprintf(string, "GL_TEXTURE_COMPRESSION_HINT = GL_FASTEST"); break; case GL_DONT_CARE: sprintf(string, "GL_TEXTURE_COMPRESSION_HINT = GL_DONT_CARE"); break; case GL_NICEST: sprintf(string, "GL_TEXTURE_COMPRESSION_HINT = GL_NICEST"); break; } DrawString(2, 44, string); // ilość obsługiwanych formatów kompresji tekstur glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &var); sprintf(string, "GL_NUM_COMPRESSED_TEXTURE_FORMATS = %i", var); DrawString(650, 14 * (var - 14), string); // wykaz obsługiwanych formatów kompresji tekstur GLint formats[256]; glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); for (int i = 0; i < var; i++) { switch (formats[i]) { // formaty rozszerzenia EXT_texture_compression_s3tc case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: sprintf(string, "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"); break; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: sprintf(string, "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"); break; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: sprintf(string, "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"); break; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: sprintf(string, "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"); break; // formaty rozszerzenia 3DFX_texture_compression_FXT1 case GL_COMPRESSED_RGB_FXT1_3DFX: sprintf(string, "GL_COMPRESSED_RGB_FXT1_3DFX"); break; case GL_COMPRESSED_RGBA_FXT1_3DFX: sprintf(string, "GL_COMPRESSED_RGBA_FXT1_3DFX"); break; // format rozszerzenia ATI_texture_compression_3dc // (nie występuje w pliku glext.h) case 0x8837: sprintf(string, "GL_COMPRESSED_RGB_3DC_ATI"); break; // pozostrałe formaty default: sprintf(string, "Format nieznany (0x%X)", formats[i]); break; } if (i < 42) DrawString(2, 70 + 14 * i, string); else DrawString(650, -56 + 14 * i, string); } // skierowanie poleceń do wykonania glFlush(); // zamiana buforów koloru glutSwapBuffers(); }
/** * Creates a texture for the given text using the given font object. * The caller has to free the memory for the TextureSpec object and the * pData in the TextureSpec object. */ std::pair<CLTextTextureSpec*, GLubyte*> CQFontRenderer::getTexture(QFont& font, const std::string& text, double zoomFactor) { CLTextTextureSpec* pSpec = NULL; // find out what size the text will have font.setStyleStrategy(QFont::ForceOutline); QFontMetrics fontMetrics(font); std::pair<double, double> size = this->getTextureSize(font, text); //std::cout << "texture size: " << size.first << "," << size.second << std::endl; // make the size a power of 2 unsigned int exponentWidth = (unsigned int)ceil(log(size.first /** zoomFactor*/ + 2) / log(2.0)); unsigned int exponentHeight = (unsigned int)ceil(log(size.second /** zoomFactor*/ + 2) / log(2.0)); unsigned int width = 1 << exponentWidth; unsigned int height = 1 << exponentHeight; // draw the text somewhere with white stroke on black background QImage image(width, height, QImage::Format_RGB32); QPainter painter(&image); painter.setBackground(Qt::black); painter.setPen(QPen(QColor(255, 255, 255, 255), 0.25, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin)); painter.setBrush(Qt::NoBrush); painter.setFont(font); painter.eraseRect(0, 0, width, height); // move over by 1,1 to get a small edge around the text painter.translate(1.0, 1.0); // we scale after the erase so that we don't have to divide the width and // the height //painter.scale(zoomFactor, zoomFactor); painter.drawText(0.0, fontMetrics.ascent() + 1, text.c_str()); painter.end(); // convert the image to an OpenGL texture image = QGLWidget::convertToGLFormat(image); // create the texture spec pSpec = new CLTextTextureSpec(); pSpec->mTextureWidth = width; pSpec->mTextureHeight = height; pSpec->mTextWidth = size.first; pSpec->mTextHeight = size.second; pSpec->mScale = zoomFactor; pSpec->mMaxScale = -1.0; pSpec->mNumComponents = 1; pSpec->mTextureName = 0; GLint w = 0; GLenum format = GL_ALPHA; glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); while (w == 0 && width > 1 && height > 1) { // divide the size by two in each direction width = width >> 1; height = height >> 1; glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); } GLubyte* textureData = NULL; if (w != 0) { if (w != pSpec->mTextureWidth) { pSpec->mTextureWidth = width; pSpec->mTextureHeight = height; } textureData = new GLubyte[width * height]; pSpec->mAscent = (double)fontMetrics.ascent(); unsigned int i, iMax = width * height; for (i = 0; i < iMax; ++i) { textureData[i] = image.bits()[4 * i]; } } return std::pair<CLTextTextureSpec*, GLubyte*>(pSpec, textureData); }
int hrCache::getCompressedImageSize() const { GLint param = 0; glGetTexLevelParameteriv(target, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, ¶m); return param; }
/* Readfile uses imageio to read in an image, and binds it to an OpenGL * texture name. Requires OpenGL 2.0 or better. * * filename: name of file to load * * texName: A pointer to where the OpenGL texture name should be stored. * (Remember that the "texture name" is really just some unsigned int). * * returns: aspect ratio of the image in the file. */ float readfile(char *filename, GLuint *texName, GLuint *numTiles) { static int verbose=1; // change this to 0 to print out less info /* Try to load the image. */ imageio_info iioinfo; iioinfo.filename = filename; iioinfo.type = CharPixel; iioinfo.map = "RGBA"; iioinfo.colorspace = sRGBColorspace; char *image = (char*) imagein(&iioinfo); if(image == NULL) { fprintf(stderr, "\n%s: Unable to read image.\n", filename); return -1; } /* "image" is a 1D array of characters (unsigned bytes) with four * bytes for each pixel (red, green, blue, alpha). The data in "image" * is in row major order. The first 4 bytes are the color information * for the lowest left pixel in the texture. */ int width = (int)iioinfo.width; int height = (int)iioinfo.height; float original_aspectRatio = (float)width/height; if(verbose) printf("%s: Finished reading, dimensions are %dx%d\n", filename, width, height); /* OpenGL only supports textures if they are small enough. If * the texture is too large, we need to split it into smaller * textures and render each texture on its own * quad. Typically, the limit is 4096 pixels in each * dimension. This code will always split the image vertically * in half...and then decide how many tiles are necessary * horizontally. This allows for long horizontal panoramas but * not long vertical panoramas. */ /* Since we display image as being two tiles tall, make sure * image isn't too tall. */ if(height > 4096*2) { printf("Source image must <= 8192 pixels tall."); exit(1); } int subimgH = height/2; // height of a the tiles int workingWidth = width; *numTiles = 1; // number of tiles in horizontal direction /* Calculate number of tiles horizontally we need. */ while(workingWidth > 4096) { /* If image is too wide, split the width of the tile * in half---doubling the number of tiles in the * horizontal direction */ *numTiles = *numTiles * 2; workingWidth = workingWidth / 2; } int subimgW = workingWidth; if(*numTiles > MAX_TILES/2.0) { printf("Too many tiles"); exit(1); } glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, subimgW, subimgH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); int tmp; glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tmp); if(tmp == 0) { fprintf(stderr, "%s: File is too large (%d x %d). I can't load it!\n", filename, subimgW, subimgH); free(image); exit(1); } /* Generate all of the textures that we need. */ glGenTextures(*numTiles*2, texName); for(GLuint curTile=0; curTile < *numTiles*2; curTile = curTile+2) { /* Prepare to copy the data from the array into the * texture, tell OpenGL to skip pixels appropriately * so that each tile gets the right part of the * image. */ glPixelStorei(GL_UNPACK_ROW_LENGTH, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, curTile/2.0*subimgW); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glBindTexture(GL_TEXTURE_2D, texName[curTile]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, subimgW, subimgH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); glPixelStorei( GL_UNPACK_SKIP_PIXELS, curTile/2.0*subimgW ); glPixelStorei( GL_UNPACK_SKIP_ROWS, subimgH); glBindTexture(GL_TEXTURE_2D, texName[curTile+1]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, subimgW, subimgH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); } free(image); return original_aspectRatio; }
int __glXDispSwap_GetTexImage(__GLXclientState * cl, GLbyte * pc) { GLint level, compsize; GLenum format, type, target; GLboolean swapBytes; __GLX_DECLARE_SWAP_VARIABLES; __GLXcontext *cx; ClientPtr client = cl->client; int error; char *answer, answerBuffer[200]; GLint width = 0, height = 0, depth = 1; xGLXSingleReply reply = { 0, }; REQUEST_FIXED_SIZE(xGLXSingleReq, 20); __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; } pc += __GLX_SINGLE_HDR_SIZE; __GLX_SWAP_INT(pc + 0); __GLX_SWAP_INT(pc + 4); __GLX_SWAP_INT(pc + 8); __GLX_SWAP_INT(pc + 12); level = *(GLint *) (pc + 4); format = *(GLenum *) (pc + 8); type = *(GLenum *) (pc + 12); target = *(GLenum *) (pc + 0); swapBytes = *(GLboolean *) (pc + 16); glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height); if (target == GL_TEXTURE_3D) { glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth); } /* * The three queries above might fail if we're in a state where queries * are illegal, but then width, height, and depth would still be zero anyway. */ compsize = __glGetTexImage_size(target, level, format, type, width, height, depth); if (compsize < 0) return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); __glXClearErrorOccured(); glGetTexImage(*(GLenum *) (pc + 0), *(GLint *) (pc + 4), *(GLenum *) (pc + 8), *(GLenum *) (pc + 12), answer); if (__glXErrorOccured()) { __GLX_BEGIN_REPLY(0); __GLX_SWAP_REPLY_HEADER(); __GLX_SEND_HEADER(); } else { __GLX_BEGIN_REPLY(compsize); __GLX_SWAP_REPLY_HEADER(); __GLX_SWAP_INT(&width); __GLX_SWAP_INT(&height); __GLX_SWAP_INT(&depth); ((xGLXGetTexImageReply *) &reply)->width = width; ((xGLXGetTexImageReply *) &reply)->height = height; ((xGLXGetTexImageReply *) &reply)->depth = depth; __GLX_SEND_HEADER(); __GLX_SEND_VOID_ARRAY(compsize); } return Success; }
//-------------------------------------------------------------------------- /// \brief This function loads the specified image file and returns the /// openGL texture object for it. Only tga, bmp and pcx images are /// supported. /// \param filename - the image file to use for the texture /// \return compressed - if true DXT compression will be used. /// unsigned int LoadTexture(const char* filename,bool compressed, bool makeMips, int *outWidth, int *outHeight) { #ifndef _WIN32 // #if MACINTOSH // This is a HACK for the Mac version which has some directory trouble. // This hardcoded path should be fixed soon to something more flexible. char buffer[1000]; const char *currentDirectory = getcwd( buffer, 1000); // // printf("Texture Directorily: %s\n",currentDirectory); // // char *strstr = strFind(currentDirectory,"build"); // const char *substring = strstr(currentDirectory, "build"); // printf("substring: %s\n", substring); // chdir(currentDirectory); // chdir("/Users/puck 1/Desktop/trunk/BrainMobile/runtime"); // chdir("/Users/SPL/Desktop/DWDT/dwd/BrainMobile/runtime"); chdir("/Applications/DWD/dwd/NeuroGrocer/runtime"); #endif // check to see if file is already loaded. std::map<std::string,TexRef>::iterator it = g_Textures.find(filename); if ( it!=g_Textures.end()) { it->second.ref++; return it->second.idx; } // if not, try to load the file. unsigned int w=0,h=0,bpp=0; unsigned char* pixels=0; int len = static_cast<int>(strlen(filename)); // load a bmp if( (filename[len-3] == 'b' || filename[len-3] == 'B') && (filename[len-2] == 'm' || filename[len-2] == 'M') && (filename[len-1] == 'p' || filename[len-1] == 'P') ) { if(!LoadBmpImage(filename,&pixels,&w,&h,&bpp)) return 0; } else // load a pcx if( (filename[len-3] == 'p' || filename[len-3] == 'P') && (filename[len-2] == 'c' || filename[len-2] == 'C') && (filename[len-1] == 'x' || filename[len-1] == 'X') ) { if(!LoadPcxImage(filename,&pixels,&w,&h,&bpp)) return 0; } else // load a tga if( (filename[len-3] == 't' || filename[len-3] == 'T') && (filename[len-2] == 'g' || filename[len-2] == 'G') && (filename[len-1] == 'a' || filename[len-1] == 'A') ) { if(!LoadTgaImage(filename,&pixels,&w,&h,&bpp)) return 0; } else { std::cerr << "Unsupported image format\n"; return 0; } // generat the correct texture type for the image unsigned int tex_object; switch(bpp) { case 1: tex_object = MakeGlTexture(GL_ALPHA,pixels,w,h,compressed, makeMips); break; case 2: break; case 3: tex_object = MakeGlTexture(GL_RGB,pixels,w,h,compressed, makeMips); break; case 4: tex_object = MakeGlTexture(GL_RGBA,pixels,w,h,compressed, makeMips); break; default: break; } int data_size=0; if(compressed) { glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,&data_size); } else { data_size = bpp*w*h; } // delete the pixel data because we no longer need it free(pixels); // insert the texture into a map to keep track of it g_Textures.insert( std::make_pair( std::string(filename), TexRef(tex_object,data_size) ) ); if (outWidth != NULL) *outWidth = w; if (outHeight != NULL) *outHeight = h; // return GL texture object return tex_object; }
void DispatchMipmapVoxelGridComputeShader::call() { p_computeShader->useProgram(); // bind to access image size glBindTexture( GL_TEXTURE_2D, p_voxelGrid->handle ); int current_mipmap_res; double totalExecutionTime = 0.0; for ( int i = 1; i <= p_voxelGrid->numMipmaps; i++ ) { // bind voxel grid mipmap base level glBindImageTexture( 0, // texture image unit p_voxelGrid->handle, // texture name i-1, // mipmap level GL_FALSE, // layered 0, // layer GL_READ_ONLY, // only read access GL_R32UI); // 1 channel 32 bit unsigned int // bind voxel grid mipmap target level glBindImageTexture( 1, // texture image unit p_voxelGrid->handle, // texture name i, // mipmap level GL_FALSE, // layered 0, // layer GL_WRITE_ONLY, // only write access GL_R32UI); // 1 channel 32 bit unsigned int glGetTexLevelParameteriv( GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, ¤t_mipmap_res ); // DEBUGLOG->log( "current mipmap target level size : ", current_mipmap_res ); // make sure mipmap is written before proceeding glMemoryBarrier( GL_SHADER_IMAGE_ACCESS_BARRIER_BIT ); // set suitable amount of work groups m_num_groups_x = current_mipmap_res / p_computeShader->getLocalGroupSizeX() + ( ( current_mipmap_res % p_computeShader->getLocalGroupSizeX() == 0 ) ? 0 : 1 ); m_num_groups_y = current_mipmap_res / p_computeShader->getLocalGroupSizeY() + ( ( current_mipmap_res % p_computeShader->getLocalGroupSizeY() == 0 ) ? 0 : 1 ); m_num_groups_z = 1; // dispatch compute shader DispatchComputeShaderListener::call(); // add this execution time to the total execution time if ( m_queryTime ) { totalExecutionTime += m_executionTime; } } if ( m_queryTime ) { m_executionTime = totalExecutionTime; } // arbitrary barrier glMemoryBarrier( GL_ALL_BARRIER_BITS ); // unbind textures glBindTexture( GL_TEXTURE_2D, 0); glBindImageTexture(0, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI ); glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI ); }
static void Init( void ) { GLfloat maxBias; if (!glutExtensionSupported("GL_EXT_texture_lod_bias")) { printf("Sorry, GL_EXT_texture_lod_bias not supported by this renderer.\n"); exit(1); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &TexObj); glBindTexture(GL_TEXTURE_2D, TexObj); if (glutExtensionSupported("GL_SGIS_generate_mipmap")) { /* test auto mipmap generation */ GLint width, height, i; GLenum format; GLubyte *image = LoadRGBImage(TEXTURE_FILE, &width, &height, &format); if (!image) { printf("Error: could not load texture image %s\n", TEXTURE_FILE); exit(1); } /* resize to 256 x 256 */ if (width != 256 || height != 256) { GLubyte *newImage = malloc(256 * 256 * 4); gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image, 256, 256, GL_UNSIGNED_BYTE, newImage); free(image); image = newImage; } printf("Using GL_SGIS_generate_mipmap\n"); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, format, 256, 256, 0, format, GL_UNSIGNED_BYTE, image); free(image); /* make sure mipmap was really generated correctly */ width = height = 256; for (i = 0; i < 9; i++) { GLint w, h; glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h); printf("Level %d size: %d x %d\n", i, w, h); assert(w == width); assert(h == height); width /= 2; height /= 2; } } else if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) { printf("Error: could not load texture image %s\n", TEXTURE_FILE); exit(1); } /* mipmapping required for this extension */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &maxBias); printf("LOD bias range: [%g, %g]\n", -maxBias, maxBias); BiasMin = -100 * maxBias; BiasMax = 100 * maxBias; /* Since we have (about) 8 mipmap levels, no need to bias beyond * the range [-1, +8]. */ if (BiasMin < -100) BiasMin = -100; if (BiasMax > 800) BiasMax = 800; }
// NOTE: Always saves in TGA format void DGTexture::saveToFile(const char* fileName){ if (_isLoaded) { FILE* fh; char fullFileName[DGMaxFileLength - 4]; strncpy(fullFileName, fileName, DGMaxFileLength - 4); if (_compressionLevel) { TEXMainHeader header; TEXSubHeader subheader; GLint internalformat, size; // TODO: Must check that the texture is RGB // NOTE: Let's try to support alpha channel for these textures glBindTexture(GL_TEXTURE_2D, _ident); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &size); _bitmap = (GLubyte*)malloc(size * sizeof(GLubyte)); glGetCompressedTexImage(GL_TEXTURE_2D, 0, _bitmap); header.compressionLevel = 1; strcpy(header.name, this->name()); // This is the object name header.width = (short)_width; header.height = (short)_height; header.numTextures = 0; subheader.cubePosition = 0; subheader.depth = (short)_depth; subheader.size = (int)size; subheader.format = (int)internalformat; strncat(fullFileName, ".tex", 4); fh = fopen(fullFileName, "wb"); fwrite(&TEXIdent, 1, 8, fh); fwrite(&header, 1, sizeof(header), fh); fwrite(&subheader, 1, sizeof(subheader), fh); fwrite(_bitmap, 1, sizeof(GLubyte) * size, fh); free(_bitmap); fclose(fh); } else { unsigned char cGarbage = 0, type, mode; short int iGarbage = 0; int i; GLint size; strncat(fullFileName, ".tga", 4); fh = fopen(fullFileName, "wb"); if (fh == NULL) return; glBindTexture(GL_TEXTURE_2D, _ident); // We do this in case the texture wasn't loaded glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &_width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &_height); //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH, &texture_data->depth); _depth = 24; // Hardcoded to 24 bits mode = _depth / 8; if ((_depth == 24) || (_depth == 32)) type = 2; else type = 3; fwrite(&cGarbage, sizeof(unsigned char), 1, fh); fwrite(&cGarbage, sizeof(unsigned char), 1, fh); fwrite(&type, sizeof(unsigned char), 1, fh); fwrite(&iGarbage, sizeof(short int), 1, fh); fwrite(&iGarbage, sizeof(short int), 1, fh); fwrite(&cGarbage, sizeof(unsigned char), 1, fh); fwrite(&iGarbage, sizeof(short int), 1, fh); fwrite(&iGarbage, sizeof(short int), 1, fh); fwrite(&_width, sizeof(short int), 1, fh); fwrite(&_height, sizeof(short int), 1, fh); fwrite(&_depth, sizeof(unsigned char), 1, fh); fwrite(&cGarbage, sizeof(unsigned char), 1, fh); _depth = mode; size = _width * _height * _depth; _bitmap = (GLubyte*)malloc(size * sizeof(GLubyte)); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, _bitmap); if (mode >= 3) { unsigned char aux; for (i = 0; i < _width * _height * mode ; i+= mode) { aux = _bitmap[i]; _bitmap[i] = _bitmap[i + 2]; _bitmap[i + 2] = aux; } } fwrite(_bitmap, 1, sizeof(GLubyte) * size, fh); fclose(fh); free(_bitmap); } } }
PIGLIT_GL_TEST_CONFIG_END static bool test_getsubimage(GLenum target, GLsizei width, GLsizei height, GLsizei numSlices, GLenum intFormat) { const GLint bufSize = width * height * 4 * sizeof(GLubyte); GLubyte *texData; GLubyte *refData = malloc(6 * bufSize); /* 6 for cubemaps */ GLubyte *testData = malloc(6 * bufSize); /* 6 for cubemaps */ GLuint tex; int i, slice, compressedSize, compSize; int blockWidth, blockHeight, blockSize; bool pass = true; const int level = 0; int x0, y0, x1, y1, w0, h0, w1, h1; printf("Testing %s %s %d x %d\n", piglit_get_gl_enum_name(target), piglit_get_gl_enum_name(intFormat), width, height); /* For all S3TC formats */ blockWidth = blockHeight = 4; if (intFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || intFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { blockSize = 8; } else { assert(intFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT || intFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); blockSize = 16; } /* Size must be multiple of block dims */ assert(width % blockWidth == 0); assert(height % blockHeight == 0); compressedSize = (width / blockWidth) * (height / blockHeight) * blockSize; if (0) { printf("byte per block row: %d\n", (width / blockWidth) * blockSize); printf("compressed image size = %d\n", compressedSize); } /* initial texture data */ texData = malloc(compressedSize); for (i = 0; i < compressedSize; i++) { texData[i] = (i+10) & 0xff; } glGenTextures(1, &tex); glBindTexture(target, tex); /* Define texture image */ if (target == GL_TEXTURE_CUBE_MAP) { for (slice = 0; slice < 6; slice++) { glCompressedTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice, level, intFormat, width, height, 0, compressedSize, texData); } glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize); assert(numSlices == 6); } else if (target == GL_TEXTURE_CUBE_MAP_ARRAY) { assert(numSlices % 6 == 0); glCompressedTexImage3D(target, level, intFormat, width, height, numSlices, 0, compressedSize * numSlices, NULL); for (slice = 0; slice < numSlices; slice++) { glCompressedTexSubImage3D(target, level, 0, 0, slice, width, height, 1, intFormat, compressedSize, texData); } glGetTexLevelParameteriv(target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize); compSize /= numSlices; } else if (target == GL_TEXTURE_2D_ARRAY) { glCompressedTexImage3D(target, level, intFormat, width, height, numSlices, 0, compressedSize * numSlices, NULL); for (slice = 0; slice < numSlices; slice++) { glCompressedTexSubImage3D(target, level, 0, 0, slice, width, height, 1, intFormat, compressedSize, texData); } glGetTexLevelParameteriv(target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize); compSize /= numSlices; } else { assert(target == GL_TEXTURE_2D); glCompressedTexImage2D(target, level, intFormat, width, height, 0, compressedSize, texData); glGetTexLevelParameteriv(target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize); assert(numSlices == 1); } assert(compSize == compressedSize); /* Should be no GL errors */ if (!piglit_check_gl_error(GL_NO_ERROR)) { pass = false; } refData = calloc(1, numSlices * compressedSize); testData = calloc(1, numSlices * compressedSize); /* compute pos/size of sub-regions */ x0 = 0; y0 = 0; x1 = width / 4; /* quarter width */ y1 = height / 2; /* half height */ /* Position must be multiple of block dims */ assert(x1 % blockWidth == 0); assert(y1 % blockHeight == 0); w0 = x1 - x0; w1 = width - x1; h0 = y1 - y0; h1 = height - y1; /* Sizes must be multiple of block dims */ assert(w0 % blockWidth == 0); assert(w1 % blockWidth == 0); assert(h0 % blockHeight == 0); assert(h1 % blockHeight == 0); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, width); glPixelStorei(GL_PACK_IMAGE_HEIGHT, height); glPixelStorei(GL_PACK_COMPRESSED_BLOCK_WIDTH, blockWidth); glPixelStorei(GL_PACK_COMPRESSED_BLOCK_HEIGHT, blockHeight); glPixelStorei(GL_PACK_COMPRESSED_BLOCK_SIZE, blockSize); /* Should be no GL errors */ if (!piglit_check_gl_error(GL_NO_ERROR)) { pass = false; } /* * Get whole compressed image (the reference) */ if (target == GL_TEXTURE_CUBE_MAP) { for (slice = 0; slice < 6; slice++) { glGetCompressedTexImage( GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice, level, refData + slice * compressedSize); } } else { glGetCompressedTexImage(target, level, refData); } if (!piglit_check_gl_error(GL_NO_ERROR)) { pass = false; } /* * Now get four sub-regions which should be equivalent * to the whole reference image. */ /* lower-left */ glPixelStorei(GL_PACK_SKIP_PIXELS, x0); glPixelStorei(GL_PACK_SKIP_ROWS, y0); glGetCompressedTextureSubImage(tex, level, x0, y0, 0, w0, h0, numSlices, numSlices * compressedSize, testData); /* lower-right */ glPixelStorei(GL_PACK_SKIP_PIXELS, x1); glPixelStorei(GL_PACK_SKIP_ROWS, y0); glGetCompressedTextureSubImage(tex, level, x1, y0, 0, w1, h0, numSlices, numSlices * compressedSize, testData); /* upper-left */ glPixelStorei(GL_PACK_SKIP_PIXELS, x0); glPixelStorei(GL_PACK_SKIP_ROWS, y1); glGetCompressedTextureSubImage(tex, level, x0, y1, 0, w0, h1, numSlices, numSlices * compressedSize, testData); /* upper-right */ glPixelStorei(GL_PACK_SKIP_PIXELS, x1); glPixelStorei(GL_PACK_SKIP_ROWS, y1); glGetCompressedTextureSubImage(tex, level, x1, y1, 0, w1, h1, numSlices, numSlices * compressedSize, testData); /* defaults */ glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); /* Should be no GL errors */ if (!piglit_check_gl_error(GL_NO_ERROR)) { pass = false; } /* now compare the images */ for (slice = 0; slice < numSlices; slice++) { int sliceStart = slice * compressedSize; if (memcmp(refData + sliceStart, testData + sliceStart, compressedSize)) { int i; for (i = 0; i < compressedSize; i++) { if (refData[sliceStart + i] != testData[sliceStart + i]) { printf("fail in slice/face %d at offset %d\n", slice, i); printf("expected %d, found %d\n", refData[sliceStart + i], testData[sliceStart + i]); break; } } printf("Failure for %s %s\n", piglit_get_gl_enum_name(target), piglit_get_gl_enum_name(intFormat)); pass = false; } } free(texData); free(refData); free(testData); glDeleteTextures(1, &tex); return pass; }
PsychError SCREENSetOpenGLTexture(void) { PsychWindowRecordType *windowRecord, *textureRecord; int texid, w, h, d, testarg, textureShader, usefloatformat = 0; int specialFlags = 0; GLenum target = 0; texid=w=h=d=-1; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumInputArgs(9)); //The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(4)); //The required number of inputs PsychErrorExit(PsychCapNumOutputArgs(2)); //The maximum number of outputs // Get the window record from the window record argument and get info from the window record PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); // Get the texture record from the texture record argument. // Check if either none ( [] or '' ) or the special value zero was // provided as Psychtoolbox textureHandle. In that case, we create a new // empty texture record instead of reusing an existing one. testarg=0; PsychCopyInIntegerArg(2, FALSE, &testarg); if (testarg==0) { // No valid textureHandle provided. Create a new empty textureRecord. PsychCreateWindowRecord(&textureRecord); textureRecord->windowType=kPsychTexture; textureRecord->screenNumber = windowRecord->screenNumber; // Assign parent window and copy its inheritable properties: PsychAssignParentWindow(textureRecord, windowRecord); // Mark it valid and return handle to userspace: PsychSetWindowRecordValid(textureRecord); } else { // None of the special values provided. We assume its a handle to a valid // and existing PTB texture and try to retrieve the textureRecord: PsychAllocInWindowRecordArg(2, TRUE, &textureRecord); } // Is it a textureRecord? if (!PsychIsTexture(textureRecord)) { PsychErrorExitMsg(PsychError_user, "You tried to set texture information on something else than a texture!"); } // Query OpenGL texid: PsychCopyInIntegerArg(3, TRUE, &texid); // Query OpenGL texture target: PsychCopyInIntegerArg(4, TRUE, (int*) &target); // Query optional override width: PsychCopyInIntegerArg(5, FALSE, &w); // Query optional override height: PsychCopyInIntegerArg(6, FALSE, &h); // Query optional override depth: PsychCopyInIntegerArg(7, FALSE, &d); // Get optional texture shader handle: textureShader = 0; PsychCopyInIntegerArg(8, FALSE, &textureShader); // Get optional specialFlags: PsychCopyInIntegerArg(9, FALSE, &specialFlags); // Activate OpenGL rendering context of windowRecord: PsychSetGLContext(windowRecord); // Bind the provided external OpenGL texture object: PsychTestForGLErrors(); glBindTexture(target, texid); PsychTestForGLErrors(); // Binding worked. Query its size and format unless override values are given: if (w==-1) glGetTexLevelParameteriv(target, 0, GL_TEXTURE_WIDTH, (GLint*) &w); if (h==-1) glGetTexLevelParameteriv(target, 0, GL_TEXTURE_HEIGHT, (GLint*) &h); if (d==-1) glGetTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH, (GLint*) &d); if (w<=0) { PsychErrorExitMsg(PsychError_user, "You tried to set invalid (negative) texture width."); } if (h<=0) { PsychErrorExitMsg(PsychError_user, "You tried to set invalid (negative) texture height."); } if (d<=0) { PsychErrorExitMsg(PsychError_user, "You tried to set invalid (negative) texture depth."); } // Ok, setup texture record for texture: PsychInitWindowRecordTextureFields(textureRecord); textureRecord->depth = d; // Assume this texture has four channels. FIXME: Is this problematic? textureRecord->nrchannels = 4; PsychMakeRect(textureRecord->rect, 0, 0, w, h); // Client rect of a texture is always == rect of it: PsychCopyRect(textureRecord->clientrect, textureRecord->rect); textureRecord->texturetarget = target; // Orientation is set to 2 - like an upright Offscreen window texture: textureRecord->textureOrientation = 2; textureRecord->textureNumber = texid; // Assign GLSL filter-/lookup-shaders if needed: usefloatformat is determined // by query, whereas the 'userRequest' flag is set to zero for now. glGetTexLevelParameteriv(target, 0, GL_TEXTURE_RED_SIZE, (GLint*) &d); if (d <= 0) glGetTexLevelParameteriv(target, 0, GL_TEXTURE_LUMINANCE_SIZE, (GLint*) &d); if (d < 16) usefloatformat = 0; if (d >= 16) usefloatformat = 1; if (d >= 32) usefloatformat = 2; // Assign bpc value: textureRecord->bpc = (int) d; PsychAssignHighPrecisionTextureShaders(textureRecord, windowRecord, usefloatformat, (specialFlags & 2) ? 1 : 0); // specialFlags setting 8? Disable auto-mipmap generation: if (specialFlags & 0x8) textureRecord->specialflags |= kPsychDontAutoGenMipMaps; // A specialFlags setting of 32? Protect texture against deletion via Screen('Close') without providing a explicit handle: if (specialFlags & 32) textureRecord->specialflags |= kPsychDontDeleteOnClose; // User specified override shader for this texture provided? This is useful for // basic image processing and procedural texture shading: if (textureShader!=0) { // Assign provided shader as filtershader to this texture: We negate it so // that the texture blitter routines know this is a custom shader, not our // built in filter shader: textureRecord->textureFilterShader = -1 * textureShader; } // Unbind texture: glBindTexture(target, 0); // printf("id %i target: %i w %i h %i", texid, target, w, h); // Return new (or old) PTB textureHandle for this texture: PsychCopyOutDoubleArg(1, FALSE, textureRecord->windowIndex); PsychCopyOutRectArg(2, FALSE, textureRecord->rect); // Done. return(PsychError_none); }
static GLboolean test_teximage_formats(void) { GLint i; GLubyte *image; GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); image = (GLubyte *) malloc(TexWidth * TexHeight * 2 * sizeof(GLubyte)); for (i = 0; i < NUM_INT_FORMATS; i++) { const struct format_info *info = &IntFormats[i]; const GLuint comps = (info->BaseFormat == GL_ALPHA) ? 1 : 2; GLfloat expected[4], result[4]; GLfloat error = 2.0 / 255.0; /* XXX fix */ fill_texture_image(TexWidth, TexHeight, comps, image); glTexImage2D(GL_TEXTURE_2D, 0, info->IntFormat, TexWidth, TexHeight, 0, info->BaseFormat, GL_UNSIGNED_BYTE, image); if (check_error(__FILE__, __LINE__)) { fprintf(stderr, "%s: Error in glTexImage2D for " "internalFormat = %s\n", TestName, info->Name); return GL_FALSE; } if (0) { GLint f; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &f); assert(f == info->IntFormat); } glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(TexWidth, 0); glTexCoord2f(1, 1); glVertex2f(TexWidth, TexHeight); glTexCoord2f(0, 1); glVertex2f(0, TexHeight); glEnd(); /* setup expected polygon color */ expected[0] = info->expected0; expected[1] = 0.5; expected[2] = 0.0; expected[3] = 1.0; /* test center pixel */ result[0] = result[1] = result[2] = 0.0; result[3] = 1.0; glReadPixels(TexWidth/2, TexHeight/2, 1, 1, GL_LUMINANCE_ALPHA, GL_FLOAT, result); if (check_error(__FILE__, __LINE__)) { fprintf(stderr, "%s: Error in glReadPixels(format = GL_LA)\n", TestName); return GL_FALSE; } if (fabsf(result[0] - expected[0]) > error || fabsf(result[1] - expected[1]) > error || fabsf(result[2] - expected[2]) > error || fabsf(result[3] - expected[3]) > error) { fprintf(stderr, "%s: failure with format %s:\n", TestName, info->Name); fprintf(stderr, " expected color = %g, %g, %g, %g\n", expected[0], expected[1], expected[2], expected[3]); fprintf(stderr, " result color = %g, %g, %g, %g\n", result[0], result[1], result[2], result[3]); return GL_FALSE; } glutSwapBuffers(); } free(image); glDisable(GL_TEXTURE_2D); return GL_TRUE; }
// For GLX, we implement wglBindTexARB() as a copy operation. // We copy the pbuffer image to the currently bound texture. // If there's any rendering to the pbuffer before the wglReleaseTexImage() // call, the results are undefined (and permitted by the extension spec). // // The spec says that glTexImage and glCopyTexImage calls which effect // the pbuffer/texture should not be allowed, but we do not enforce that. // // The spec says that when a pbuffer is released from the texture that // the contents do not have to be preserved. But that's what will happen // since we're copying here. bool bindTexImage(Drawable *pBuffer, int iBuffer) { GLint readBufSave; GLint width, height; assert(pBuffer->pbuffer); // Save the current drawing surface and bind the pbuffer surface GLXDrawable prevDrawable = glXGetCurrentDrawable(); GLXContext prevContext = glXGetCurrentContext(); GlxDrawable *glxPBuffer = static_cast<GlxDrawable *>(pBuffer); glXMakeCurrent(display, glxPBuffer->window, prevContext); glGetIntegerv(GL_READ_BUFFER, &readBufSave); assert(iBuffer == GL_FRONT_LEFT || iBuffer == GL_BACK_LEFT || iBuffer == GL_FRONT_RIGHT || iBuffer == GL_BACK_RIGHT || iBuffer == GL_AUX0); // set src buffer glReadBuffer(iBuffer); // Just copy image from pbuffer to texture switch (pBuffer->pbInfo.texTarget) { case GL_TEXTURE_1D: glGetTexLevelParameteriv(GL_TEXTURE_1D, pBuffer->mipmapLevel, GL_TEXTURE_WIDTH, &width); if (width == pBuffer->width) { // replace existing texture glCopyTexSubImage1D(GL_TEXTURE_1D, pBuffer->mipmapLevel, 0, // xoffset 0, 0, // x, y pBuffer->width); } else { // define initial texture glCopyTexImage1D(GL_TEXTURE_1D, pBuffer->mipmapLevel, pBuffer->pbInfo.texFormat, 0, 0, // x, y pBuffer->width, 0); } break; case GL_TEXTURE_2D: glGetTexLevelParameteriv(GL_TEXTURE_2D, pBuffer->mipmapLevel, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, pBuffer->mipmapLevel, GL_TEXTURE_HEIGHT, &height); if (width == pBuffer->width && height == pBuffer->height) { // replace existing texture glCopyTexSubImage2D(GL_TEXTURE_2D, pBuffer->mipmapLevel, 0, 0, // xoffset, yoffset 0, 0, // x, y pBuffer->width, pBuffer->height); } else { // define initial texture glCopyTexImage2D(GL_TEXTURE_2D, pBuffer->mipmapLevel, pBuffer->pbInfo.texFormat, 0, 0, // x, y pBuffer->width, pBuffer->height, 0); } break; case GL_TEXTURE_CUBE_MAP: { const GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + pBuffer->cubeFace; glGetTexLevelParameteriv(target, pBuffer->mipmapLevel, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(target, pBuffer->mipmapLevel, GL_TEXTURE_HEIGHT, &height); if (width == pBuffer->width && height == pBuffer->height) { // replace existing texture glCopyTexSubImage2D(target, pBuffer->mipmapLevel, 0, 0, // xoffset, yoffset 0, 0, // x, y pBuffer->width, pBuffer->height); } else { // define new texture glCopyTexImage2D(target, pBuffer->mipmapLevel, pBuffer->pbInfo.texFormat, 0, 0, // x, y pBuffer->width, pBuffer->height, 0); } } break; default: ; // no op } // restore glReadBuffer(readBufSave); // rebind previous drawing surface glXMakeCurrent(display, prevDrawable, prevContext); return true; }
GLuint blur( Shader blur, GLuint texture, int amount) { static bool createAll = true; static GLuint pingpongFBO[2]; static GLuint pingpongBuffer[2]; static GLuint vao; static GLuint vbo[2]; if(createAll) { int w, h; glBindTexture(GL_TEXTURE_2D, texture); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); std::cout << w << h << std::endl; glGenFramebuffers(2, pingpongFBO); glGenTextures(2, pingpongBuffer); for (GLuint i = 0; i < 2; i++) { glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]); glBindTexture(GL_TEXTURE_2D, pingpongBuffer[i]); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB16F, w, h, 0, GL_RGB, GL_FLOAT, NULL ); 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); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongBuffer[i], 0 ); } int quad_triangleCount = 2; int quad_triangleList[] = {0, 1, 2, 2, 1, 3}; float quad_vertices[] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; // Quad glBindVertexArray(vao); // Bind indices and upload data glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[0]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad_triangleList), quad_triangleList, GL_STATIC_DRAW); // Bind vertices and upload data glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT)*2, (void*)0); glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW); createAll = false; } GLboolean horizontal = true, first_iteration = true; amount = amount + (amount%2); blur.use(); for (GLuint i = 0; i < amount; i++) { glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); glUniform1i(glGetUniformLocation(blur.getProgram(), "horizontal"), horizontal); glBindTexture( GL_TEXTURE_2D, first_iteration ? texture : pingpongBuffer[!horizontal] ); glBindVertexArray(vao); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0); horizontal = !horizontal; if (first_iteration) first_iteration = false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); Utils::checkGlError("blur"); return pingpongBuffer[!horizontal]; }
static void Init( void ) { unsigned i; static const GLenum pnames[] = { GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE, GL_TEXTURE_LUMINANCE_SIZE, GL_TEXTURE_INTENSITY_SIZE, GL_TEXTURE_BORDER, GL_TEXTURE_INTERNAL_FORMAT, GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH, ~0 }; printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); printf("\nThis program should log some data about a texture and exit.\n"); printf("This is a regression test for bug #3050. If the bug still\n"); printf("exists, a GLX protocol error will be generated.\n"); printf("https://bugs.freedesktop.org/show_bug.cgi?id=3050\n\n"); if ( ! glutExtensionSupported( "GL_NV_texture_rectangle" ) && ! glutExtensionSupported( "GL_EXT_texture_rectangle" ) && ! glutExtensionSupported( "GL_ARB_texture_rectangle" ) ) { printf( "This test requires one of GL_ARB_texture_rectangle, GL_EXT_texture_rectangle,\n" "or GL_NV_texture_rectangle be supported\n." ); exit( 1 ); } glBindTexture( GL_TEXTURE_RECTANGLE_NV, 1 ); glTexImage2D( GL_PROXY_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); for ( i = 0 ; pnames[i] != ~0 ; i++ ) { GLint param_i; GLfloat param_f; GLenum err; glGetTexLevelParameteriv( GL_PROXY_TEXTURE_RECTANGLE_NV, 0, pnames[i], & param_i ); err = glGetError(); if ( err ) { printf("glGetTexLevelParameteriv(GL_PROXY_TEXTURE_RECTANGLE_NV, 0, 0x%04x, & param) generated a GL\n" "error of 0x%04x!", pnames[i], err ); exit( 1 ); } else { printf("glGetTexLevelParameteriv(GL_PROXY_TEXTURE_RECTANGLE_NV, 0, 0x%04x, & param) = 0x%04x\n", pnames[i], param_i ); } glGetTexLevelParameterfv( GL_PROXY_TEXTURE_RECTANGLE_NV, 0, pnames[i], & param_f ); err = glGetError(); if ( err ) { printf("glGetTexLevelParameterfv(GL_PROXY_TEXTURE_RECTANGLE_NV, 0, 0x%04x, & param) generated a GL\n" "error of 0x%04x!\n", pnames[i], err ); exit( 1 ); } else { printf("glGetTexLevelParameterfv(GL_PROXY_TEXTURE_RECTANGLE_NV, 0, 0x%04x, & param) = %.1f (0x%04x)\n", pnames[i], param_f, (GLint) param_f ); } } }
image* texture_get_image(texture* t) { int width = 0; int height = 0; int format = 0; glBindTexture(GL_TEXTURE_2D, texture_handle(t)); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); if ((width == 0) || (height == 0)) { error("Texture has zero size width/height: (%i, %i)", width, height); } unsigned char* data = malloc(width * height * 4); float* data_flt; unsigned int* data_int; switch (format) { case GL_RGBA: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); break; case GL_ALPHA16: data_flt = malloc(sizeof(float) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_ALPHA, GL_FLOAT, data_flt); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { data[(y*4*width) + (x*4) + 0] = pow(data_flt[(y*width) + x], 256.0) * 255; data[(y*4*width) + (x*4) + 1] = pow(data_flt[(y*width) + x], 256.0) * 255; data[(y*4*width) + (x*4) + 2] = pow(data_flt[(y*width) + x], 256.0) * 255; data[(y*4*width) + (x*4) + 3] = pow(data_flt[(y*width) + x], 256.0) * 255; } free(data_flt); break; case GL_RGBA32F: case GL_RGBA16F: data_flt = malloc(4 * sizeof(float) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, data_flt); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { data[(y*4*width) + (x*4) + 0] = clamp(data_flt[(y*4*width) + (x*4) + 0] * 127 + 127, 0, 255); data[(y*4*width) + (x*4) + 1] = clamp(data_flt[(y*4*width) + (x*4) + 1] * 127 + 127, 0, 255); data[(y*4*width) + (x*4) + 2] = clamp(data_flt[(y*4*width) + (x*4) + 2] * 127 + 127, 0, 255); data[(y*4*width) + (x*4) + 3] = clamp(data_flt[(y*4*width) + (x*4) + 3] * 127 + 127, 0, 255); } free(data_flt); break; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT24: data_int = malloc(sizeof(unsigned int) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, data_int); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { data[(y*4*width) + (x*4) + 0] = data_int[(y*width) + x]; data[(y*4*width) + (x*4) + 1] = data_int[(y*width) + x]; data[(y*4*width) + (x*4) + 2] = data_int[(y*width) + x]; data[(y*4*width) + (x*4) + 3] = data_int[(y*width) + x]; } free(data_int); break; default: error("Can't convert that particular texture format %i to an image.", format); } SDL_GL_CheckError(); image* i = image_new(width, height, data); free(data); return i; }
CLLineStippleTexture::CLLineStippleTexture(const std::vector<unsigned int>& dasharray): mPatternLength(0), mTextureLength(0), mTextureName(0) { if (!dasharray.empty()) { std::vector<unsigned int>::const_iterator it = dasharray.begin(), endit = dasharray.end(); while (it != endit) { this->mPatternLength += *it; ++it; } // we only need to create a texture if the pattern length is not 0 if (this->mPatternLength != 0) { // the texture size should be a multiple of 2 unsigned int exponent = (unsigned int)ceil(log((double)this->mPatternLength) / log(2.0)); if (exponent <= 31) { this->mTextureLength = 1 << exponent; // make sure the texture name is really free this->mTextureName = 0; GLint w = -1; glTexImage1D(GL_PROXY_TEXTURE_1D, 0, GL_ALPHA, this->mTextureLength, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_WIDTH, &w); if (w != 0) { GLubyte* pTextureData = new GLubyte[this->mTextureLength]; // now we create the pattern it = dasharray.begin(); unsigned int i; bool gap = false; unsigned int index = 0; while (it != endit) { for (i = 0; i < *it; ++i) { // if it is a gap, we write 0, otherwise we write 255 pTextureData[index] = gap ? 0 : 255; ++index; } gap = !gap; ++it; } // fill the rest of the texture with 255 while (index < this->mTextureLength) { pTextureData[index++] = 70; } // now we load the texture data into OpenGL glGenTextures(1, &this->mTextureName); // make sure a new texture name has been created assert(this->mTextureName != 0); glBindTexture(GL_TEXTURE_1D, this->mTextureName); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexImage1D(GL_TEXTURE_1D, 0, GL_ALPHA, this->mTextureLength, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pTextureData); // delete the memory delete[] pTextureData; } else { std::cerr << "Line stipple texture of this size is not supported by the current OpenGL implementation." << std::endl; } } else { std::cerr << "texture to large." << std::endl; } } } }
static void makeImages(int image) { #define WIDTH 512 #define HEIGHT 512 if (glutExtensionSupported("GL_SGIS_generate_mipmap") && image) { /* test auto mipmap generation */ GLint width, height, i; GLenum format; GLubyte *image = LoadRGBImage(TEXTURE_FILE, &width, &height, &format); if (!image) { printf("Error: could not load texture image %s\n", TEXTURE_FILE); exit(1); } /* resize */ if (width != WIDTH || height != HEIGHT) { GLubyte *newImage = malloc(WIDTH * HEIGHT * 4); gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image, WIDTH, HEIGHT, GL_UNSIGNED_BYTE, newImage); free(image); image = newImage; } printf("Using GL_SGIS_generate_mipmap\n"); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, format, WIDTH, HEIGHT, 0, format, GL_UNSIGNED_BYTE, image); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); free(image); /* make sure mipmap was really generated correctly */ width = WIDTH; height = HEIGHT; for (i = 0; i < 10; i++) { GLint w, h; glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h); printf("Level %d size: %d x %d\n", i, w, h); width /= 2; height /= 2; } } else { static const GLubyte colors[10][3] = { {128, 128, 128}, {0, 255, 255}, {255, 255, 0}, {255, 0, 255}, {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {0, 255, 255}, {255, 255, 0}, {255, 255, 255} }; int i, sz = 512; for (i = 0; i < 10; i++) { MakeImage(i, sz, sz, colors[i]); printf("Level %d size: %d x %d\n", i, sz, sz); sz /= 2; } } }
static inline void dumpTextureImage(JSONWriter &json, GLenum target, GLint level) { GLint width, height = 1, depth = 1; width = 0; glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width); if (target != GL_TEXTURE_1D) { height = 0; glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height); if (target == GL_TEXTURE_3D) { depth = 0; glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth); } } if (width <= 0 || height <= 0 || depth <= 0) { return; } else { char label[512]; GLint active_texture = GL_TEXTURE0; glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); snprintf(label, sizeof label, "%s, %s, level = %i", enumToString(active_texture), enumToString(target), level); json.beginMember(label); json.beginObject(); // Tell the GUI this is no ordinary object, but an image json.writeStringMember("__class__", "image"); json.writeNumberMember("__width__", width); json.writeNumberMember("__height__", height); json.writeNumberMember("__depth__", depth); // Hardcoded for now, but we could chose types more adequate to the // texture internal format json.writeStringMember("__type__", "uint8"); json.writeBoolMember("__normalized__", true); json.writeNumberMember("__channels__", 4); GLubyte *pixels = new GLubyte[depth*width*height*4]; resetPixelPackState(); glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels); restorePixelPackState(); json.beginMember("__data__"); char *pngBuffer; int pngBufferSize; Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize); json.writeBase64(pngBuffer, pngBufferSize); free(pngBuffer); json.endMember(); // __data__ delete [] pixels; json.endObject(); } }
M(void, glGetTexLevelParameteriv, jint target, jint level, jint pname, jobject params) { glGetTexLevelParameteriv(target, level, pname, BUFF(GLint, params)); }