open gl es2: fragment shader optimization - android

I have following simple fragment shader
precision lowp float;
uniform sampler2D u_texture_image;
uniform sampler2D u_texture_mask;
uniform lowp float u_blink;
varying lowp vec2 v_texCoords_image;
varying lowp vec2 v_texCoords_mask;
varying lowp float v_shadow;
void main() {
lowp vec4 color= vec4(texture2D(u_texture_image, v_texCoords_image));
lowp vec4 mask_color= vec4(texture2D(u_texture_mask, v_texCoords_mask));
//masking image
color = vec4(color.xyz,mask_color.a);
//blink
color =mix(color,vec4(1.0,1.0,1.0,mask_color.a),u_blink);
//check if its a shadow
color=mix(color, mask_color*0.3, v_shadow);
gl_FragColor = color;
}
I draw with this code 4400 polygons and get 25 fps(~40ms between onDrawFrame calls).This is not enough since this is not whole scene.Can I somehow optimize this code?My target fps is 30.Also I wonder are there some profiling tools for fragment shader code?
ADD:How do I call fragment shader
private void drawPieces() {
//set my shader
piecesProgram.useProgram();
//set uniforms
piecesProgram.setUniforms(MVPMatrix, textureImageId, textureMaskId,new PointF(2f,2f),0f);
//load my vertcices with glVertexAttribPointer
piecesMesh.bindPieceData(piecesProgram,false);
//draw it with glDrawElements
piecesMesh.drawPieces(false);
piecesMesh.disableAttributes(piecesProgram);
}

This shader does not look that complex.
What hardware are you using?
Are you recompiling this shader every time you use it?
How are you calling this shader?
Apple has written a nice article about GLSL best prectices
https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html

Related

Android OpenGL ES 2.0:How to zoom texture with depth map?

Android OpenGL ES 2.0, I bind bitmap and depth map bitmap to fragment_shader.glsl,
precision mediump float;
uniform sampler2D sDepth;
uniform sampler2D sTexture;
uniform float time;
varying vec2 varyTexCoord;
void main() {
vec4 depth=texture2D(sDepth, varyTexCoord);
gl_FragColor=texture2D(sTexture, varyTexCoord);
}
sTexture : original bitmap
sDepth: depth map(ARGB_8888, 0~255, 0:far 255:near)
vertex_shader.glsl
attribute vec4 vPosition;
attribute vec2 vTexCoord;
uniform mat4 vMatrix;
varying vec2 varyTexCoord;
void main() {
gl_Position = vPosition;
varyTexCoord = vTexCoord;
}
now I want to make parallax effect :According to the depth of field value, zoom in the image, the zoom in of the near area is higher than that of the far area, creating parallax effect.
Can you give us some ideas? Thank you.
Create a mesh on a base of regular grid, let say 10x10 in (x,y) space.
Set z coordinate from depth map.
Make uv coordinates.
Render mesh with you color texture, and use gl_position = projectionMatrix * scale * vertex;
Try different dimensions for grid to find best one.

Uniform type mismatch error - OpenGL ES 3.0 shader program linked on Android 7/8/9 but failed on iOS 10/11?

I was frustrated by an error when linking OpenGL es shader 3.0 program on iOS.
I have one vertex shader and one fragment shader and they are linked to generate a single program.
There are shared uniforms and uniform blocks in both shaders. I understand that these uniforms must have exactly same type, precision and name, so that I even copy the uniform declaration from one shader to the other shader.
Here is the code of my vertex shader:
// Vertex shader
#version 300 es
precision highp float;
// ...........................
// Shared uniforms ...
uniform mat4 viewMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 texcoordMatrix;
uniform mat4 projMatrix;
uniform bool shadingEnabled;
uniform bool fogEnabled;
uniform bool flatShading;
uniform bool specularEnabled;
uniform bool generateReflectionTexCoord;
uniform float zBias;
layout (std140) uniform cbFog
{
int g_fogMode;
float g_fogStart;
float g_fogEnd;
float g_fogDensity;
vec4 g_fogColor;
};
layout (std140) uniform cbMaterial
{
vec4 mtlAmbient;
vec4 mtlDiffuse;
vec4 mtlSpecular;
vec4 mtlEmissive;
int mtlSpecularPower;
float _padding4;
float _padding5;
float _padding6;
};
// ...........................
// Vertex shader's input and output ...
// ...........................
// Vertex shader code ...
And here is the code of my fragment shader:
// Fragment shader
#version 300 es
precision highp float;
// ...........................
// Shared uniforms ...
uniform mat4 viewMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 texcoordMatrix;
uniform mat4 projMatrix;
uniform bool shadingEnabled;
uniform bool fogEnabled;
uniform bool flatShading;
uniform bool specularEnabled;
uniform bool generateReflectionTexCoord;
uniform float zBias;
layout (std140) uniform cbFog
{
int g_fogMode;
float g_fogStart;
float g_fogEnd;
float g_fogDensity;
vec4 g_fogColor;
};
layout (std140) uniform cbMaterial
{
vec4 mtlAmbient;
vec4 mtlDiffuse;
vec4 mtlSpecular;
vec4 mtlEmissive;
int mtlSpecularPower;
float _padding4;
float _padding5;
float _padding6;
};
// ...........................
// Fragment shader's input and output ...
// ...........................
// Fragment shader code ...
Please note that all uniform declarations are copied from vertex shader into fragment shader so that they are guaranteed to be identical.
The result is that the program can be successfully linked on Android and some OpenGL ES simulators like PowerVR, but it fail to be linked on iOS 10/11 and the following is the error message:
Error when linking shader program:
ERROR: Uniform type mismatch '<uniform cbMaterial>'
ERROR: Uniform type mismatch '<uniform cbFog>'
The iOS OpenGL ES complains that uniform block cbMaterial and cbFog have mismatched type.
Anyone can help me find the reason for me? Thanks!
PS: I understand that OpenGL ES might be deprecated on macOS 10.14 and iOS 12, I still need to get this working on iOS for certain maintenance reason.

