After call glLinkProgram the app freezes - android

UPDATED
I'm trying to draw texture with openGL ES3 and used instanced drawing for my drawing application. This is my vertex shader
#version 300 es
precision highp float;
uniform mat3 u_Matrix;
in vec2 Position;
in vec2 TexPosition;
struct Data {
vec2 pos;
vec2 scale;
uint color;
float rotation;
};
layout(std140) uniform InstanceData {
Data data[256];
};
out vec4 v_Color;
out vec2 v_TexPosition;
void main() {
vec2 endPos = Position * data[gl_InstanceID].scale;
if (data[gl_InstanceID].rotation != 0.0) {
float cos = cos(data[gl_InstanceID].rotation);
float sin = sin(data[gl_InstanceID].rotation);
endPos = vec2(endPos.x * cos - endPos.y * sin, endPos.x * sin +
endPos.y * cos) + data[gl_InstanceID].pos;
} else {
endPos = endPos + data[gl_InstanceID].pos;
}
uint fColor = data[gl_InstanceID].color;
v_Color.r = float((fColor & 0x00FF0000U) >> 16) / 255.0;
v_Color.g = float((fColor & 0x0000FF00U) >> 8) / 255.0;
v_Color.b = float(fColor & 0x000000FFU) / 255.0;
v_Color.a = float((fColor & 0xFF000000U) >> 24) / 255.0;
v_TexPosition = TexPosition;
gl_Position = vec4(u_Matrix * vec3(endPos, 1.0), 1.0);
}
and this is my fragment_shader
#version 300 es
precision highp float;
in vec2 v_TexPosition;
in vec4 v_Color;
uniform sampler2D u_Texture2D;
out vec4 fragColor;
void main() {
vec4 color = texture(u_Texture2D, v_TexPosition);
fragColor = vec4(v_Color.rgb, color.a * v_Color.a);
}
When I created the program, attached shaders and try to link to program, the app is freezes on line glLinkProgram. Shaders and program have normal id.
This work normal on some devices (sony xperia Z -android 5.0, smasung s7 edge android 7, nexus 5x - android 7, nexus 6p - android 7) but this doesn't work on other part of devices(motX- android 5.1, smasung s5 android 6.0). All devices have android version greater then 5.0, and in code I checked for opengl ES3 supporting.
Is there some reason for this? Is it from device(how to check it)? or did I did something wrong?
I'm passed data to instanceBuffer with this way :
instanceBuffer.putFloat(posX);
instanceBuffer.putFloat(posY);
instanceBuffer.putFloat(scaleX);
instanceBuffer.putFloat(scaleY);
instanceBuffer.putInt(colorARGB);
instanceBuffer.putFloat((float) Math.toRadians(rotate));
instanceBuffer.position(instanceBuffer.position() + 8);
used +8 offsets because struct data read elements with vec4 size (16byte)
When I write my struct only with one vec4 :
struct Data {
vec4 posAndScale;
};
and pass data:
instanceBuffer.putFloat(posX);
instanceBuffer.putFloat(posY);
instanceBuffer.putFloat(scaleX);
instanceBuffer.putFloat(scaleY);
This works on all devices,
But when I added one more vec4 :
struct Data {
vec4 posAndScale;
vec4 color;
};
and pass data
instanceBuffer.putFloat(posX);
instanceBuffer.putFloat(posY);
instanceBuffer.putFloat(scaleX);
instanceBuffer.putFloat(scaleY);
instanceBuffer.putFloat(color.r);
instanceBuffer.putFloat(color.g);
instanceBuffer.putFloat(color.b);
instanceBuffer.putFloat(color.a);
app not freezes but nothing happened when I try to draw. It's seems like on some devices std140 work with different way or like data not passed to shader when wrote struct with 2 vec4-s

Ok I found some solution. This work normally since opengl es versionl 3.1. I think 3.0 version doesn't support struct data which contains float or int element.

