GLSL ES fragment shader produces very different results on different devices

删除回忆录丶 提交于 2020-01-14 18:45:53

问题


I am developing a game for Android using OpenGL ES 2.0 and have a problem with a fragment shader for drawing stars in the background. I've got the following code:

precision mediump float;
varying vec2 transformed_position;

float rand(vec2 co) {
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

void main(void) {
    float distance = 10.0;
    float quantization_strength = 4.0;
    vec3 background_color = vec3(0.09, 0.0, 0.288);
    vec2 zero = vec2(0.0, 0.0);
    vec2 distance_vec = vec2(distance, distance);
    vec2 quantization_vec = vec2(quantization_strength, quantization_strength);
    vec2 new_vec = floor(transformed_position / quantization_vec) * quantization_vec;
    if(all(equal(mod(new_vec, distance_vec), zero))) {
        float rand_val = rand(new_vec);
        vec3 current_color = background_color * (1.0 + rand_val);
        gl_FragColor = vec4(current_color.x, current_color.y, current_color.z, 1.0);
    } else {
        gl_FragColor = vec4(background_color.x, background_color.y, background_color.z, 1.0 );
    }
}

My aim is to 'quantize' the fragment coordinates, so 'stars' are not 1px in size, and then light up quantized pixels that are distant enough by a random amount. This code, however, produces different results depending on where it is executed. I have used GLSL Sandbox (http://glsl.heroku.com), Nexus 7 and HTC Desire S to create comparison:

As you can see, GLSL Sandbox produces dense grid with many stars visible. On Nexus 7 stars are much fewer and distributed along lines (which may be not obvious on this small image) - the rand function does not work as expected. Desire S draws no stars at all.

Why does the rand function work so strangely on Nexus 7 (if I modify the vector used for dot product, stars are distributed along lines at different angle)? And what might cause Desire S not to render the stars?

I would also appreciate any optimization tips for this shader, as I am very inexperienced with GLSL. Or perhaps there is better way to draw 'stars' via fragment shader?

UPDATE

I changed the code to this (I used http://glsl.heroku.com/e#9364.0 as reference):

precision mediump float;
varying highp vec2 transformed_position;
highp float rand(vec2 co) {
    highp float a = 1e3;
    highp float b = 1e-3;
    highp float c = 1e5;
    return fract(sin((co.x+co.y*a)*b)*c);
}

void main(void) {
    float size = 15.0;
    float prob = 0.97;
    lowp vec3 background_color = vec3(0.09, 0.0, 0.288);
    highp vec2 world_pos = transformed_position;
    vec2 pos = floor(1.0 / size * world_pos);
    float color = 0.0;
    highp float starValue = rand(pos);
    if(starValue > prob) {
    vec2 center = size * pos + vec2(size, size) * 0.5;
    float xy_dist = abs(world_pos.x - center.x) * abs(world_pos.y - center.y) / 5.0;
    color = 0.6 - distance(world_pos, center) / (0.5 * size) * xy_dist;
    }
    if(starValue < prob || color < 0.0) {
        gl_FragColor = vec4(background_color, 1.0);
    } else {
        float starIntensity = fract(100.0 * starValue);
        gl_FragColor = vec4(background_color * (1.0 + color * 3.0 * starIntensity), 1.0);
    }
}

Desire S now gives me very nice, uniformly distributed stars. But the problem with Nexus 7 is still there. With prob = 0.97, no stars are displayed, and with very low prob = 0.01, they appear very sparsely placed along horizontal lines. Why does Tegra 3 behave so strangely?

来源:https://stackoverflow.com/questions/17596393/glsl-es-fragment-shader-produces-very-different-results-on-different-devices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!