Fragment Shader in dot3 bumpmapping. . .

Ostsol

New member
Okay. . . I've -finally- managed to get bump-mapping working two different ways: calculating the light vector in tangent space in software, and doing the same via a vertex shader. Upon examining fragment shaders, however, it looks like the same job will require an entirely different method. Vertex colours appear to be irrelevant since the shading is done on a per pixel basis. Not only that, but fragment shading seems to deal entirely with textures.

I can see the basic theory as to how this -might- be accomplished. One has to find the light vector in tangent space to the individual pixel. This will determine the colour and can be sent through the fragment shader to undergo the same equations with the tangent map that they go through via the texture environments. I hope that made sense. . . because I have no idea how I might get that colour to the fragment shader in the first place. . .

Any possible help, here?
 
Check out the RADEON 8500 Point Light Shader sample

Check out the RADEON 8500 Point Light Shader sample

I think you'll want to check out the source for the RADEON™ 8500 Point Light Shader sample. This application uses both fragment shaders and vertex shaders to do a variety of effects, including per-pixel lighting.

If you have any questions after stepping through this source, let us know.

-Jason
 
You can access the primary color in a fragment shader, just like you access a constant or a register. For instance like this:

Code:
glColorFragmentOp2ATI(GL_MUL_ATI,  GL_REG_0_ATI,         GL_NONE, GL_NONE,
                                   GL_REG_1_ATI,         GL_NONE, GL_NONE,
                                   GL_PRIMARY_COLOR_ARB, GL_NONE, GL_NONE);
 
Re: Check out the RADEON 8500 Point Light Shader sample

Re: Check out the RADEON 8500 Point Light Shader sample

JasonM [ATI] said:
I think you'll want to check out the source for the RADEON™ 8500 Point Light Shader sample. This application uses both fragment shaders and vertex shaders to do a variety of effects, including per-pixel lighting.

If you have any questions after stepping through this source, let us know.

-Jason

Yeah, I've noticed that, but given the number of other fragment shader effects that are used in conjunction with Dot3 bumpmapping in the rusty shader, I haven't been having the easiest of times at isolating the single effect. I'll certainly take another look into it again, though. . . Thanks. . .

You can access the primary color in a fragment shader, just like you access a constant or a register.

Thanks! Somehow I missed that when looking through the fragment shader specs. . . :hmm: Anyway, I had been thinking that per-pixel bumpmapping was a matter of calculating the light vector on a per pixel basis, making for more accurate bumpmapping. As a beginning, however, I guess that simulating the texture environments with fragment shaders would be a good idea, though. . .


I'm really having a quite amusing time experimenting with fragment shaders. I've managed to accidentally create some really strange things -- none of which I wanted, but they're interesting nevertheless. My latest misshap resulted in concentric circles (instead of textures), each of which blends from black on the inner edge to white on the outer. Really cool. . . but not exactly what I wanted. Still, this points to some interesting possibilities in the area of textures created by mathematical equations. . . I think I'll take a screenshot of this strange result I got. . .
 
Re: Re: Check out the RADEON 8500 Point Light Shader sample

Re: Re: Check out the RADEON 8500 Point Light Shader sample

Ostsol said:
Anyway, I had been thinking that per-pixel bumpmapping was a matter of calculating the light vector on a per pixel basis, making for more accurate bumpmapping.

Sure, there are many ways to do it, puting lightvectors into the primary color won't really give you per pixel lighting though IMO, as much of it is still just interpolated. I don't use primary color to store the lightvector, I store the lightvector in the texture coordinates and get lightvectors on a per pixel basis from a 3d texture. It's very easy and gives good results.
 
Okay, I seem to have a problem. I've been trying to emulate the same thing that is accomplished via texture environments. . .

Code:
// bump map
glActiveTextureARB (GL_TEXTURE0_ARB);
	glEnable (GL_TEXTURE_2D);
	glBindTexture (GL_TEXTURE_2D, normalmapID);

	glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
	glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);

	glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);

	glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

// base texture
glActiveTextureARB (GL_TEXTURE1_ARB);
	glEnable (GL_TEXTURE_2D);
	glBindTexture (GL_TEXTURE_2D, basetextureID);

	glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
	glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);

	glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);

	glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

. . . using the fragment shader.

According to the specs for ARB_texture_env_dot3 and ARB_texture_env_combine, the equations to produce a bump-mapped effect should be the following:

R = G = B = 4 * ((l.r - 0.5) * (n.r - 0.5) + (l.g - 0.5) * (n.g - 0.5) + (l.b- 0.5) * (n.b - 0.5))

"l" is the light vector and "n" is the normal map. That result is then modulated with the base map.

I determined the light vector and multiplied it into tangent space per vertex in the vertex shader and assigned it as the primary colour. In the fragment shader I tried to emulate the above equation like this:

Code:
gluiFragmentShader = glGenFragmentShadersATI (1);
glBindFragmentShaderATI (gluiFragmentShader);
glBeginFragmentShaderATI ();
{
	// sample the bump map
	glSampleMapATI (GL_REG_1_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STR_ATI);

	// sample the base map
	glSampleMapATI (GL_REG_2_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI);

	// 4 * ((l.r - 0.5) * (n.r - 0.5) + (l.g - 0.5) * (n.g - 0.5) + (l.b- 0.5) * (n.b - 0.5))
	glColorFragmentOp2ATI (GL_DOT3_ATI,
				   GL_REG_3_ATI, GL_NONE, GL_4X_BIT_ATI,
				   GL_PRIMARY_COLOR_ARB, GL_NONE, GL_BIAS_BIT_ATI,
				   GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI);

	// modulate reg 3 with the base map
	glColorFragmentOp2ATI (GL_MUL_ATI,
				   GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
				   GL_REG_3_ATI, GL_NONE, GL_NONE,
				   GL_REG_2_ATI, GL_NONE, GL_NONE);
}
glEndFragmentShaderATI ();

