OpenGL ES 2.0 无法编译着色器 Android
OpenGL ES 2.0 can't compile shaders Android
我在 OpenGL ES 2.0 中遇到着色器编译器问题。每次我尝试编译着色器时,它都不会编译,我也不知道为什么。我可以创建着色器,编译给我错误。
这是我的 Renderer
class
的代码
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.GLSurfaceView.Renderer;
import android.util.Log;
public class ProjekcikRenderer implements Renderer {
private static final int POSITION_COMPONENT_COUNT = 2;
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,
1f, 1f,
0f, 1f,
0f, 0f,
1f, 0f,
1, 1f
};
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 = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
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);
}
}
glShaderSource(vertexShader, vertexShaderSource);
final int[] compileStatus = new int[1];
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;
}
int fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
program = linkProgram(vertexShader, fragmentShader);
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 int compileVertexShader(String shaderCode){
return compileShader(GL_VERTEX_SHADER, shaderCode);
}
public static int compileFragmentShader(String shaderCode){
return compileShader(GL_FRAGMENT_SHADER, shaderCode);
}
private static int compileShader(int type, String shaderCode){
final int shaderObjectId = glCreateShader(type);
String s = new String(Integer.toString(type));
if(shaderObjectId == 0){
if(LoggerConfig.ON){
Log.w(TAG, "Could not create new shader");
}
return 0;
} else {
if(LoggerConfig.ON){
Log.w(TAG, s);
}
}
glShaderSource(shaderObjectId, shaderCode);
final int[] compileStatus = new int[1];
glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatus, 0);
if(LoggerConfig.ON){
Log.v(TAG, "Results of compiling source:" + "\n" + shaderCode + "\n" + glGetShaderInfoLog(shaderObjectId));
}
if(compileStatus[0] == 0){
glDeleteShader(shaderObjectId);
if(LoggerConfig.ON){
Log.w(TAG, "Compilation of shader failed");
}
return 0;
}
return shaderObjectId;
}
public static int linkProgram (int vertexShaderId, int fragmentShaderId){
final int programObjectId = 0;
glAttachShader(programObjectId, vertexShaderId);
glAttachShader(programObjectId, fragmentShaderId);
glLinkProgram(programObjectId);
if(programObjectId == 0){
if(LoggerConfig.ON){
Log.w(TAG, "Could not create new program");
}
return 0;
}
final int[] linkStatus = new int[1];
glGetProgramiv(programObjectId, GL_LINK_STATUS, linkStatus, 0);
if(LoggerConfig.ON){
Log.v(TAG, "Results of linking program:\n" + glGetProgramInfoLog(programObjectId));
}
if(linkStatus[0] == 0){
glDeleteProgram(programObjectId);
if(LoggerConfig.ON){
Log.w(TAG, "Linking of program failed");
}
return 0;
}
return programObjectId;
}
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;
}
}
这是我的 vertex
着色器
attribute vec4 a_Position;
void main(){
gl_Position = a_Position;
}
和logs
08-12 09:26:46.350 1281-1281/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libEGL_mali.so
08-12 09:26:46.350 1281-1281/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libGLESv1_CM_mali.so
08-12 09:26:46.350 1281-1281/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libGLESv2_mali.so
08-12 09:26:46.370 1281-1281/pl.projekcik D/OpenGLRenderer﹕ Enabling debug mode 0
08-12 09:26:46.400 1281-1308/pl.projekcik D/ProjekcikRenderer﹕ CREATING VERTEX SHADER
08-12 09:26:46.400 1281-1308/pl.projekcik W/ProjekcikRenderer﹕ 1
08-12 09:26:46.400 1281-1308/pl.projekcik V/ProjekcikRenderer﹕ Results of compiling source:
attribute vec4 a_Position;
void main(){
gl_Position = a_Position;
}
08-12 09:26:46.400 1281-1308/pl.projekcik W/ProjekcikRenderer﹕ Compilation of shader failed
08-12 09:26:46.430 1281-1283/pl.projekcik D/dalvikvm﹕ GC_CONCURRENT freed 225K, 8% free 6284K/6791K, paused 12ms+5ms, total 44ms
如有任何帮助,我们将不胜感激。我使用的是 Kevin Brothael 的书 OpenGL ES 2 for Android
,因为这是我第一次使用 OpenGL。
编辑 我在 Prestigio PMP7880D3G 上使用 Android 4.1.1 和一些 "Quad Core GPU"。但是几乎相同的代码(用于着色器编译的函数在附加 class ShaderHelper
中)代码在 Xperia Z1 Compact 上的 Android 5.0.2 运行 上不起作用。
首先,您确定渲染上下文是为 ES 2.0 设置的吗?如果您使用的是 GLSurfaceView
,它将默认为 ES 1.1,除非有其他要求,但该部分代码未包含在此处(尽管它似乎是根据日志正确设置的) .
其次,与桌面OpenGL 的GLSL 着色器相反,GL ES 着色器中的变量需要指定精度。因此,在 attribute vec4 a_Position;
的位置,您需要将其指定为例如attribute highp vec4 a_Position;
。这应该足以让这个特定的简单顶点着色器编译。
您在拨打 glShaderSource()
后错过了对 GLES20.glCompileShader(vertexShader)
的通话
尝试在此处修复您的代码:
glShaderSource(vertexShader, vertexShaderSource);
glCompileShader(vertexShader); // <-- this line is missing.
// Now see if the compilation worked.
int[] compiled = new int[1];
glGetShaderiv(vertexShader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0)
{
// Handle errors with shader compilation.
}
这是我用来在 OpenGL-ES 2.0 中生成程序的代码存根:
private int loadShader(String strSource, int iType)
{
int[] compiled = new int[1];
int iShader = GLES20.glCreateShader(iType);
GLES20.glShaderSource(iShader, strSource);
GLES20.glCompileShader(iShader);
GLES20.glGetShaderiv(iShader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Log.d("Load Shader Failed", "Compilation\n" + GLES20.glGetShaderInfoLog(iShader));
return 0;
}
return iShader;
}
public int loadProgram(String strVSource, String strFSource)
{
int iVShader;
int iFShader;
int iProgId;
int[] link = new int[1];
iVShader = loadShader(strVSource, GLES20.GL_VERTEX_SHADER);
if (iVShader == 0)
{
Log.d("Load Program", "Vertex Shader Failed");
return 0;
}
iFShader = loadShader(strFSource, GLES20.GL_FRAGMENT_SHADER);
if(iFShader == 0)
{
Log.d("Load Program", "Fragment Shader Failed");
return 0;
}
iProgId = GLES20.glCreateProgram();
GLES20.glAttachShader(iProgId, iVShader);
GLES20.glAttachShader(iProgId, iFShader);
GLES20.glLinkProgram(iProgId);
GLES20.glGetProgramiv(iProgId, GLES20.GL_LINK_STATUS, link, 0);
if (link[0] <= 0) {
Log.d("Load Program", "Linking Failed");
return 0;
}
GLES20.glDeleteShader(iVShader);
GLES20.glDeleteShader(iFShader);
return iProgId;
}
我在 OpenGL ES 2.0 中遇到着色器编译器问题。每次我尝试编译着色器时,它都不会编译,我也不知道为什么。我可以创建着色器,编译给我错误。
这是我的 Renderer
class
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.GLSurfaceView.Renderer;
import android.util.Log;
public class ProjekcikRenderer implements Renderer {
private static final int POSITION_COMPONENT_COUNT = 2;
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,
1f, 1f,
0f, 1f,
0f, 0f,
1f, 0f,
1, 1f
};
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 = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
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);
}
}
glShaderSource(vertexShader, vertexShaderSource);
final int[] compileStatus = new int[1];
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;
}
int fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
program = linkProgram(vertexShader, fragmentShader);
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 int compileVertexShader(String shaderCode){
return compileShader(GL_VERTEX_SHADER, shaderCode);
}
public static int compileFragmentShader(String shaderCode){
return compileShader(GL_FRAGMENT_SHADER, shaderCode);
}
private static int compileShader(int type, String shaderCode){
final int shaderObjectId = glCreateShader(type);
String s = new String(Integer.toString(type));
if(shaderObjectId == 0){
if(LoggerConfig.ON){
Log.w(TAG, "Could not create new shader");
}
return 0;
} else {
if(LoggerConfig.ON){
Log.w(TAG, s);
}
}
glShaderSource(shaderObjectId, shaderCode);
final int[] compileStatus = new int[1];
glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatus, 0);
if(LoggerConfig.ON){
Log.v(TAG, "Results of compiling source:" + "\n" + shaderCode + "\n" + glGetShaderInfoLog(shaderObjectId));
}
if(compileStatus[0] == 0){
glDeleteShader(shaderObjectId);
if(LoggerConfig.ON){
Log.w(TAG, "Compilation of shader failed");
}
return 0;
}
return shaderObjectId;
}
public static int linkProgram (int vertexShaderId, int fragmentShaderId){
final int programObjectId = 0;
glAttachShader(programObjectId, vertexShaderId);
glAttachShader(programObjectId, fragmentShaderId);
glLinkProgram(programObjectId);
if(programObjectId == 0){
if(LoggerConfig.ON){
Log.w(TAG, "Could not create new program");
}
return 0;
}
final int[] linkStatus = new int[1];
glGetProgramiv(programObjectId, GL_LINK_STATUS, linkStatus, 0);
if(LoggerConfig.ON){
Log.v(TAG, "Results of linking program:\n" + glGetProgramInfoLog(programObjectId));
}
if(linkStatus[0] == 0){
glDeleteProgram(programObjectId);
if(LoggerConfig.ON){
Log.w(TAG, "Linking of program failed");
}
return 0;
}
return programObjectId;
}
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;
}
}
这是我的 vertex
着色器
attribute vec4 a_Position;
void main(){
gl_Position = a_Position;
}
和logs
08-12 09:26:46.350 1281-1281/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libEGL_mali.so
08-12 09:26:46.350 1281-1281/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libGLESv1_CM_mali.so
08-12 09:26:46.350 1281-1281/pl.projekcik D/libEGL﹕ loaded /system/lib/egl/libGLESv2_mali.so
08-12 09:26:46.370 1281-1281/pl.projekcik D/OpenGLRenderer﹕ Enabling debug mode 0
08-12 09:26:46.400 1281-1308/pl.projekcik D/ProjekcikRenderer﹕ CREATING VERTEX SHADER
08-12 09:26:46.400 1281-1308/pl.projekcik W/ProjekcikRenderer﹕ 1
08-12 09:26:46.400 1281-1308/pl.projekcik V/ProjekcikRenderer﹕ Results of compiling source:
attribute vec4 a_Position;
void main(){
gl_Position = a_Position;
}
08-12 09:26:46.400 1281-1308/pl.projekcik W/ProjekcikRenderer﹕ Compilation of shader failed
08-12 09:26:46.430 1281-1283/pl.projekcik D/dalvikvm﹕ GC_CONCURRENT freed 225K, 8% free 6284K/6791K, paused 12ms+5ms, total 44ms
如有任何帮助,我们将不胜感激。我使用的是 Kevin Brothael 的书 OpenGL ES 2 for Android
,因为这是我第一次使用 OpenGL。
编辑 我在 Prestigio PMP7880D3G 上使用 Android 4.1.1 和一些 "Quad Core GPU"。但是几乎相同的代码(用于着色器编译的函数在附加 class ShaderHelper
中)代码在 Xperia Z1 Compact 上的 Android 5.0.2 运行 上不起作用。
首先,您确定渲染上下文是为 ES 2.0 设置的吗?如果您使用的是 GLSurfaceView
,它将默认为 ES 1.1,除非有其他要求,但该部分代码未包含在此处(尽管它似乎是根据日志正确设置的) .
其次,与桌面OpenGL 的GLSL 着色器相反,GL ES 着色器中的变量需要指定精度。因此,在 attribute vec4 a_Position;
的位置,您需要将其指定为例如attribute highp vec4 a_Position;
。这应该足以让这个特定的简单顶点着色器编译。
您在拨打 glShaderSource()
GLES20.glCompileShader(vertexShader)
的通话
尝试在此处修复您的代码:
glShaderSource(vertexShader, vertexShaderSource);
glCompileShader(vertexShader); // <-- this line is missing.
// Now see if the compilation worked.
int[] compiled = new int[1];
glGetShaderiv(vertexShader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0)
{
// Handle errors with shader compilation.
}
这是我用来在 OpenGL-ES 2.0 中生成程序的代码存根:
private int loadShader(String strSource, int iType)
{
int[] compiled = new int[1];
int iShader = GLES20.glCreateShader(iType);
GLES20.glShaderSource(iShader, strSource);
GLES20.glCompileShader(iShader);
GLES20.glGetShaderiv(iShader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Log.d("Load Shader Failed", "Compilation\n" + GLES20.glGetShaderInfoLog(iShader));
return 0;
}
return iShader;
}
public int loadProgram(String strVSource, String strFSource)
{
int iVShader;
int iFShader;
int iProgId;
int[] link = new int[1];
iVShader = loadShader(strVSource, GLES20.GL_VERTEX_SHADER);
if (iVShader == 0)
{
Log.d("Load Program", "Vertex Shader Failed");
return 0;
}
iFShader = loadShader(strFSource, GLES20.GL_FRAGMENT_SHADER);
if(iFShader == 0)
{
Log.d("Load Program", "Fragment Shader Failed");
return 0;
}
iProgId = GLES20.glCreateProgram();
GLES20.glAttachShader(iProgId, iVShader);
GLES20.glAttachShader(iProgId, iFShader);
GLES20.glLinkProgram(iProgId);
GLES20.glGetProgramiv(iProgId, GLES20.GL_LINK_STATUS, link, 0);
if (link[0] <= 0) {
Log.d("Load Program", "Linking Failed");
return 0;
}
GLES20.glDeleteShader(iVShader);
GLES20.glDeleteShader(iFShader);
return iProgId;
}