PDA

View Full Version : large fixed point values in glsl



blubee
08-12-2015, 11:46 PM
I wrote a simple program to draw a mandelbrot set in the fragment shader, it's currently using a uniform float as it's scale factor which allows a certain degree of zoom ability but then the image quality deteriorates really badly and I can't get to some of the more interesting places in the set.

I was wondering is it possible to use large fixed point values and send them into the fragment shader?

I would need a really large factional part and only 1 or 2 bits for decimal since it'll be around 1 to -1.[0000000000...]

I might be approaching the problem wrong I am unsure that's why I am asking here. How can I send such large numbers to the fragment shader? I noticed that I am able to do logical shifts in the fragment shader so 1<<30 or 1>>30 both work.

I am just unsure how to put it together. Here's the fragment shader btw.


#version 330 core

in vec4 fcolor;
in vec2 fTexCoord;
in vec2 fCoord;

uniform int maxIterations;
uniform sampler1D mandiTexture;
uniform vec2 center;
uniform float scale;

out vec4 color;

void main()
{
float ONE_OVER_LOG_TWO = 1.0f/0.69314718055f;
vec2 c, z;
vec4 colora, colorb;

c.x = (fCoord.x * scale) + center.x;
c.y = (fCoord.y * scale) + center.y;

int i;
z = vec2(0.0f, 0.0f);
float size, smoothed, colorI;

for(i=0; i< maxIterations; i++) {
float x = (z.x * z.x - z.y * z.y) + c.x;
float y = (z.y * z.x + z.x * z.y) + c.y;

if((x * x + y * y) > (1 << 30))
{
break;
}
z.x = x;
z.y = y;
}

vec4 tcolor;

if (i == maxIterations)
{
tcolor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
else
{
float tr, tg, tb;
float t = float(i)/float(maxIterations);
tr = (9*(1-t)*t*t*t);
tg = (15*(1-t)*(1-t)*t*t);
tb = (8.5*(1-t)*(1-t)*(1-t)*t);
tcolor = vec4(tr, tg, tb, 1.0f);
}

color = tcolor;
}

GClements
08-13-2015, 04:10 AM
I might be approaching the problem wrong I am unsure that's why I am asking here. How can I send such large numbers to the fragment shader? I noticed that I am able to do logical shifts in the fragment shader so 1<<30 or 1>>30 both work.
If you can rely upon support for OpenGL 4.0 or later, you can just use double precision (i.e. GLSL variables of type "double" and glUniform2d() etc).

Otherwise, you're limited to 32-bit signed or unsigned integers (and vectors thereof), both for the uniforms and for local variables within the shader. Bear in mind that any multiplies will also be limited to a 32-bit result, so for fixed-point arithmetic you'd need to perform up to four 16x16->32 multiplies for each fixed-point multiply.

blubee
08-14-2015, 12:28 PM
thanks for the reply, with this project I cannot use double precision as it's on mobile mainly.

On the irc channel someone recommended checking out perturbation, that seems like quite a lot of math. Is that something feasible to get better resolution on android?

currently I get about this much detail with 32 bit float values in the fragment shader.
20422043

GClements
08-14-2015, 02:52 PM
thanks for the reply, with this project I cannot use double precision as it's on mobile mainly.
Even highp floats aren't guaranteed to have more than a 16-bit mantissa. And the fragment shader isn't required to support highp, only mediump. mediump floats may only have a 10-bit mantissa, and integers may only have 11 bits (including the sign). highp integers (where supported) need only have 17 bits (including the sign).

You can use glGetShaderPrecisionFormat (https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderPrecisionFormat.xml) to determine the number of bits of precision for each type and precision for each shader type.

If you want reasonable precision even on devices which only meet the minimum requirements of the specification, you'll need to use two or three integers to store each component and implement your own add/subtract/multiply operations.


currently I get about this much detail with 32 bit float values in the fragment shader.
That looks more like a consequence of the iteration limit than precision.