I am writing an android game using Love2D in which I am using a Gaussian Blur Shader to get a bloom effect, however I am testing it on PC, and the results on PC and Android are very different, to the point of making the shader useless on Android.
Here is how the PC version looks like:
And Here is how the Android version looks like:
Both are running with the following shaders, doing a pass with offset direction vertical and horizontal.
// Vertex Shader:
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
varying vec2 coordinate2b;
varying vec2 coordinate1b;
varying vec2 coordinate0f;
varying vec2 coordinate1f;
varying vec2 coordinate2f;
uniform vec2 offset_direction;
vec4 position(mat4 transform_projection, vec4 vertex_position)
{
coordinate2b = VertexTexCoord.xy + -3.230769 * offset_direction;
coordinate1b = VertexTexCoord.xy + -1.384615 * offset_direction;
coordinate0f = VertexTexCoord.xy + 0.000000 * offset_direction;
coordinate1f = VertexTexCoord.xy + 1.384615 * offset_direction;
coordinate2f = VertexTexCoord.xy + 3.230769 * offset_direction;
return transform_projection * vertex_position;
}
// Fragment Shader:
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
varying vec2 coordinate2b;
varying vec2 coordinate1b;
varying vec2 coordinate0f;
varying vec2 coordinate1f;
varying vec2 coordinate2f;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords)
{
vec4 c = vec4(0.0);
c += vec4(0.070270) * Texel(texture, coordinate2b);
c += vec4(0.316216) * Texel(texture, coordinate1b);
c += vec4(0.227027) * Texel(texture, coordinate0f);
c += vec4(0.316216) * Texel(texture, coordinate1f);
c += vec4(0.070270) * Texel(texture, coordinate2f);
return c * color;
}
I am currently guessing the problem is with float precision, but I am not sure what I would have to do to fix that.
Thanks to Columbo, I found out two different problems when running the game on my android.
First was that texture filtering was not linear, this making the scaling optimization not working and having weird problems with scaling.
Second, love2d for android is not supporting gamma correction, so when running on my phone the game was not rendering color correctly and the blur was not visible due to the dark background.
Always check for gamma correction!
Related
in opengl es program i input two textures and use fragment shader:
varying highp vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform lowp float intensity;
void main() {
highp vec4 newColor = texture2D(inputImageTexture2,textureCoordinate2);
highp vec4 vColor = texture2D(inputImageTexture, textureCoordinate);
newColor.r = newColor.r + vColor.r * (1.0 - newColor.a);
newColor.g = newColor.g + vColor.g * (1.0 - newColor.a);
newColor.b = newColor.b + vColor.b * (1.0 - newColor.a);
gl_FragColor = vec4(mix(vColor.rgb, newColor.rgb, 0.86), newColor.a);
};
but the result have some "error color" here, how to fix this?
I found the answer myself, this is because I write and read from a same FBO texture, and now I change it and work fine!
My games runs fine on newer devices (eg..droid turbo, galaxy note 3) but on my motorola xoom there are problems, such as :
1) My shaderProgram causes the stage that is drawn inside of it to not be rendered
2) Touch inputs don't work every time using InputProcessor (only senses 90% of the time)
These are the problems I currently notice. Could this be because it is an older OS version (4.1.2)? Not that old. Are known bugs with libgdx's ShaderProgram? Even then, the touch input not sensing every click is very strange. Thanks for your time and help! My rendering code for the shaderProgram is all correct, so no need to show that. And for touchInput, I am just using touchDown method from InputProcessor.
EDIT :
Error produced by shaderProgram
"(22) : error C1101: ambiguous overloaded function reference "smoothstep(mediump float, float, lowp float)"
Vertex Shader
#version 100
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
uniform mat4 u_worldView;
uniform vec2 u_lightPos;
uniform vec3 u_lightColor;
uniform vec4 u_spaceColor;
varying vec4 v_color;
varying vec2 v_texCoords;
varying vec2 v_lightPos;
varying vec3 v_lightColor;
varying vec2 v_position;
varying vec4 v_spaceColor;
void main() {
v_color = a_color;
v_lightColor = u_lightColor;
v_lightPos = u_lightPos;
v_position.xy = a_position.xy;
v_texCoords = a_texCoord0;
gl_Position = u_worldView * a_position;
v_spaceColor = u_spaceColor;
}
Fragment Shader
#version 100
#ifdef GL_ES
precision lowp float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
varying vec2 v_lightPos;
varying vec3 v_lightColor;
varying vec2 v_position;
varying vec4 v_spaceColor;
uniform sampler2D u_texture;
void main() {
for(int row = 0; row < 2; row++) {
for(int col = 0; col < 2; col++) {
float dist = distance(v_position, vec2(-1 + col, 1 - row));
float delta = 0.1;
float alpha = smoothstep(100.0-delta, 100.0, dist);
if(dist > 23.0){
gl_FragColor = mix(v_spaceColor, v_color, alpha);
}
else{
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}
}
}
}
I needed to create some ripling effect for one sprite in my game, here's the vertexShader:
attribute vec4 a_position; // just taking in necessary attributes
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans; // Combination of view and projection matrix
varying vec2 v_texCoords;
void main() {
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position; //as I said, it is sprite so no need for modelMatrix
}
and here's the fragment:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoords;
uniform sampler2D u_texture; //texture of sprite
uniform float time;
void main()
{
vec2 uv;
if (time > 0.0) { // time is > 0.0 when I want the ripling effect to be applied,
vec2 cPos = -1.0 + 2.0 * v_texCoords.xy; // converting tex.Coords to -1 - 1
float cLength = length(cPos); //taking length of it
uv = v_texCoords.xy +( (cPos/cLength)*cos(cLength*12.0-time*4.0)*0.03 ) // just some calculations for the ripling effect
}
else
uv = v_texCoords.xy; // if I don't want to use the ripling effect, I use normal texCoords
vec4 tex = texture2D(u_texture, uv); //sampling texture
gl_FragColor = tex;
}
It all works fine, the performance's fine on PC, but when running it on android, the performance is a lot worse... As you can see, shader's are trivial but they somehow are expensive.. Anyways, sprite I draw has width about 2000 - 4000 px and height 720. Also, when I replace v_texCoords with different vector(for example vec2(1, 1)) in cPos calc: vec2 cPos = -1.0 + 2.0 * v_texCoords.xy; the performance improves heavily..
I don't really know what's so expensive there. If anyone had some advices, I'd be happy. Thanks in advance
In Blender Cycles render, there's a shader type called Glossy. Now I want to implement this glossy shader using OpenGL ES 2.0 on Android. I'm wondering where can I find a GLSL implementation of this shader? Below is an image displaying the glossy reflection (see the reflection on the plane).
That effect is basically just a gaussian blur filter. There is a good example of this for OpenGL ES 2.0 in the PowerVR SDK in these files:
\Examples\Intermediate\Bloom\OGLES2\BlurVertShader.vsh:
// Blur filter kernel shader
//
// 0 1 2 3 4
// x--x--X--x--x <- original filter kernel
// y---X---y <- filter kernel abusing the hardware texture filtering
// |
// texel center
//
//
// Using hardware texture filtering, the amount of samples can be
// reduced to three. To calculate the offset, use this formula:
// d = w1 / (w1 + w2), whereas w1 and w2 denote the filter kernel weights
attribute highp vec3 inVertex;
attribute mediump vec2 inTexCoord;
uniform mediump float TexelOffsetX;
uniform mediump float TexelOffsetY;
varying mediump vec2 TexCoord0;
varying mediump vec2 TexCoord1;
varying mediump vec2 TexCoord2;
void main()
{
// Pass through vertex
gl_Position = vec4(inVertex, 1.0);
// Calculate texture offsets and pass through
mediump vec2 offset = vec2(TexelOffsetX, TexelOffsetY);
TexCoord0 = inTexCoord - offset;
TexCoord1 = inTexCoord;
TexCoord2 = inTexCoord + offset;
}
\Examples\Intermediate\Bloom\OGLES2\BlurFragShader.vsh:
uniform lowp sampler2D sTexture;
/*
Separated Gaussian 5x5 filter, first row: 1 5 6 5 1
*/
varying mediump vec2 TexCoord0;
varying mediump vec2 TexCoord1;
varying mediump vec2 TexCoord2;
void main()
{
lowp vec3 color = texture2D(sTexture, TexCoord0).rgb * 0.333333;
color = color + texture2D(sTexture, TexCoord1).rgb * 0.333333;
color = color + texture2D(sTexture, TexCoord2).rgb * 0.333333;
gl_FragColor.rgb = color;
}
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.