Calculate mean of a row in the fragment shader (OpenGL ES 2.0)

I am currently programming an application for image processing. To achieve the needed performance, I have to use the GPU to compute the camera input, more specifically use OpenGL ES 2.0.
With the help of this project (https://github.com/yulu/ShaderCam) I achieved to pass the image to the pipeline and do simple operations with the fragment shader (like inverting colors etc).
My knowledge of GLSL, fragment shaders and vertex shaders is fairly limited but I am aware of pipeline constraints and what the two shaders do in the pipeline.
So - formulating the problem - I would like to calculate the average color of a row in my received image and return it (per row) to my application.
I read here https://stackoverflow.com/a/13866636/8038866 that this is generally possible, however I can't seem to find out the following things:
1 (edit: SOLVED by simply passing the w and h of my texture to the vertex and fragment shader):
Knowing where the row ends (and having that information in the fragment shader). For this I assume that I would have to pass the width of the picture to the vertex shader and from there to the fragment shader, right?
2.: How to calculate the average the color values of each row in the fragment shader and then pass them to the application. If I understand it correctly - the fragment shader only excutes the code per pixel, so I am not sure how to achieve this.
Here are the two very basic shaders
vertex shader:
uniform mat4 uTransformM;
uniform mat4 uOrientationM;
uniform vec2 ratios;
attribute vec2 aPosition;
varying vec2 vTextureCoord;
void main(){
gl_Position = vec4(aPosition, 0.0, 1.0);
vTextureCoord = (uTransformM * ((uOrientationM * gl_Position + 1.0)*0.5)).xy;
gl_Position.xy *= ratios;
}
fragment shader:
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES sTexture;
varying vec2 vTextureCoord;
void main(){
gl_FragColor = texture2D(sTexture, vTextureCoord);
//calc mean per row and pass it back
}
I am very thankful for every advice or help you can provide.
I found a way that does the trick for me. The idea is to calculate the mean for only one row of pixels and then later in the application to get this line with
glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid * data);
Here is my fragment shader (notice that the width of the surface is required as well):
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES sTexture;
varying float width;
varying vec2 vTextureCoord;
void main(){
vec4 accumulatedRGB = texture2D(sTexture, vec2(0,vTextureCoord.y));
if(vTextureCoord.x < 0.50 && vTextureCoord.x > 0.499){ //small enough to only cover one line
for(float i=1.0;i<=width;++i)
{
float xPosOnTexture = i/width;
vec4 current = texture2D(sTexture, vec2(xPosOnTexture,vTextureCoord.y));
accumulatedRGB += current;
}
vec4 mean = accumulatedRGB/width;
gl_FragColor = vec4(mean.rgb , mean.a);//avg color for one line
}
else{
gl_FragColor = vec4(0.0,0.0,0.0,0.0);//rest of the screen
}
}

libgdx - changing sprite color to white

I want to colorize a sprite so that RGB channels are all 1 and alpha remains unchanged.
I gather this should be done with shaders, but the two accepted answers on StackOverflow (Change sprite color into white and libgdx changing sprite color while hurt) don't work for me - the result is transparent, and they don't work on http://shdr.bkcore.com/ either
All you need is to replace the RGB each with 1.0 in the fragment shader.
Vertex shader-- This is like the one in SpriteBatch with vertex color removed since you aren't using it:
attribute vec4 a_position;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
void main()
{
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position;
}
Fragment shader-- grab just the alpha value from the texture.:
#ifdef GL_ES
precision lowp float; //since the only value we're storing is part of a color
#endif
varying vec2 v_texCoords;
uniform sampler2D u_texture;
void main()
{
float alpha = texture2D(u_texture, v_texCoords).a;
gl_FragColor = vec4(1.0, 1.0, 1.0, alpha);
}

Remove normals from vertex and fragment shader

I'm developing an Android 2.2 application with OpenGL ES 2.0 stuff in C++.
Here are my vertex and fragment shader:
static const char* cubeMeshVertexShader = "
attribute vec4 vertexPosition;
attribute vec4 vertexNormal;
attribute vec2 vertexTexCoord;
varying vec2 texCoord;
varying vec4 normal;
uniform mat4 modelViewProjectionMatrix;
void main()
{
gl_Position = modelViewProjectionMatrix * vertexPosition;
normal = vertexNormal;
texCoord = vertexTexCoord;
}
";
static const char* cubeFragmentShader = "
precision mediump float;
varying vec2 texCoord;
varying vec4 normal;
uniform sampler2D texSampler2D;
void main()
{
gl_FragColor = texture2D(texSampler2D, texCoord);
}
";
I'm very new on OpenGL ES 2.0 development.
Someone told me that if I want lights on my render I have to make some complicates modification on vertex and fragment shader. So, I don't how to do that, normals are not necessary.
My question is:
How do I modify vertex and fragment shaders for not using normals?
Thanks
I think there is no way around using normals if you want to have lighting. I usually export the normals from my 3d package and use those, but you can always create them on the fly in your c++ code.
http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681

Categories

Resources