Archived

This topic is now archived and is closed to further replies.

Per Pixel Lighting -> GL_TEXTURE_3D

This topic is 5174 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, Instead of using a 2D texture and a 1D texture for the light, I'd like to use a 3D texture. So, I've writtent the code for initialising it but the initialisation failed. Is there a problem ?
/*

	Slug Production	(c)	2003 - http://www.slug-production.be.tf/

	File : "GL_EXT_texture_3D.cpp"
	  
	Programmed by : Leyder Dylan (slug-production@be.tf)

*/


# include <windows.h>
# include <gl\gl.h>

# include "GLExt.h"
# include "Texture-3D.h"


// EXT Texture 3D Initialisation

PFNGLTEXIMAGE3DEXTPROC glTexImage3DEXT = NULL;

// The Texture_3D is supported or not ? By default, not supported

bool EXT_Texture_3D = false;


// **********************************************

bool Init_Texture_3D()
{
    
	// The name of the extension

	char *Extension;

    Extension = (char *) glGetString(GL_EXTENSIONS);
   
    if (!(strstr(Extension, "GL_EXT_texture3D")) == 1)
		{ 
			// The "GL_EXT_texture3D" extension is not supported

			MessageBox(NULL,"'GL_EXT_texture3D'","ERROR : Extension not supported :",MB_ICONERROR);
		} 
	
	else 
		{
			// The "GL_EXT_texture3D" is supported

			
			// EXT Texture 3D Initialisation

			glTexImage3DEXT     =  (PFNGLTEXIMAGE3DEXTPROC)     wglGetProcAddress("GL_EXT_texture3D");
      
			// EXT Texture 3D Initialisation failed !

			if (!glTexImage3DEXT)
				{
					MessageBox(NULL,"GL_EXT_texture3D","ERROR : Initialisation failed !",MB_ICONERROR);
					
					return false;
				}
		}

	return true;

}
I've a GeForce 4 4200 Ti and it supports the extension. Thanks all. ======================== Leyder Dylan (dylan.leyder@slug-production.be.tf http://www.slug-production.be.tf/ [edited by - Leyder Dylan on October 9, 2003 5:57:49 PM]

Share this post


Link to post
Share on other sites
Oups, got it.

Tryed to initialise an extension as a function.

Now, the extension is loaded correctly but when I want to generate a 3D texture, I've an error "the memory can not be read..."

According the "OpenGL 1.2", there's no errors in this code :


glBindTexture(GL_TEXTURE_3D, Texture_TGA[Loop_02].Texture_ID);

glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

glTexImage3DEXT(GL_TEXTURE_3D, 0, GL_RGB, Texture_TGA[Loop_02].width, Texture_TGA[Loop_02].height, Texture_TGA[Loop_02].height, 0, GL_RGB, GL_UNSIGNED_BYTE, Texture_TGA[Loop_02].imageData);


For the "depth" parameter of the 3D texture, I use the height or the width of the texture. The problem comes from that ?

Thanks sir.

========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/

[edited by - Leyder Dylan on October 9, 2003 12:40:37 AM]

Share this post


Link to post
Share on other sites
You are probably accessing memory out of bounds.

Since you are trying to do light falloff function you can use GL_INTENSITY(or GL_ALPHA) instead of GL_RGB. You also have to apply glTexParameteri to all 3 axis (S,T,R).

Try something like this:


int textureID = 0;
int width = 64;
int height = 64;
int depth = 64; // might be called "slices" or something less confusing
unsigned char* data = new unsigned char[ width * height * depth ];
// fill this data here with some nice fall-off function
//...
glGenTextures( 1, &textureID );
glBindTexture( GL_TEXTURE_3D, textureID );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );

glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

glTexImage3DEXT( GL_TEXTURE_3D, 0, GL_INTENSITY, width, height, depth, 0, GL_INTENSITY, GL_UNSIGNED_BYTE, data );


You should never let your fears become the boundaries of your dreams.

Share this post


Link to post
Share on other sites
Ok thanks but the problem is that I need to add a depth to my texture.

My texture has a height and width BUT NO DEPTH.

It''s possible to add the depth to a texture ?

I searched on the web and every demo generates a 3D texture himself not from a external texture (tga or jpg or ...)

So the problem is the depth ...

========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/

Share this post


Link to post
Share on other sites
That''s because tga or jpg are picture format for 2D images, as most formats on the web.
Your best bet is to take a stack of images having the same prefix and the suffix as id for instance :
[ image00.jpg image01.jpg image02.jpg ... image63.jpg ]

