1. 程式人生 > >從零開始OpenGL ES(四) 繪製紋理 圖片

從零開始OpenGL ES(四) 繪製紋理 圖片

理論


image

首先是兩個座標系

假如現在有一張圖片,是通過紋理座標系繪製出來的,圖片的左上角(0,0),左下角(0,1),
那麼我需要把紋理座標系和頂點座標系對齊, 那麼要把紋理座標系中(0,0)這個點,放到頂點座標系中的(-1,0)這個點.
相應的要把紋理座標系的(0,1)這個點,放到頂點座標系中(-1,-1)這個點. 後面以此類推

具體做法: 先把OpenGL 需要展示的區域畫出來(就是整個螢幕),再按照上面的做法 把紋理座標系貼到頂點座標系中.

頂點Shader

vertex_shader.glsl

attribute vec4 av_Position;
attribute vec2 af_Position;
varying vec2 v_texPo;
void main() {
    v_texPo = af_Position;
    gl_Position = av_Position;
}


注: attribute 只能在vertex中使用
varying 用於vertex和fragment之間傳遞值

  1. attribute vec4 av_Position; 這個是之前寫過的 頂點座標系
  2. attribute vec2 af_Position; 這個是紋理座標系 vec2 圖片是2d的 就用兩個向量x,y
  3. varying vec2 v_texPo; 在頂點座標和片元座標之間傳遞資料 v_texPo 這個值需要在頂點座標和片源座標的檔案中定義一直.

片元Shader

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中傳遞值。

  1. precision mediump float; 精度
  2. varying vec2 v_texPo; 從頂點Shader 獲取到的值
  3. uniform sampler2D sTexture; 紋理的屬性 因為是在片元裡面 所以用uniform修飾 傳值
  4. texture2D 把顏色取出來的方法 這裡實際上就是做的兩個座標的轉換

繪製紋理過程

1、載入shader和生成program過程不變

2、建立和繫結紋理:

    GLES20.glGenTextures(1, textureId, 0);
	GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureid);

glGenTextures 就是建立紋理 引數.1 是建立多少個紋理 texturId 是個整形的陣列. 0 是從0開始
glBindTexture 繫結紋理 把生成的textrueId 生成的紋理繫結到GL_TEXTURE_2D 上

3、設定環繞和過濾方式
環繞(超出紋理座標範圍):
(s == x t == y GL_REPEAT 重複)

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

過濾(紋理畫素對映到座標點):(縮小、放大:GL_LINEAR線性)

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

4、設定圖片
(bitmap)

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

5、繫結頂點座標和紋理座標

6、繪製圖形

程式碼

按照前面文章

繪製四邊形 實際上的點 按照 v1 v2 v3 v4 繪製

在頂點座標系中就是

//頂點座標
    private final  float[] vertexData={
            -1f,-1f,
            1f,-1f,
            -1f,1f,
            1f,1f
    };


但是紋理座標系和頂點座標系不一樣 需要對應起來所以紋理座標系是

  //紋理座標
    private final float[] textureData={
            0f,1f,
            1f,1f,
            0f,0f,
            0f,1f
    };

其他程式碼:

package com.xyyy.www.opengldemo;

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 java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

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

/**
 * @author liuml
 * @explain  渲染圖片
 * @time 2018/11/15 11:19
 */
public class XYRenderImage implements GLSurfaceView.Renderer {

    private Context context;
    //頂點座標
    private final  float[] vertexData={
            -1f,-1f,
            1f,-1f,
            -1f,1f,
            1f,1f
    };

    //紋理座標  正常
//    private final float[] textureData={
//            0f,1f,
//            1f,1f,
//            0f,0f,
//            1f,0f
//    };
    //紋理座標 倒立
    private final float[] textureData={
            1f,0f,
            0f,0f,
            1f, 1f,
            0f, 1f
    };


    private FloatBuffer vertexBuffer;//頂點buffer
    private FloatBuffer textureBuffer;//紋理buffer
    private int program;
    private int avPosition;//頂點座標
    private int afPosition;//紋理座標
    private int textureId;//紋理id儲存
//    private int afColor;


