Vertex Color Blend: lerp or multiply?

I was wondering which of the following vertex blending method is faster:

fixed4 baseTex = tex2D( _MainTex, i.uv_Main.xy );
fixed4 splat01 = tex2D( _SplatTex01, i.uv_Splat1.xy );
                
// Method 1: multiply texture by vertex color
fixed4 diff = baseTex;
diff.rgb = baseTex.rgb * i.color.a;
diff.rgb += splat01.rgb * i.color.r;

// Method 2: lerp between map 1 and 2 by vertex color
fixed4 diffBase;
diffBase = lerp( baseTex, splat01, i.color.r );

Personally, I like method #2 the best:
Smaller code to achieve the same thing.
Base texture will always show-up no matter what the vertex color is.

But I presume that doing a ‘lerp’ operation is more expensive then multiplying the textures by each vertex color. How much more expensive though? Will it slow the frame-rate down on a mobile device?

Thanks for any help in advance and thank you for your time!
Stephane

You’ve got to know your hardware. “Mobile device” is not a GPU class. With PowerVR hardware, this .r stuff is a bad idea. fixed translates to lowp, and swizzling lowp vectors is slow. .rgb or .a are all you want to access, if you can help it. I have no idea if this is true of other vendors’ hardware.

Don’t presume until you’re familiar with the hardware. This is what I have used to gain that familiarity, along with profiling on iOS devices:
http://www.imgtec.com/powervr/insider/powervr-pvrunisco.asp

My prediction is that the lerp will be faster, and neither method will yield any noticeable difference.

Thanks for the reply Jessy, very informative as always. I’m mostly working on iPhone/iPod 3rd and 4th gen devices. So swizzling lowp vectors is slow, how about swizzling highp vectors instead? Would it be faster even though it’s higher precision? Maybe using fixed function pipeline would be faster for this kind of shader?

I do actually use high vectors in the fragment shader, but only for special cases that involve scalars instead of vectors. Why don’t you pick out the scalar you need in the vertex shader, and send that over to the fragment shader?

No, the pipeline isn’t actually in place; it’s only emulated. A programmable shader done right will always be faster.

Picking the scalar in the vertex shader and sending it to the fragment shader is exactly what I wanted to do at first, but I couldn’t figure out how to do it, since I’m lerping texture2D maps, and this doesn’t work in the vertex shader the way I am currently doing it. Do you have any tips to make that happen?

That’s what I thought…I just have to make sure I use the correct precisions then :slight_smile:

Not in Cg. Here’s what you’d need for the relevant portion of the fragment shader to work in GLSL.

varying mediump vec2 uv_Main, uv_Splat1;
varying lowp float vertMix;
	
uniform lowp sampler2D baseTex, splat01;
void main() {
	lowp vec4 diffBase = mix(texture2D(baseTex, uv_Main), texture2D(splat01, uv_Splat1), vertMix);
	//...

Thanks for the code sample Jessy.
I ended up creating a single half value in the vertex2frag struct, and storing v.color.r into that variable in the vertex shader, and using the stored version in the fragment shader, that way there’s no funny business going on in the fragment shader with .r!

You were very helpful as always and I appreciate your help, thank you!

I wouldn’t recommend that. PVRUniSCo told me that used five times more cycles per-pixel, than lowp! There won’t be any visual benefit, if the textures are fixed4. It also told me using .r doesn’t result in any slowdown in the mix statement, and that using .a or .b of a lowp vec4 is twice as fast as using a lowp float. I can’t get the latest version of the app to run, with the latest compilers, so it’s possible that some of this isn’t true, but I’d be inclined to listen to the results, when it wouldn’t affect coding speed. YMMV.

Yep, I noticed the slowdown hahaha. You know I tried using PVRUniSCo a while back but I was having a hard time getting it to work correctly so I gave up and moved on, but I should give it another try now, maybe this time around will be a better experience :slight_smile:

Thanks Jessy!