致命异常:GLThread 919

时间:2014-10-28 12:52:36

标签: android

我尝试创建一个相机应用。在这个应用程序中拍照并对拍摄的照片应用几个滤镜。过滤器由OpenGL实现。此应用仅适用于Nexus5 ,在其他设备中,强行关闭 FATAL EXCEPTION:GLThread 。谢谢!

Logcat错误在下面给出

10-28 18:28:55.215    6217-6449/com.camera_with_filter.camera_filter E/ShaderHelper﹕ Error compiling shader: Compile failed.
ERROR: 0:1: 'vec2' : No precision defined for this type
ERROR: 1 compilation errors. No code generated.10-28 18:28:55.253    6217-6449/com.camera_with_filter.camera_filter E/AndroidRuntime﹕ FATAL EXCEPTION: GLThread 660
java.lang.RuntimeException: Error creating shader.
        at com.camera_with_filter.camera_filter.ShaderHelper.compileShader(ShaderHelper.java:44)
        at com.camera_with_filter.camera_filter.MyGLRenderer.onSurfaceCreated(MyGLRenderer.java:156)
        at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1520)
        at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1266)

1.SaderHelper.java

公共类ShaderHelper {     private static final String TAG =“ShaderHelper”;

/** 
 * Helper function to compile a shader.
 * 
 * @param shaderType The shader type.
 * @param shaderSource The shader source code.
 * @return An OpenGL handle to the shader.
 */
public static int compileShader(final int shaderType, final String shaderSource) 
{
    int shaderHandle = GLES20.glCreateShader(shaderType);

    if (shaderHandle != 0) 
    {
        // Pass in the shader source.
        GLES20.glShaderSource(shaderHandle, shaderSource);

        // Compile the shader.
        GLES20.glCompileShader(shaderHandle);

        // Get the compilation status.
        final int[] compileStatus = new int[1];
        GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

        // If the compilation failed, delete the shader.
        if (compileStatus[0] == 0) 
        {
            Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shaderHandle));
            GLES20.glDeleteShader(shaderHandle);
            shaderHandle = 0;
        }
    }

    if (shaderHandle == 0)
    {           
        throw new RuntimeException("Error creating shader.");
    }

    return shaderHandle;
}

/**
 * Helper function to compile and link a program.
 * 
 * @param vertexShaderHandle An OpenGL handle to an already-compiled vertex shader.
 * @param fragmentShaderHandle An OpenGL handle to an already-compiled fragment shader.
 * @param attributes Attributes that need to be bound to the program.
 * @return An OpenGL handle to the program.
 */
public static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) 
{
    int programHandle = GLES20.glCreateProgram();

    if (programHandle != 0) 
    {
        // Bind the vertex shader to the program.
        GLES20.glAttachShader(programHandle, vertexShaderHandle);           

        // Bind the fragment shader to the program.
        GLES20.glAttachShader(programHandle, fragmentShaderHandle);

        // Bind attributes
        if (attributes != null)
        {
            final int size = attributes.length;
            for (int i = 0; i < size; i++)
            {
                GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
            }                       
        }

        // Link the two shaders together into a program.
        GLES20.glLinkProgram(programHandle);

        // Get the link status.
        final int[] linkStatus = new int[1];
        GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);

        // If the link failed, delete the program.
        if (linkStatus[0] == 0) 
        {               
            Log.e(TAG, "Error compiling program: " + GLES20.glGetProgramInfoLog(programHandle));
            GLES20.glDeleteProgram(programHandle);
            programHandle = 0;
        }
    }

    if (programHandle == 0)
    {
        throw new RuntimeException("Error creating program.");
    }

    return programHandle;
}

}

2.MyGLRender

