OpenGL ES 2.0 を使用して Android 用のゲームを開発していますが、バックグラウンドで星を描画するためのフラグメント シェーダーに問題があります。私は次のコードを持っています:
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 );
}
}
私の目的は、フラグメント座標を「量子化」することです。そのため、「星」のサイズは 1 ピクセルではなく、十分に離れた量子化されたピクセルをランダムな量で照らします。ただし、このコードは、実行される場所によって異なる結果を生成します。GLSL Sandbox ( http://glsl.heroku.com )、Nexus 7、および HTC Desire S を使用して比較を作成しました。
ご覧のとおり、GLSL Sandbox は、多くの星が見える密集したグリッドを生成します。Nexus 7 では、星ははるかに少なく、線に沿って分布しています (この小さな画像ではわかりにくいかもしれません) -rand
関数は期待どおりに機能しません。Desire S は星をまったく描画しません。
Nexus 7 で関数が奇妙に機能するのはなぜですかrand
(内積に使用されるベクトルを変更すると、星は異なる角度で線に沿って分布します)。また、Desire S が星をレンダリングしない原因は何でしょうか?
私は GLSL に非常に慣れていないので、このシェーダーの最適化のヒントもいただければ幸いです。それとも、フラグメント シェーダーを使用して「星」を描画するより良い方法があるのでしょうか?
アップデート
コードを次のように変更しました (参照としてhttp://glsl.heroku.com/e#9364.0を使用しました):
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 は、均一に分布したとても素敵な星を与えてくれます。しかし、Nexus 7 の問題はまだ残っています。prob = 0.97 の場合、星は表示されず、非常に低い prob = 0.01 の場合、星は水平線に沿ってまばらに配置されて表示されます。Tegra 3 の挙動がおかしいのはなぜですか?