Click here to Skip to main content
15,868,016 members
Articles / Multimedia / OpenGL
Article

anyTex - a class for non-restrictive textures in OpenGL

Rate me:
Please Sign up or sign in to vote.
4.85/5 (12 votes)
24 Jul 2005CPOL4 min read 62.5K   2.9K   20   8
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)


Written By
Software Developer (Senior)
Europe Europe
More than 30 years of software development experience.
(also playing the SCRUM Master role depending on the project)

Comments and Discussions

 
GeneralThank You Pin
eoge21-Mar-06 1:54
eoge21-Mar-06 1:54 
This is fantastic! Thank you.

I wonder is there a way to hide the lines between the tiles (when zooming up close)? See example below.

http://www.eoghanmccabe.com/c.jpg
GeneralRe: Thank You Pin
Mircea Puiu21-Mar-06 2:30
Mircea Puiu21-Mar-06 2:30 
GeneralRe: Thank You Pin
eoge21-Mar-06 3:06
eoge21-Mar-06 3:06 
GeneralRe: Thank You [modified] Pin
__xt21-Apr-06 1:53
__xt21-Apr-06 1:53 
GeneralRe: Thank You Pin
JWood27-Sep-06 8:24
JWood27-Sep-06 8:24 
GeneralRe: Thank You Pin
Mircea Puiu28-Sep-06 0:33
Mircea Puiu28-Sep-06 0:33 
GeneralMan , i love your approach Pin
Fade (Amit BS)20-Oct-05 8:23
Fade (Amit BS)20-Oct-05 8:23 
GeneralRe: Man , i love your approach Pin
Mircea Puiu22-Oct-05 21:31
Mircea Puiu22-Oct-05 21:31 

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

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