- Home /
shader inverse(float4x4) function
Is there a way to successfully use the standard CG inverse(float4x4) / GLSL inverse(mat4) function in a Unity shader? When used in my surface shader, compilation chokes saying GLSL can't find a valid overload:
GLSL vertex shader: ERROR: 0:356: 'inverse' : no matching overloaded function
When I
#pragma exclude_renderers gles
it compiles, but as soon as I actually patch the code into anything that gets executed (in this case by putting the '#pragma vertex:vert' into the surface shader to run my custom vertex pre-shader), it breaks again and reports inverse is an undefined variable
Program 'vert_surf', undefined variable "inverse"
And before you ask, yes, I really do need to take an inverse here, and no, I can't guarantee offhand that the matrix will be simple enough to use any of the short-of-really-doing-the-proper-inverse hacks. The only alternative might be if I could couple my own complete vertex shader with a standard surface-shader rather than performing creative pre-vertex-shader-proper math, but I have seen no examples of that being viable.
Cg inverse() def: http://http.developer.nvidia.com/Cg/inverse.html
GLSL inverse() def: http://www.opengl.org/sdk/docs/manglsl/
You can't just precompute it and pass it in as a, ummm, uniform? You really have a different matrix for each vertex?
Decent point- for each vertex, no, but for each frame, yes. And the base matrix (long story short- it's the $$anonymous$$VP, but precisely what I'm doing is under NDA) is already in there, so crunching its inverse out in script every frame just to pass it to the shader which has access to the original matrix and should be able to take an inverse seems like equally much overkill to writing an inverse function in the shader.
I just looked -- about 300 math ops (multiplies and adds.) Not too bad, but not great. And Unity doesn't provide that one. I'd give it a try and see how fast it runs. Can you usually use a short-cut, toss in an "if $$anonymous$$VP hasn't changed..."
$$anonymous$$VP changes every frame, unfortunately. Crazy custom effect going on here. I've implemented my own inverse in two ways so far- if I'm doing less in the surface shader (e.g. basic diffuse/specular lighting), I can fit a fewer-lines/more-arithmetic-ops raw computation. I hit the cap on operations per shader on my card if I do that on e.g. a bumped-specular shader, though, in which case I have to build 16 3x3 submatrices and make a lot of deter$$anonymous$$ant() calls for the adjugate method proper.
Answer by DBN · Feb 16, 2014 at 09:12 PM
In case anyone else finds this question like I did, here's the function I ended up writing:
float4x4 inverse(float4x4 input)
{
#define minor(a,b,c) determinant(float3x3(input.a, input.b, input.c))
//determinant(float3x3(input._22_23_23, input._32_33_34, input._42_43_44))
float4x4 cofactors = float4x4(
minor(_22_23_24, _32_33_34, _42_43_44),
-minor(_21_23_24, _31_33_34, _41_43_44),
minor(_21_22_24, _31_32_34, _41_42_44),
-minor(_21_22_23, _31_32_33, _41_42_43),
-minor(_12_13_14, _32_33_34, _42_43_44),
minor(_11_13_14, _31_33_34, _41_43_44),
-minor(_11_12_14, _31_32_34, _41_42_44),
minor(_11_12_13, _31_32_33, _41_42_43),
minor(_12_13_14, _22_23_24, _42_43_44),
-minor(_11_13_14, _21_23_24, _41_43_44),
minor(_11_12_14, _21_22_24, _41_42_44),
-minor(_11_12_13, _21_22_23, _41_42_43),
-minor(_12_13_14, _22_23_24, _32_33_34),
minor(_11_13_14, _21_23_24, _31_33_34),
-minor(_11_12_14, _21_22_24, _31_32_34),
minor(_11_12_13, _21_22_23, _31_32_33)
);
#undef minor
return transpose(cofactors) / determinant(input);
}
Not too confident on the math or the speed but it worked for my needs. This code is released under the WTFPL license.
Answer by sean · Feb 22, 2012 at 03:54 PM
As a stop-gap, determinant() seems to be usable, so it's possible to write a tedious but fairly straightforward adjugate-method inverse function. This can chew up GPU resources/instructions, though, so a way to get at the inverse() ops directly would still be welcome.
Your answer
Follow this Question
Related Questions
Shardelab/CG shaders not working on iOS 1 Answer
How to force the compilation of a shader in Unity? 5 Answers
Cg Language incompatibility Desktop VS GLSL Android 0 Answers
How to prevent shader optimizations? 1 Answer
Grabpass refraction masking 0 Answers