JOGL 失败;我做什么都是黑屏。着色器出现故障,glGetAttribLocation returns -1

JOGL failure; whatever I do is black screen. Shaders malfunctioning, glGetAttribLocation returns -1

我遇到了 JOGL 故障。我根本无法让它显示任何东西。我已经使 Android OpenGL ES 正常工作,但这里有 2 个大问题。首先,没有任何显示。其次,我的 none 个变量存在于着色器编译器中。

很抱歉这不是 SSCEE。我只是有这个臭虫,我无法用更短的代码重现它。

import java.awt.Dimension;
import java.io.File;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import javax.swing.JFrame;

import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.leonidnediak.labyrinth.annoyingGLstuff.ShaderStuff;
import com.leonidnediak.labyrinth.util.FileUtil;

public class Main implements GLEventListener {

public static File codeSource;

static {
    try {
        codeSource = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI());
    } catch (URISyntaxException e) {

    }
}

public static final Dimension size = new Dimension(400, 600);



public static int program;
public static int aColorLocation;
public static int aPositionLocation;
public static int uMatrixLocation;

public static void main(String[] args) {
    GLProfile profile = GLProfile.get(GLProfile.GL2);
    GLCapabilities cap = new GLCapabilities(profile);

    GLCanvas canvas = new GLCanvas(cap);
    canvas.addGLEventListener(new Main());
    canvas.setSize(size);

    JFrame frame = new JFrame();
    frame.setSize(size);
    frame.setResizable(false);
    frame.add(canvas);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

@Override
public void display(GLAutoDrawable autoDrawable) {
    GL2 gl = autoDrawable.getGL().getGL2();
    gl.glClear(GL2.GL_COLOR_BUFFER_BIT);

    gl.glEnableVertexAttribArray(aPositionLocation);
    FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(4*9).asFloatBuffer();
    vertexBuffer.put(new float[] {-1, 1, 0, 0, -1, 0, 1, 1, 0});
    vertexBuffer.position(0);
    gl.glVertexAttribPointer(aPositionLocation, 3, GL2.GL_FLOAT, false, 12, vertexBuffer);
    gl.glEnableVertexAttribArray(aColorLocation);
    FloatBuffer colorBuffer = ByteBuffer.allocateDirect(4*9).asFloatBuffer();
    colorBuffer.put(new float[] {1, 1, 1, 1, 1, 1, 1, 1, 1});
    colorBuffer.position(0);
    gl.glVertexAttribPointer(aPositionLocation, 3, GL2.GL_FLOAT, false, 12, colorBuffer);
    gl.glDrawArrays(GL2.GL_TRIANGLES, 0, 3);
}

@Override
public void dispose(GLAutoDrawable autoDrawable) {

}

@Override
public void init(GLAutoDrawable autoDrawable) {
    GL2 gl = autoDrawable.getGL().getGL2();
    program = ShaderStuff.buildProgram(gl, FileUtil.fileContents(new File(codeSource, "vertexShader.glsl")), FileUtil.fileContents(new File(codeSource, "fragmentShader.glsl")));
    int[] arr = new int[1];
    gl.glGetProgramiv(program, GL2.GL_ACTIVE_ATTRIBUTES, arr, 0);
    System.out.println(arr[0]);
    aColorLocation = gl.glGetAttribLocation(program, "a_Color");
    aPositionLocation = gl.glGetAttribLocation(program, "a_Position");
    uMatrixLocation = gl.glGetUniformLocation(program, "u_Matrix");
    System.out.println(program);
    gl.glUniformMatrix4fv(uMatrixLocation, 1, false, new float[] {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}, 0);
}

@Override
public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4) {

}

}

抱歉缩进,Whosebug 迫使我缩进很多。 那是我的主要 class。 这是我的 ShaderStuff:

import com.jogamp.opengl.GL2;

public class ShaderStuff {

public static int compileVertexShader(GL2 gl, String shaderCode) {
    return compileShader(gl, GL2.GL_VERTEX_SHADER, shaderCode);
}

public static int compileFragmentShader(GL2 gl, String shaderCode) {
    return compileShader(gl, GL2.GL_FRAGMENT_SHADER, shaderCode);
}

private static int compileShader(GL2 gl, int type, String shaderCode) {
    final int shaderObjectId = gl.glCreateShader(type);
    if (shaderObjectId == 0) {
        return 0;

    }
    gl.glShaderSource(shaderObjectId, 1, new String[] {shaderCode}, null);
    gl.glCompileShader(shaderObjectId);
    final int[] compileStatus = new int[1];
    gl.glGetShaderiv(shaderObjectId, GL2.GL_COMPILE_STATUS, compileStatus, 0);
    if (compileStatus[0] == 0) {
        //gl.glDeleteShader(shaderObjectId);
        //return 0;
    }
    return shaderObjectId;
}

public static int linkProgram(GL2 gl, int vertexShaderId, int fragmentShaderId) {
    final int programObjectId = gl.glCreateProgram();
    if (programObjectId == 0) {
        return 0;
    }
    gl.glAttachShader(programObjectId, vertexShaderId);
    gl.glAttachShader(programObjectId, fragmentShaderId);
    gl.glLinkProgram(programObjectId);
    final int[] linkStatus = new int[1];
    gl.glGetProgramiv(programObjectId, GL2.GL_LINK_STATUS, linkStatus, 0);
    if (linkStatus[0] == 0) {
        //gl.glDeleteProgram(programObjectId);
        //return 0;
    }
    return programObjectId;
}

public static int buildProgram(GL2 gl, String vertexS, String fragS) {
    int program;
    int vertexShader = compileVertexShader(gl, vertexS);
    int fragmentShader = compileVertexShader(gl, fragS);
    program = linkProgram(gl, vertexShader, fragmentShader);
    validateProgram(gl, program);
    return program;
}

public static boolean validateProgram(GL2 gl, int programObjectId) {
    gl.glValidateProgram(programObjectId);
    final int[] validateStatus = new int[1];
    gl.glGetProgramiv(programObjectId, GL2.GL_VALIDATE_STATUS, validateStatus, 0);
    return validateStatus[0] != 0;
}

}

编辑:问题出在我的 GLSL 中,但我找不到我的失败。

顶点着色器:

attribute vec4 a_Color;
attribute vec4 a_Position;

uniform mat4 u_Matrix;

varying vec4 v_Color;

void main()
{
    v_Color = a_Color;
    gl_Position = u_Matrix * a_Position;
    gl_PointSize = 1.0;
}

片段着色器:

precision mediump float;

varying vec4 v_Color;

void main()
{
    gl_FragColor = v_Color;
}

几个observations/hints:

  • 保持位置分层,如 here,它不易出错并使您的代码更具可读性:

    public class Semantic { // or Location
    
        public static class Attr {
    
            public static int POSITION = 0;
            public static int COLOR = 3;
        }
    }
    
  • 不要在display()中的每一帧都分配一个新的FloatBuffer,在init()中初始化它并重新使用它。你可以用我的一个工具来处理它,我稍后告诉你。

  • 避免重新发明轮子,你可以完全避免你的 ShaderStuff class,使用 jogl 已经提供给我们的,here 一个例子。它会自动打印出任何编译错误。

  • 您的目标是哪个 GLES 版本?因为在着色器中 varying 已弃用,请使用 inout 代替

  • gl_FragColor相同,使用out vec4 FragColor;

我们有其他 jogl 用户正在朝这个方向努力,我们可以创建一个简单明了的 hello 三角形示例,专门为 android 制作,您会感兴趣吗?