public class MyGLRenderer implements Renderer {
private final Context mActivityContext;
private String mFilepath;

private final FloatBuffer mTexcoordPositions;
private final FloatBuffer mVerticesPositions;

private int mImageUniformHandle;
private int mStepUniformHandle;

private int mProgramHandle;
private int mPositionHandle;
private int mTexcoordHandle;


private int mEmbossProgram;
private int mBlurProgram;
private int mEdgeProgram;
private int mGrayScaleProgram;
private int mNegProgram;
private int mToonshadingProgram;
private int mNormalProgram;
private int height = 1600;
private int width = 900;

private int mProgramID = 1;

private int mTextureDataHandle;
private final int mBytesPerFloat = 4;

private final int mPositionDataSize = 2;
private final int mTexcoordDataSize = 2;

private boolean mScreenshot;
private final float[] vertices = {
        1.0f, 1.0f,
        -1.0f, 1.0f,
        1.0f, -1.0f,
        -1.0f, 1.0f,
        -1.0f, -1.0f,
        1.0f, -1.0f
};
private final float[] texcoords = {
        0.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f,
        1.0f, 0.0f,
};

@Override
public void onDrawFrame(GL10 arg0) {
    // TODO Auto-generated method stub

    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);


    mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "Position");
    mTexcoordHandle = GLES20.glGetAttribLocation(mProgramHandle, "Texcoords");
    mStepUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_step");
    mImageUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_image");


    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

    // Bind the texture to this unit.
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
    if (mImageUniformHandle != -1)
        GLES20.glUniform1i(mImageUniformHandle, 0);
    if (mStepUniformHandle != -1)
        GLES20.glUniform2f(mStepUniformHandle, 1.0f / (float) width, 1.0f / (float) height);
    Draw();
    if (mScreenshot == true)
        Log.d("mScreenshot", "true");
    if (mScreenshot) {
        Log.d("screenshot", "start");
        int screenshotSize = width * height;
        ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
        bb.order(ByteOrder.nativeOrder());
        GLES20.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);
        int pixelsBuffer[] = new int[screenshotSize];
        bb.asIntBuffer().get(pixelsBuffer);
        bb = null;
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        bitmap.setPixels(pixelsBuffer, screenshotSize - width, -width, 0, 0, width, height);
        pixelsBuffer = null;

        short sBuffer[] = new short[screenshotSize];
        ShortBuffer sb = ShortBuffer.wrap(sBuffer);
        bitmap.copyPixelsToBuffer(sb);

        //Making created bitmap (from OpenGL points) compatible with Android bitmap
        for (int i = 0; i < screenshotSize; ++i) {
            short v = sBuffer[i];
            sBuffer[i] = (short) (((v & 0x1f) << 11) | (v & 0x7e0) | ((v & 0xf800) >> 11));
        }
        sb.rewind();
        bitmap.copyPixelsFromBuffer(sb);
        try {
            StringBuffer sbFilepath = new StringBuffer(mFilepath);
            String sProgType = getProgramType();
            int insertIdx = sbFilepath.length() - 4;
            System.out.println(sbFilepath.insert(insertIdx, sProgType).toString());
            FileOutputStream fos = new FileOutputStream(sbFilepath.insert(insertIdx, sProgType).toString());
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            // handle
        }

        mScreenshot = false;
    }
}

@Override
public void onSurfaceChanged(GL10 arg0, int arg1, int arg2) {
    // TODO Auto-generated method stub

}

@Override
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
    // TODO Auto-generated method stub
    Log.d("onSurfaceCreated", "start");
    GLES20.glClearColor(0.3f, 0.0f, 0.0f, 0.0f);

    // Use culling to remove back faces.
    GLES20.glEnable(GLES20.GL_CULL_FACE);

    // Enable depth testing
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    String[] attr = new String[]{"Position", "Texcoords"};
    String vertexShader = getVertexShader();
    String fragmentShader = getFragmentShader(R.raw.passthroughfs);
    final int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
    int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    mNormalProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, attr);

    fragmentShader = getFragmentShader(R.raw.embossfs);
    fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    mEmbossProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, attr);

    fragmentShader = getFragmentShader(R.raw.boxblurfs);
    fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    mBlurProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, attr);

    fragmentShader = getFragmentShader(R.raw.edgefs);
    fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    mEdgeProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, attr);

    fragmentShader = getFragmentShader(R.raw.grayscalefs);
    fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    mGrayScaleProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, attr);

    fragmentShader = getFragmentShader(R.raw.negfs);
    fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    mNegProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, attr);

    fragmentShader = getFragmentShader(R.raw.toonshadingfs);
    fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    mToonshadingProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, attr);

    //  mProgramHandle = mToonshadingProgram;
