Android 上的 openGl es 在右上角显示一个 Square

Posted

技术标签:

【中文标题】Android 上的 openGl es 在右上角显示一个 Square【英文标题】:openGl es on Android displays a Square at the top right corner 【发布时间】:2021-04-05 05:30:37 【问题描述】:

我写了一个代码,它应该在屏幕上绘制一个带有颜色渐变的正方形,但由于某种原因,它还在屏幕的右上角绘制了一个蓝色正方形。蓝色方块有时会改变它的颜色,当我更改代码中的内容时,这与它完全无关,例如我的渲染器中的一行代码,我在其中读取以像素为单位的屏幕大小。有时当我截屏时它也会消失。 代码如下:

import android.content.Context;
import android.opengl.GLES30;
import android.util.Log;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;


public class Square 
int ShaderProgramID;
private FloatBuffer vertexBuffer;
private int vertexBufferID;
private int vertexCount;
private int vertexStride;
static final int COORDS_PER_VERTEX = 3;
static final int COLORS_PER_VERTEX = 4;
static final int SIZE_OF_FLOAT = 4;
static final float coords[] = 
        //x:    y:     z:            r:    g:    b:    a:
        -0.5f, 0.5f, 0.0f,         1.0f, 0.0f, 0.0f, 1.0f,
        -0.5f,-0.5f, 0.0f,         0.0f, 1.0f, 0.0f, 1.0f,
         0.5f,-0.5f, 0.0f,         0.0f, 0.0f, 1.0f, 1.0f,
        -0.5f, 0.5f, 0.0f,         1.0f, 0.0f, 0.0f, 1.0f,
         0.5f,-0.5f, 0.0f,         0.0f, 1.0f, 0.0f, 1.0f,
         0.5f, 0.5f, 0.0f,         0.0f, 0.0f, 1.0f, 1.0f

;
public Square(Context context)  
    String vertexShaderSrc = ReadFromfile("defaultVertexShader.glsl", context);
    String fragmentShaderSrc = ReadFromfile("defaultFragmentShader.glsl", context);

    int vertexID = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER);
    GLES30.glShaderSource(vertexID, vertexShaderSrc);
    GLES30.glCompileShader(vertexID);
    Log.d("Golden", GLES30.glGetShaderInfoLog(vertexID));

    int fragmetID = GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER);
    GLES30.glShaderSource(fragmetID, fragmentShaderSrc);
    GLES30.glCompileShader(fragmetID);
    Log.d("Golden", GLES30.glGetShaderInfoLog(fragmetID) );

    ShaderProgramID = GLES30.glCreateProgram();
    GLES30.glAttachShader(ShaderProgramID, vertexID);
    GLES30.glAttachShader(ShaderProgramID, fragmetID);
    GLES30.glBindAttribLocation(ShaderProgramID, 0, "aPos");
    GLES30.glBindAttribLocation(ShaderProgramID, 1, "aColor");
    GLES30.glLinkProgram(ShaderProgramID);

    positionHandle = GLES30.glGetAttribLocation(ShaderProgramID, "aPos");
    colorHandle = GLES30.glGetAttribLocation(ShaderProgramID, "aColor");

    //vertexBuffer = FloatBuffer.allocate(coords.length);
    //vertexBuffer = ByteBuffer.allocate(coords.length*4).asFloatBuffer();
    //vertexBuffer.put(coords);
    //vertexBuffer.position(0);
    ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * 4);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(coords);
    vertexBuffer.position(0);

    IntBuffer buffer = IntBuffer.allocate(1);
    GLES30.glGenBuffers(1, buffer);
    vertexBufferID = buffer.get(0);
    GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, vertexBufferID);
    GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, coords.length * 4, vertexBuffer, GLES30.GL_STATIC_DRAW);

    vertexCount = coords.length / (COORDS_PER_VERTEX + COLORS_PER_VERTEX);
    vertexStride = (COORDS_PER_VERTEX + COLORS_PER_VERTEX) * 4;

