这是我第一次使用Android和OpenGL ES,但我对直接OpenGL有相当多的经验。我只是想画一个红色三角形。没有制服,只有一个顶点属性。
顶点着色器:
#version 300 es
in vec3 in_loc;
void main() {
gl_Position.xyz = in_loc;
}
片段着色器:
#version 300 es
precision mediump float;
out vec4 outColor;
void main() {
outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
结果:
我在着色器创建,编译,附件和链接期间检查并且没有错误。我已尝试将precision mediump float;
更改为precision highp float;
和precision lowp float;
。
通常我希望这个直的黑色输出表示一个破碎的片段着色器,但我没有得到任何错误,而且据我所知,这个非常简单的代码是'与在线发现的各种示例代码相同。
着色器创建代码:
public class Shader {
public enum Type { VERTEX, FRAGMENT }
static private int createShader(String src, Type type) {
int shaderHandle = 0;
switch (type) {
case VERTEX:
shaderHandle = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER);
break;
case FRAGMENT:
shaderHandle = GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER);
break;
}
if (shaderHandle == 0) {
Log.e("Shader", "Failed to create shader");
return 0;
}
// Compile shader
GLES30.glShaderSource(shaderHandle, src);
GLES30.glCompileShader(shaderHandle);
// Check for compile errors
int status[] = { 0 };
GLES30.glGetShaderiv(shaderHandle, GLES30.GL_COMPILE_STATUS, status, 0);
if (status[0] == 0) {
Log.e("Shader", "Failed to compile shader");
Log.e("Shader", GLES30.glGetShaderInfoLog(shaderHandle));
GLES30.glDeleteShader(shaderHandle);
return 0;
}
// Check for OpenGL errors
if (Util.isGLError()) {
GLES30.glDeleteShader(shaderHandle);
return 0;
}
return shaderHandle;
}
static private int createProgram(int vertShaderHandle, int fragShaderHandle) {
int programHandle = GLES30.glCreateProgram();
if (programHandle == 0) {
Log.e("Shader", "Failed to create program");
return 0;
}
// Attach and link shaders to form program
GLES30.glAttachShader(programHandle, vertShaderHandle);
GLES30.glAttachShader(programHandle, fragShaderHandle);
GLES30.glLinkProgram(programHandle);
// Check for linking errors
int status[] = { 0 };
GLES30.glGetProgramiv(programHandle, GLES30.GL_LINK_STATUS, status, 0);
if (status[0] == 0) {
Log.e("Shader", "Failed to link program");
Log.e("Shader", GLES30.glGetProgramInfoLog(programHandle));
GLES30.glDeleteProgram(programHandle);
return 0;
}
// Check for OpenGL errors
if (Util.isGLError()) {
GLES30.glDeleteProgram(programHandle);
return 0;
}
return programHandle;
}
private String name;
private int programHandle;
public Shader(String name) {
this.name = name;
this.programHandle = 0;
}
public boolean initFromSrc(String vertSrc, String fragSrc) {
// Create shaders
int vertShaderHandle = createShader(vertSrc, Type.VERTEX);
if (vertShaderHandle == 0) {
Log.e("Shader", "Failed to create vertex shader");
return false;
}
int fragShaderHandle = createShader(fragSrc, Type.FRAGMENT);
if (fragShaderHandle == 0) {
Log.e("Shader", "Failed to create fragment shader");
GLES30.glDeleteShader(vertShaderHandle);
return false;
}
// Create shader program
programHandle = createProgram(vertShaderHandle, fragShaderHandle);
if (programHandle == 0) {
Log.e("Shader", "Failed to create program");
GLES30.glDeleteShader(vertShaderHandle);
GLES30.glDeleteShader(fragShaderHandle);
return false;
}
// Shaders can now be deleted
GLES30.glDeleteShader(vertShaderHandle);
GLES30.glDeleteShader(fragShaderHandle);
return true;
}
public boolean initFromFile(String vertFile, String fragFile) {
String vertSrc = Util.readTextFile(vertFile);
if (vertSrc == null) {
Log.e("Shader", "Failed to read shader file: " + vertFile);
return false;
}
String fragSrc = Util.readTextFile(fragFile);
if (fragSrc == null) {
Log.e("Shader", "Failed to read shader file: " + fragFile);
return false;
}
return initFromSrc(vertSrc, fragSrc);
}
public int getProgramHandle() { return programHandle; }
}
其他一切:
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
GLES30.glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
shader = new Shader("basic");
if (!shader.initFromFile("shaders/basic.vert", "shaders/basic.frag")) {
Log.e("MainRenderer", "Failed to initialize basic shader");
}
float[] locs = {
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f
};
ByteBuffer locsBB = ByteBuffer.allocateDirect(locs.length * 4);
locsBB.order(ByteOrder.nativeOrder());
FloatBuffer locsFB = locsBB.asFloatBuffer();
locsFB.put(locs);
int[] vboArr = { 0 };
GLES30.glGenBuffers(1, vboArr, 0);
int vboHandle = vboArr[0];
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboHandle);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, locs.length * 4, locsBB, GLES30.GL_STATIC_DRAW);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
int[] indices = {
0, 1, 2
};
ByteBuffer indicesBB = ByteBuffer.allocateDirect(indices.length * 4);
indicesBB.order(ByteOrder.nativeOrder());
IntBuffer indicesIB = indicesBB.asIntBuffer();
indicesIB.put(indices);
int[] iboArr = { 0 };
GLES30.glGenBuffers(1, iboArr, 0);
int iboHandle = iboArr[0];
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, iboHandle);
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, indices.length * 4, indicesBB, GLES30.GL_STATIC_DRAW);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0);
int[] vaoArr = { 0 };
GLES30.glGenVertexArrays(1, vaoArr, 0);
vaoHandle = vaoArr[0];
if (vaoHandle == 0) {
Log.e("MainRenderer", "Failed to create vao");
}
GLES30.glBindVertexArray(vaoHandle);
int locationAI = GLES30.glGetAttribLocation(shader.getProgramHandle(), "in_loc");
GLES30.glEnableVertexAttribArray(locationAI);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboHandle);
GLES30.glVertexAttribPointer(locationAI, 3, GLES30.GL_FLOAT, false, 0, 0);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, iboHandle);
GLES30.glBindVertexArray(0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0);
}
@Override
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
// Draw triangle
GLES30.glBindVertexArray(vaoHandle);
GLES30.glDrawElements(GLES30.GL_TRIANGLES, 3, GLES30.GL_UNSIGNED_INT, 0);
GLES30.glBindVertexArray(0);
}
答案 0 :(得分:1)
正如Ville指出的那样,问题是我没有在绘制方法中使用该程序。
修:
// Draw triangle
// Actually use the program
GLES30.glUseProgram(shader.getProgramHandle());
GLES30.glBindVertexArray(vaoHandle);
GLES30.glDrawElements(GLES30.GL_TRIANGLES, 3, GLES30.GL_UNSIGNED_INT, 0);
GLES30.glBindVertexArray(0);
GLES30.glUseProgram(0);