简体   繁体   中英

Can't link compiled shaders to program OpenGL ES 2.0 Android

I have a problem with linking shaders to program in OpenGL ES 2.0. Here's my code

package pl.projekcik;

import android.content.Context;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.logging.Logger;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import util.LoggerConfig;
import util.ShaderHelper;
import util.TextResourceReader;

import static android.opengl.GLES20.*;
import static android.opengl.GLUtils.*;
import static android.opengl.Matrix.*;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;

public class ProjekcikRenderer implements Renderer {

private static final int POSITION_COMPONENT_COUNT = 3;
private static final int BYTES_PER_FLOAT = 4;
private final FloatBuffer vertexData;
private final Context context;
private int program;
private static final String U_COLOR = "u_COLOR";
private int uColorLocation;
private static final String A_POSITION = "a_Position";
private int aPositionLocation;
private static final String TAG = "ProjekcikRenderer";

public ProjekcikRenderer(Context context){
    this.context = context;
    float[] tableVertices = {
        0f, 0f, 0f,
        1f, 1f, 0f,
        0f, 1f, 0f,

        0f, 0f, 0f,
        1f, 0f, 0f,
        1, 1f, 0f
    };

    vertexData = ByteBuffer
            .allocateDirect(tableVertices.length * BYTES_PER_FLOAT)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer();

    vertexData.put(tableVertices);
}

@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config){
    glClearColor(1.0f, 1.0f, 0.5f, 0.0f);
    String vertexShaderSource = null;
    String fragmentShaderSource = null;
    try{
        vertexShaderSource = TextResourceReader.readTextFileFromResource(context, R.raw.simple_vertex_shader);
        fragmentShaderSource = TextResourceReader.readTextFileFromResource(context, R.raw.simple_fragment_shader);
    } catch (IOException e){
        throw new RuntimeException("IOException", e);
    } catch (Exception e){
        throw new RuntimeException("Other Exception", e);
    }

    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    Log.d(TAG, "CREATING VERTEX SHADER");
    String s = new String(Integer.toString(vertexShader));
    if(vertexShader == 0){
        if(LoggerConfig.ON){
            Log.w(TAG, "Could not create new VERTEX shader");
        }
        return;
    } else {
        if(LoggerConfig.ON){
            Log.w(TAG, s);
        }
    }
    GLES20.glShaderSource(vertexShader, vertexShaderSource);
    GLES20.glCompileShader(vertexShader);
    final int[] compileStatus = new int[1];
    GLES20.glGetShaderiv(vertexShader, GL_COMPILE_STATUS, compileStatus, 0);
    if(LoggerConfig.ON){
        Log.v(TAG, "Results of compiling source:" + "\n" + vertexShaderSource + "\n" + glGetShaderInfoLog(vertexShader));
    }
    if(compileStatus[0] == 0){
        glDeleteShader(vertexShader);
        if(LoggerConfig.ON){
            Log.w(TAG, "Compilation of shader failed");
        }
        return;
    } else {
        if(LoggerConfig.ON){
            Log.v(TAG, "VERTEX SHADER COMPILED");
        }
    }

    int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    Log.d(TAG, "CREATING FRAGMENT SHADER");
    s = new String(Integer.toString(fragmentShader));
    if(fragmentShader == 0){
        if(LoggerConfig.ON){
            Log.w(TAG, "Could not create new FRAGMENT shader");
        }
        return;
    } else {
        if(LoggerConfig.ON){
            Log.w(TAG, s);
        }
    }
    GLES20.glShaderSource(fragmentShader, fragmentShaderSource);
    GLES20.glCompileShader(vertexShader);
    GLES20.glGetShaderiv(vertexShader, GL_COMPILE_STATUS, compileStatus, 0);
    if(LoggerConfig.ON){
        Log.v(TAG, "Results of compiling source:" + "\n" + fragmentShaderSource + "\n" + glGetShaderInfoLog(fragmentShader));
    }
    if(compileStatus[0] == 0){
        glDeleteShader(fragmentShader);
        if(LoggerConfig.ON){
            Log.w(TAG, "Compilation of shader failed");
        }
        return;
    } else {
        if(LoggerConfig.ON){
            Log.v(TAG, "FRAGMENT SHADER COMPILED");
        }
    }

    program = GLES20.glCreateProgram();
    s = new String(Integer.toString(program));
    Log.v("PROGRAM ID: ", s);
    if(program == 0){
        if(LoggerConfig.ON){
            Log.w(TAG, "Could not create new program");
        }
        return;
    }

    try{
        GLES20.glAttachShader(program, vertexShader);
        GLES20.glAttachShader(program, fragmentShader);
    } catch (Exception e){
        Log.w("ATTACH", "COULD NOT ATTACH 1 OR MORE SHADERS");
    }

    try{
        GLES20.glLinkProgram(program);
    } catch (Exception e){
        Log.w("LINK", "Link program failed");
    }


    final int[] linkStatus = new int[1];
    glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
    if(LoggerConfig.ON){
        Log.v(TAG, "Results of linking program:\n" + glGetProgramInfoLog(program));
    }
    if(linkStatus[0] == 0){
        glDeleteProgram(program);
        if(LoggerConfig.ON){
            Log.w(TAG, "Linking of program failed");
        }
        return;
    }

    if(LoggerConfig.ON){
        validateProgram(program);
    }

    glUseProgram(program);

    uColorLocation = glGetUniformLocation(program, U_COLOR);
    aPositionLocation = glGetAttribLocation(program, A_POSITION);
    vertexData.position(0);
    glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, 0, vertexData);
    glEnableVertexAttribArray(aPositionLocation);
}