private int positionHandle;
private int colorHandle;
public void draw() 
    GLES30.glUseProgram(ShaderProgramID);

    vertexBuffer.position(0);
    GLES30.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES30.GL_FLOAT, false, vertexStride, vertexBuffer);
    GLES30.glEnableVertexAttribArray(positionHandle);


    vertexBuffer.position(3);
    GLES30.glVertexAttribPointer(colorHandle, COLORS_PER_VERTEX, GLES30.GL_FLOAT, false, vertexStride, vertexBuffer);
    GLES30.glEnableVertexAttribArray(colorHandle);


    GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, coords.length);
    GLES30.glDisableVertexAttribArray(positionHandle);
    GLES30.glDisableVertexAttribArray(colorHandle);



public String ReadFromfile(String fileName, Context context) 
    StringBuilder ReturnString = new StringBuilder();
    InputStream fIn = null;
    InputStreamReader isr = null;
    BufferedReader input = null;
    try 
        fIn = context.getResources().getAssets()
                .open(fileName);
        isr = new InputStreamReader(fIn);
        input = new BufferedReader(isr);
        String line = "";
        while ((line = input.readLine()) != null) 
            ReturnString.append(line + "\n");
        
     catch (Exception e) 
        e.getMessage();
     finally 
        try 
            if (isr != null)
                isr.close();
            if (fIn != null)
                fIn.close();
            if (input != null)
                input.close();
         catch (Exception e2) 
            e2.getMessage();
        
    
    return ReturnString.toString();


片段着色器:

#version 300 es
precision mediump float;
in vec4 vColor;
out vec4 oColor;
void main()

oColor = vColor;

顶点着色器:

#version 300 es
in vec3 aPos;
in vec4 aColor;
out vec4 vColor;

void main()

vColor = aColor;
gl_Position = vec4(aPos,1.0);

【问题讨论】:

您必须将顶点绑定到GL_ARRAY_BUFFER traget 而不是GL_ELEMENT_ARRAY_BUFFER 目标。请参阅glVertexAttribPointer 如果一个非零命名缓冲区对象绑定到 GL_ARRAY_BUFFER 目标(请参阅 glBindBuffer),则指针被视为缓冲区对象数据存储中的字节偏移量 【参考方案1】:

您必须将顶点绑定到GL_ARRAY_BUFFER traget 而不是GL_ELEMENT_ARRAY_BUFFER 目标:

IntBuffer buffer = IntBuffer.allocate(1);
GLES30.glGenBuffers(1, buffer);
vertexBufferID = buffer.get(0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vertexBufferID);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, coords.length * 4, vertexBuffer, GLES30.GL_STATIC_DRAW);

glVertexAttribPointer:

如果非零命名缓冲区对象绑定到GL_ARRAY_BUFFER target(请参阅glBindBuffer),则指针被视为缓冲区对象数据存储中的字节偏移量。

在你的情况下 stride 是 28 个字节 ((3+4) * 4)。顶点的偏移量为0字节,颜色属性的偏移量为12字节(3 * 4):

GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vertexBufferID);

GLES30.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, 
    GLES30.GL_FLOAT, false, 7*4, 0);
GLES30.glVertexAttribPointer(colorHandle, COLORS_PER_VERTEX, 
    GLES30.GL_FLOAT, false, 7*4, 3*4);

GLES30.glEnableVertexAttribArray(positionHandle);
GLES30.glEnableVertexAttribArray(colorHandle);

glDrawArrays的最后一个参数是顶点数,而不是数组中的浮点数:

GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, coords.length / 7);

GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, coords.length / 7);

【讨论】:

【参考方案2】:

在 glDrawArrays 中必须有你要绘制的顶点数,而不是顶点缓冲区的长度。

GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexCount);

【讨论】:

以上是关于Android 上的 openGl es 在右上角显示一个 Square的主要内容,如果未能解决你的问题,请参考以下文章

Android设备上的OpenGL ES 2.0扩展[关闭]

在 Android 上的 OpenGL ES 2.0 中使用 VBO/IBO

OpenGL ES有不同的UV坐标?

如何确定Android OpenGL ES上的最大纹理内存

Android 上的 Opengl ES:如何使用 gluUnProject?

使用 Android 上的 OpenGL ES 2.0,在帧缓冲区上渲染时是不是可以保留多重采样?