Otherwise you would have to go into other exotic picture formats but I don''t know any good one that supports 3D pictures.

As for the purpose of testing, you can simply consider depth==1 and load any jpeg or tga image : it will do the trick, and will allow you at least to test if 3D texture is mounted to the graphics card correctly and if rendering is supported in hardware.

Share this post


Link to post
Share on other sites
_DarkWIng_,

With a 2D Texture, I need to use 2 texture units for lighting a scene with Per Pixel Lighting.

---------------------
Why 2 texture units ?
---------------------

The first texture unit is used for the coordinates (x,y) :

glMultiTexCoord2f(GL_TEXTURE_2D,X,Y);


The second texture unit is used for the coordinates (z) :

glMultiTexCoord1f(GL_TEXTURE_2D,Z);




For the moment I used only 2 2D textures. I'll update the code for using a 1D texture and a 2D texture.





With a 3D texture, I need only one texture unit for lighting a scene with Per Pixel Lighting.

The texture unit is used for the coordinates (x,y,z) :


glMultiTexCoord3f(GL_TEXTURE_2D,X,Y,Z);


Each solution has some problems :

GL_TEXTURE_2D
Advantages : - Relatively low hardware requirements
Disadvantages : - 2 texture units used


GL_TEXTURE_3D
Advantages : - 1 texture unit used
Disadvantages : - Required the "GL_EXT_texture3D" extension

Hope this light your mind a little bit




Vincoof,

You're right for the trick, it works but not well.

Here're 2 screenshots (I'm lighting a box (6 faces) ) with a 2D Texture :

- When I start the program, I've this :




- When I light a corner of the box, I've this :



Not bad don't you ? But I need to fix the 1D texture as you can see on the back face. The ground texture is OK but the wall texture is "rectangular".




Now, with the 3D Texture :

- When I start the program, I've this :



==> First, the problem comes from the "Y" texture coordinate. The program doesn't care of it.


- When I light a corner of the box, I've this :



On "Y" again, the texture is rectangular.



So for me :
- Does the problem come from the fake 2D texture (your trick) ?
- Are some parameters not correctly set up ?

I followed your idea, the texture is a 2D one generated in a 3D one with depth = 1.

Next take a look on the following code :

   
// We set the Texture Coord.

glMultiTexCoord3fARB(GL_TEXTURE0_ARB, s, t, r);
//glMultiTexCoord4fARB(GL_TEXTURE0_ARB, s, t, r, 0.5f);



I've tryed the 3f with X, Y, Z as parameters. Next, I tryed with the 4f with X, Y, Z, 1.0f as parameters but the result is the same.

For me, again, the problem comes from the trick ...

Any idea ?

Thanks.

========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/


[edited by - Leyder Dylan on October 10, 2003 4:56:45 PM]

Share this post


Link to post
Share on other sites
OK. So you are using 3D texture for distance attenuation. I tought so but you were talking about loading textures so animated normal maps also came to mind. I used both in my shaders.
Then it should be better if you just build texture form some formula at load time instead of loading texture from disk. It alos saves you some space.
You can use something like :
dist = distance from point to center
value = (1-(dist^2))^2
clamp value to [0..1] range.

If you need full code to generate this texture I'll post some old source code.


(To use vincoofs idea you just replace 2D texture with 3D, but still keep the 1D. This is just to test if your 3D texure loads correctly.)

You should never let your fears become the boundaries of your dreams.

[edited by - _DarkWIng_ on October 10, 2003 5:23:48 PM]

Share this post


Link to post
Share on other sites
To all, you'll find a demo for both (2D and 3D texture using) on my website.

You'll see yourself what's wrong but I hope that for the next week, the code will be OK and that I could release the source code.

Thanks Drakwing, I'll try to generate a 3D texture at the runtime.

For :

quote:

You can use something like :
dist = distance from point to center
value = (1-(dist^2))^2
clamp value to [0..1] range.



For me, the problem comes from the fake 3D texture.

Because with 2 textures, everything is OK. But thanks anyway.

For :

quote:
(To use vincoofs idea you just replace 2D texture with 3D, but still keep the 1D. This is just to test if your 3D texure loads correctly.)


I tested that, so for you it's not a good idea for only using a 3D texture for lighting a scene ?

What about your lighting engine ? It's possible to have some screenshots ?

========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/

