Shaders and Projective Textures

Ostsol

New member
Erg. . . Okay, here's the problem: I don't know how to do it. :D Any instructions or links to pages that might have instructions on what I'm supposed to do for this?
 
Have you managed to do projected textures without shaders?

You should have ended up with 4d texture coordinates, where the fourth component is some sort of w or q, or whatever that's called :D

Anyways, if you're already at that point, insted of

glSampleMapATI(bla,bla,GL_SWIZZLE_STR_ATI,bla);

you use

glSampleMapATI(bla,bla,GL_SWIZZLE_STQ_DQ_ATI,bla);

HTH :)
 
Yep, I know that part, but. . . Hmm. . . let me explain a little further about what I have. . .

I'm also using vertex arrays via ATI_vertex_array_object. If I send in the texture array I end up with that texture coordinate. If I don't send in it in, I get no texture coordinate. I guess the big question is: where do the texture coordinates generated by glTexGen appear? Or am I going about this all wrong?
 
Ok, I've got it working, finally -- more or less. I'm using ARB_vertex_program and ARB_fragment_program, so I have no idea how it'd work with older extensions. Anyway, ARB_vertex_program allows one to access the data created by glTexGen. It's merely a matter of doing some reading on exactly what that method does and performing some calculations in the vertex shader to generate the texture coordinates.
 
Ok, I lied. It's working, but in a really crappy way -- not at all the same as it does without shaders. Here's my vertex program code:

Code:
!!ARBvp1.0

PARAM	mvp[4] = {state.matrix.mvp};
PARAM	texgenS = state.texgen[0].object.s;
PARAM	texgenT = state.texgen[0].object.t;
PARAM	texgenR = state.texgen[0].object.r;
PARAM	texgenQ = state.texgen[0].object.q;
PARAM	texmat[4] = {state.matrix.texture};

TEMP	texcoords;

MOV		result.color, vertex.normal;

DP4		result.position.x, mvp[0], vertex.position;
DP4		result.position.y, mvp[1], vertex.position;
DP4		result.position.z, mvp[2], vertex.position;
DP4		result.position.w, mvp[3], vertex.position;

DP4		texcoords.x, texgenS, vertex.position;
DP4		texcoords.y, texgenT, vertex.position;
DP4		texcoords.z, texgenR, vertex.position;
DP4		texcoords.w, texgenQ, vertex.position;

DP4		texcoords.x, texmat[0], texcoords;
DP4		texcoords.y, texmat[1], texcoords;
DP4		texcoords.z, texmat[2], texcoords;
DP4		texcoords.w, texmat[3], texcoords;

MOV		result.texcoord[0], texcoords;

END

According to the specs on glTexGen (..), each coordinate is defined by the following formula:

g = p1 * vo.x + p2 * vo.y + p3 * vo.z + p4 * vo.w

Basically, the dot 4 product of the "p" values and the vertex in object space.

As far as I can tell, further modifications by the texture matrix take place after this. This is applied simply by multiplying the matrix by the vector.

Is this all right? It doesn't seem to be working at all like it's supposed to. . .

Here's my fragment program code, too:

Code:
!!ARBfp1.0

OUTPUT	final = result.color;

ATTRIB	normal = fragment.color;

TEMP	temp, temp1, base;

# directional light vector
PARAM	lightdir = {1.0, 0.5, 0.0, 1.0};

# base texture
TEX		base, fragment.texcoord[0], texture[0], 2D;

# normalize the normal vector
DP3		temp, normal, normal;
RSQ		temp, temp.r;
MUL		temp, temp, normal;

# normalize the light vector
DP3		temp1, lightdir, lightdir;
RSQ		temp1, temp1.r;
MUL		temp1, temp1, lightdir;

# N.L
DP3		temp, temp, temp1;

# modulate with base texture
MUL		temp, temp, base;

# make sure the alpha is set to 1.0
MOV		temp.a, 1.0;

# output the result
MOV_SAT	final, temp;

END
 
Originally posted by Ostsol
Here's my fragment program code, too:

Code:
!!ARBfp1.0

OUTPUT	final = result.color;

ATTRIB	normal = fragment.color;

TEMP	temp, temp1, base;

# directional light vector
PARAM	lightdir = {1.0, 0.5, 0.0, 1.0};

# base texture
[color=red]TEX		base, fragment.texcoord[0], texture[0], 2D;[/color]

# normalize the normal vector
DP3		temp, normal, normal;
RSQ		temp, temp.r;
MUL		temp, temp, normal;

# normalize the light vector
DP3		temp1, lightdir, lightdir;
RSQ		temp1, temp1.r;
MUL		temp1, temp1, lightdir;

# N.L
DP3		temp, temp, temp1;

# modulate with base texture
MUL		temp, temp, base;

# make sure the alpha is set to 1.0
MOV		temp.a, 1.0;

# output the result
MOV_SAT	final, temp;

END
Try the TXP instruction :)
 
Doesn't make much of a difference. The thing still behaves much differently than when not using shaders.

For example, here's my transforms for the texture when I'm not using shaders:

glMatrixMode (GL_TEXTURE);
glLoadIdentity ();
glTranslatef (0.5f, 0.5f, 0.0f);
glScalef (0.5f, 0.5f, 1.0f);
gluPerspective (25.0f, 1.0f, 0.1f, 10000.0f);
glRotatef (10.0f, 1.0f, 0.0f, 0.0f);

This should translate the texture a bit to centre it in the window, double the size, adjust further for perspective, and rotate it 10° down. It works alright, everything behaving as it should.

However, if I try the same thing -with- shaders, the result is entirely different. The texture is translated the wrong direction, forcing me to change it to glTranslatef (-0.5f, -0.5f, 0.0f). Next the rotation is wrong, too. Instead of projecting the texture 10° down, it skews it to the left. In fact, the only rotation that gives the correct result is on the z axis.
 
I must admit I have never used ARB_vertex_program/ARB_fragment_program, so I'm a little stumped here.

But it sounds like a case of your matrix order being reversed, ie instead of row major you're getting column major. Which is strange, because the default matrix handling of ARB_vp seems to be just like in standard GL.

So, suggestion #1 (unlikely to work better, IMO):

PARAM texmat[4] = {state.matrix.texture.transpose};

__________________

Another thing I've noticed in your vertex program is your use of
MOV result.texcoord[0], texcoords;

I'm not sure, but I think this could be the major issue.
Try
MOV result.texcoord, texcoords;
instead to copy the complete vector. If that compiles and works, you may want to get rid of the final move altogether. Some examples in the spec document do that, and it would work out like this
Code:
!!ARBvp1.0

PARAM mvp[4] = {state.matrix.mvp};
PARAM texgenS = state.texgen[0].object.s;
PARAM texgenT = state.texgen[0].object.t;
PARAM texgenR = state.texgen[0].object.r;
PARAM texgenQ = state.texgen[0].object.q;
PARAM texmat[4] = {state.matrix.texture};

TEMP texcoords;

MOV result.color, vertex.normal;

DP4 result.position.x, mvp[0], vertex.position;
DP4 result.position.y, mvp[1], vertex.position;
DP4 result.position.z, mvp[2], vertex.position;
DP4 result.position.w, mvp[3], vertex.position;

DP4 texcoords.x, texgenS, vertex.position;
DP4 texcoords.y, texgenT, vertex.position;
DP4 texcoords.z, texgenR, vertex.position;
DP4 texcoords.w, texgenQ, vertex.position;

DP4 result.texcoord.x, texmat[0], texcoords;
DP4 result.texcoord.y, texmat[1], texcoords;
DP4 result.texcoord.z, texmat[2], texcoords;
DP4 result.texcoord.w, texmat[3], texcoords;

END

_________________

I firmly believe that my TXP instead of TEX suggestion for the fragment program is right on. Please keep it like that.
 
Whoa. . . that last fix you suggested to the output of my texture coordinates fixed it all. . . In object linear mode, the projection behaves exactly the same with and without shaders, now. About the TXP vs TEX, it now makes a difference -- which is really strange because I decided to check the value of w in the texture coordinate by assiging it to r, g, and b in the fragment program and outputing the result. The result was white. *shrugs* Anyway it works now, so I'm happy. :)

I've gotten it to work in eye linear mode, too. The problem there was that the vertex coords have to be multiplied by the modelview matrix, rather than the modelview-projection matrix (which I had been using before). Just for reference, here's my vertex shader program for eye linear mode:

Code:
!!ARBvp1.0

PARAM	mvp[4] = {state.matrix.mvp};
PARAM	mv[4] = {state.matrix.modelview};
PARAM	texgenS = state.texgen[0].eye.s;
PARAM	texgenT = state.texgen[0].eye.t;
PARAM	texgenR = state.texgen[0].eye.r;
PARAM	texgenQ = state.texgen[0].eye.q;
PARAM	texmat[4] = {state.matrix.texture};

TEMP	texcoords, vertcoords;

MOV		result.color, vertex.normal;

DP4		result.position.x, mvp[0], vertex.position;
DP4		result.position.y, mvp[1], vertex.position;
DP4		result.position.z, mvp[2], vertex.position;
DP4		result.position.w, mvp[3], vertex.position;

DP4		vertcoords.x, mv[0], vertex.position;
DP4		vertcoords.y, mv[1], vertex.position;
DP4		vertcoords.z, mv[2], vertex.position;
DP4		vertcoords.w, mv[3], vertex.position;

DP4		texcoords.x, texgenS, vertcoords;
DP4		texcoords.y, texgenT, vertcoords;
DP4		texcoords.z, texgenR, vertcoords;
DP4		texcoords.w, texgenQ, vertcoords;

DP4		result.texcoord.x, texmat[0], texcoords;
DP4		result.texcoord.y, texmat[1], texcoords;
DP4		result.texcoord.z, texmat[2], texcoords;
DP4		result.texcoord.w, texmat[3], texcoords;

END

Thanks for all the help! :)
 
Back
Top