美文网首页OpenGL ES
附录(6)使用顶点缓存区绘制

附录(6)使用顶点缓存区绘制

作者: 大旺旺的弟弟小旺旺 | 来源:发表于2021-06-27 10:34 被阅读0次

顶点缓存区在第六章已经说过,这里整理一个案例。还是最简单的代码,绘制一个三角形。这案例继承附录5中的基类。

不使用顶点缓存区

/**
 * 三角形
 */
public class Triangle extends BaseGameScreen {
    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    static final int COORDS_PER_VERTEX = 3;
    private FloatBuffer vertexBuffer;
    static float triangleCoords[] = {
            0.5f,  0.5f, 0.0f, // top
            -0.5f, -0.5f, 0.0f, // bottom left
            0.5f, -0.5f, 0.0f  // bottom right
    };

    //顶点个数
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    //顶点之间的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每个顶点四个字节
    //设置颜色,依次为红绿蓝和透明通道
    float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    private int mPositionHandle;
    private int mColorHandle;
    float d = 0.01F;
    public Triangle(){

    }

    public void create(){
        ByteBuffer bb = ByteBuffer.allocateDirect(
                triangleCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);

        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
        mProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(mProgram,vertexShader);
        GLES20.glAttachShader(mProgram,fragmentShader);
        GLES20.glLinkProgram(mProgram);
        //程序加入到环境里面
        GLES20.glUseProgram(mProgram);
//        检查是否有效
        GLES20.glValidateProgram(mProgram);
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    }


    @Override
    public void surfaceChange(int width, int height) {
        GLES20.glViewport(0,0,width,height);
    }

    @Override
    public void dispose() {

    }


    @Override
    public void render() {
        //获取位置句柄   属性句柄

        GLES20.glEnableVertexAttribArray(mPositionHandle);
        //准备三角形的坐标数据
        GLES20.glVertexAttribPointer(
                mPositionHandle,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                false,
                vertexStride,
                vertexBuffer);
        //获取片元着色器的vColor成员的句柄

        color[1] = color[1]-d;
        if (color[1]<=0||color[1]>=1){
            d=-d;
        }
        //设置绘制三角形的颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);
        //绘制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
        //禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

}

使用顶点缓存区

package com.example.myapplication.learn.shape;

import android.opengl.GLES20;

import com.example.myapplication.MainActivity;
import com.example.myapplication.learn.shape.base.BaseGameScreen;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

/**
 * 三角形
 */
public class TriangleBuffer extends BaseGameScreen {
    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    static final int COORDS_PER_VERTEX = 3;
    private FloatBuffer vertexBuffer;
    static float triangleCoords[] = {
            0.5f,  0.5f, 0.0f, // top
            -0.5f, -0.5f, 0.0f, // bottom left
            0.5f, -0.5f, 0.0f  // bottom right
    };

    //顶点个数
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    //顶点之间的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每个顶点四个字节
    //设置颜色,依次为红绿蓝和透明通道
    float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    private int mPositionHandle;
    private int mColorHandle;
    float d = 0.01F;
    public TriangleBuffer(MainActivity activity){

    }

    public void create(){
        ByteBuffer bb = ByteBuffer.allocateDirect(
                triangleCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);

        createVBO();

        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
        mProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(mProgram,vertexShader);
        GLES20.glAttachShader(mProgram,fragmentShader);
        GLES20.glLinkProgram(mProgram);
        //程序加入到环境里面
        GLES20.glUseProgram(mProgram);
//        检查是否有效
        GLES20.glValidateProgram(mProgram);
        //得到活跃的unifor
        int arr[] = new int[1];
        int arr1[] = new int[1];
        int arr2[] = new int[1];
        int arr3[] = new int[1];
        byte arr4[] = new byte[10];
        GLES20.glGetProgramiv(mProgram,GLES20.GL_ACTIVE_UNIFORMS,arr,0);
        GLES20.glGetActiveUniform(
                mProgram,
                1,
                1,
                arr1,
                1,
                arr2,
                1,
                arr3,
                1,
                arr4,
                0
                );
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    }


    @Override
    public void surfaceChange(int width, int height) {
        GLES20.glViewport(0,0,width,height);
    }

    @Override
    public void dispose() {

    }