I experienced the same issue. The Nexus 7 (2013) was freezing when I called gllinkprogram(). I found that this only happened when I had 'if statements' in my shader. I was able to change both of my 'if statements' into 'conditional operators' and it worked.
E.g. (cond)? cond1:cond2

Related

opengl es 3.0 glsl multiplication crashes

I'm currently working on a Bug in an image processing app under Android. On the devices that are available for me (Z5, Z3, Nexus 5x, OnePlus3, S6, Pixel C) it only happens on the Pixel C:
It seams like a simple floating point multiplication in a fragment shader causes the whole device to crash (not responding, needs reboot).
This is the shader source:
#version 300 es
#ifdef GL_ES
precision mediump float;
#endif
///////////////////////////////////////////////////////////////////////////////
// Uniforms
//
/**
* Uniform sampler2D variable for accessing input texture.
*/
uniform sampler2D u_Texture; ///< Input texture.
///////////////////////////////////////////////////////////////////////////////
// Varyings
//
/**
* Varying variable representing the texture coordinates for sampling.
* #minimum 0.0 0.0
* #maximum 1.0 1.0
*/
in vec2 v_TexCoord; ///< Input texture coordinates.
layout(location=0) out vec2 o_Color;
/**
* Compute tangent flow at current fragment position.
*/
void main (void)
{
vec3 tensor = texture(u_Texture, v_TexCoord).xyz;
float tensorXSubTensorY = tensor.x - tensor.y;
vec2 lengthTensor = vec2(tensorXSubTensorY, tensor.z+tensor.z);
/*********************************************/
/*************BELOW CAUSES CRASH**************/
float value = lengthTensor.x*lengthTensor.x;
//float val2 = lengthTensor.y*lengthTensor.y;
float lambda1 = 0.5 * (tensorXSubTensorY - value);
vec2 tangent = vec2(lambda1, tensor.z);
o_Color = (length(tangent) > 0.0) ? normalize(tangent) : vec2(0.0, 1.0);
}
The texture used is a Half-Float RGBA16F texture. Setting the value to e.g. 2.0f doesn't crash the device.
Is there any reason, why this line could be problematic?

GLSL ES fragment shader produces very different results on different devices

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?

Issue with shader execution flow on PowerVR GPU

