ARB Vertex Program that Does Nothing?

Discuss programming topics that involve the OpenGL API.
Post Reply
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

ARB Vertex Program that Does Nothing?

Post by jitspoe »

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.

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?

Post by jitspoe »

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);
}
revelator
Posts: 2621
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Re: ARB Vertex Program that Does Nothing?

Post by revelator »

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.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: ARB Vertex Program that Does Nothing?

Post by Spike »

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?
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: ARB Vertex Program that Does Nothing?

Post by jitspoe »

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.
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: ARB Vertex Program that Does Nothing?

Post by jitspoe »

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:

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:

Image

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:

Image

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:

Image

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

Image

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?

Post by jitspoe »

Just came across this on the vertex program spec:
(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?
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: ARB Vertex Program that Does Nothing?

Post by Spike »

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.
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: ARB Vertex Program that Does Nothing?

Post by jitspoe »

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.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: ARB Vertex Program that Does Nothing?

Post by Spike »

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.
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: ARB Vertex Program that Does Nothing?

Post by jitspoe »

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:

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:
Image

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;
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: ARB Vertex Program that Does Nothing?

Post by Spike »

some lovely curves there...
Post Reply