    public XYRenderImage(Context context){
        this.context = context;
        vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(vertexData);
        vertexBuffer.position(0);


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

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        String vertexSource = XYShaderUtil.readRawText(context, R.raw.img_vertex_shader);
        String fragmentSource = XYShaderUtil.readRawText(context, R.raw.img_fragment_shader);
        program = XYShaderUtil.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);

//            BitmapFactory.Options options = new BitmapFactory.Options();
//            options.inScaled = false;
            Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.test);
            if (bitmap == null) {
                return;
            }
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
            bitmap.recycle();
            bitmap = null;
        }

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width,int height) {
        //繪製區域
        GLES20.glViewport(0,0,width,height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        //清屏緩衝區
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        //利用顏色清屏
        GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);


        //讓program可用
        GLES20.glUseProgram(program);
        //頂點座標
        GLES20.glEnableVertexAttribArray(avPosition);
        GLES20.glVertexAttribPointer(avPosition, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
        //紋理座標
        GLES20.glEnableVertexAttribArray(afPosition);
        GLES20.glVertexAttribPointer(afPosition, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    }
}

效果:

image

相關推薦

開始OpenGL ES() 繪製紋理 圖片

理論 首先是兩個座標系 假如現在有一張圖片,是通過紋理座標系繪製出來的,圖片的左上角(0,0),左下角(0,1), 那麼我需要把紋理座標系和頂點座標系對齊, 那麼要把紋理座標系中(0,0)這個點,放到頂點座標系中的(-1,0)這個點. 相應的要把紋理座標系的

開始OpenGL ES(三) 繪製四邊形

原理 現在要實現用OpenGLES 實現四邊形. 一個四邊形是可以由兩個三角形構成 那麼我畫兩個相連的三角形來實現一個四邊形. 如圖 有個規定.:圖形環繞方向必須一致,要麼全是順時針 要麼全是逆時針 1、GL_TRIANGLES: v1, v2, v3, v3, v

開始openGL—— 二、 基本圖形繪製

前言 這是從零開始openGL系列文章的第二篇,在上篇文章中介紹了基本的環境配置,這篇文章將介紹如何繪製基本圖形(圓、三角形、立方體、圓柱、圓錐)。 基本框架 下面這裡我先給出opengl的3D繪圖的基本框架 #include <windows.h> #include <string.h&

PowerShell學習小結——PowerShell開始系列之

PowerShell能堅持看到這裏的同學,相信對PowerShell的命令使用應該不陌生,由於後面的內容較為繁雜,所以必須要熟悉PowerShell命令這裏準備了一些基礎的題目,有興趣的一定要動手操作一下:如何查看wuauserv服務運行狀態如何停止wuauserv服務如何查看explorer進程有服務器條件

開始學習jQuery () 使用jQuery操作元素的屬性與樣式

本系列文章導航 一.摘要 本篇文章講解如何使用jQuery獲取和操作元素的屬性和CSS樣式. 其中DOM屬性和元素屬性的區分值得大家學習. 二.前言 通過前面幾章我們已經能夠完全控制jQuery包裝集了,  無論是通過選擇器選取物件,

【Kettle開始】第彈之Kettle轉換資料抽取使用

Kettle版本:3.2GA JDK版本:1.6.0_41 OS:NT 需求:需要把業務系統庫、TXT檔案、EXCEL檔案中的資料抽取到資料倉庫中。 1、  建立轉換(Ctrl+N),轉換名稱為:R

開始學習jQuery ()

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.

開始學Python():變數與基本資料型別

上一章我們簡單的瞭解了一下python的程式碼縮排,基礎的輸出語句,多行語句和單行多行註釋,今天我們來了解下python的變數與基本資料型別,讓我們在以後的程式設計中,對各種型別瞭如指掌! 變數的賦值 為了方便給下面各種資料型別做詳解,我們首先學習一下變

【工作筆記】開始學ExtJs6( )—— 首頁樹狀選單和Tab頁的實現

題外話 做一個專案要向完成對應的模組,肯定是先要有樹形選單結構,點選對應才dna跳轉到相應介面,在extjs中如何實現。是上週遇到的一個小問題,現在做做記錄 app目錄下建立data/me

開始openGL——三、模型載入及滑鼠互動實現

前言  在上篇文章中,介紹了基本圖形的繪製。這篇部落格中將介紹模型的載入、繪製以及滑鼠互動的實現。 模型載入 模型儲存 要實現模型的讀取、繪製,我們首先需要知道模型是如何儲存在檔案中的。 通常模型是由網格組成的,且一般為三角網格。原因為: 其它多邊形網格可以容易地剖分為三角形 三點共面:保證平面性

開始openGL——五、光線追蹤

前言 前面介紹了基本圖形、模型、曲線的繪製,但是,在好像還沒有感受到那種3D遊戲裡一些能驚豔到自己的效果,即真實感還不是很足。這篇文章中介紹的光線追蹤,是實現真實感必不可少的。拿下面的兩張圖片來對比 對比一下是不是被下面這張圖片的效果驚豔到了?可以很明顯感覺到,下面的這個圖片效果要好的多。這篇部落格將

開始openGL——紋理貼圖與n次B樣條曲線

前言 在上篇文章中,介紹瞭如何載入繪製模型以及滑鼠互動的實現,並且遺留了個問題,就是沒有模型表面沒有紋理,看起來很醜。這篇文章將介紹如何貼紋理,以及曲線的繪製。 紋理貼圖 紋理載入 既然是貼圖,那首先我們得要有合適的紋理圖片,openGL中支援的圖片為bmp格式。在這裡我還用到了個額外的庫glaux,但當時在

android平臺下OpenGL ES 3.0開始

OpenGL ES 3.0學習實踐 android平臺下OpenGL ES 3.0從零開始 android平臺下OpenGL ES 3.0繪製純色背景 android平臺下OpenGL ES 3.0繪製圓點、直線和三角形 android平臺下OpenGL E

開始OpenGL ES 2.0【1】

這一節主要內容是矩陣的使用,投影和相機相關知識。一、矩陣相關        由於OpenGL ES使用的是列向量,所以向量與矩陣計算方式為 矩陣乘向量;在DirectX中使用的是行向量計算方式為 向量乘矩陣。二、投影相關        在OpenGL ES中投影方式有兩種,分

OpenGL ES 開始系列9:動畫基礎和關鍵幀動畫

Creating a Rotation Matrix from a Quaternion 從一個四元數中建立旋轉矩陣 這另外的一個方法相對簡單些。並且這個基本演算法來自於Matrix FAQ,雖然我需要把它轉換成行優先的順序。 static inline void Matrix3DSetUsingQuater

開始學android&lt;Bitmap圖形組件.十七.&gt;

alt getheight drawtext layout pla cin mas 簡單 制圖 android.graphics.Bitmap(位圖)是Android手機中專門提供的用於操作圖片資源的操作類,使用此類能夠直接從資源文件之中進行圖片資源的讀取。而且對這些圖

開始學習html(十)單位和值

type 當我 總結 學生 專註 bfc span blog 設置顏色 一、顏色值 1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5

開始的linux 第

cd命令詳解 linux文件類型 pwd命令從零開始的linux 第四章哈嘍~~小編又回來啦~~(被同學們接住後扔進了水裏....)QAQ...你們怎麽能這麽對待小編...(啪..崩..咚..劈..咚..啪..)(鼻青臉腫的小編)額...同學們看起來精神不錯,早起活動活動筋骨對身體有好處....好啦,

開始學習前端JAVASCRIPT — 11、JavaScript基礎this指向的種情況

事件 箭頭 註意 idt 轉移 如果 箭頭函數 javascrip function JavaScript中this的四種情況(非嚴格模式) 1、當this所在函數是事件處理函數時,this指向事件源。2、當this所在函數是構造函數時,this指向new出來的

開始學 Web 之 DOM()節點

def clas scrip while p標簽 設置 ner 操作 text 大家好,這裏是「 Daotin的夢囈 」從零開始學 Web 系列教程。此文首發於「 Daotin的夢囈 」公眾號,歡迎大家訂閱關註。在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相