Ive been trying to make a 2.5D engine with depth and normal map textures for a few weeks now, not unlike whats used here Linky. After thinking the drawing of a depth map in the fragment shader from a texture was impossible due to ES 2.0 missing the gl_fragDepth variable I found a tutorial for iOS where they used glBlendEquation with the mode GL_MIN/GL_MAX to "fake" depth buffering of the fragment to a framebuffer-texture Linky. Unfortunely GLES20.glBlendEquation makes the application crash on both my phones (SGS 1/2) with UnsupportedOperationException. So Im wondering if anyone has used this function to any success? GL_MIN/GL_MAX also seems to be missing from the Android Opengl ES 2.0 spec so Im probably out of luck here...
Any ideas?
BTW It does seem to work in GL11Ext but since Im using the fragment shader for normal mapping this wont work from me.
i was experimenting on my Vega tablet (Tegra) and this worked for me:
fragment shader:
#extension GL_NV_shader_framebuffer_fetch : require
// makes gl_LastFragColor accessible
precision highp float;
varying vec2 v_texcoord;
uniform sampler2D n_sampler;
void main()
{
vec4 v_tex = texture2D(n_sampler, v_texcoord);
gl_FragColor = min(gl_LastFragColor, v_tex); // MIN blending
}
Pretty easy, huh? But i'm afraid this will be NV-only.
Related
I'm making a simple image filter app in android and I implemented lowpass filter using same method in GPUImage(https://github.com/BradLarson/GPUImage)
it buffers the previous and current camera frames mixture and render it.
So i created a buffer FBO and render the current camera texture, re-use it as a texture for mixture in lowpass filter shader with next camera texture.
I tested my code with some smartphones(Galaxy S10, Nexus 6P, etc..) and it worked well. However in Galaxy S8(Mali-G71) the result is strange and I don't know what was wrong.
These are the wrong results
Here are my code:
Fragment shader:
varying vec2 vTextureCoord;
uniform sampler2D sTexture1;
uniform float filterStrength;
void main() {
vec4 texColor0 = texture2D(sTexture, vTextureCoord);
vec4 texColor1 = texture2D(sTexture1, vTextureCoord);
gl_FragColor = mix(texColor0, texColor1, filterStrength);
}
What can cause this results?
Thanks in advance.
The artifacts look tile aligned for Mali, so if I had to guess you are reading the currently bound framebuffer color attachment as an input texture at the same time as writing in to it.
This is "implementation defined" behavior in the specification, and concurrent reads and writes will definitely do bad things on a tile-based renderer like Mali.
I try to create noise screen on Android device. For getting random I use this formula:
fract((sin(dot(gl_FragCoord.xy ,vec2(0.9898,78.233)))) * 4375.85453)
I tested it in http://glslsandbox.com/ and it's work perfect.
Result form http://glslsandbox.com/
But on phone and tablet I have another result
On Nexus 9 I receive this:
But it's not so bad. On LG-D415 I receive this
Can somebody help me with it?
Shader:
#ifdef GL_ES
precision mediump float;
#endif
float rand(vec2 co){
return fract((sin(dot(co.xy ,vec2(0.9898,78.233)))) * 4375.85453);
}
void main() {
vec2 st = gl_FragCoord.xy;
float rnd = rand(st);
gl_FragColor = vec4(vec3(rnd),1.0);
}
It's almost certainly a precision issue. Your mediump based code might be executed as standard single precision float on some devices or half precision on others (or anywhere in between).
Half precision simply isn't enough to do those calculations with any degree of accuracy.
You could change your calculations to use highp, but then you'll run into the next problem which is that many older devices don't support highp in fragment shaders.
I'd strongly recommend you create a noise texture, and just sample from it. It'll produce much more consistent results across devices, and I'd expect it to be much faster on the majority of mobile GPUs.
This is an interesting article about floating point precision: http://www.youi.tv/mobile-gpu-floating-point-accuracy-variances/
This is the related app on the Google Play store.
This is a more in-depth discussion of GPU precision: https://community.arm.com/groups/arm-mali-graphics/blog/2013/05/29/benchmarking-floating-point-precision-in-mobile-gpus
I'm writing shader codes in the GPUImage framework in Android. Then I encounter a problem of array indexing in the fragment shader.
According to Appendix of The OpenGL ES Shading Language, in vertex shader, uniform arrays can be indexed by any integer, and varying arrays can be indexed by constant-index-expression. In fragment shader, both (uniform/varying) arrays can only be indexed by constant-index-expression. Under the definition of constant-index-expression, the for-loop index should be able to used as an array index.
However, things go wrong when I use the loop index as array index in fragment shader. There is no compile error and the shader codes can be run, but it seems that the program treats all index value to 0 during every round in the loop.
Here is my fragment shader codes:
uniform sampler2D inputImageTexture;
uniform highp float sample_weights[9]; // passed by glUniform1fv
varying highp vec2 texture_coordinate;
varying highp vec2 sample_coordinates[9]; // computed in the vertex shader
...
void main()
{
lowp vec3 sum = vec3(0.0);
lowp vec4 fragment_color = texture2D(inputImageTexture, texture_coordinate);
for (int i = 0; i < 9; i++)
{
sum += texture2D(inputImageTexture, sample_coordinates[i]).rgb * sample_weights[i];
}
gl_FragColor = vec4(sum, fragment_color.a);
}
The result will be correct if I unroll the loop and access [0] to [8] for the arrays.
However, when using the loop index, the result is wrong and becomes the same as running
sum += texture2D(inputImageTexture, sample_coordinates[0]).rgb * sample_weights[0];
by 9 times, and there is no compile error reported during the process.
I've only tested one device, which is Nexus 7 with Android version 4.3. The GPUImage framework uses android.opengl.GLES20, but not GLES30.
Is this an additional restriction on shader codes in Android devices, or in OpenGL ES 2.0, or it is a device-dependent issue?
Updated:
After testing more Android devices (4.1~4.4), It seems that only that Nexus 7 device has this issue. The results on other devices are correct. It's weird. Is this an implementation issue on individual devices?
This is a little known fact, but texture lookups inside loops are an undefined thing in GLSL. Specifically the tiny sentence: "Derivatives are undefined within non-uniform control flow", see section 8.9 of the GLSL ES spec. And see section 3.9.2 to find out what non uniform control flow. The fact that this works on other devices is by chance.
Your only option may be to un roll the loop unfortunately.
I'm learning OpenGL ES 2.0 in Android, do you know of a library providing already existing shaders?
I'm on a project with a friend who's developing on iOS, he told me that he can use GLKBaseEffect to avoid devolping custom shaders, as long as we don't need complex features. Is there an equivalent of that BaseEffect in Android?
I'm asking this because the two of us have been assigned this project by a professor, who told us that it's not important for this project to develop custom shaders, so I'm guessing there is a compilation of basical shaders that I can browse.
Is that correct?
Thank you for your help!
Android doesn't support something like the GLKBaseEffect class but I want you to know that shader is just supported for being programable so shader is not hard at all if you use simple shader codes.
If you don't want to do any post imageprocessing don't change fragment shader that is only what you should do.
Vertex shader
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
void main(void)
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy;
}
Fragment shader
uniform sampler2D texture0;
varying vec2 textureCoordinate;
void main()
gl_FragColor = texture2D(texture0, textureCoordinate);
}
Now you need to put only three values position, texture cordinate and texture :) as you need to do anywhere
I've been starting out using LibGDX to develop for PC as well as Android. I'm currently working on a little project requiring me to write custom shaders in GLSL (based on full-screen quads). Coming from a HLSL environment I had a little trouble setting the whole shader system up in combination with SpriteBatch (as I want to keep the code simple where I can).
I have the following shader code working on desktop:
Vertexshader:
attribute vec4 a_position;
uniform mat4 u_projectionViewMatrix;
void main()
{
gl_Position = a_position * u_projectionViewMatrix;
}
Fragmentshader:
uniform vec2 effectOrigin;
uniform vec2 effectDir;
void main()
{
float distToOrigin = distance(effectOrigin.xy, gl_FragCoord.xy);
gl_FragColor = vec4(mod(distToOrigin+effectDir.x*30, 30)-15, 0.0, 0.0, 1.0);
}
As I said it works on desktop (Windows), and gives me a nice circle pattern. On Android however it doesn't compile and gives me just the cleared background color. I suspected it had something to do with OpenGL ES 2 permissions on Android so I added this line to the manifest:
<uses-feature android:glEsVersion="0x00020000" android:required="true" />, but this didn't seem to make a difference.
I also thought it might have something to do with the precision of the floats and vectors, but I wasn't able to figure out how I would have to change them in order to fix it.
Is there someone who can help me on this? I haven't been able to find an answer elsewhere!
Thanks in advance,
Yuri
P.S. Is there a way to see what went wrong during compiling of the shaders? I know debugging is hard on shaders, but it would be awesome to have at least some idea of where it could've gone wrong during compilation.
Fixed it using P.T.´s suggestion on logging the compilation!
There were two problems in the fragment shader, the fixed shader looks like this:
precision mediump float;
uniform vec2 effectOrigin;
uniform vec2 effectDir;
void main()
{
float distToOrigin = distance(effectOrigin.xy, gl_FragCoord.xy);
gl_FragColor = vec4(mod(distToOrigin+effectDir.x*30.0, 30.0)-15.0, 0.0, 0.0, 1.0);
}
I added the precision definition at the top, and also changed the constant values from integers to floats (e.g. 15 to 15.0) to fix it!
Thanks P.T.!