I've encountered a problem which I believe is related to optimization of GLSL compilation of PowerVR GPUs. On Adreno and Tegra GPUs fragment shader works just fine, but on PowerVR (Motorola Droid) it produces incorrect result in conditional statement.
I've fixed the problem by changing conditional statement in fragment shader code. Instead of calling return in block for if statement I've added else block and it works OK on PowerVR now.
Logic of both shaders is absolutely identical, gl_FragColor is set in both cases.
Please explain this behavior of PowerVR OpenGL driver so I can avoid problems in future. Why does it handle conditional statements this way?
Here is the old fragment shader, which works incorrectly on PowerVR GPUs:
precision mediump float;
varying vec3 vNormal;
varying vec3 vViewVec;
varying vec2 vTextureCoord;
uniform sampler2D sTexturePumpkin;
void main(void)
{
const float sheen = 0.68;
const float noiseScale = 0.05;
const float furriness = 10.0;
const vec4 lightDir = vec4(0.267260, 0.267260, -0.925820, 0.0);
vec4 color = texture2D(sTexturePumpkin, vTextureCoord/*vec2(0.0,0.0)*/);
if(vTextureCoord.y > 0.7) { // in this case PowerVR displays incorrect color
gl_FragColor = color;
return;
}
float diffuse = 0.5 * (1.0 + dot(vNormal, vec3(lightDir.x, lightDir.y, -lightDir.z)));
float cosView = clamp(dot(normalize(vViewVec), vNormal), 0.0, 1.0);
float shine = pow(1.0 - cosView * cosView, furriness);
gl_FragColor = (color + sheen * shine) * diffuse; // in this case PowerVR works correctly
}
The new fragment shader code, which works fine on both Adreno and PowerVR GPU:
precision mediump float;
varying vec3 vNormal;
varying vec3 vViewVec;
varying vec2 vTextureCoord;
uniform sampler2D sTexturePumpkin;
void main(void)
{
const float sheen = 0.68;
const float noiseScale = 0.05;
const float furriness = 10.0;
const vec4 lightDir = vec4(0.267260, 0.267260, -0.925820, 0.0);
vec4 color = texture2D(sTexturePumpkin, vTextureCoord/*vec2(0.0,0.0)*/);
if(vTextureCoord.y > 0.7) {
gl_FragColor = color;
}
else {
float diffuse = 0.5 * (1.0 + dot(vNormal, vec3(lightDir.x, lightDir.y, -lightDir.z)));
float cosView = clamp(dot(normalize(vViewVec), vNormal), 0.0, 1.0);
float shine = pow(1.0 - cosView * cosView, furriness);
gl_FragColor = (color + sheen * shine) * diffuse;
}
}
OK so after deeper investigation I have found that it's not a bug of shader compiler but a specific way of processing fragment shaders execution. It is generally a bad idea to put a simple discard; or return; statement with some code coming after it. It still can be executed and cause unpredictable result.
There are some articles that explains this behavior applicable to discard; statement, and as I see the similar behavior can happen with return; too.
Please read one here: http://people.freedesktop.org/~idr/OpenGL_tutorials/03-fragment-intro.html#infinite-loop
As is it said here, in certain cases you can even achieve infinite loop by incorrect usage of discard;.
Fragment shaders are executed by GPU not for a single texel at a time, usually in batches of 2x2 pixels. And this parallel running of fragment shader can cause code after return;.
So, for fragment shader to handle if statements correctly, you have to always use else in if operators, not simply exiting function by return; or discard;. This is exactly what I've done.

OpenGL ES 2.0, messing with all things

I'm making a multi-platform Game Engine (Open source in the future), and I was making a game based on it. When testing on a Samsung Galaxy S2 (I9100B), it runs perfectly, but when I tried to run on my other phone (Samsung Galaxy S) the things get messy.
Here is a screenshot when running on Galaxy S2:
And here is when I run on the Galaxy S:
I managed to reduce the number of triangles in the scene too, but even with 50 triangles on the screen I got the same problem.
Disabling the lighting reduces the problem, but does not eliminate it. I thought that was a memory problem on my phone, so I tried on another Galaxy S, but the same problem occurs.
Does someone know where I can start looking? The automatic GC is not frequent (about 2 times per 5 seconds).
Samsung Galaxy S2:
Android Version 2.3.4
Kernel: 2.6.35.7-I9100UHKI2-CL553601 se.infra#SEI-07 #2
Samsung Galaxy S:
Android Version 2.3.3
Kernek: 2.6.35.7-I9000BVJJW4-CL240848 pescio#bldhp-4 #28
Fragment Shader Code:
precision mediump float;
uniform sampler2D uSampler;
uniform float uIsPoint;
uniform float uEnableLight;
uniform float uDisableTexture;
varying vec4 vColor;
varying vec2 vTextureCoord;
varying vec4 vPosition;
uniform vec3 uPointLightingColor;
varying vec3 vColorWeight;
void main(){
if(uIsPoint >= 2.0) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}else{
vec4 calcColor;
if(uEnableLight >= 2.0)
calcColor = vec4(vColor.rgb * vColorWeight, vColor.a);
else
calcColor = vColor;
vec4 texColor = vec4(1.0,1.0,1.0,1.0);
if(uDisableTexture < 2.0)
texColor = texture2D(uSampler, vTextureCoord);
gl_FragColor = vec4(texColor.rgb * calcColor.rgb, texColor.a*calcColor.a);
}
}
Vertex Shader Code:
//Atributos
uniform mat4 uMVMatrix; //Model/View Matrix
uniform mat4 uPMatrix; //Model/View/Projection Matrix
uniform mat3 uNMatrix; //Normal Matrix
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
attribute vec2 aTextureCoord;
attribute vec3 aNormal;
varying vec4 vColor;
varying vec2 vTextureCoord;
varying vec3 vNormal;
varying vec4 vPosition;
//Lighting
uniform vec3 uAmbientColor;
uniform vec3 uLightDir;
uniform vec3 uLightColor;
uniform vec3 uSpecLightColor;
uniform float uShine;
varying vec3 vColorWeight;
void main(){
//Lighting
vec3 normal = normalize(uNMatrix * aNormal);
vec3 lightNorm = normalize(uLightDir);
float lightWeight = max(dot(aNormal,lightNorm),0.0);
vec3 halfVec = normalize(uLightDir - gl_Position.xyz);
float specWeight = pow(max(dot(normal,halfVec),0.0),uShine);
vColorWeight = uAmbientColor + (lightWeight * uLightColor) + (uSpecLightColor*specWeight);
//Others
vNormal = uNMatrix * aNormal;
vPosition = uMVMatrix * vec4(aVertexPosition,1.0);
gl_Position = uPMatrix * vPosition;
vColor = aVertexColor;
gl_PointSize = 2.0;
vTextureCoord = aTextureCoord;
}
Try increasing your depth buffer precision.
http://www.opengl.org/wiki/Depth_Buffer_Precision
This looks like a vertex ordering issue. The Galaxy S probably has back face culling turned on by default, so it will remove all triangles that do not face the viewer.
Which triangles are front-facing can be determined with glFrontFace()
You should try both clockwise and counter-clockwise to see if the culled and non-culled triangles switch places. If they do, you must either turn off back-face culling or make sure the vertex order is the same for all triangles.

