android - 无法将已编译的着色器链接到 OpenGL ES 2.0 Android 程序

标签 android opengl-es opengl-es-2.0

我在将着色器链接到 OpenGL ES 2.0 中的程序时遇到问题。 这是我的代码

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;
}

问题是,在成功编译着色器之后,我正在尝试将我的着色器附加到我的程序中。它看起来像 ot 的附加着色器,但链接没有。这是此操作的日志:

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

任何帮助将不胜感激

最佳答案

你的问题在这里:

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

您正在编译 vertexShader 而不是 fragmentShader,因此 vertexShader 被编译了两次,而 fragmentShader 根本没有被编译。

关于android - 无法将已编译的着色器链接到 OpenGL ES 2.0 Android 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31961079/

相关文章:

java - 干净的架构/MVP : Using different repositories for different models. 可以吗?

ios - 结合 Cocos2d 和 GLKView 渲染相同的数据

android - 在 OpenGL ES 中使用帧缓冲区的深度和模板渲染缓冲区附件

ios - 处理小物体上的手指检测

android - 以地理 Intent 开始的谷歌地图 7 将在最接近坐标的地址而不是确切位置放置图钉

android - android可以做 "waitForResponse"吗

oop - 在面向对象的设置中使用OpenGL绘图操作?

iphone - OpenGL ES 2.0 纹理对象的多个实例

OpenGL ES 线程中的 Android 时序不是单调的

android - RecyclerView 没有显示我预期的输出