Click here to Skip to main content
Click here to Skip to main content

anyTex - a class for non-restrictive textures in OpenGL

, 24 Jul 2005
Rate this:
Please Sign up or sign in to vote.
anyTex - a class for non-restrictive textures in OpenGL.

Sample Image

Introduction

Working with textures in OpenGL meant until very recently working with images with sizes of power of two, limited to 1024, 2048 or 4096. On April 26, 2005, Mark J. Kilgard published the NVIDIA OpenGL 2.0 Support notes, making direct reference to the fact that "NVIDIA’s GeForce 6 Series and NV4xGL-based Quadro FX GPUs fully support non-power-of-two textures at the fragment level" (of course, with some limitations). From a programmer's point of view, it may be sometimes attractive to work with images of whatever size (and I mean pretty large images) and think of them implicitly as non-power-of-two large textures, let's say of a 8000 x 3000 pixel size, and not to care a bit about the well known texture "kitchen".

anyTex is a class allowing you to load a bitmap of a given color depth from a file and think of it as texture with no restrictions (of course, limited by the computer resources, that is something we have to live with).

Working with the class

anyTex comes with two files, anytex.cpp and anytex.h, which you have to add to your project. Make sure you have OpenGL32.lib, GLu32.lib, GLaux.lib in the Link tab of your project settings. Then #include "anytex.h" in the header file of your main dialog class. Add a public member of type AnyTex to the main dialog class:

AnyTex m_atImage;

Add a CStatic control to your application, which will be responsible for rendering your OpenGL scenes (I made that choice just for the sake of the presentation). Then, add a CStatic derived class with the wizard and map a variable of that type to the control. Let us assume that m_oglDisplay is the name of that variable. In the OnInitDialog() function, create the OpenGL rendering context by passing the address of the control to the InitializeOpenGL() function provided by the anyTex class:

if ( !m_atImage.InitializeOpenGL(&m_oglDisplay) ) 
{
    AfxMessageBox("Cannot initialize OpenGL");
    PostMessage(WM_QUIT);
}

Before going further, keep in mind that, behind the scene, anyTex still works with power-of-two classical textures as basic square cells. By default, the cell size is 1024. Should you want to set another cell size, you are free to do it by calling the SetTexCellSize(int nSize) function provided by anyTex. You may choose whatever value you want for nSize. anyTex adjusts it automatically to 128, 256, 512 or 1024. Load a bitmap image of your choice and create the anyTex texture, which will be called further on just anyTex for simplicity.

if ( m_atImage.LoadBmpImage("test.bmp") ) m_atImage.CreateTex();

The CreateTex() function needs a boolean parameter, which by default is false, this leading to creation of 2D image textures. By calling the function with the parameter set to true, mipmaps are generated. From now on, you have only to call the PreRender() function (which can be overwritten according to your needs) and the Render() function of the anyTex class from within the OnPaint() function of your CStatic derived class.

The things behind

anyTex is supported by a CList <UINT, UINT> m_listTex, storing the ID of the texture cells. The bitmap is brought into the memory as a DIB. anytex "goes" throughout the DIB, sequentially extracting squares with the same size as the basic texture cell. Each square is blitted to a memory device context, resulting a DDB. The DDB is converted to a DIB having a 32 color depth, which is used then to generate a basic texture cell or its corresponding mipmaps, according to the boolean parameter passed to the AnyText::CreateTex() function. The texture ID is added to m_listTex.

Texture creation

anyTex considers a square texture canvas of size 1 mapped over the anyTex object in the following way:

Texture creation

anyTex is top-left aligned to the canvas. The AnyTex::Render() function renders anyText as it is, as a whole. Should you now be interested in 3D rendering and need to use the component texture cells individually, all you have to do is to call the:

UINT AnyTex::RetrieveTexCell(double atX, double atY, 
         double &renLeft, double &renTop, double &renSize)

function and pass the atX, atY position on the logical canvas as parameters. The function returns the texture ID for the corresponding cell or 0 in case no one is found. A non-zero ID means a valid ID, and the basic cell pointed by that ID is rendered at renLeft, renTop and has the size stored in renSize, values which can be used further in your computations.

History

  • Created: July 22, 2005.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Mircea Puiu
Software Developer (Senior)
Europe Europe
More than 22 years of software development experience.
SCRUM Master nowadays

Comments and Discussions

 
GeneralThank You Pinmembereoge21-Mar-06 1:54 
GeneralRe: Thank You PinmemberMircea Puiu21-Mar-06 2:30 
GeneralRe: Thank You Pinmembereoge21-Mar-06 3:06 
GeneralRe: Thank You [modified] Pinmember__xt21-Apr-06 1:53 
GeneralRe: Thank You PinmemberJWood27-Sep-06 8:24 
GeneralRe: Thank You PinmemberMircea Puiu28-Sep-06 0:33 
GeneralMan , i love your approach PinmemberFade (Amit BS)20-Oct-05 8:23 
GeneralRe: Man , i love your approach PinmemberMircea Puiu22-Oct-05 21:31 
You're welcome.
 
SkyWalker

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 25 Jul 2005
Article Copyright 2005 by Mircea Puiu
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid