single pass 6-way blend

Hi,

I’m currently implementing the Real-Time Hatching (http://research.microsoft.com/~hoppe/hatching.pdf) in my engine, and I’ve got a little problem. Quote from the paper “The first multitexturing stage performs two dot product, while the second stage adds the results”. In fact, I have to do two dotproduct between two texture and two color (primary and secondary) then blend this two results. For the moment my shaders use the GL_ARB_texture_env_combine extension and I don’t know why I can implement such stages? And even if I try to use three stage like, first one do a dotproduct, second too, and the third blend, I can’t because in the third stage I cannot reach the first result. Of course I can do it with three passes, but I don’t want to. Anyone’s got a idea? I may be miss a extension that permit to do that…

Arath

Just a quick idea, might not work ( the extension is not fresh in my mind ):

Perhaps you could compute the first dotproduct and store in in alpha, then in the next stage copy it to alpha ( to keep it ) while you use RGB to store the second dotproduct. In the third stage setup the blending.

I’m not oblige to use the gl_arb_texture_combine extension, but of course I try to use arb extension to make my engine compatible with most 3d cards. BTW is there any extension to do that :

Result = A dotprod Color0 + B dotprod Color1

Is it possible to do it with register combiner (I’ve got a nvidia card)?

Arath

Yes, it’s possible with Register Combiners ( and ATI’s fragment shaders ). If you don’t have to use ARB extensions, then I would definitely recommend using these extensions.

Originally posted by Arath:
[b]Hi,

I’m currently implementing the Real-Time Hatching (http://research.microsoft.com/~hoppe/hatching.pdf) in my engine, and I’ve got a little problem. Quote from the paper “The first multitexturing stage performs two dot product, while the second stage adds the results”. In fact, I have to do two dotproduct between two texture and two color (primary and secondary) then blend this two results. For the moment my shaders use the GL_ARB_texture_env_combine extension and I don’t know why I can implement such stages? And even if I try to use three stage like, first one do a dotproduct, second too, and the third blend, I can’t because in the third stage I cannot reach the first result. Of course I can do it with three passes, but I don’t want to. Anyone’s got a idea? I may be miss a extension that permit to do that…

Arath[/b]

I’ve implemented myself that sort of blending.
I’ve used NV_register_combiners on nvidia cards and GL_MODULATE_ADD_ATIX or GL_ATI_fragment_shader for ATI cards.
If these extensions aren’t supported you can make it with two passes cause without vertex programs this method will be pretty slow (if you are trying to render a real scene and not that 8000 polygons models)

Joel.

Thanks for your answer, I can’t hide I am a little bit disapointed by the fact there ain’t no solution with arb extension. I don’t own a ATI so it will be hard to implement this effect for thoses 3d card family … it will be done in two passes

joel > I planed to use the gl_arb_vertex_program to speed up the “lighting” coefficient calculation and my scene will weight about 50 ktri.

Arath

Perhaps you could compute the first dotproduct and store in in alpha, then in the next stage copy it to alpha ( to keep it ) while you use RGB to store the second dotproduct. In the third stage setup the blending.

Hey PH, you’ve got a good idea !
Arath: why do you think it wouldn’t work ?

Oh, and yes it’s very easy to perform such computations with register combiners.

Originally posted by Arath:
[b]Thanks for your answer, I can’t hide I am a little bit disapointed by the fact there ain’t no solution with arb extension. I don’t own a ATI so it will be hard to implement this effect for thoses 3d card family … it will be done in two passes

joel > I planed to use the gl_arb_vertex_program to speed up the “lighting” coefficient calculation and my scene will weight about 50 ktri.

Arath[/b]

Perhaps the solution PH gived you (store temp results in alpha) can give you the solution. Never played with this trick but I think it could work if you don’t have transparent objects.
With vertex programs i got that effect running well (don’t know exactly how much tris but quite a lot). I’ve slighty modified the wy they do their blending though cause i don’t use alpha ramps at the boundaries of the patches and i don’t calculate patches the way they do. with 50k tris and rendering with patch boundaries alpha i don’t think you’ll get high frame rate.
On nvidia’s site they have have a paper that covers this technique. They suggest a method to optimize the way you render your patches.

N.B. : not using alpha boundaries affects the quality of the rendering you get. It is just fine for me as their method was “too good”…

Joel.

vincoof > It might work to store the result in the alpha (I didn’t check completly the extension registry spec), but even I cannot have the secondary color fragement in the texture combine arb, the token isn’t defined!

Arath

I cannot have the secondary color fragement in the texture combine arb

You’re right, and obviously you use the secondary color in the following equation :
Result = A dotprod Color0 + B dotprod Color1

If your secondary color is constant you could fill the texture environment constant and use it instead, otherwise you could “waste” another texture unit bound to a normalized cube map, and call glMultiTexCoord3f(normalized_cube_map_unit, X, Y, Z) instead of calling glSecondaryColor3f(X, Y, Z).

The algorithm would be :

texture unit 0 :
TEXTURE_ENV_MODE = COMBINE
COMBINE_RGB = DOT3_RGBA
SOURCE0_RGB = PREVIOUS
OPERAND0_RGB = SRC_COLOR
SOURCE1_RGB = TEXTURE
OPERAND1_RGB = SRC_COLOR
>> outputRGB = previousRGB.textureRGB = primaryRGB.tex0RGB
>> outputALPHA = previousRGB.textureRGB = primaryRGB.tex0RGB

texture unit 1 :
TEXTURE_ENV_MODE = COMBINE
COMBINE_RGB = REPLACE
SOURCE0_RGB = TEXTURE
OPERAND0_RGB = SRC_COLOR
COMBINE_ALPHA = REPLACE
SOURCE0_ALPHA = PREVIOUS
OPERAND0_ALPHA = SRC_ALPHA
>> outputRGB = textureRGB = tex1RGB
>> outputALPHA = previousALPHA = primaryRGB.tex0RGB

texture unit 2 :
TEXTURE_ENV_MODE = COMBINE
COMBINE_RGB = DOT3_RGB
SOURCE0_RGB = PREVIOUS
OPERAND0_RGB = SRC_COLOR
SOURCE1_RGB = TEXTURE
OPERAND1_RGB = SRC_COLOR
COMBINE_ALPHA = REPLACE
SOURCE0_ALPHA = PREVIOUS
OPERAND0_ALPHA = SRC_ALPHA
>> outputRGB = previousRGB.textureRGB = tex1RGB.tex2RGB
>> outputALPHA = previousALPHA = primaryRGB.tex0RGB

texture unit 3 :
TEXTURE_ENV_MODE = COMBINE
COMBINE_RGB = ADD
SOURCE0_RGB = PREVIOUS
OPERAND0_RGB = SRC_COLOR
SOURCE1_RGB = PREVIOUS
OPERAND1_RGB = SRC_ALPHA
COMBINE_ALPHA = whatever you want
>> outputRGB = previousRGB+previousALPHA = (tex1RGB.tex2RGB) + (primaryRGB.tex0RGB)
>> outputALPHA = whatever

It’s heavy to use 4 texture units, so I strongly recommend using register combiners instead, because you don’t need to waste a texture unit for addition and don’t need to waste a texture unit for simulating glSecondaryColor.

thanks vincoof, unfortunately my secondary color is calculated in the vertex program (as well as the primary). As I want to code a full compatible program (and since I don’t own an ATI card), I have to do two passes :frowning:

Arath

Is it posssible to alterate the texture environment constant color with ARB_vertex_programs ?

Originally posted by Arath:
[b]thanks vincoof, unfortunately my secondary color is calculated in the vertex program (as well as the primary). As I want to code a full compatible program (and since I don’t own an ATI card), I have to do two passes :frowning:

Arath[/b]

I suggest you to code two path ways. one for nvidia cards and one for satdard OpenGL. I know it seems quite a pain but i managed 3 code paths (one more for ATI).
I’ really don’t think you will get real time with a 50k tris scene and multi pass with your vertex program. I don’t know if you have written it so far but mine it quite big.

Here are ouputs of a vertex program :

result.position
result.color
result.color.primary
result.color.secondary
result.color.front
result.color.front.primary
result.color.front.secondary
result.color.back
result.color.back.primary
result.color.back.secondary
result.fogcoord
result.pointsize
result.texcoord
result.texcoord[n]

IMHO, I can’t use a trick with this :frowning:

Arath

ok I’m not really surprised. Too bad though.

by the way, anyone try to use arb vertex program with nv_vertex_array_range? they didn’t talk about in the spec.

Arath

Originally posted by Arath:
[b]by the way, anyone try to use arb vertex program with nv_vertex_array_range? they didn’t talk about in the spec.

Arath[/b]

haven’t done it yet but i know it works with NV_vertex_program so it will surely be the same for the ARB version.

Joel.

If they don’t talk about it in the specifications, that simply means that there is no conflict (or that means they did half the job, which I doubt).

>>Result = A dotprod Color0 + B dotprod Color1
Is it possible to do it with register combiner (I’ve got a nvidia card)?<<

yes possible on my gf2mx in a single pass
with register combiners my landscape texturing uses the above