The result is a black and white image that doesn't even appear to be done properly anyway. What looks like the base map is rendered (in black and white), but the colour is not uniform across the texture. If I don't bother modulating with the base map, there doesn't seem to be a difference. Interestingly enough, the base map appears to be just a totally white field. When I bypass all operations and just output the original texture, what was supposed to be the bump map results in the base map. What was supposed to be the base map is the white field. This would explain why modulating or not makes no difference: all the values in the base map are 1.0. I've enen tried commenting everything out except for:

Code:
glSampleMapATI (GL_REG_2_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI);

glColorFragmentOp1ATI (GL_MOV_ATI,
			   GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
			   GL_REG_2_ATI, GL_NONE, GL_NONE);

No effect. The base map is still white.

Any ideas as to what is going on?
 
Two things to try on the fragment shader:
  1. use STQ swizzle for 2D textures
  2. OR together the bias and 2x bits on the arguments to the dot product and don't scale the output
    [/list=1]-Jason
 
Re: Re: Re: Check out the RADEON 8500 Point Light Shader sample

Re: Re: Re: Check out the RADEON 8500 Point Light Shader sample

Humus said:


Sure, there are many ways to do it, puting lightvectors into the primary color won't really give you per pixel lighting though IMO, as much of it is still just interpolated. I don't use primary color to store the lightvector, I store the lightvector in the texture coordinates and get lightvectors on a per pixel basis from a 3d texture. It's very easy and gives good results.
Nothing wrong with using color interpolators for doing this, it's just that it wont give you the best output.

I prefer using a slightly tesselated model (in the model for now, I might move it to PNTriangles later), and then use JUST texture coords.

Cube maps (or any kind of texture) for normalization gives low precision output and is REALLY noticeable on specular lighting and perpixel reflections/refractions. They are ok for doing just DOT3 though.
 
JasonM [ATI] said:
Two things to try on the fragment shader:
  1. use STQ swizzle for 2D textures
  2. OR together the bias and 2x bits on the arguments to the dot product and don't scale the output
    [/list=1]-Jason


  1. Doesn't seem to help. . .

    It looks like the only problem is that the fragment shader appears to be only able to sample the one texture and defaults the data for the other one to just all white. Not only that, but it is the -wrong- texture. The register assigned to sample from texture unit 0, the one that is supposed to have the normal map, displays the base map data. When I reverse my texture binding (assigning the base map to texture unit 0 and the normal map to texture unit 1):

    Code:
    glActiveTextureARB (GL_TEXTURE0_ARB);
    	glEnable (GL_TEXTURE_2D);
    	glBindTexture (GL_TEXTURE_2D, basemapID);
    
    glActiveTextureARB (GL_TEXTURE1_ARB);
    	glEnable (GL_TEXTURE_2D);
    	glBindTexture (GL_TEXTURE_2D, bumpmapID);

    . . . the opposite occurs -- it is the normal map that can be displayed and the base map that is whited out. I can only get one texture to work at a time! Infuriating!
 
Hmm. . . another strange thing: Right now texture unit 0 give me the wrong texture, but at least it gives me a texture, while unit 1 gives me white. If I abandon unit 1 and use unit 2 in its place (binding the texture to 2, of course), it is unit 2 that works and gives me the right texture while unit 0 gives me white. Ack!
 
What the smeg!? Ok. . . is there something about texture unit 0 that I don't know about? Is it reserved or does it have something special associated with it? I just moved everything up one texture unit. That that was formerly in texture unit 1 is now in 2 and that that was formerly in texture unit 0 is now in 1. Unit 0 is no longer being used. . . and now everything works. :hmm: Is this a bug?
 
Actually, that makes sense. The map sampled is determined by the first argument to glSampleMapATI ( uint dst, uint interp, enum swizzle ). The second argument determines which interpolator to use, not which texture to sample. So, what you're doing is sampling texture 1 with your zeroth set of texture coordinates and texture 2 with your 1st set of texture coordinates. You're not sampling texture 0 at all. Try:
Code:
	glSampleMapATI (GL_REG_0_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STQ_ATI);	
	glSampleMapATI (GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STQ_ATI);
and subsequently change the rest of the code to use the right registers (r0 and r1).

-Jason
 
Ah! That works! So when sampling textures one has to make sure to match up the registers and interpolators?

(Now that you've mentioned it, I do remember seeing an old version of the ATI Hardware Shading document where the tokens used were GL_INTERP_x_ATI -- or something like that --, rather than GL_TEXTUREx_ARB. Based on an old, spec I guess.)

Thanks for the help!
 
No, you don't have to match them up, you just have to realize that the texture you sample is tied to the register, not the interpolator.

-Jason
 
JasonM [ATI] said:
No, you don't have to match them up, you just have to realize that the texture you sample is tied to the register, not the interpolator.

-Jason

Ah. . . Okay. . . I understand where the data for texture samples comes from now. I'll just have to do some studying and experimentation to figure out interpolators, now. Thanks for all the help!
 
Back
Top