[edited by - Leyder Dylan on October 10, 2003 7:05:55 PM]

Share this post


Link to post
Share on other sites
"...for you it''s not a good idea for only using a 3D texture for lighting a scene?..."

It is a good idea, but you have to generate full 3D texture not use just one plane (2D) of it. What vincoof sugested was just to test if your 3D texture loading even works. For making real use of it you have to use full 3d texture. 64x64x64 will be large enough.


I''ll try to make a small demo from old engine. (might take some time)

You should never let your fears become the boundaries of your dreams.

Share this post


Link to post
Share on other sites
quote:
It is a good idea, but you have to generate full 3D texture not use just one plane (2D) of it. What vincoof sugested was just to test if your 3D texture loading even works. For making real use of it you have to use full 3d texture. 64x64x64 will be large enough.


Yes, Vincoof''s idea was good, but now, I''ll try to generate a 3D texture while the OpenGL initialisation and we will see ...

quote:
I''ll try to make a small demo from old engine. (might take some time)


Thanks and no problem for the time.


========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/

Share this post


Link to post
Share on other sites
DarkWing's right about the fact that I simply proposed to test the 3D texture functionality by using a 3D texture wth depth==1. At least it shows that function pointers are initialized coorectly and the new tokens are used accordingly. With that said, the sole purpose was test

I think it's pretty easy to compute an attenuation cube from scratch. From the top of my head, I would write something like :
GLuint generateAttenuationTexture3D(GLuint size)
{
GLuint tex;
GLint x, y, z;
GLubyte *data;
GLfloat fsize = (GLfloat)size - 1.f;
GLfloat fcenter = .5f * fsize;
data = new GLubyte[size*size*size];
for (x = 0; x < size; x++)
for (y = 0; y < size; y++)
for (z = 0; z < size; z++)
{
GLfloat fx = ((GLfloat)x-fcenter)/fsize;
GLfloat fy = ((GLfloat)y-fcenter)/fsize;
GLfloat fz = ((GLfloat)z-fcenter)/fsize;
GLint index = z*size*size+y*size+x;
GLfloat fdistance;
GLubyte byte;

fdistance = (GLfloat)sqrt(fx*fx + fy*fy + fz*fz);
if (fdistance >= 1.f) byte = 0;
else if (fdistance <= 0.f) byte = 255;
else byte = 255.f * (1.f - fdistance);

data[index] = byte;
}
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_3D_EXT, tex);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage3D(GL_TEXTURE_3D_EXT, 0, GL_LUMINANCE, size, size, size, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
delete[] data;
return tex;
}

Then call :
GLuint my3DTex = generateAttenuationTexture3D(64);

and bind this object whenever you want :
glBindTexture(GL_TEXTURE_3D_EXT, my3DTex);
glEnable(GL_TEXTURE_3D_EXT);

[edit: typo]

[edited by - vincoof on October 13, 2003 8:32:54 AM]

Share this post


Link to post
Share on other sites
Thanks again Vincoof for having wasted your time for me, but I''ve found the solution.

I''ve not tryed your code because mine works. It''s pretty the same as yours :


/*

Slug Production (c) 2003 - http://www.slug-production.be.tf/

File : "Attenuation_3D_Texture_Generation.cpp"

Programmed by : Leyder Dylan (slug-production@be.tf)

*/



# include <windows.h>
# include <gl\gl.h>

# include <math.h>

# include "GLExt.h"

// EXT Texture 3D Initialisation

extern PFNGLTEXIMAGE3DEXTPROC glTexImage3DEXT;

// The Attenuation 3D Texture

GLuint Attenuation_3D_Texture;

// Attenuation 3D Texture Generation

