Android OpenGL ES基本用法(4),绘制纹理图片


目录


纹理坐标相当于:srcRect
顶点坐标相当于:dstRect
在这里插入图片描述

vertex_shader.glsl

//vec4使用4个向量xyzw
attribute vec4 av_Position;
//这里绘制2D图形,所以使用vec2两个向量的即可xy
attribute vec2 af_Position;
varying vec2 v_texPo;
void main() {
    v_texPo = af_Position;
    gl_Position = av_Position;
}

注: attribute 只能在vertex中使用
    	varying 用于vertex和fragment之间传递值

fragment_shader.glsl

//精度
precision mediump float;
varying vec2 v_texPo;
uniform sampler2D sTexture;
void main() {
    gl_FragColor=texture2D(sTexture, v_texPo);
}

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

GLTestView.java

package com.jianji.delogo.Test.MediaCodec;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
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, -1f,
            1f, -1.0f,
            -1f, 1.0f,
            1f, 1f
    };
    float[] textureData = {
            0f, 1f,
            1f, 1f,
            0f, 0f,
            1f, 0f
    };
    //为坐标分配本地内存地址,不受jvm的影响
    FloatBuffer vertexBuffer;
    FloatBuffer textureBuffer;

    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);

        textureBuffer = ByteBuffer.allocateDirect(textureData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(textureData);
        textureBuffer.position(0);
    }

    private int program;
    private int avPosition;
    private int afPosition;
    private int textureId;

    /**
     * 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");
            afPosition = GLES20.glGetAttribLocation(program, "af_Position");

            int[] textureIds = new int[1];
            //生成纹理
            GLES20.glGenTextures(1, textureIds, 0);
            if (textureIds[0] == 0) {
                return;
            }
            textureId = textureIds[0];
            //绑定纹理
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
            //环绕方式
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
            //过滤方式
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.default_banner_chat);
            if (bitmap == null) {
                return;
            }
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
            bitmap.recycle();
        }
    }

    /**
     * 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.glEnableVertexAttribArray(avPosition);
        //size 指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
        //stride 指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。
        //size 2 代表(x,y),stride 8 代表跨度 (2个点为一组,2个float有8个字节)
        GLES20.glVertexAttribPointer(avPosition, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);

        GLES20.glEnableVertexAttribArray(afPosition);
        GLES20.glVertexAttribPointer(afPosition, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    }
}

正常显示一张图片

在这里插入图片描述

只显示左下三角

//这里只需要绘制三个点
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 3);

在这里插入图片描述

只显示图片的右上1/4

    //坐标区域
    float[] vertexData = {
            -1f, -1f,
            1f, -1.0f,
            -1f, 1.0f,
            1f, 1f
    };
	//纹理区域
    float[] textureData = {
//            0f, 1f,
//            1f, 1f,
//            0f, 0f,
//            1f, 0f
            0.5f, 0.5f,
            1f, 0.5f,
            0.5f, 0f,
            1f, 0f
    };

在这里插入图片描述

整个图片,放在显示区域的右上1/4

    //坐标区域
    float[] vertexData = {
//            -1f, -1f,
//            1f, -1.0f,
//            -1f, 1.0f,
//            1f, 1f
            0f, 0f,
            1f, 0f,
            0f, 1f,
            1f, 1f
    };
    //纹理区域
    float[] textureData = {
            0f, 1f,
            1f, 1f,
            0f, 0f,
            1f, 0f
    };

在这里插入图片描述

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android中使用OpenGL ES 3.0加载纹理有以下步骤: 1. 初始化OpenGL ES环境:在OpenGL ES操作前,需要初始化OpenGL ES环境,创建GLSurfaceView实例,并设置渲染器。 2. 创建纹理对象:使用OpenGL ES函数glGenTextures生成纹理对象ID,并绑定到当前活动的纹理单元。 3. 加载纹理图像:通过Android的Bitmap对象加载纹理图像,可以使用BitmapFactory类的decodeResource方法从资源中加载或使用Bitmap类的createBitmap方法动态创建。调用glTexImage2D将图像数据传输到纹理对象中。 4. 设置纹理过滤器:可以使用glTexParameteri函数设置纹理的放大缩小过滤器,如GL_LINEAR或GL_NEAREST。 5. 设置纹理包裹模式:可以使用glTexParameteri函数设置纹理的包裹模式,如GL_CLAMP_TO_EDGE或GL_REPEAT。 6. 加载纹理坐标:通过定义纹理坐标数组,确定纹理映射到对象的哪个部分。在顶点着色器中使用纹理坐标进行纹理采样。 7. 绘制纹理:在绘制OpenGL场景时,通过在顶点着色器和片段着色器中使用纹理坐标,并利用纹理采样器将纹理应用到对象上。 8. 释放纹理资源:当纹理不再使用时,需要调用glDeleteTextures函数释放纹理对象。 总之,使用OpenGL ES 3.0加载纹理需要创建纹理对象、加载纹理图像、设置纹理过滤器与包裹模式、加载纹理坐标,并在绘制时通过纹理采样器将纹理应用到对象上。记得释放纹理资源,以避免内存泄漏。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值