    @Override
    public void render() {
        //获取位置句柄   属性句柄

        GLES20.glEnableVertexAttribArray(mPositionHandle);
        //准备三角形的坐标数据
        useVboDraw();
//        GLES20.glVertexAttribPointer(
//                mPositionHandle,
//                COORDS_PER_VERTEX,
//                GLES20.GL_FLOAT,
//                false,
//                vertexStride,
//                vertexBuffer);
        //获取片元着色器的vColor成员的句柄

        color[1] = color[1]-d;
        if (color[1]<=0||color[1]>=1){
            d=-d;
        }
        //设置绘制三角形的颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);
        //绘制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
        //禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

    int vboId = 0;
    private void createVBO() {
        //1. 创建VBO
        int[] vbos = new int[1];
        GLES20.glGenBuffers(vbos.length, vbos, 0);
        vboId = vbos[0];
        //2. 绑定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //3. 分配VBO需要的缓存大小
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
                triangleCoords.length * 4 +
                        triangleCoords.length * 4,
                null, GLES20.GL_STATIC_DRAW);
        //4. 为VBO设置顶点数据的值
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER,
                0,
                triangleCoords.length * 4,
                vertexBuffer);
//        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, textureData.length * 4, textureBuffer);
        //5. 解绑VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

    private void useVboDraw() {
        //1. 绑定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //2. 设置顶点数据
        GLES20.glVertexAttribPointer(
                mPositionHandle,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                false,
                vertexStride,
                0);

        //3. 解绑VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }
}

区别在哪里,只有两个地方,第一个创建缓存区放入数据,第二个是使用缓存区。

   private void createVBO() {
        //1. 创建VBO
        int[] vbos = new int[1];
        GLES20.glGenBuffers(vbos.length, vbos, 0);
        vboId = vbos[0];
        //2. 绑定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //3. 分配VBO需要的缓存大小
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
                triangleCoords.length * 4 +
                        triangleCoords.length * 4,
                null, GLES20.GL_STATIC_DRAW);
        //4. 为VBO设置顶点数据的值
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER,
                0,
                triangleCoords.length * 4,
                vertexBuffer);
//        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, textureData.length * 4, textureBuffer);
        //5. 解绑VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

第二个是使用

   private void useVboDraw() {
        //1. 绑定VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //2. 设置顶点数据
        GLES20.glVertexAttribPointer(
                mPositionHandle,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                false,
                vertexStride,
                0);

        //3. 解绑VBO
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

创建部分,不需要做任何修改, 只需要加入创建代码即可,使用部分,需要删除之前顶点的指定方式,换成这个调用方法即可。

相关文章

  • 附录(6)使用顶点缓存区绘制

    顶点缓存区在第六章已经说过,这里整理一个案例。还是最简单的代码,绘制一个三角形。这案例继承附录5中的基类。 不使用...

  • OpenGL ES 地球月亮渲染案例

    思维导图 处理ArrayBuffer封装 创建顶点缓存数组 分配顶点数据,准备绘制 绘制 重新缓存顶点数组 Vie...

  • DX中绘制物体

    DX绘制 使用顶点缓存绘制直线这次我使用了之前写好的模板来快速开始这样可以免去每次都重复编写一样的代码模板中实现了...

  • 1.图形管线

    1.图形管线 顶点缓存区 -> 顶点着色器 -> 图元 -> 光栅化 -> 纹理 -> 片段着...

  • OpenGL ES 索引绘图

    传统绘图与索引绘图的区别 我们使用传统的数组绘制方式绘制一个立方体时,可能每个面使用6个顶点(绘制两个三角形),其...

  • 十三、OpenGL ES 之索引绘图

    传统绘图与索引绘图的区别 我们使用传统的数组绘制方式绘制一个立方体时,可能每个面使用6个顶点(绘制两个三角形),其...

  • CUDA与OpenGL互操作之纹理映射

    引言 在《CUDA与OpenGL互操作之顶点缓存映射》中讲解了如何使用CUDA操作OpenGL中的顶点缓存数据,从...

  • OpenGLES入门 4 -- 多边形

    步骤 1、初始化上下文;2、设置缓冲区3、设置着色器4、确定顶点坐标,绘制 ps: 跟圆的绘制也只是顶点坐标的不同...

  • OpenGL ES 顶点着色器与片元着色解析

    1.OpenGL ES 3.0 图形管线流程图 2.流程图节点解析 1.顶点数组/顶点缓存区 顶点数组: 这个部分...

  • OpenGL ES 常见滤镜处理

    图片滤镜实现思路 前提条件:能够用GLSL显示普通图片 思路 初始化(上下文,顶点数组,顶点数据,顶点缓存区,CA...

网友评论

    本文标题:附录(6)使用顶点缓存区绘制

    本文链接:https://www.haomeiwen.com/subject/qytxultx.html