问题描述
是否可以在不使用LibGDX的情况下从RoboVM 访问iOS上的OpenGL ES ?如果是这样,是否有任何有用的参考?
Is it possible to access OpenGL ES on iOS from RoboVM without using LibGDX? If so, are there any useful references?
我唯一能找到的是2年前的这个超级简单的演示:
http://robovm.com/ios-opengles-in-java-on-robovm/
但是除了glClearColor和glClear之外,它没有提供任何其他功能.
The only thing I can find is this super-simple demo from over 2 years ago:
http://robovm.com/ios-opengles-in-java-on-robovm/
But it doesn't provide any functions besides glClearColor and glClear.
不过,Apple GLKit框架似乎已实现.我只是找不到所有实际的glWhatever(...)函数...
The Apple GLKit framework seems to be implemented, though. I just can't find all the actual glWhatever(...) functions...
推荐答案
是的,有可能.为此,您需要做两件事:1.访问OpenGL ES函数(例如glClear(...)
等)和2. a 您的应用程序中的UIView 可以绘制GL图像.
Yes, it is possible. You need two things for this: 1. Access to the OpenGL ES functions (like glClear(...)
, etc.) and 2. a UIView in your app that can draw the GL image.
找出第二点非常容易.您可以使用 GLKView (需要iOS 5.0)或 CAEAGLLayer (需要iOS 2.0),如果您怀旧的话.对于这两者,都有大量在线教程,介绍如何在Objective-C中使用它们,这些教程可以轻松翻译为RoboVM.因此,在这里我不会花太多时间.
Turns out the second point is very easy. You can either use a GLKView (requires iOS 5.0) or a CAEAGLLayer (requires iOS 2.0) if you're feeling nostalgic. For both, there are tons of tutorials online on how to use them in Objective-C, which can readily be translated to RoboVM. So, I won't spend too much time on this point here.
访问OpenGL ES功能要困难一些,因为RoboVM并没有附带定义文件.因此,我们必须使用 Bro 构建自己的数据库.事实证明,一旦您全神贯注于Bro处理C字符串,变量指针,IntBuffers之类的方法(实际上非常漂亮!),它就非常简单.我在原始问题中链接的超简单演示是正确的起点.
Access to the OpenGL ES functions is a little more difficult, as RoboVM doesn't ship with the definitions file out of the box. So, we'll have to build our own using Bro. Turns out, once you wrap your head around how Bro handles C-strings, variable pointers, IntBuffers and such (which is actually quite beautiful!), it's really pretty straight forward. The super-simple demo I linked to in the original question is the right starting point.
为了简洁起见,让我在这里发布我编写的文件的一个非常简短的版本,以说明如何处理不同数据类型:
In the interest of brevity, let me post here just a very abridged version of the file I wrote to illustrate the way the different data types can be handled:
import java.nio.Buffer;
import java.nio.IntBuffer;
import org.robovm.rt.bro.Bro;
import org.robovm.rt.bro.Struct;
import org.robovm.rt.bro.annotation.Bridge;
import org.robovm.rt.bro.annotation.Library;
import org.robovm.rt.bro.ptr.BytePtr;
import org.robovm.rt.bro.ptr.BytePtr.BytePtrPtr;
import org.robovm.rt.bro.ptr.IntPtr;
@Library("OpenGLES")
public class GLES20 {
public static final int GL_DEPTH_BUFFER_BIT = 0x00000100;
public static final int GL_STENCIL_BUFFER_BIT = 0x00000400;
public static final int GL_COLOR_BUFFER_BIT = 0x00004000;
public static final int GL_FALSE = 0;
public static final int GL_TRUE = 1;
private static final int MAX_INFO_LOG_LENGTH = 10*1024;
private static final ThreadLocal<IntPtr> SINGLE_VALUE =
new ThreadLocal<IntPtr>() {
@Override
protected IntPtr initialValue() {
return Struct.allocate(IntPtr.class, 1);
}
};
private static final ThreadLocal<BytePtr> INFO_LOG =
new ThreadLocal<BytePtr>() {
@Override
protected BytePtr initialValue() {
return Struct.allocate(BytePtr.class, MAX_INFO_LOG_LENGTH);
}
};
static {
Bro.bind(GLES20.class);
}
@Bridge
public static native void glClearColor(float red, float green, float blue, float alpha);
@Bridge
public static native void glClear(int mask);
@Bridge
public static native void glGetIntegerv(int pname, IntPtr params);
// DO NOT CALL THE NEXT METHOD WITH A pname THAT RETURNS MORE THAN ONE VALUE!!!
public static int glGetIntegerv(int pname) {
IntPtr params = SINGLE_VALUE.get();
glGetIntegerv(pname, params);
return params.get();
}
@Bridge
private static native int glGetUniformLocation(int program, BytePtr name);
public static int glGetUniformLocation(int program, String name) {
return glGetUniformLocation(program, BytePtr.toBytePtrAsciiZ(name));
}
@Bridge
public static native int glGenFramebuffers(int n, IntPtr framebuffers);
public static int glGenFramebuffer() {
IntPtr framebuffers = SINGLE_VALUE.get();
glGenFramebuffers(1, framebuffers);
return framebuffers.get();
}
@Bridge
private static native void glShaderSource(int shader, int count, BytePtrPtr string, IntPtr length);
public static void glShaderSource(int shader, String code) {
glShaderSource(shader, 1, new BytePtrPtr().set(BytePtr.toBytePtrAsciiZ(code)), null);
}
@Bridge
private static native void glGetShaderInfoLog(int shader, int maxLength, IntPtr length, BytePtr infoLog);
public static String glGetShaderInfoLog(int shader) {
BytePtr infoLog = INFO_LOG.get();
glGetShaderInfoLog(shader, MAX_INFO_LOG_LENGTH, null, infoLog);
return infoLog.toStringAsciiZ();
}
@Bridge
public static native void glGetShaderPrecisionFormat(int shaderType, int precisionType, IntBuffer range, IntBuffer precision);
@Bridge
public static native void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, IntBuffer data);
@Bridge
private static native void glVertexAttribPointer(int index, int size, int type, int normalized, int stride, Buffer pointer);
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, Buffer pointer) {
glVertexAttribPointer(index, size, type, normalized ? GL_TRUE : GL_FALSE, stride, pointer);
}
}
请注意,大多数方法是如何通过普通的 @Bridge 注释的本机定义公开的,但是对于某些方法而言,在Java中定义将String
转换为*char
或例如,从IntPtr
解包结果.
Note how most methods are exposed via just trivial @Bridge-annotated native definitions, but for some it's convenient to define a wrapper method in Java that converts a String
to a *char
or unpacks a result from an IntPtr
for example.
我没有发布整个库文件,因为它仍然很不完整,只会使查找不同参数类型的处理示例变得更加困难.
I didn't post my whole library file, since it is still very incomplete and it'll just make it harder to find the examples of how different parameter types are handled.
要节省一些工作,您可以从libGDX的 GL20.java .并且 OpenGL ES文档对于方法(数据类型GLenum
和GLbitfield
对应于Java int
).
To save yourself some work, you can copy the GL constant definitions from libGDX's GL20.java. And the OpenGL ES docs are a great reference for the calling signature of the methods (the data types GLenum
and GLbitfield
correspond to a Java int
).
然后您可以通过在GLES20.
之前添加静态名称(例如在Android上)来静态调用gl方法,例如:
You can then call the gl-methods statically by prepending GLES20.
(just like on Android), e.g.:
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
结果证明Bro非常聪明,您甚至不需要像在libGDX中那样在robovm.xml中包含<framework>OpenGLES</framework>
标记.
Turns out Bro is so smart that you don't even need to include the <framework>OpenGLES</framework>
tag in robovm.xml any more, like you would with libGDX.
然后-您知道什么? -我的应用程序启动的速度大约是仍在使用libGDX时的3倍.并且它解决了我遇到的另一个问题(请参见. 耶!"摆脱不必要的行李.
And - What do you know? - my app starts about 3 times as quickly as it did when it was still using libGDX. And it fixed another issue I had (see LibGDX displays black screen while app is paused but still visible (e.g. during in-app purchase password dialog) on iOS). "Yay!" for getting rid of unnecessary baggage.
让生活有些烦恼的一件事是,如果您弄乱了方法的调用签名或内存分配,您的应用程序将崩溃,并在IDE中显示非常无用的由于信号11终止"消息-控制台,其中不包含有关应用程序终止位置的信息.
The one thing that makes life a little annoying is that if you mess up the call signature of a method or the memory allocation, your app will simply crash with a very unhelpful "Terminated due to signal 11" message in the IDE-console that contains no information about where the app died.
这篇关于是否可以在不使用LibGDX的情况下从RoboVM访问OpenGL ES?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!