I am trying to create applications with opengl. Debugging on a real device.
I create the context like this::
GLSurfaceView baseView = new GLSurfaceView(this);
baseView.setEGLContextClientVersion(3);
baseView.setRenderer(new GameView());
I compile shaders like this:
int program = GLES20.glCreateProgram();
int idShad = (type == 0) ? GLES20.GL_VERTEX_SHADER : GLES20.GL_FRAGMENT_SHADER;
int shader = GLES20.glCreateShader(idShad);
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
int[] isCompiled = new int[1];
glGetShaderiv(shader, GL_COMPILE_STATUS, isCompiled, 0);
if (isCompiled[0] == GL_FALSE) {
String infoLog = "";
infoLog = glGetShaderInfoLog(shader);
glDeleteShader(shader);
String typeShader = (type == 0) ? "Vertex Shader" : "Fragment Shader";
Log.e("OpenGl", "Cannot compile " + typeShader + ": " + infoLog);
System.exit(-1);
}
glAttachShader(program, shader);
But I always getting this error:
Cannot compile: Vertex Shader: 0:3: L0001: Typename expected, found '�'
I get it when loading from a file and when creating a line in the code
For any code, even an empty shader, here are examples:
public static final String baseMatrixVX =
"#version 300 es\n"
+ "void main() {\n"
+ "}\0";
public static final String texMatrixVX =
"#version 330\n"
+ "layout(location = 0) in vec3 pos;\n"
+ "layout(location = 1) in vec3 color;\n"
+ "layout(location = 2) in vec2 tex;\n"
+ "out vec3 colorOut;\n"
+ "out vec2 texOut;\n"
+ "uniform bool enabledCam;\n"
+ "uniform mat4 projection;\n"
+ "uniform mat4 cam;\n"
+ "uniform mat4 model;\n"
+ "void main() {\n"
+ "if (enabledCam) {\n"
+ " gl_Position = projection * model * cam * vec4(pos, 1.0f);\n"
+ "} else {\n"
+ " gl_Position = projection * model * vec4(pos, 1.0f);\n"
+ "}\n"
+ "colorOut = vec3(color);\n"
+ "texOut = tex;\n"
+ "}\0";
What am I doing wrong?
P.S device supports opengle es 3 and above
It turned out that the problem is in the last character \0.
Should be used instead \n
Related
I try to write a small program in OpenGL ES 2.0. But i found i quit hard to inspect the variable in shader language.
For example i want to know the value in ver vertex shader. I will pass the value to fragment shader and put the value as the Red in glFragColor. But i found it quit hard to pass the value. If i declare the value using varying, then the value will change.
Here is the code, the log is the value i want to print.
public static final String VERTEX_SHADER =
"attribute vec4 position;\n" +
"attribute vec2 inputTextureCoordinate;\n" +
"\n" +
"uniform float texelWidthOffset; \n" +
"uniform float texelHeightOffset; \n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepLeftTextureCoordinate;\n" +
"varying vec2 twoStepsLeftTextureCoordinate;\n" +
"varying vec2 oneStepRightTextureCoordinate;\n" +
"varying vec2 twoStepsRightTextureCoordinate;\n" +
"varying float log;\n" +
"\n" +
"void main()\n" +
"{\n" +
"log = -0.1;\n" +
"gl_Position = position;\n" +
"vec2 firstOffset;\n" +
"vec2 secondOffset;\n" +
// "if (sqrt(pow(position.x, 2) + pow(position.y, 2)) < 0.2) {\n" +
// "log = -position.x;\n" +
"if (position.x < 0.3) {\n" +
"log = 0.7;\n" +
"firstOffset = vec2(3.0 * texelWidthOffset, 3.0 * texelHeightOffset);\n" +
"secondOffset = vec2(3.0 * texelWidthOffset, 3.0 * texelHeightOffset);\n" +
"} else {\n" +
"firstOffset = vec2(texelWidthOffset, texelHeightOffset);\n" +
"secondOffset = vec2(texelWidthOffset, texelHeightOffset);\n" +
"log = -0.1;\n" +
"}\n" +
"\n" +
"centerTextureCoordinate = inputTextureCoordinate;\n" +
"oneStepLeftTextureCoordinate = inputTextureCoordinate - firstOffset;\n" +
"twoStepsLeftTextureCoordinate = inputTextureCoordinate - secondOffset;\n" +
"oneStepRightTextureCoordinate = inputTextureCoordinate + firstOffset;\n" +
"twoStepsRightTextureCoordinate = inputTextureCoordinate + secondOffset;\n" +
"}\n";
public static final String FRAGMENT_SHADER =
"precision highp float;\n" +
"\n" +
"uniform sampler2D inputImageTexture;\n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepLeftTextureCoordinate;\n" +
"varying vec2 twoStepsLeftTextureCoordinate;\n" +
"varying vec2 oneStepRightTextureCoordinate;\n" +
"varying vec2 twoStepsRightTextureCoordinate;\n" +
"varying float log;\n" +
"\n" +
"void main()\n" +
"{\n" +
"if (log != -0.1) {\n" +
"gl_FragColor.rgba = vec4(log, 0.0, 0.0, 1.0);\n" +
// "return;\n" +
// "}\n" +
"} else { \n" +
"lowp vec4 fragmentColor;\n" +
"fragmentColor = texture2D(inputImageTexture, centerTextureCoordinate) * 0.2;\n" +
"fragmentColor += texture2D(inputImageTexture, oneStepLeftTextureCoordinate) * 0.2;\n" +
"fragmentColor += texture2D(inputImageTexture, oneStepRightTextureCoordinate) * 0.2;\n" +
"fragmentColor += texture2D(inputImageTexture, twoStepsLeftTextureCoordinate) * 0.2;\n" +
"fragmentColor += texture2D(inputImageTexture, twoStepsRightTextureCoordinate) * 0.2;\n" +
"\n" +
"gl_FragColor = fragmentColor;\n" +
// "gl_FragColor.rgba = vec4(0.0, 1.0, 0.0, 1.0);\n" +
// "}\n" +
"}\n";
Or is there any better method to do this.
When comparing floating point values, instead of doing this :
if (log != -0.1)
You should allow a little delta/tolerance on the value to account for floating point precision and the eventual value "change" you may get from passing it as a varying.
So you should do something like :
if (abs(log - (-0.1)) >= 0.0001)
Here the 0.0001 I chosen is a bit arbitrary ... It has to be a small value ...
Another example with ==
Instead of :
if (log == 0.7)
do
if (abs(log - 0.7) <= 0.0001)
However here you probably also have another issue:
The vertex shader executes for each 3 vertex of all your triangles (or quads)
So for a specific triangle, you may set different values (-0.1 or 0.7) for log for each vertex
Now the problem is that in the fragment shader the GPU will interpolate between the 3 log values depending on which pixel it is rendering ... so in the end you can get any value in [-0.1,0.7] interval displayed on screen :-(
To avoid this kind of issue, I personally use #ifdefs in my shaders to be able to switch them between normal and debug mode, and can switch between the two with a keypress. I never try to mix normal and debug displays based on if tests, especially when the test is based on a vertex position.
So in your case I would first create a specific debug version of the shader, and then use 0.0 and 1.0 as values for log, like this what you will see are red gradients, the more red the color is, the closer you are to the case you want to test.
I am learning about OpenGL ES and in particular, compute shaders in OpenGL ES 3.1, specifically, in Android 5.0.1.
I have 3 shaders defined (compute, vertex, and fragment) and attached to two different programs, one for the compute shader and one for the vertex and fragment shaders.
I have no problem when I only use the vertex and fragment shaders but now that I added the compute shader I get the following error:
02-11 20:02:10.375 13243-13264/com.example.daan.daggl2 I/VERSION﹕ OpenGL ES 3.1 NVIDIA 349.00
02-11 20:02:10.472 13243-13264/com.example.daan.daggl2 A/libc﹕ Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 13264 (GLThread 9847)
I'm trying to figure out what I'm missing but I'm new to this topic and I'm not sure where to begin looking for the problem.
The object's constructor is:
public Triangle() {
buffers = new int[1];
GLES31.glGenBuffers(1, buffers, 0);
gVBO = buffers[0];
// set up the vertex and fragment shaders
int vertexShader = MyGLRenderer.loadShader(
GLES31.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES31.GL_FRAGMENT_SHADER, fragmentShaderCode);
program = GLES31.glCreateProgram();
GLES31.glAttachShader(program, vertexShader);
GLES31.glAttachShader(program, fragmentShader);
GLES31.glLinkProgram(program);
checkGLError("LinkProgram/program");
// set up the compute shader
int computeShader = MyGLRenderer.loadShader(
GLES31.GL_COMPUTE_SHADER, computeShaderCode);
computeProgram = GLES31.glCreateProgram();
GLES31.glAttachShader(computeProgram, computeShader);
GLES31.glLinkProgram(computeProgram);
checkGLError("LinkProgram/computeProgram");
}
The draw function:
public void draw(float[] mvpMatrix, float[] color) {
GLES31.glUseProgram(computeProgram);
checkGLError("UseProgram/computeProgram");
int radiusId = GLES31.glGetUniformLocation(
computeProgram, "radius");
indexBufferBinding = 0;
GLES31.glUniform1f(radiusId, (float) radius);
GLES31.glBindBufferBase(
GLES31.GL_SHADER_STORAGE_BUFFER, indexBufferBinding, gVBO);
checkGLError("glBindBuffer/gVBO");
GLES31.glDispatchCompute(2, 2, 1);
GLES31.glBindBufferBase(
GLES31.GL_SHADER_STORAGE_BUFFER, indexBufferBinding, 0);
// See note 1 below
//GLES31.glMemoryBarrier(
// GLES31.GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
GLES31.glMemoryBarrier(
GLES31.GL_SHADER_STORAGE_BARRIER_BIT);
checkGLError("glMemoryBarrier/1");
GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, gVBO);
checkGLError("glBindBuffer/gVBO");
GLES31.glUseProgram(program);
int posId = GLES31.glGetAttribLocation(
program, "a_v4Position");
int fillId = GLES31.glGetAttribLocation(
program, "a_v4FillColor");
int mvpMatrixId = GLES31.glGetUniformLocation(
program, "mvp_matrix");
GLES31.glEnableVertexAttribArray(posId);
GLES31.glEnableVertexAttribArray(fillId);
GLES31.glUniformMatrix4fv(mvpMatrixId, 1, false, mvpMatrix, 0);
// See note 2 below
GLES31.glDrawArrays(GLES31.GL_POINTS, 0, 3);
}
For reference, the shaders are at the end of the post.
Notes:
I can't find GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT in the Android documentation. Shouldn't it be there? The documentation mentions it.
The draw call crashes the application. Up until before glDrawArrays() everything seems fine.
Any ideas on what to look for are appreciated.
Vertex Shader:
private final String vertexShaderCode =
"uniform mat4 mvp_matrix;" +
"attribute vec4 a_v4Position;" +
"attribute vec4 a_v4FillColor;" +
"varying vec4 v_v4FillColor;" +
"void main(void) {" +
" v_v4FillColor = a_v4FillColor;" +
" gl_Position = mvp_matrix * a_v4Position;" +
"}";
Fragment Shader:
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 v_v4FillColor;" +
"void main(void) {" +
" gl_FragColor = v_v4FillColor;" +
"}";
Compute Shader:
private final String computeShaderCode =
"#version 310 es" +
"\n" +
"uniform float radius;" +
"struct Vector3f { float x; float y; float z; float w; };" +
"struct AttribData { Vector3f v; Vector3f c; };" +
"layout(std140, binding = 0) buffer destBuffer { AttribData data[]; } outBuffer;" +
"layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" +
"void main() {" +
" ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);" +
" uint gWidth = gl_WorkGroupSize.x * gl_NumWorkGroups.x;" +
" uint gHeigth = gl_WorkGroupSize.y * gl_NumWorkGroups.y;" +
" uint gSize = uint(gWidth) * uint(gHeigth);" +
" uint offset = uint(storePos.y)*gWidth + uint(storePos.x);" +
" float alpha = 2.0 * 3.1159265359 * (float(offset) / float(gSize));" +
" outBuffer.data[offset].v.x = float(sin(alpha)) * float(radius);" +
" outBuffer.data[offset].v.y = float(cos(alpha)) * float(radius);" +
" outBuffer.data[offset].v.z = 0.0;" +
" outBuffer.data[offset].v.w = 1.0;" +
" outBuffer.data[offset].c.x = float(storePos.x) / float(gWidth);" +
" outBuffer.data[offset].c.y = 0.0;" +
" outBuffer.data[offset].c.z = 1.0;" +
" outBuffer.data[offset].c.w = 1.0;" +
"}";
Yes, GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT is missing in the Android Java bindings. There's a tradition of the Java OpenGL bindings in Android being incomplete. There are still things missing from the 3.0 bindings as well.
In this case, since it's just an enum value, you can easily work around it by defining the value itself. The C/C++ definition is:
#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
So in Java, you can add a definition like this to your code:
static final int GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT = 0x00000001;
As for the crash, I'm not totally sure. I notice that there's no glVertexAttribPointer() calls in the posted code. If they are indeed not in your code, that would certainly be a problem.
I have a problem with application. is a simple application atm using opengl es2.0 which running on android 2.2 device HTC sense. I can running the application on my 4.0.3 emulator as well as my device which running android 4.0.
When running on android 2.2, i have this error:
> FATAL EXCEPTION: GLThread 9
java.lang.RuntimeException: Error compiling shader:
SimpleShader.loadShader(SimpleShader.java:87)
SimpleShader.<init>(SimpleShader.java:54)
etc
I assumed that the device can run android 2.2 as the document told LINKS TO DOCUMENTATION, but not sure about the shader part though.
Here is my shader code:
String verticesShader =
"uniform mat4 uScreen;\n" +
"attribute vec2 aPosition;\n" +
"attribute vec3 aColor;\n" +
"attribute vec2 aTexPos; \n" +
"varying vec2 vTexPos; \n" +
"varying vec3 vColor;\n" +
"void main() {\n" +
" vTexPos = aTexPos; \n" +
" gl_Position = uScreen * vec4(aPosition.xy, 0.0, 1.0);\n" +
" vColor = aColor;\n" +
"}";
// Our fragment shader. Just return vColor.
// If you look at this source and just said 'WTF?', remember
// that all the attributes are defined in the VERTEX shader and
// all the 'varying' vars are considered OUTPUT of vertex shader
// and INPUT of the fragment shader. Here we just use the color
// we received and add a alpha value of 1.
String fragmentShader =
"uniform float uUseTexture; \n" +
"uniform float uAlpha; \n" +
"uniform sampler2D uTexture;\n" +
"precision mediump float;\n"+
"varying vec2 vTexPos; \n" +
"varying vec3 vColor;\n" +
"void main(void)\n" +
"{\n" +
" if ( uUseTexture != 1.0 ) \n" +
" gl_FragColor = vec4(vColor.xyz, 1); \n" +
" else \n" +
" gl_FragColor = texture2D(uTexture, vTexPos); \n" +
" gl_FragColor.a *= uAlpha;" +
//" gl_FragColor = vec4(vColor.xyz, 1);\n" +
"}";
private int loadShader(int shader, String shaderSrc) {
// TODO Auto-generated method stub
int handle = GLES20.glCreateShader(shader);
if (handle == GLES20.GL_FALSE)
throw new RuntimeException("Error creating shader!");
GLES20.glShaderSource(handle, shaderSrc);
GLES20.glCompileShader(handle);
int[] compileStatus = new int[1];
GLES20.glGetShaderiv(handle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
if (compileStatus[0] ==0)
{
String error = GLES20.glGetShaderInfoLog(handle);
GLES20.glDeleteShader(handle);
throw new RuntimeException("Error compiling shader: " + error);
}
else
return handle;
}
The application works fine on my latest device with android 4.0+
Have you considered checking your OpenGL ES GLSL version on both the android 2.2 device and the android 4.0+ device?
You can print it with GLES20.glGetString(GLES20.GL_SHADING_LANGUAGE_VERSION).
I'm trying to create 3D scene. There is textured Earth with clouds. I think that clouds I will be able to create by transparent sphere and texture of clouds on it(if I'm wrong please correct me). So I have some code below:
ShaderProgram shader;
Mesh mesh, cloudMesh;
Texture texture, cloudTexture;
Matrix4 matrix = new Matrix4();
public void create() {
String vertexShader = "attribute vec4 a_position; \n"
+ "attribute vec4 a_color;\n"
+ "attribute vec2 a_texCoords;\n"
+ "uniform mat4 u_worldView;\n"
+ "varying vec4 v_color;"
+ "varying vec2 v_texCoords;"
+ "void main() \n"
+ "{ \n"
+ " v_color = vec4(1, 1, 1, 1); \n"
+ " v_texCoords = a_texCoords; \n"
+ " gl_Position = u_worldView * a_position; \n"
+ "} \n";
String fragmentShader = "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "varying vec4 v_color;\n"
+ "varying vec2 v_texCoords;\n"
+ "uniform sampler2D u_texture;\n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n"
+ "}";
shader = new ShaderProgram(vertexShader, fragmentShader);
if (shader.isCompiled() == false) {
System.exit(0);
}
mesh = ObjLoader.loadObj(Gdx.files.internal("objects/earth.obj").read());
cloudMesh = ObjLoader.loadObj(Gdx.files.internal("objects/cloud_sphere.obj").read());
texture = new Texture(Gdx.files.internal("images/earthmap.jpg"));
cloudTexture = new Texture(Gdx.files.internal("images/earth_clouds_map.jpg"));
}
public void render() {
angle += Gdx.graphics.getDeltaTime() * 30;
matrix.setToRotation(axis, angle);
Gdx.graphics.getGL20().glViewport(-10, 10, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
Gdx.graphics.getGL20().glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.graphics.getGL20().glEnable(GL20.GL_TEXTURE_2D);
Gdx.graphics.getGL20().glEnable(GL20.GL_BLEND);
Gdx.graphics.getGL20().glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
texture.bind();
shader.begin();
shader.setUniformMatrix("u_worldView", matrix);
shader.setUniformi("u_texture", 0);
mesh.render(shader, GL20.GL_TRIANGLE_STRIP);
shader.end();
//SHOULD I USE SHADER PROGRAM LIKE BELOW?
cloudTexture .bind();
shader.begin();
shader.setUniformMatrix("u_worldView", matrix);
shader.setUniformi("u_texture", 0);
cloudMesh.render(shader, GL20.GL_TRIANGLE_STRIP);
shader.end();
}
So I don't see any textures on spheres. Where is mistake? If someone have any ideas, links or examples it will be appreciated!
Before loading your textures you have to define a "slot" where your texture will be stored:
Gdx.graphics.getGL20().glActiveTexture(GL20.GL_TEXTURE0);
texture = new Texture(Gdx.files.internal("images/earthmap.jpg"));
texture.bind();
Gdx.graphics.getGL20().glActiveTexture(GL20.GL_TEXTURE1);
cloudTexture = new Texture(Gdx.files.internal("images/earth_clouds_map.jpg"));
cloudTexture.bind();
in your render-method you then bind the texture and assign it to the shader using these "slots"
shader.setUniformi("u_texture", 0);
...
...
shader.setUniformi("u_texture", 1);
that should be all...
How can I draw a pixel(2D view)for Android using OpenGlEs?
It is simple when we use for drawing
draw(Canvas canvas)
{
...
}
So using it we draw
canvas.drawPoint(i, j, paint);
But in OpenGlEs I still haven't got any function like it.
Please reply
Thank in Advance
GLES20Renderer.programLight = GLES20.glCreateProgram();
int vertexShaderLight = GLES20Renderer.loadShader(GLES20.GL_VERTEX_SHADER, GLES20Renderer.vertexShaderCodeLight);
int fragmentShaderLight = GLES20Renderer.loadShader(GLES20.GL_FRAGMENT_SHADER, GLES20Renderer.fragmentShaderCodeLight);
GLES20.glAttachShader(GLES20Renderer.programLight, vertexShaderLight);
GLES20.glAttachShader(GLES20Renderer.programLight, fragmentShaderLight);
GLES20.glLinkProgram(GLES20Renderer.programLight);
uPLocationLight = GLES20.glGetUniformLocation(GLES20Renderer.programLight, "uP");
uVPositionLocationLight = GLES20.glGetUniformLocation(GLES20Renderer.programLight, "uVPosition");
GLES20.glUseProgram(GLES20Renderer.programLight);
GLES20.glUniform4f(uVPositionLocationLight, LightPosInEyeSpace[0], LightPosInEyeSpace[1], LightPosInEyeSpace[2], LightPosInEyeSpace[3]);
GLES20.glUniformMatrix4fv(uPLocationLight, 1, false, ProjectionMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
private static final String vertexShaderCodeLight =
"uniform vec4 uVPosition; \n"
+ "uniform mat4 uP; \n"
+ "void main(){ \n"
+ " gl_PointSize = 15.0; \n"
+ " gl_Position = uP * uVPosition; \n"
+ "} \n";
private static final String fragmentShaderCodeLight =
"#ifdef GL_FRAGMENT_PRECISION_HIGH \n"
+ "precision highp float; \n"
+ "#else \n"
+ "precision mediump float; \n"
+ "#endif \n"
+ "void main(){ \n"
+ " gl_FragColor = vec4(1.0,1.0,1.0,1.0); \n"
+ "} \n";
glDrawElements(GL_POINTS, 0, num_points, point_array);
You can also use glDrawArrays if you use glVertexPointer first.
Use glPointParameter, glPointSize, and glColor to modify the appearance of the points. Using glPointSizePointer lets you specify an array of point sizes, which is handy for particle effects.