【问题标题】:OpenGL ES draw a square on androidOpenGL ES在android上画一个正方形
【发布时间】:2021-04-04 20:28:24
【问题描述】:

我尝试在 OpenGL ES 中为 android 绘制一个正方形,但由于某种原因,我的代码崩溃了,或者只显示了 clearColor。我敢肯定,带有渲染器和 GLSurfaceView 类的项目设置是正确的,并且从文件导入顶点和片段着色器的功能有效。这是绘制正方形的代码(构造函数在我的渲染器类的 onDrawFrame 方法的 draw 方法中调用 onSurfaceCreated):

import android.content.Context;
import android.opengl.GLES20;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
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, 0.0f, 1.0f, 1.0f,
             0.5f, 0.5f, 0.0f,         1.0f, 1.0f, 1.0f, 1.0f,

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

        int vertexID = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        GLES20.glShaderSource(vertexID, vertexShaderSrc);
        GLES20.glCompileShader(vertexID);

        int fragmetID = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(fragmetID, fragmentShaderSrc);
        GLES20.glCompileShader(fragmetID);

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

        positionHandle = GLES20.glGetAttribLocation(ShaderProgramID, "a_Position");
        colorHandle = GLES20.glGetAttribLocation(ShaderProgramID, "a_Color");

        vertexBuffer = FloatBuffer.allocate(coords.length);
        vertexBuffer.put(coords);
        vertexBuffer.position(0);
        IntBuffer buffer = IntBuffer.allocate(1);
        GLES20.glGenBuffers(1, buffer);
        vertexBufferID = buffer.get(0);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferID);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, coords.length * 4, vertexBuffer, GLES20.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() {
        GLES20.glUseProgram(ShaderProgramID);


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


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


        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.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();
    }
}

这是 VertexShaderCode:

attribute vec4 aPos;
attribute vec4 aColor;

varying vec4 v_Color;

void main()
{
    v_Color = a_Color;
    gl_Position = a_Position;
}

这是 FragmentShaderCode

precision mediump float;
varying vec4 v_Color;
void main()
{
    gl_FragColor = v_Color;
}

【问题讨论】:

    标签: java android opengl-es opengl-es-2.0 gpu


    【解决方案1】:

    在顶点着色器中:

    attribute vec4 aPos;
    

    position 是 4 分量向量,但在“vertexBuffer”中位置写为 3 分量向量。所以尝试改进着色器:

    attribute vec3 aPos;
    

    也使用了“a_Position”,但未在任何地方声明,请这样做:

    gl_Position = vec4(a_Pos,1.0);
    

    并在这里改进:

    positionHandle = GLES20.glGetAttribLocation(ShaderProgramID, "a_Pos");
    

    此代码可以显示着色器是否编译,以及错误。

    int[] compiled = new int[1];
            GLES31.glGetShaderiv(shader, GLES31.GL_COMPILE_STATUS, compiled, 0);
            if (compiled[0] == 0) {
                GLES31.glDeleteShader(shader);
                throw new RuntimeException("Could not compile program: "
                        + GLES31.glGetShaderInfoLog(shader) + " | ");
            }
    

    这是准备浮动缓冲区的正确方法:

    ByteBuffer bb = ByteBuffer.allocateDirect(coords.length*4);
    bb.order(ByteOrder.nativeOrder());
    
    FloatBuffer vertexBuffer = bb.asFloatBuffer();
    

    【讨论】:

    • 顶点现在看起来像这样:attribute vec3 aPos;属性 vec4 aColor;不同的 vec4 vColor; void main() { v_Color = aColor; gl_Position = aPos; } 但它仍然崩溃。我也确保在代码中的任何地方只使用 aPos 和 aColor 而不是 a_Pos 或 a_Color
    • gl_Position = vec4(a_Pos,1.0);
    • 我修复了所有错误,现在着色器编译成功,但应用程序仍然崩溃
    • 哪一行崩溃了?
    • 第 76 行:GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
    【解决方案2】:

    这是当前代码:

    import android.content.Context;
    import android.opengl.GLES20;
    import android.opengl.GLES31;
    import android.util.Log;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    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, 0.0f, 1.0f, 1.0f,
             0.5f, 0.5f, 0.0f,         1.0f, 1.0f, 1.0f, 1.0f,
    
    };
    public Square(Context context)  {
        String vertexShaderSrc = ReadFromfile("defaultVertexShader.glsl", context);
        String fragmentShaderSrc = ReadFromfile("defaultFragmentShader.glsl", context);
    
        int vertexID = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        GLES20.glShaderSource(vertexID, vertexShaderSrc);
        GLES20.glCompileShader(vertexID);
    
        int fragmetID = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(fragmetID, fragmentShaderSrc);
        GLES20.glCompileShader(fragmetID);
    
        ShaderProgramID = GLES20.glCreateProgram();
        GLES20.glAttachShader(ShaderProgramID, vertexID);
        GLES20.glAttachShader(ShaderProgramID, fragmetID);
        GLES20.glBindAttribLocation(ShaderProgramID, 0, "aPos");
        GLES20.glBindAttribLocation(ShaderProgramID, 1, "aColor");
        GLES20.glLinkProgram(ShaderProgramID);
    
        positionHandle = GLES20.glGetAttribLocation(ShaderProgramID, "aPos");
        colorHandle = GLES20.glGetAttribLocation(ShaderProgramID, "aColor");
    
        vertexBuffer = FloatBuffer.allocate(coords.length);
        vertexBuffer.put(coords);
        vertexBuffer.position(0);
        IntBuffer buffer = IntBuffer.allocate(1);
        GLES20.glGenBuffers(1, buffer);
        vertexBufferID = buffer.get(0);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferID);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, coords.length * 4, vertexBuffer, GLES20.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() {
        GLES20.glUseProgram(ShaderProgramID);
    
        vertexBuffer.position(0);
        GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, 0);
        GLES20.glEnableVertexAttribArray(positionHandle);
    
    
        vertexBuffer.position(3);
        GLES20.glVertexAttribPointer(colorHandle, COLORS_PER_VERTEX, GLES20.GL_FLOAT,        false, vertexStride, 3);
        GLES20.glEnableVertexAttribArray(colorHandle);
    
    
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.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 310 es
    precision mediump float;
    in vec4 vColor;
    void main()
    {
    gl_FragColor = vColor;
    }
    

    顶点:

    #version 310 es
    attribute vec3 aPos;
    attribute vec4 aColor;
    out vec4 vColor;
    
    void main()
    {
    vColor = aColor;
    gl_Position = vec4(aPos,1.0);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多