Android OpenGL ES基本用法(2),绘制三角图形


目录


OpenGL的坐标系

在这里插入图片描述

顶点着色器,片元着色器

在这里插入图片描述

vertex_shader.glsl

attribute vec4 av_Position;
void main(){
    gl_Position = av_Position;
}

注: attribute 只能在vertex中使用

fragment_shader.glsl

precision mediump float;
uniform vec4 af_Potion;
void main(){
    gl_FragColor = af_Potion;
}

注: uniform 用于在application中向vertex和fragment中传递值。

ShaderUtil.java

package com.jianji.delogo.Test.MediaCodec;

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ShaderUtil {
    private static final String TAG = "ShaderUtil";

    /**
     * 读取shader
     *
     * @param context
     * @param rawId
     * @return
     */
    public static String readRawTxt(Context context, int rawId) {
        InputStream inputStream = context.getResources().openRawResource(rawId);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer sb = new StringBuffer();
        String line;

        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line).append("\n");
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 加载shader
     *
     * @param shaderType
     * @param source
     * @return
     */
    private static int loadShader(int shaderType, String source) {
        //创建shader
        int shader = GLES20.glCreateShader(shaderType);
        if (shader != 0) {
            //关联source
            GLES20.glShaderSource(shader, source);
            //编译
            GLES20.glCompileShader(shader);
            //获取编译状态
            int[] compile = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0);
            if (compile[0] != GLES20.GL_TRUE) {
                //失败
                Log.e(TAG, "loadShader: shader compile error");
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
    }

    /**
     * 生成程序
     *
     * @param vertexSource
     * @param fragmentSource
     * @return
     */
    public static int createProgram(String vertexSource, String fragmentSource) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {
            return 0;
        }
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (fragmentShader == 0) {
            return 0;
        }
        //创建
        int program = GLES20.glCreateProgram();
        if (program != 0) {
            //附加着色器
            GLES20.glAttachShader(program, vertexShader);
            GLES20.glAttachShader(program, fragmentShader);
            //连接
            GLES20.glLinkProgram(program);
            //检查连接是否成功
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] != GLES20.GL_TRUE) {
                //出错
                Log.e(TAG, "createProgram: link program error");
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }
}

GLTestView.java

package com.jianji.delogo.Test.MediaCodec;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;

import com.jianji.delogo.R;

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

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;


public class GLTestView extends GLSurfaceView implements GLSurfaceView.Renderer {

    private Context context;

    //绘制坐标范围
    float[] vertexData = {
            -1f, 0.0f,
            0.0f, 1.0f,
            1.0f, 0.0f
    };
    //为坐标分配本地内存地址,不受jvm的影响
    FloatBuffer vertexBuffer;

    public GLTestView(Context context) {
        this(context, null);
    }

    public GLTestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        //设置OpenGL的版本
        setEGLContextClientVersion(2);
        setRenderer(this);
        vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                .order(ByteOrder.nativeOrder())//对齐,加快处理速度
                .asFloatBuffer()
                .put(vertexData);
        //指向0的位置
        vertexBuffer.position(0);
    }

    private int program;
    private int avPosition;
    private int afColor;

    /**
     * Called when the surface is created or recreated.
     */
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        String vertexSource = ShaderUtil.readRawTxt(context, R.raw.vertex_shader);
        String fragmentSource = ShaderUtil.readRawTxt(context,R.raw.fragment_shader);

        program = ShaderUtil.createProgram(vertexSource,fragmentSource);
        if (program > 0) {
            avPosition = GLES20.glGetAttribLocation(program,"av_Position");
            afColor = GLES20.glGetUniformLocation(program,"af_Color");
        }
    }

    /**
     * Called when the surface changed size.
     */
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //设置大小位置
        GLES20.glViewport(0, 0, width, height);
    }

    /**
     * Called to draw the current frame.
     */
    @Override
    public void onDrawFrame(GL10 gl) {
        //清屏,清理掉颜色的缓冲区
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        //设置清屏的颜色,这里是float颜色的取值范围的[0,1]
        GLES20.glClearColor(1.0f, 0f, 0f, 1.0f);

        //使用program
        GLES20.glUseProgram(program);

        //设置颜色,和颜色的色值
        GLES20.glUniform4f(afColor,1f,1f,0f,1f);

        //设置为可用的状态
        GLES20.glEnableVertexAttribArray(avPosition);
        //size 指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
        //stride 指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。
        GLES20.glVertexAttribPointer(avPosition,2,GLES20.GL_FLOAT,false,8, vertexBuffer);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,3);
    }
}

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenGL ES 2.0 中,绘制基本图形需要创建一个顶点数组并将其传递给着色器进行渲染。以下是绘制基本图形的一些示例代码: 1. 绘制三角形 ```c++ GLfloat vertices[] = { -0.5f, -0.5f, 0.0f, // 左下角 0.5f, -0.5f, 0.0f, // 右下角 0.0f, 0.5f, 0.0f // 顶部 }; glVertexAttribPointer(positionAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray(positionAttribLocation); glDrawArrays(GL_TRIANGLES, 0, 3); ``` 2. 绘制矩形 ```c++ GLfloat vertices[] = { -0.5f, -0.5f, 0.0f, // 左下角 0.5f, -0.5f, 0.0f, // 右下角 0.5f, 0.5f, 0.0f, // 右上角 -0.5f, 0.5f, 0.0f // 左上角 }; glVertexAttribPointer(positionAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray(positionAttribLocation); GLuint indices[] = { 0, 1, 2, 0, 2, 3 }; glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices); ``` 3. 绘制圆形 ```c++ const int segments = 30; // 圆形的分段数 GLfloat vertices[(segments + 1) * 3]; for (int i = 0; i <= segments; i++) { float angle = 2.0f * M_PI * static_cast<float>(i) / static_cast<float>(segments); vertices[i * 3] = cosf(angle); vertices[i * 3 + 1] = sinf(angle); vertices[i * 3 + 2] = 0.0f; } glVertexAttribPointer(positionAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray(positionAttribLocation); glDrawArrays(GL_TRIANGLE_FAN, 0, segments + 1); ``` 以上代码中,`positionAttribLocation` 是顶点着色器中位置变量的位置。`glVertexAttribPointer` 函数将顶点数据传递给着色器。`glEnableVertexAttribArray` 函数启用顶点属性数组。`glDrawArrays` 函数使用传递的数据绘制图形。 对于矩形,我们使用了索引缓冲对象 (`GLuint indices[]`) 来指定顶点的顺序。`GL_TRIANGLE_FAN` 参数指定绘制圆形时使用的绘制模式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值