Why same fragment shader gives different results on different android phones?

I am trying to implement a blur filter with OpenGL ES 2.0 on Android.
Here is the code i am using:
varying highp vec2 fragTexCoord;
highp vec2 u_Scale;
uniform sampler2D s_texture;
highp vec2 gaussFilter[7];
uniform highp float radius;
highp vec4 boxVerBlur(){
gaussFilter[0] = vec2( -3.0,0.015625);
gaussFilter[1] = vec2(-2.0, 0.09375);
gaussFilter[2] = vec2(-1.0, 0.234375);
gaussFilter[3] = vec2(0.0, 0.3125);
gaussFilter[4] = vec2(1.0, 0.234375);
gaussFilter[5] = vec2(2.0, 0.09375);
gaussFilter[6] = vec2(3.0, 0.015625);
highp vec4 color = vec4(0,0,0,1);
u_Scale = vec2( 1.0/radius, 0 );
for( int i = 0; i < 7; i++ )
{
color += texture2D( s_texture, vec2(
fragTexCoord.x + gaussFilter[i].x*u_Scale.x,
fragTexCoord.y + gaussFilter[i].x*u_Scale.y )) * gaussFilter[i].y;
}
return color;
}
void main(void)
{
gl_FragColor = boxVerBlur();
}
On "Samsung Galaxy S" it works as expected. However when i run same app on "Samsung Galaxy Ace," it results a brighter texture without blur effect.
Result from Galaxy S:
Result from Galaxy ACE:
I'll assume that by gaussFilter1 and gaussFilter2 you meant gaussFilter[1] and gaussFilter[2].
The only problem with your code I noticed is that you are adding the alpha, try adding only the rgb:
color.rgb += texture2D( s_texture, vec2(
fragTexCoord.x + gaussFilter[i].x*u_Scale.x,
fragTexCoord.y + gaussFilter[i].x*u_Scale.y )).rgb * gaussFilter[i].y;
It shouldn't cause your problem, but imho it worth a try, and even if it don't solve the problem, you will be saving an unnecessary sum for each texture access.

Categories

Resources