@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height){
    glViewport(0, 0, width, height);
}

@Override
public void onDrawFrame(GL10 glUnused){
    glClear(GL_COLOR_BUFFER_BIT);
    glUniform4f(uColorLocation, 0.0f, 0.0f, 0.0f, 1.0f);
    glDrawArrays(GL_TRIANGLES, 0, 6);
}

public static boolean validateProgram(int programObjectId){
    glValidateProgram(programObjectId);

    final int[] validateStatus = new int[1];
    glGetProgramiv(programObjectId, GL_VALIDATE_STATUS, validateStatus, 0);
    Log.v(TAG, "Results of validating program: " + validateStatus[0] + "\nLog: " + glGetProgramInfoLog(programObjectId));
    return validateStatus[0] != 0;
}

}

The problem is, after succesfully compiling shaders I'm trying to attach my shaders to my program. It looks like ot's attaching shaders, but linking doesn't. Here's log of from this operation:

08-12 11:24:10.330  23044-23044/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libEGL_mali.so
08-12 11:24:10.330  23044-23044/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libGLESv1_CM_mali.so
08-12 11:24:10.340  23044-23044/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libGLESv2_mali.so
08-12 11:24:10.350  23044-23044/pl.projekcik D/OpenGLRenderer﹕ Enabling debug mode 0
08-12 11:24:10.420  23044-23057/pl.projekcik D/ProjekcikRenderer﹕ CREATING VERTEX SHADER
08-12 11:24:10.420  23044-23057/pl.projekcik W/ProjekcikRenderer﹕ 1
08-12 11:24:10.420  23044-23057/pl.projekcik V/ProjekcikRenderer﹕ Results of compiling source:
    attribute highp vec4 a_Position;
    void main(){
    gl_Position = a_Position;
    }
08-12 11:24:10.420  23044-23057/pl.projekcik V/ProjekcikRenderer﹕ VERTEX SHADER COMPILED
08-12 11:24:10.420  23044-23057/pl.projekcik D/ProjekcikRenderer﹕ CREATING FRAGMENT SHADER
08-12 11:24:10.420  23044-23057/pl.projekcik W/ProjekcikRenderer﹕ 2
08-12 11:24:10.420  23044-23057/pl.projekcik V/ProjekcikRenderer﹕ Results of compiling source:
    precision mediump float;
    uniform vec4 u_Color;
    void main(){
    gl_FragColor = u_Color;
    }
08-12 11:24:10.420  23044-23057/pl.projekcik V/ProjekcikRenderer﹕ FRAGMENT SHADER COMPILED
08-12 11:24:10.420  23044-23057/pl.projekcik V/PROGRAM ID:﹕ 3
08-12 11:24:10.420  23044-23057/pl.projekcik V/ProjekcikRenderer﹕ Results of linking program:
    L0101 All attached shaders must be compiled prior to linking
08-12 11:24:10.420  23044-23057/pl.projekcik W/ProjekcikRenderer﹕ Linking of program failed
08-12 11:24:10.430  23044-23046/pl.projekcik D/dalvikvm﹕ GC_CONCURRENT freed 270K, 8% free 6260K/6791K, paused 17ms+4ms, total 81ms

Any help would be greatly appreciated

Your problem is here:

GLES20.glShaderSource(fragmentShader, fragmentShaderSource);
GLES20.glCompileShader(vertexShader); 
GLES20.glGetShaderiv(vertexShader, GL_COMPILE_STATUS, compileStatus, 0);

You're compiling the vertexShader instead of the fragmentShader, so the vertexShader is getting compiled twice, and the fragmentShader isn't getting compiled at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM