I'm learning OpenGL through a great book that uses OpenGL version 3.3 in the Premake 4 plataform, but I actually want to learn OpenGL for Android, which supports OpenGL version 2.0. It's pretty much the same, as the concepts are the same, but I'm having some trouble with the Shader Language code.
For example, in the book the autor implements a Vertex Shader with the code:
#version 330
layout(location = 0) in vec4 position;
void main(){
gl_Position = position;
}
After a lot of research I was able to implement this exactly Vertex Shader code in Android with the code:
String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
But I can't figure out how can I implement this Vertex Shader below:
#version 330
layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
smooth out vec4 theColor;
void main() {
gl_Position = position;
theColor = color;
}
The book is http://arcsynthesis.org/gltut/Basics/Tut02%20Vertex%20Attributes.html
You cannot implement the shader as it is written in OpenGL ES 2.0. This shader is written against the OpenGL 3.3 GLSL specification, OpenGL ES 2.0 uses syntax roughly equivalent to GLSL 120 (OpenGL 2.1).
The smooth qualifier is used to control interpolation between shader stages, GLSL ES does not support this, all vertex shader outputs are smoothly interpolated in GLSL ES.
layout (...) is unsupported by GLSL ES, you must use glBindAttribLocation (...) to set the location.
in and out are not supported by GLSL ES, you must use attribute for vertex shader inputs and varying for vertex shader outputs and fragment shader inputs.
And last, #version 330 is invalid. In OpenGL ES 2.0, there is only one GLSL ES specification, version 1.0 (so a compliant OpenGL ES 2.0 shader should begin with #version 100).
To answer your question about implementing that particular vertex shader:
#version 100
attribute vec4 position;
attribute vec4 color;
varying vec4 theColor;
void main() {
gl_Position = position;
theColor = color;
}
This is of course only half of the equation, you need to pair it with a fragment shader that also uses OpenGL ES 2.0-compliant syntax.
A minimal fragment shader that would work with this vertex shader:
#version 100
varying vec4 theColor; // In GLSL 330 this would be written as: in vec4 theColor;
void main (void) {
gl_FragColor = theColor;
}
Related
OpenGL ES 3.0 on Android, when I use Pow(x) during preprocessing and Pow(1.0/x) during post-processing, image will display abnormally.
At first I thought there was a problem with the middle fragment shader, but later I removed all the middle fragment shaders and still showed exceptions. What is the reason for this?
Initial rendering process:
preprocessing -> other filters -> post-processing
Modified rendering process code,delete other filters and post-processing:
#version 300 es
precision highp float;
uniform sampler2D mTexture;
uniform float mPow;
in vec2 vTexCoord;
out vec4 vFragColor;
void main() {
vec4 vFragColor1 = pow(texture(mTexture, vTexCoord), vec4(mPow));
vFragColor = pow(vFragColor1, vec4(1.0/mPow));
}
pow range: 0.0-100.0
I'm trying ro render a 3d mesh on android, the positions of the vertices are provided like so:
var positionHandle = GLES20.glGetAttribLocation(program, "vPosition").also {
GLES20.glEnableVertexAttribArray(it)
GLES20.glVertexAttribPointer(
it, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer
)
}
My vertex shader:
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
varying vec4 positionOut;
void main() {
gl_Position = uMVPMatrix * vPosition;
positionOut = vPosition;
}
Fragment shader:
varying vec4 positionOut;
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0,1,1);
}
This code works fine on one device (Android 9 on OnePlus device) but it doesn't work on (Android 10 Samsung Galaxy device) and no errors are thrown.
If I remove the line varying vec4 positionOut; from the fragment shader the render works.
The question is why only the definition of a varying variable breaks the render? I don't use the variable now but I want to use it in the next step.
Your code is invalid as per the spec:
The fragment language has no default precision qualifier for floating point types. Hence for float, floating
point vector and matrix variable declarations, either the declaration must include a precision qualifier or
the default float precision must have been previously declared.
So you either have to declare it as for example varying mediump ec4 positionOut;, or you put into some scope of a precision statement.
I'm attempting to create an alpha radial gradient effect (kind of lighting) using a simple shader.
The effect is created correctly, however the gradient is not smooth.
The precision is set to highp, so I don't really know where to look.
This shader is currently running on Android, using OpenGL ES 2.0.
This is how the gradient currently looks like:
And this is my current shader:
Vertex:
precision highp float;
attribute vec4 vPosition;
attribute vec2 vStaticInterpolation;
varying vec2 interpolator;
void main() {
interpolator = vStaticInterpolation;
gl_Position = vPosition;
}
Fragment:
precision highp float;
uniform float alphaFactor;
varying vec2 interpolator;
float MAX_ALPHA = 0.75;
void main() {
float x = distance(interpolator, vec2(0.0, 0.0));
float alpha = MAX_ALPHA - MAX_ALPHA * x;
alpha = max(alpha, 0.0);
gl_FragColor = vec4(0.925, 0.921, 0.843, alpha);
gl_FragColor.a *= alphaFactor;
}
The shader receives constant attributes for interpolation (from -1.0 to 1.0) in vStaticInterpolation.
The actual color is currently hard-coded in the shader.
It looks to be related to a dithering problem.
This could depend on the OpenGL driver implementation of your mobile device (though I don't know which model you are currently using). In the past it used to be an issue.
Possible tests you could perform are:
Disable Opengl dithering:
GLES20.glDisable(GLES20.GL_DITHER);
Impose an RGB888 surface when you create the surface. It is usually done in the ConfigChooser function. I try to remember by hard, this is part of the code of my application:
new AndroidGL.ConfigChooser(8, 8, 8, 8, depth, stencil) :
I'm using a fragment shader that uses dFdy dFdx functions to calculate the normal of the
face to view in a flat appearance. This shader has been running ok in gles 2.0 and 3.0. Inexplicably, shader don't work in Android 4.4 ( KitKat - gles3.0 ).
(Solved!!.. individual derivatives for each component, solve the problem).
In order check error, i prepared these shaders :
//Vertex Shader
#version 300 es
precision highp float;
precision highp int;
uniform mat4 PMatrix; //Projection Matrix (varies according to camera)
uniform mat4 MVMatrix; //Model View Matrix (no change)
in vec3 vPosition;
out vec3 vPos;
main()
{
gl_Position=PMatrix * MVMatrix * vec4(vPosition.xyz,1.0);
vPos = (MVMatrix * vec4(vPosition.xyz,1.0)).xyz;
}
// Fragment shader
#version 300 es
#extension GL_OES_standard_derivatives : enable
precision highp float;
precision highp int;
in vec3 vPos;
main()
{
// don't run correctly
// vec3 fdx = dFdx(vPos);
// vec3 fdy = dFdy(vPos);
// ***Solved!*** this run correctly in KitKat
vec3 fdx = vec3(dFdx(vPos.x),dFdx(vPos.y),dFdx(vPos.z));
vec3 fdy = vec3(dFdy(vPos.x),dFdy(vPos.y),dFdy(vPos.z));
vec3 N = normalize(cross(fdx,fdy));
fragColor = vec4(N,1.0);
}
Drawing a cube, in Android<4.4 colors remain fixed for each side, independently of camera position (correct, the color identifies each normal-face). In Android 4.4 , colors vary if you move the camera.
Analyzing each derived separately :
1.- fragColor=vec4(normalize( fdx ), 1.0); colors are constantly changing (wrong)
2.- fragColor=vec4(normalize( fdy ), 1.0); the colors remain quasi-stable (quasi-ok)
A bug in the implementation of these features in Android 4.4?
We are doing something wrong?
You said that this was originally a GLES2 shader, and you are using highp in a fragment shader unconditionally? That is a disaster waiting to happen because GLES2 implementations are not required to support highp in fragment shaders. Likewise, support for dFdx (...), dFdy (...) and fwidth (...) is optional.
You need to check for GL_OES_standard_derivatives and GL_FRAGMENT_PRECISION_HIGH in the GLES2 implementation of this fragment shader.
To that end, you might consider the accuracy hint for derivatives:
GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES (GLES2, if the extension is supported)
GL_FRAGMENT_SHADER_DERIVATIVE_HINT (GLES3)
Individual derivatives in each component solve the problem in KitKat:
// Replace vec3 fdx = dFdx(vPos) by:
vec3 fdx = vec3(dFdx(vPos.x),dFdx(vPos.y),dFdx(vPos.z));
// Replace vec3 fdy = dFdy(vPos) by:
vec3 fdy = vec3(dFdy(vPos.x),dFdy(vPos.y),dFdy(vPos.z));
I've seen similar things on some AMD desktop setups.
Where dFdy( .xyz ) worked fine on NVIDIA/intel I had to do the derivate per-component to get it correctly for some AMD cards.
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