我正在使用GLSurfaceView和react native在Android上进行开发,遇到了一个非常奇怪的问题。
我创建了一个自定义OpenGL渲染器,想将其作为较大React Native视图中的组件使用。但是,当我将JS端的组件大小设置为所需尺寸时,其他部分的屏幕变黑了。
以下是创建该视图的React Native代码:
``````
ImageBlendView是一个react-native UI组件,遵循RN网站这里的说明制作而成,它创建了一个带有紫色矩形的红色背景。它只是一个相当基本的Opengl渲染器,以从JS传递的颜色和红色清除颜色绘制矩形。我在它上面添加了一个文本框并将组件大小设为50高度。 我无法弄清楚为什么ImageBlendView组件被黑色环绕。 清晰的颜色是红色,所以我知道它不是我的渲染器清除不该清除的像素。然而,似乎与我的渲染器类相关,因为当我注释GLSurfaceView类中设置它为渲染器的那一行时,正常的白色背景就会回来,并且组件上方的文本可见。
请注意,在上述类中,我可以禁用setRenderer行,并使黑色消失。
我的渲染器在OpenGLRenderer.java文件中。
我创建了一个自定义OpenGL渲染器,想将其作为较大React Native视图中的组件使用。但是,当我将JS端的组件大小设置为所需尺寸时,其他部分的屏幕变黑了。
以下是创建该视图的React Native代码:
``````
public render() {
return (
<View style={{ backgroundColor: '#ffffff' }}>
<Text>Hello World!</Text>
<ImageBlendView style={{ height: 50 }} boxColour="#f442df" />
</View>
);
}
ImageBlendView是一个react-native UI组件,遵循RN网站这里的说明制作而成,它创建了一个带有紫色矩形的红色背景。它只是一个相当基本的Opengl渲染器,以从JS传递的颜色和红色清除颜色绘制矩形。我在它上面添加了一个文本框并将组件大小设为50高度。 我无法弄清楚为什么ImageBlendView组件被黑色环绕。 清晰的颜色是红色,所以我知道它不是我的渲染器清除不该清除的像素。然而,似乎与我的渲染器类相关,因为当我注释GLSurfaceView类中设置它为渲染器的那一行时,正常的白色背景就会回来,并且组件上方的文本可见。
// setRenderer(new OpenGLRenderer(_context, colour));
自定义UI组件的结构与教程中相同,但我会详细解释一下。
ImageBlendView添加到一个包中,并在视图管理器列表中捆绑:
public class OTSNativePackage implements ReactPackage {
@Nonnull
@Override
public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
List<NativeModule> nativeModules = new ArrayList<>();
return nativeModules;
}
@Nonnull
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(new ImageBlendView());
}
}
ImageBlendView.java继承了SimpleViewManager,它创建了一个OpenGLView的实例,该实例又继承了GLSurfaceView。
public class ImageBlendView extends SimpleViewManager<OpenGLView> {
public static final String REACT_CLASS = "ImageBlendView";
private static OpenGLView _openGLView;
@Nonnull
@Override
public String getName() {
return REACT_CLASS;
}
@Nonnull
@Override
protected OpenGLView createViewInstance(@Nonnull ThemedReactContext reactContext) {
_openGLView = new OpenGLView(reactContext);
return _openGLView;
}
@ReactProp(name = "boxColour")
public void setBoxColour(OpenGLView view, String color) {
_openGLView.init(color);
}
}
OpenGLView.java
public class OpenGLView extends GLSurfaceView {
private Context _context;
public OpenGLView(Context context) {
super(context);
_context = context;
}
public OpenGLView(Context context, AttributeSet attrs) {
super(context, attrs);
_context = context;
}
public void init(String colour){
setEGLContextClientVersion(2);
setPreserveEGLContextOnPause(true);
// If I disable the following line the black goes away
setRenderer(new OpenGLRenderer(_context, colour));
}
}
请注意,在上述类中,我可以禁用setRenderer行,并使黑色消失。
我的渲染器在OpenGLRenderer.java文件中。
public class OpenGLRenderer implements GLSurfaceView.Renderer {
private Context _context;
private FloatBuffer vertexBuffer;
private ShortBuffer drawListBuffer;
private int positionHandle, program, colorHandle;
static final int COORDS_PER_VERTEX = 3;
static float squareCoords[] = {
-0.5f, 0.5f, 0.0f, // top left
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f, // bottom right
0.5f, 0.5f, 0.0f }; // top right
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
float color[] = {0.5f, 0.5f, 0.55f, 1.0f};
private int vertexCount;
private int vertexStride; // 4 bytes per vertex
public OpenGLRenderer(Context context, String colorStr){
super();
_context = context;
color = new float[]{(float)Integer.valueOf( colorStr.substring( 1, 3 ), 16 ) / 256.0f,
(float)Integer.valueOf( colorStr.substring( 3, 5 ), 16 ) / 256.0f,
(float)Integer.valueOf( colorStr.substring( 5, 7 ), 16 ) / 256.0f, 1.0f};
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(1f,0f,0f,1f);
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
vertexCount = squareCoords.length / COORDS_PER_VERTEX;
vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
compileShaders();
sendData();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
GLES20.glScissor(0,0, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(positionHandle);
}
private void sendData(){
positionHandle = GLES20.glGetAttribLocation(program, "position");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
colorHandle = GLES20.glGetUniformLocation(program, "vColor");
GLES20.glUniform4fv(colorHandle, 1, color, 0);
}
private void compileShaders() {
int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexShader, getShaderSource(R.raw.vertex_shader));
int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, getShaderSource(R.raw.fragment_shader));
GLES20.glCompileShader(vertexShader);
GLES20.glCompileShader(fragmentShader);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
GLES20.glUseProgram(program);
}
private String getShaderSource(int input){
StringBuilder total = new StringBuilder();
try{
InputStream stream =
_context.getResources().openRawResource(input);
BufferedReader r = new BufferedReader(new InputStreamReader(stream));
total = new StringBuilder();
for (String line; (line = r.readLine()) != null; ) {
total.append(line).append('\n');
}
} catch (IOException e){
System.out.println(e.getMessage());
}
return total.toString();
}
}
我最近尝试的方法是在onSurfaceChanged方法中调用GLES20.glScissor(0,0,width,height)。我希望通过裁剪到组件的大小和高度,不会影响其余像素,但很明显这不是OpenGL的问题,而是设置的问题。