Question

I am trying to create animated background for one of my applications.

Basically, I want my activity to display animated Perlin or Simplex noise as the background. For low energy consumption I am trying to do everything using OpenGL. Unfortunately, I know very little about OpenGL.

I started with Displaying Graphics with OpenGL ES and it worked. Then I tried to replace drawing code and vertex / fragment shaders for the Square but ended up with runtime exceptions.

I am trying to use following vertex shader:

uniform mat4 uMVPMatrix;
attribute vec4 vPosition;

void main()
{
    gl_Position = uMVPMatrix * vPosition;
}

and slightly changed fragment shader from Ashima Arts:

float snoise(vec3 v) { 
  // ..
}


uniform float time; // Used for texture animation

void main( void )
{
  vec3 v_texCoord3D = gl_Position.xyz; 

  vec3 uvw = v_texCoord3D + 0.1*vec3(snoise(v_texCoord3D + vec3(0.0, 0.0, time)),
    snoise(v_texCoord3D + vec3(43.0, 17.0, time)),
    snoise(v_texCoord3D + vec3(-17.0, -43.0, time)));
  // Six components of noise in a fractal sum
  float n = snoise(uvw - vec3(0.0, 0.0, time));
  n += 0.5 * snoise(uvw * 2.0 - vec3(0.0, 0.0, time*1.4)); 
  n += 0.25 * snoise(uvw * 4.0 - vec3(0.0, 0.0, time*2.0)); 
  n += 0.125 * snoise(uvw * 8.0 - vec3(0.0, 0.0, time*2.8)); 
  n += 0.0625 * snoise(uvw * 16.0 - vec3(0.0, 0.0, time*4.0)); 
  n += 0.03125 * snoise(uvw * 32.0 - vec3(0.0, 0.0, time*5.6)); 
  n = n * 0.7;
  // A "hot" colormap - cheesy but effective 
  gl_FragColor = vec4(vec3(1.0, 0.5, 0.0) + vec3(n, n, n), 1.0);
}

The draw function:

public void draw(float[] mvpMatrix)
{
    GLES20.glUseProgram(m_program);

    int positionHandle = GLES20.glGetAttribLocation(m_program, "vPosition");
    GLES20.glEnableVertexAttribArray(positionHandle);

    int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
    GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, m_vertexBuffer);

    int timeHandle = GLES20.glGetUniformLocation(m_program, "time");
    GLES20.glUniform1f(timeHandle, time);

    int mvpMatrixHandle = GLES20.glGetUniformLocation(m_program, "uMVPMatrix");
    BackgroundRenderer.checkGlError("glGetUniformLocation");

    GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);
    BackgroundRenderer.checkGlError("glUniformMatrix4fv");

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, m_drawListBuffer);

    GLES20.glDisableVertexAttribArray(positionHandle);
}

Unfortunately, all I get is

java.lang.RuntimeException: glGetUniformLocation: glError 1282

raised on this line

int mvpMatrixHandle = GLES20.glGetUniformLocation(m_program, "uMVPMatrix");

How should I change my code?

Was it helpful?

Solution

You have a couple of problems here:

  1. You never checked the shader compile log, if you did you would have seen that the fragment shader does not compile.
  2. You only check glGetError (...) after a single call, and thus you thought that int mvpMatrixHandle = GLES20.glGetUniformLocation(m_program, "uMVPMatrix"); was the source of your GL_INVALID_OPERATION, when in fact glUseProgram (...) was the first line of code in your function to trigger it.

I have corrected your vertex and fragment shaders so that they will compile... you cannot use gl_Position in a fragment shader, and this is why your shader was failing to compile and your program was not linking.

Modified Vertex Shader:

uniform   mat4 uMVPMatrix;
attribute vec4 vPosition;
varying   vec4 vtx_pos;

void main()
{
    gl_Position = uMVPMatrix * vPosition;
    vtx_pos     = gl_Position;
}

Modified Fragment Shader:

varying vec4  vtx_pos;
uniform float time; // Used for texture animation

float snoise(vec3 v) { 
  // ..
}

void main( void )
{
  vec3 v_texCoord3D = vtx_pos.xyz; 

  vec3 uvw = v_texCoord3D + 0.1*vec3(snoise(v_texCoord3D + vec3(0.0, 0.0, time)),
    snoise(v_texCoord3D + vec3(43.0, 17.0, time)),
    snoise(v_texCoord3D + vec3(-17.0, -43.0, time)));
  // Six components of noise in a fractal sum
  float n = snoise(uvw - vec3(0.0, 0.0, time));
  n += 0.5 * snoise(uvw * 2.0 - vec3(0.0, 0.0, time*1.4)); 
  n += 0.25 * snoise(uvw * 4.0 - vec3(0.0, 0.0, time*2.0)); 
  n += 0.125 * snoise(uvw * 8.0 - vec3(0.0, 0.0, time*2.8)); 
  n += 0.0625 * snoise(uvw * 16.0 - vec3(0.0, 0.0, time*4.0)); 
  n += 0.03125 * snoise(uvw * 32.0 - vec3(0.0, 0.0, time*5.6)); 
  n = n * 0.7;
  // A "hot" colormap - cheesy but effective 
  gl_FragColor = vec4(vec3(1.0, 0.5, 0.0) + vec3(n, n, n), 1.0);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top