问题描述
我正在尝试使用 java 在 android 中制作 OpenGL ES 应用程序,但我遇到了一个主要问题:
I'm trying to make an OpenGL ES app in android using java and I have run in a major issue:
GLES20.glCreateShader(type)
(类型为 GLES20.GL_VERTEX_SHADER 或 GLES20.GL_FRAGMENT_SHADER)总是返回 0.
GLES20.glCreateShader(type)
(type beeing GLES20.GL_VERTEX_SHADER or GLES20.GL_FRAGMENT_SHADER) always returns 0.
我试过了:
- 使用 GLES30 和 GLES31
- 将 setEGLContextClientVersion 设置为 2 和 3
- 在我代码的几乎所有类中进行调用,包括 laucher 类
- 并且我已经检查过我的设备是否支持 OpenGl ES 3.1(并且出于某种原因它说:OpenGL ES 扩展包:3.2,我不明白,因为我认为它去了高达 3.1).
- Using GLES30 and GLES31
- setting setEGLContextClientVersion to 2 and to 3
- making the call in pretty much all the classes of my code, including the laucher class
- and I've checked that my device supports OpenGl ES 3.1 (and for some reason it says: OpenGL ES extention pack : 3.2 , which I don't understand, because I thaught that it went up to 3.1).
它总是,总是返回 0!
And it always, always returns 0!
我知道还有其他帖子提出了同样的问题,但似乎没有一个适合我的情况,其中一个仍然没有解决,但它已经 5 年了,没有更多的活动了.请帮帮我!
I know that there is other posts with the same question, but none of them seemed to suit my case, and one of them is still not solved, but it's 5 years old and there's no more activity on it. Please help me!
为了清楚起见,这是我的 glSurfaceView 的代码:
For clarity, here's the code of my glSurfaceView :
//Warning: I'm no where near finished
//and cleanup needs to be made once I get it working.
//If something looks weird or makes no sense, it's part of debugging or testing
public class renderer implements GLSurfaceView.Renderer{
private Object obj;
public StaticShader shader;
private Object ball;
private int bytePerFloat = 4;
private int stride = 3*bytePerFloat; //#of elements * bpf
private int positionOffset = 0;
private int positionSize = 3;
//private int colorOffset = 3;
//private int colorSize = 4;
private ObjectLoader objectLoader;
private AssetManager assets;
private Context context;
//The important part is from here...
renderer(AssetManager a, Context b){
assets = a;
context = b;
}
public void onSurfaceCreated(GL10 gl, EGLConfig config){
shader = new StaticShader(assets, context);
float[] verts =
{
//x,y,z
//r,g,b,a
0.5f,0.5f,0.0f,
0.5f,-0.5f,0.0f,
-0.5f,-0.5f,0.0f,
-0.5f,0.5f,0.0f
};
int[] indices = {
0,1,3,
3,1,2
};
//obj = new Object(verts,indices,shader,bytePerFloat);
//ball = objectLoader.LoadFromFile("ball.obj",shader, bytePerFloat);
}
//... To here
public void onSurfaceChanged(GL10 gl, int width, int height){
GLES20.glViewport(0,0,width,height);
}
public void onDrawFrame(GL10 gl){
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
if(shader.isCompiled && shader.hasFoundFile && shader.canReadFile){
GLES20.glClearColor(0.0f,1.0f,0.0f,1.0f);
}else{
GLES20.glClearColor(1.0f,0.0f,0.0f,1.0f);
}
//render(obj);
//render(ball);
}
private void render(Object object){
try{
object.getShader().start();
GLES30.glBindVertexArray(object.getVaoID());
GLES30.glEnableVertexAttribArray(0);
GLES30.glDrawElements(GLES20.GL_TRIANGLES, object.getVertCount(), GLES30.GL_UNSIGNED_INT,0);
GLES30.glDisableVertexAttribArray(0);
GLES30.glBindVertexArray(0);
object.getShader().stop();
}catch(Exception e){
}
}
}
StaticShader 目前基本上实现了 ShaderProgram:
StaticShader basically implements ShaderProgram for now:
public abstract class ShaderProgram {
private int programID;
private int vertexShaderID;
private int fragmentShaderID;
public boolean hasFoundFile = true;
public boolean isCompiled = true;
public boolean canReadFile = true;
public ShaderProgram (AssetManager assets, Context context, String vertexFile, String fragmentFile){
//int shdID = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
//Toast.makeText(context,Integer.toString(shdID),Toast.LENGTH_LONG).show();
//Toast.makeText(context,EGL14.eglGetCurrentContext().toString(),Toast.LENGTH_LONG).show();
//ShaderID = loadShader(assets, context, vertexFile, GLES20.GL_VERTEX_SHADER);
//fragmentShaderID = loadShader(assets,context, fragmentFile, GLES20.GL_FRAGMENT_SHADER);
programID = GLES20.glCreateProgram();
GLES20.glAttachShader(programID, vertexShaderID);
GLES20.glAttachShader(programID, fragmentShaderID);
GLES20.glLinkProgram(programID);
GLES20.glValidateProgram(programID);
}
public void start(){
GLES20.glUseProgram(programID);
}
public void stop(){
GLES20.glUseProgram(0);
}
protected abstract void bindAttributes();
protected void bindAttribute(int attribute, String variableName){
GLES20.glBindAttribLocation(programID, attribute, variableName);
}
private int loadShader(AssetManager assets, Context context,String fileName, int type){
int shaderID = 0;
try{
InputStream file = assets.open(fileName);
Scanner scan = new Scanner(file);
String code = new String();
while(scan.hasNext()){
code = new String(code + scan.nextLine() + "/n");
}
shaderID = GLES20.glCreateShader(type);
//GLES20.glShaderSource(shaderID, code);
//Toast.makeText(context,Integer.toString(shaderID),Toast.LENGTH_LONG).show();
//GLES20.glCompileShader(shaderID);
int[] compileStatus = new int[1];
GLES20.glGetShaderiv(shaderID,GLES20.GL_COMPILE_STATUS,compileStatus,0);
if(compileStatus[0] == 0){
//Toast.makeText(context,GLES20.glGetShaderInfoLog(),Toast.LENGTH_LONG).show();
GLES20.glDeleteShader(shaderID);
isCompiled = false;
}
}catch(FileNotFoundException e){
hasFoundFile = false;
}catch(IOException e){
canReadFile = false;
}catch(Exception e){
isCompiled = false;
}
return shaderID;
}
}
这是启动器类:
public class MainActivity extends Activity {
private renderer surface;
private GLSurfaceView surfaceView;
private int STORAGE_PERMISSION_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
surfaceView = new GLSurfaceView(this);
surfaceView.setEGLContextClientVersion(2);
surface = new renderer(getAssets(),getApplicationContext());
surfaceView.setRenderer(surface);
setContentView(surfaceView);
}
protected void onPause(){
super.onPause();
surfaceView.onPause();
}
protected void onResume(){
super.onResume();
surfaceView.onResume();
}
}
我需要 AssetManager 来加载文件和用于调试的上下文,因为我没有使用 VisualStudio,这是我获取调试信息的唯一方法.
I need the AssetManager to load up files and Context for debuging, since I'm not using VisualStudio, it's my only way of getting debugging info.
推荐答案
我认为这是你的问题.glSurfaceView
的 OpenGLES 上下文仅绑定到 GLThread
.您确实需要将所有 OpenGLES 代码置于 glSurfaceView.Renderer
的功能之一的下游,例如onSurfaceCreated
或 onDrawFrame
.
This is your problem I think. glSurfaceView
's OpenGLES context is only bound to the GLThread
. You really need to have all your OpenGLES code downstream from one of glSurfaceView.Renderer
's functions e.g. onSurfaceCreated
or onDrawFrame
.
eglGetCurrentContext
函数可以告诉您是否有一个 OpenGLES 上下文绑定到当前线程.在没有上下文的情况下调用任何 OpenGLES 函数将导致不会通过 glGetError
报告的错误.在调试版本中,我会在每个 OpenGLES 调用中检查上下文和 glGetError
.
The function eglGetCurrentContext
can tell you if there's an OpenGLES context bound to the current thread. Calling any OpenGLES functions without a context will result in bugs that aren't reported through glGetError
. In debug builds, I check both the context and glGetError
on every single OpenGLES call.
我不知道在 GLThread
上使用 AssetManager 和 Context 有什么真正的障碍.
I'm not aware of any real obstacle to using AssetManager and Context on the GLThread
.
这篇关于为什么 GLES20.glCreateShader 总是返回 0?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!