GLuint Attenuation_3D_Texture_Generation(const int Attenuation_3D_Texture_Size)
{
// Create a strip of data for our 1d texture

GLubyte * attenData=new GLubyte[Attenuation_3D_Texture_Size];

// Unable to create space to hold attenuation texture data

if (!attenData)
return false;

// Attenuation 3D Texture Generation

for(int i = 0; i < Attenuation_3D_Texture_Size; ++ i)
{
// Get distance from centre to this point

float dist = (float)i;
dist -= (float)Attenuation_3D_Texture_Size / 2 - 0.5f;
dist /= (float)Attenuation_3D_Texture_Size / 2 - 0.5f;

// Square and Clamp to [0,1]

dist = dist * dist;

if(dist > 1.0f)
dist = 1.0f;

if(dist < 0.0f)
dist = 0.0f;

// Fill this in as color

attenData[i] = GLubyte(dist * 255);

// Make sure the color is 255 at the edges

attenData[0] = 255;
attenData[Attenuation_3D_Texture_Size - 1] = 255;
}

// The 3D Texture Size

GLubyte * Attenuation_3D_Texture_Data = new GLubyte[Attenuation_3D_Texture_Size * Attenuation_3D_Texture_Size * Attenuation_3D_Texture_Size];

// Unable to create space to hold attenuation texture data

if(!Attenuation_3D_Texture_Data)
return false;

int currentByte = 0;
GLubyte dataI, dataJ, dataK;

for(i = 0; i < Attenuation_3D_Texture_Size; ++ i)
{
dataI = attenData[i];

for(int j = 0; j < Attenuation_3D_Texture_Size; ++ j)
{
dataJ = attenData[j];

for(int k = 0; k < Attenuation_3D_Texture_Size; ++ k)
{
dataK = attenData[k];
GLuint newData;

newData = dataI+dataJ+dataK;
if(newData > 255)
newData = 255;

// Invert data as there is no need to do any more summing

// Thus the invert need not wait until the register combiners

newData = 255 - newData;

Attenuation_3D_Texture_Data[currentByte] = newData;
++ currentByte;
}
}
}
glGenTextures(1, &Attenuation_3D_Texture);
glBindTexture(GL_TEXTURE_3D_EXT, Attenuation_3D_Texture);

glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

glTexImage3DEXT(GL_TEXTURE_3D_EXT, 0, GL_INTENSITY8, Attenuation_3D_Texture_Size, Attenuation_3D_Texture_Size, Attenuation_3D_Texture_Size, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, Attenuation_3D_Texture_Data);

// Delete Attenuation 3D Texture Data

if(Attenuation_3D_Texture_Data)
delete [] Attenuation_3D_Texture_Data;
Attenuation_3D_Texture_Data = NULL;

return Attenuation_3D_Texture;

}



As you can see, the result is perfect :










But, I''ve a last bug, in fact, it''s not a bug, it''s a setup.
The bug comes from thr Register Combiners and I need to correctly setting up the RC because :



I''ve 2 solutions to fix it :

1. Inverter the attenuation texture generation color
2. Setup up the RC

I want the 2 solutions, because it''s more logical, but I''m not a gouru with the RC, so if someone can help me to set up the RC, here''s the code :


// **********************************************

void Setup_Register_Combiners() // Setup the Register Combiners

{
// Register Combiners Initialisation. We use 1 Register

glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);

// Light Color

float Light_Color[] = { 1.0f, 1.0f, 1.0f, 1.0f };

// We give the Light Color params to the Register Combiners

glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, (float *) &Light_Color);

// Register Combiners Calcul for the Light Attenuation

// ( 1 * Texture0 + 1 * Texture1)

glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);

// Final Register Combiners Initialisation with "(1 - Attenuation) * Color" calcul

glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);

// We enable the Register Combiners

glEnable(GL_REGISTER_COMBINERS_NV);

}


========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/

Share this post


Link to post
Share on other sites
Oups, I forgot the say : The Lighting with 3D Texture demo has been updated so you can re-download it the see the result and send me feedback (if you want).

Thanks

========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/

[edited by - Leyder Dylan on October 13, 2003 11:37:47 AM]

Share this post


Link to post
Share on other sites
Great. You made it work. In to fix the problem in RC replace GL_UNSIGNED_IDENTITY_NV with GL_UNSIGNED_INVERT_NV on unit using attenuation texture. But it would be more logical to use inverted texture. It should be full white in center and full black at edges.

You should never let your fears become the boundaries of your dreams.

Share this post


Link to post
Share on other sites
The texture has a white center and black border.

Now, I''ve used "GL_UNSIGNED_INVERT_NV" and that''s correct !

Thanks a million to you all, especially "Vincoof" and "_DarkWIng_" for your help.

I don''t have the time now to update the website, I''ll do that tomorrow.

Thanks a million again ...

========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/

Share this post


Link to post
Share on other sites
OK, now I''ve updated the demos : "Lighting with 3D Texture".

The source code will probably beeing release tomorrow (tuesday) in the afternoon.

I''ve only 2 things to fix :

- Clean and comment a maximum the source code.
- Use an ASCII file for the ARB String.

Next, the source code will be released.

Thanks.

========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/

Share this post


Link to post
Share on other sites