Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to use '%' in glsl

While writing a shader program today, I encountered a situation where I have to use % to find the remainder. GLSL gave me an error saying that it is not available in the current version.

I've tried several problems. GLSL doesn't support recursive function and while loops, which is needed if I want to create a function that can give me the result of (a % b).

So, I'm currently stuck. Can someone help me with this?

Edit. I was trying to emulate a CRT screen using some shader code from this website as reference code. I wanted to modify the color of the pixels at certain row and columns, so I needed to make use of the modulo operator.

At first, I thought that the modulus function was done using the % operator. It didn't work, so I tried using recursive function/while loop as a workaround for modulus function, which didn't work either.

like image 874
Artemis Toh Avatar asked Feb 02 '16 14:02

Artemis Toh


2 Answers

GLSL doesn't support recursive function and while loops, which is needed if I want to create a function that can give me the result of (a % b).

First, neither recursion nor looping is necessary to compute a mod b. That's easily done by a - (b * floor(a/b)).

Which is exactly what the built-in mod function does. If your version of GLSL doesn't support the % operator, then you're probably not able to get real integers either. So just use the mod function on your values.

like image 98
Nicol Bolas Avatar answered Oct 22 '22 03:10

Nicol Bolas


I am using webgl2. It seems that implicit conversion doesn't happen in GLSL. So floor( int(2) / int(3) ) is invalid. I am pretty sure (but not positive) that division between integers should result in truncation (and thus flooring). But just to be safe, I decided to go with a type-casting solution.

//:unsigned integers
uint mod_u32( uint u32_bas , uint u32_div ){

    float   flt_res =  mod( float(u32_bas), float(u32_div));
    uint    u32_res = uint( flt_res );
    return( u32_res );
}

//:signed integers
uint mod_i32( uint i32_bas , uint i32_div ){

    float   flt_res =  mod( float(i32_bas), float(i32_div));
    uint    i32_res = uint( flt_res );
    return( i32_res );
}

If you are confident that division between integers results in truncation of the decimal (fractional) portion then:

x - y * (x/y)

Should be all you need, since:

mod returns the value of x modulo y. This is computed as x - y * floor(x/y).

QUOTE_SOURCE: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/mod.xhtml

like image 32
twitchdotcom slash KANJICODER Avatar answered Oct 22 '22 01:10

twitchdotcom slash KANJICODER