ARB Vertex Program that Does Nothing?
Moderator: InsideQC Admins
12 posts
• Page 1 of 1
ARB Vertex Program that Does Nothing?
I'm messing around with vertex programs now, since a lot of the calculations don't need to be done per-pixel, but I'm getting weird results.
From what I've seen, this should give the same results as not having any vertex program (since I don't use more than position and texcoords 0-2), but that's not the case. I'm getting really small, tiling textures (1 quake unit?), when it should be a texture that fills the whole screen. What am I missing here?
- Code: Select all
!!ARBvp1.0
DP4 result.position.x, state.matrix.mvp.row[0], vertex.position;
DP4 result.position.y, state.matrix.mvp.row[1], vertex.position;
DP4 result.position.z, state.matrix.mvp.row[2], vertex.position;
DP4 result.position.w, state.matrix.mvp.row[3], vertex.position;
MOV result.color, vertex.color;
MOV result.texcoord[0], vertex.texcoord[0];
MOV result.texcoord[1], vertex.texcoord[1];
MOV result.texcoord[2], vertex.texcoord[2];
END
From what I've seen, this should give the same results as not having any vertex program (since I don't use more than position and texcoords 0-2), but that's not the case. I'm getting really small, tiling textures (1 quake unit?), when it should be a texture that fills the whole screen. What am I missing here?
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
Re: ARB Vertex Program that Does Nothing?
I'm guessing it has to do with this:
- Code: Select all
// alters texture matrix to handle our reflection
void R_LoadReflMatrix (void)
{
float aspect = (float)r_newrefdef.width/r_newrefdef.height;
qglMatrixMode(GL_TEXTURE);
qglLoadIdentity();
qglTranslatef(0.5f, 0.5f, 0.0f); // Center texture
qglScalef(0.5f * (float)g_reflTexW / REFL_TEXW,
0.5f * (float)g_reflTexH / REFL_TEXH,
1.0f); /* Scale and bias */
MYgluPerspective(g_last_known_fov, aspect, 4, 4096);
qglRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // put Z going up
qglRotatef(90.0f, 0.0f, 0.0f, 1.0f); // put Z going up
// do transform
R_DoReflTransform();
qglTranslatef(0.0f, 0.0f, 0.0f);
qglMatrixMode(GL_MODELVIEW);
}
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
Re: ARB Vertex Program that Does Nothing?
Not an Expert but i noticed matrix operations tend to scale the shader pic Down. Allthough tbh the only time i seen it was back when i toyed with Water shaders for quake 1.
Productivity is a state of mind.
-

revelator - Posts: 2567
- Joined: Thu Jan 24, 2008 12:04 pm
- Location: inside tha debugger
Re: ARB Vertex Program that Does Nothing?
if your vertex.position.w is not 1, try using dph instead of dp4?
make sure your engine does not specify texture coords in pixels, but rather specifies 0-1 instead?
make sure your engine does not specify texture coords in pixels, but rather specifies 0-1 instead?
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: ARB Vertex Program that Does Nothing?
It's using whatever texture coordinates Quake2 uses.
I think the issue is that the actual UV's passed in originally got ignored due to the qglMatrixMode(GL_TEXTURE); stuff. I'm not sure if I have access to the result of that in the vertex shader. I'm basically forced to pass the vertex UV's. The UV's used appear to be the ones actually set in code, so I guess it's "correct". It's just different from the previous behavior. I'll have to make the vertex program do what the R_LoadReflMatrix() function was doing. It appears that dividing the resulting position x/y/z by w brings the uv coords into screen space, which is what I want.
I think the issue is that the actual UV's passed in originally got ignored due to the qglMatrixMode(GL_TEXTURE); stuff. I'm not sure if I have access to the result of that in the vertex shader. I'm basically forced to pass the vertex UV's. The UV's used appear to be the ones actually set in code, so I guess it's "correct". It's just different from the previous behavior. I'll have to make the vertex program do what the R_LoadReflMatrix() function was doing. It appears that dividing the resulting position x/y/z by w brings the uv coords into screen space, which is what I want.
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
Re: ARB Vertex Program that Does Nothing?
Apparently there's a few things I don't understand about UV coordinates. I thought it was just as simple as setting the X and Y on the result.texcoords. I now see that W plays a role as well.
At first, to debug things, I was just doing vertex colors, and the result of this vertex program:
Plus displaying the vertex color in the fragment program was:

I thought it was odd that the colors were basically all or nothing, instead of gradually fading, so I tried scaling the UV's but couldn't come up with a value that really made sense, and it turns out, NOT scaling them and using them as texture coords resulted in this:

Pretty much what I would expect with 0,0 being the center of the screen and going from -1 to 1. The problem is, though, I can't just add 1 and divide by 2 to center the texture on the screen. It seems the values are tied to the W. Like the final result of the UV's is X and Y divided by W.
I tried dividing the values by W and using a W of 1:
(the last line doesn't really change anything since W * its reciprocal should be 1)
This was the result:

It's roughly what I want, and I could center the texture by adding 1, but it just gets super distorted at extreme angles...

What's the proper way to go about centering this without distortion?
At first, to debug things, I was just doing vertex colors, and the result of this vertex program:
- Code: Select all
!!ARBvp1.0
TEMP pos;
DP4 pos.x, state.matrix.mvp.row[0], vertex.position;
DP4 pos.y, state.matrix.mvp.row[1], vertex.position;
DP4 pos.z, state.matrix.mvp.row[2], vertex.position;
DP4 pos.w, state.matrix.mvp.row[3], vertex.position;
MOV result.position, pos;
TEMP recipPosW; # 1 / pos.w
RCP recipPosW, vertex.position.w;
TEMP screenUVs; # uv's in screen space
MUL screenUVs, recipPosW, pos;
MOV result.color, screenUVs;
MOV result.color.z, 0.0;
MOV result.color.w, 1.0;
MOV result.texcoord[0], screenUVs;
END
Plus displaying the vertex color in the fragment program was:

I thought it was odd that the colors were basically all or nothing, instead of gradually fading, so I tried scaling the UV's but couldn't come up with a value that really made sense, and it turns out, NOT scaling them and using them as texture coords resulted in this:

Pretty much what I would expect with 0,0 being the center of the screen and going from -1 to 1. The problem is, though, I can't just add 1 and divide by 2 to center the texture on the screen. It seems the values are tied to the W. Like the final result of the UV's is X and Y divided by W.
I tried dividing the values by W and using a W of 1:
- Code: Select all
TEMP recipTexW;
RCP recipTexW, screenUVs.w;
MUL screenUVs, screenUVs, recipTexW;
MOV screenUVs.w, 1.0;
(the last line doesn't really change anything since W * its reciprocal should be 1)
This was the result:

It's roughly what I want, and I could center the texture by adding 1, but it just gets super distorted at extreme angles...

What's the proper way to go about centering this without distortion?
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
Re: ARB Vertex Program that Does Nothing?
Just came across this on the vertex program spec:
Guess that explains my initial issue.
I guess I could offset the texture coords in the fragment program to fix the distortion issue, but I'd prefer to do as much as possible at the vertex level to keep per-pixel calculations to a minimum. I wonder why dividing by w causes so much distortion. Is it just a precision issue?
(3) What part of OpenGL do vertex programs specifically bypass?
Vertex programs bypass the following OpenGL functionality:
- The modelview and projection matrix vertex transformations.
- Vertex weighting/blending (ARB_vertex_blend).
- Normal transformation, rescaling, and normalization.
- Color material.
- Per-vertex lighting.
- Texture coordinate generation and texture matrix transformations.
- Per-vertex point size computations in ARB/EXT_point_parameters
- Per-vertex fog coordinate computations in EXT_fog_coord and
NV_fog_distance.
- Client-defined clip planes.
- The normalization of AUTO_NORMAL evaluated normals
- All of the above, when computing the current raster position.
Guess that explains my initial issue.
I guess I could offset the texture coords in the fragment program to fix the distortion issue, but I'd prefer to do as much as possible at the vertex level to keep per-pixel calculations to a minimum. I wonder why dividing by w causes so much distortion. Is it just a precision issue?
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
Re: ARB Vertex Program that Does Nothing?
if you're using a texture matrix then you'll probably want to include state.matrix.texture[n] in your program and translate your texture coords by that.
texture coords cannot be interpolated linearly across your primitive (aka: affine rendering, hence distortion). You need the divide-by-w in the fragment program itself.
in glsl: screentexturecoord = ((lerpedscreenvertexpos.xy / lerpedscreenvertexpos.w) * 0.5) + 0.5;
presumably just an extra rcp and a mad in an otherwise uninteresting fragment program. although yes, it does impose an extra texture indirection.
you'll probably want a fragment program anyway if only for a decent fresnel term.
texture coords cannot be interpolated linearly across your primitive (aka: affine rendering, hence distortion). You need the divide-by-w in the fragment program itself.
in glsl: screentexturecoord = ((lerpedscreenvertexpos.xy / lerpedscreenvertexpos.w) * 0.5) + 0.5;
presumably just an extra rcp and a mad in an otherwise uninteresting fragment program. although yes, it does impose an extra texture indirection.
you'll probably want a fragment program anyway if only for a decent fresnel term.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: ARB Vertex Program that Does Nothing?
I was able to do the divide by w fine in the fragment program. I'm curious as to why that doesn't have the distortion.
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
Re: ARB Vertex Program that Does Nothing?
depth distorts. there's no other way to really say that.
simply put, the rasterizer walks the screen in terms of pixels, but as parts of the surface get further into the distance, the worldspace length of the surface that is crossed per pixel gets larger, hence the need for a divide. The GPU normally figures out the correct fractions to interpolate the varyings properly for you, giving perspective-correct texture mapping and stuff. Except you're trying to project your screen image onto a projection, so you need a second divide. or something.
google for homogenous coords or something for actually useful info if you want.
simply put, the rasterizer walks the screen in terms of pixels, but as parts of the surface get further into the distance, the worldspace length of the surface that is crossed per pixel gets larger, hence the need for a divide. The GPU normally figures out the correct fractions to interpolate the varyings properly for you, giving perspective-correct texture mapping and stuff. Except you're trying to project your screen image onto a projection, so you need a second divide. or something.
google for homogenous coords or something for actually useful info if you want.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: ARB Vertex Program that Does Nothing?
Well, here's the code that actually works, if anybody is curious. I think this is about as minimal as I could get it:
Vertex program:
Fragment program:
One thing I find strange is that I can use either of these:
TEMP recipPosW; # 1 / vertex.position.w
RCP recipPosW, vertex.position.w;
MUL screenUVs, recipPosW, pos;
or
MOV screenUVs, pos;
and the result appears to be the same. I even tried making the W component of recipPosW 1 so it wouldn't scale the W component as well, but it didn't seem to make a difference.
I thought maybe I could reduce the fragment program by 1 instruction and move the RCP to the vertex program, storing 1/w in the w component instead of w:
Added to vertex program:
Fragment program, changed:
RCP recipW, fragment.texcoord[0].w;
to:
MOV recipW, fragment.texcoord[0].w;
The result:

Not as messed up as trying to do the full calculation at the vertex level, but there still ended up being a lot of distortion. I guess, like you said, "depth distorts". There must be some kind of special interpolation going on for the w component that just will not work with a reciprocal.
Actually, when I clean up all the temp vars that aren't necessary anymore, this is the most optimal vertex prog:
Vertex program:
- Code: Select all
TEMP screenUVs; # uv's in screen space
MOV screenUVs, pos;
PARAM scaleFlipReflection = { 0.5, -0.5, 1.0, 1.0 }; # negative value is because we need to flip on Y.
MUL screenUVs, screenUVs, scaleFlipReflection;
MOV result.texcoord[0], screenUVs;
Fragment program:
- Code: Select all
TEMP recipW;
TEMP reflectionUV;
RCP recipW, fragment.texcoord[0].w;
MAD reflectionUV, recipW, fragment.texcoord[0], 0.5; # scale and center the reflection texture
TEX endColor, reflectionUV, texture, 2D;
One thing I find strange is that I can use either of these:
TEMP recipPosW; # 1 / vertex.position.w
RCP recipPosW, vertex.position.w;
MUL screenUVs, recipPosW, pos;
or
MOV screenUVs, pos;
and the result appears to be the same. I even tried making the W component of recipPosW 1 so it wouldn't scale the W component as well, but it didn't seem to make a difference.
I thought maybe I could reduce the fragment program by 1 instruction and move the RCP to the vertex program, storing 1/w in the w component instead of w:
Added to vertex program:
- Code: Select all
TEMP recipTexW;
RCP recipTexW, screenUVs.w;
MOV result.texcoord[0].w, recipTexW.w;
Fragment program, changed:
RCP recipW, fragment.texcoord[0].w;
to:
MOV recipW, fragment.texcoord[0].w;
The result:

Not as messed up as trying to do the full calculation at the vertex level, but there still ended up being a lot of distortion. I guess, like you said, "depth distorts". There must be some kind of special interpolation going on for the w component that just will not work with a reciprocal.
Actually, when I clean up all the temp vars that aren't necessary anymore, this is the most optimal vertex prog:
- Code: Select all
PARAM scaleFlipReflection = { 0.5, -0.5, 1.0, 1.0 }; # negative value is because we need to flip on Y.
MUL result.texcoord[0], pos, scaleFlipReflection;
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
12 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 2 guests