/*  switch (mProgramID){


    case 1:
        mProgramHandle = mNormalProgram;
    case 2:
        mProgramHandle = mEmbossProgram;
    case 3:
        mProgramHandle =  mBlurProgram;
    case 4:
        mProgramHandle = mEdgeProgram;
    case 5:
        mProgramHandle = mGrayScaleProgram;
    case 6:
        mProgramHandle = mNegProgram;
    default:
        mProgramHandle = mNormalProgram;

    }*/

    // Load the texture
    setEffect(mProgramID);
    GLES20.glUseProgram(mProgramHandle);
    mTextureDataHandle = TextureHelper.loadTexture(mActivityContext, mFilepath);
    Log.d("onSurfaceCreated", "done");

}

public MyGLRenderer(final Context activityContext, String file) {
    mActivityContext = activityContext;
    mFilepath = file;

    System.out.println("constructor");
    Log.d("MyGLRenderer constructor", "start construct");

    mVerticesPositions = ByteBuffer.allocateDirect(vertices.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();
    mVerticesPositions.put(vertices).position(0);
    mTexcoordPositions = ByteBuffer.allocateDirect(texcoords.length * mBytesPerFloat)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();
    mTexcoordPositions.put(texcoords).position(0);
    Log.d("MyGLRenderer constructor", "done construct");
    mScreenshot = false;

}

protected String getVertexShader() {
    return RawResourceReader.readTextFileFromRawResource(mActivityContext, R.raw.passthroughvs);
}

protected String getFragmentShader(final int resourceId) {
    return RawResourceReader.readTextFileFromRawResource(mActivityContext, resourceId);
}

private void Draw() {
    setEffect(mProgramID);
    GLES20.glUseProgram(mProgramHandle);
    mVerticesPositions.position(0);
    GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
            0, mVerticesPositions);
    GLES20.glEnableVertexAttribArray(mPositionHandle);

    mTexcoordPositions.position(0);
    GLES20.glVertexAttribPointer(mTexcoordHandle, mTexcoordDataSize, GLES20.GL_FLOAT, false,
            0, mTexcoordPositions);
    GLES20.glEnableVertexAttribArray(mTexcoordHandle);

    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}


public void setEffect(int programID) {
    switch (programID) {


        case 1:
            mProgramHandle = mNormalProgram;
            break;
        case 2:
            mProgramHandle = mEmbossProgram;
            break;
        case 3:
            mProgramHandle = mBlurProgram;
            break;
        case 4:
            mProgramHandle = mEdgeProgram;
            break;
        case 5:
            mProgramHandle = mGrayScaleProgram;
            break;
        case 6:
            mProgramHandle = mNegProgram;
            break;
        case 7:
            mProgramHandle = mToonshadingProgram;
            break;
        default:
            mProgramHandle = mToonshadingProgram;
            break;
    }
    GLES20.glUseProgram(mProgramHandle);

}

public void setPorgID(int id) {
    mProgramID = id;

}

public String getProgramType() {
    switch (mProgramID) {
        case 1:
            return "normal";
        case 2:
            return "emobss";
        case 3:
            return "blur";
        case 4:
            return "edge";
        case 5:
            return "grayscale";
        case 6:
            return "negative";
        case 7:
            return "toonshading";
        default:
            return "";
    }
}

public void saveImage() {

    mScreenshot = true;
}

}

0 个答案:

没有答案