【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android OpenGL ES 2.0如何進(jìn)行繪制紋理_第1頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android OpenGL ES 2.0如何進(jìn)行繪制紋理_第2頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android OpenGL ES 2.0如何進(jìn)行繪制紋理_第3頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android OpenGL ES 2.0如何進(jìn)行繪制紋理_第4頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android OpenGL ES 2.0如何進(jìn)行繪制紋理_第5頁
免費(fèi)預(yù)覽已結(jié)束,剩余2頁可下載查看

付費(fèi)下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】AndroidOpenGLES2.0如何進(jìn)行繪制紋理

這篇文章將為大家詳細(xì)講解有關(guān)AndroidOpenGLES2.0如何進(jìn)行繪制紋理,文章內(nèi)容質(zhì)量較高,因此在下分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。紋理,在OpenGL中,可以理解為加載到顯卡顯存中的圖片。Android設(shè)備在2.2開始支持OpenGLES2.0,從前都是ES1.0和ES1.1的版本。簡(jiǎn)單來說,OpenGL

ES是為了嵌入設(shè)備進(jìn)行功能剪裁后的OpenGL版本。ES2.0是和1.x版本不兼容的,區(qū)別和兼容性參見android官方文檔。首先,android使用openGL提供了特殊的view作為基礎(chǔ)叫做GLSurfaceView。我們的view需要繼承GLSurfaceView。java代碼public

class

MyGLSurfaceView

extends

GLSurfaceView

{

public

MyGLSurfaceView(Context

context)

{

super(context);

setFocusableInTouchMode(true);

//

Tell

the

surface

view

we

want

to

create

an

OpenGL

ES

2.0-compatible

//

context,

and

set

an

OpenGL

ES

2.0-compatible

renderer.

this.setEGLContextClientVersion(2);

this.setRenderer(new

MyRenderer());

}

}并沒有什么特別之處,androidview的渲染操作需要實(shí)現(xiàn)一個(gè)render接口,GLSurfaceView的渲染接口為android.opengl.GLSurfaceView.Renderer。我們需要實(shí)現(xiàn)接口的方法。java代碼public

class

MyRenderer

implements

Renderer

{

public

void

onDrawFrame(GL10

gl)

{}

public

void

onSurfaceChanged(GL10

gl,

int

width,

int

height)

{}

public

void

onSurfaceCreated(GL10

gl,

EGLConfig

config)

{}

}接口實(shí)現(xiàn)3個(gè)方法,對(duì)應(yīng)繪制,繪制區(qū)域變化,區(qū)域創(chuàng)建。需要說明的是參數(shù)GL10gl是OpenGLES1.x版本的對(duì)象。這里我們不會(huì)使用到。還有一點(diǎn)就是,onDrawFrame方法的調(diào)用是有系統(tǒng)調(diào)用的,不需要手動(dòng)調(diào)用。系統(tǒng)會(huì)以一定的頻率不斷的回調(diào)。接下來我們進(jìn)入ES2.0的使用,上代碼先:java代碼public

void

onSurfaceCreated(GL10

gl,

EGLConfig

config)

{

GLES20.glEnable(GLES20.GL_TEXTURE_2D);

//

Active

the

texture

unit

0

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

loadVertex();

initShader();

loadTexture();

}1、啟用2D紋理繪制區(qū)域創(chuàng)建的時(shí)候,我們?cè)O(shè)置了啟用2D的紋理,并且激活了紋理單元unit0。什么意思呢,說起來話長(zhǎng),以后慢慢說。簡(jiǎn)單說一下,記住OpenGL是基于狀態(tài)的,就是很多狀態(tài)的設(shè)置和切換,這里啟用GL_TEXTURE_2D就是一個(gè)狀態(tài)的開啟,表明OpenGL可以使用2D紋理。什么是激活紋理單元?這個(gè)和硬件有點(diǎn)關(guān)系,OpenGL要顯卡會(huì)劃分存儲(chǔ)紋理的存儲(chǔ)區(qū)域不止一個(gè)區(qū)域。這里是使用區(qū)域unit0,多重紋理繪制可以開啟多個(gè),這個(gè)以后說。接下來,調(diào)用了三個(gè)函數(shù),載入頂點(diǎn),初始化著色器,載入紋理。2、加載頂點(diǎn)OpenGL繪制圖形是根據(jù)頂點(diǎn)以后鏈接起來的。為什么要這樣,其實(shí)這樣很強(qiáng)大是一種設(shè)計(jì)吧。頂點(diǎn)可以暫時(shí)簡(jiǎn)單理解為含有位置信息的坐標(biāo)點(diǎn)。java代碼private

void

loadVertex()

{

//

float

size

=

4

this.vertex

=

ByteBuffer.allocateDirect(quadVertex.length

*

4)

.order(ByteOrder.nativeOrder())

.asFloatBuffer();

this.vertex.put(quadVertex).position(0);

//

short

size

=

2

this.index

=

ByteBuffer.allocateDirect(quadIndex.length

*

2)

.order(ByteOrder.nativeOrder())

.asShortBuffer();

this.index.put(quadIndex).position(0);

}

private

FloatBuffer

vertex;

private

ShortBuffer

index;

private

float[]

quadVertex

=

new

float[]

{

-0.5f,

0.5f,

0.0f,

//

Position

0

0,

1.0f,

//

TexCoord

0

-0.5f,

-0.5f,

0.0f,

//

Position

1

0,

0,

//

TexCoord

1

0.5f

,

-0.5f,

0.0f,

//

Position

2

1.0f,

0,

//

TexCoord

2

0.5f,

0.5f,

0.0f,

//

Position

3

1.0f,

1.0f,

//

TexCoord

3

};

private

short[]

quadIndex

=

new

short[]

{

(short)(0),

//

Position

0

(short)(1),

//

Position

1

(short)(2),

//

Position

2

(short)(2),

//

Position

2

(short)(3),

//

Position

3

(short)(0),

//

Position

0

};FloatBuffer,ShortBuffer是封裝了本地?cái)?shù)據(jù)結(jié)構(gòu)的封裝對(duì)象。是的,這個(gè)2個(gè)對(duì)象里面的數(shù)據(jù)不被java虛擬機(jī)管理,相當(dāng)于C語言的存儲(chǔ)方式。quadVertex的數(shù)據(jù)就是一個(gè)矩形的坐標(biāo),和紋理坐標(biāo)。一兩句話很難解釋清楚,這里涉及到openGL的幾個(gè)經(jīng)典的坐標(biāo)系,下次說。概括的說,openGL的坐標(biāo)是單位化的,都是0.0-1.0的浮點(diǎn)型,屏幕的中心點(diǎn)是(0,0)。而紋理的坐標(biāo)左下角是(0,0)。這里的quadVertex是在屏幕中大概花了一個(gè)矩形貼了一個(gè)圖片,position0

是左上點(diǎn),以后左下,右下,右上的順序,紋理坐標(biāo)同理。quadIndx是這剛才的這些頂點(diǎn)索引排列。這里一個(gè)矩形也就4個(gè)頂點(diǎn),每個(gè)頂點(diǎn)3個(gè)位置坐標(biāo),2個(gè)紋理坐標(biāo)。也就是說一個(gè)頂點(diǎn)有5個(gè)float數(shù)據(jù)。至于為什么頂點(diǎn)為什么這么排列下次說,是2個(gè)三角形合成了一個(gè)矩形,幾句話很難解釋清楚。所以說,這段代碼就是把矩形的位置和紋理坐標(biāo),存儲(chǔ)到本地?cái)?shù)據(jù),準(zhǔn)備后面使用而已。3、初始化著色器這個(gè)著色器就是ES2.0的特色,又叫可編程著色器,也是區(qū)別于ES1.x的本質(zhì)。這里只做簡(jiǎn)單的介紹??删幊讨魇且环N腳本,語法類似C語言,腳本分為頂點(diǎn)著色器和片段著色器,分別對(duì)應(yīng)了openGL不同的渲染流程。頂點(diǎn)著色器:java代碼uniform

mat4

u_MVPMatrix;

attribute

vec4

a_position;

attribute

vec2

a_texCoord;

varying

vec2

v_texCoord;

void

main()

{

gl_Position

=

a_position;

v_texCoord

=

a_texCoord;

}片段著色器:java代碼precision

lowp

float;

varying

vec2

v_texCoord;

uniform

sampler2D

u_samplerTexture;

void

main()

{

gl_FragColor

=

texture2D(u_samplerTexture,

v_texCoord);

}這里記住一句話,頂點(diǎn)著色器,會(huì)在頂點(diǎn)上執(zhí)行;片段著色器會(huì)在像素點(diǎn)上執(zhí)行。剛才的矩形就有4個(gè)頂點(diǎn),每個(gè)頂點(diǎn)都會(huì)應(yīng)用這個(gè)腳本。也就是說,頂點(diǎn)是位置相關(guān)信息,片段是色彩紋理相關(guān)信息。這個(gè)2段腳本都是文本,需要編譯,鏈接,等等一些操作才能被ES2.0所使用。過程就像C語言的編譯運(yùn)行過程。openGL提供了相關(guān)函數(shù)去做這些事情。java代碼private

void

initShader()

{

String

vertexSource

=

Tools.readFromAssets("VertexShader.glsl");

String

fragmentSource

=

Tools.readFromAssets("FragmentShader.glsl");

//

Load

the

shaders

and

get

a

linked

program

program

=

GLHelper.loadProgram(vertexSource,

fragmentSource);

//

Get

the

attribute

locations

attribPosition

=

GLES20.glGetAttribLocation(program,

"a_position");

attribTexCoord

=

GLES20.glGetAttribLocation(program,

"a_texCoord");

uniformTexture

=

GLES20.glGetUniformLocation(program,

"u_samplerTexture");

GLES20.glUseProgram(program);

GLES20.glEnableVertexAttribArray(attribPosition);

GLES20.glEnableVertexAttribArray(attribTexCoord);

//

Set

the

sampler

to

texture

unit

0

GLES20.glUniform1i(uniformTexture,

0);

}可以看到,頂點(diǎn)和片段一起構(gòu)成一個(gè)program,它可以被openGL所使用,是一個(gè)編譯好的腳本程序,存儲(chǔ)在顯存。GLES20.glGetAttribLocation和GLES20.glGetUniformLocation

這句話是神馬作用呢。簡(jiǎn)單說就是,java程序和著色器腳本數(shù)據(jù)通信的。把就像參數(shù)的傳遞一樣,這樣腳本就能根據(jù)外界的參數(shù)變化,實(shí)時(shí)的改變openGL流水線渲染的處理流程。封裝的加載著色器的輔助方法:java代碼public

static

int

loadProgram(String

vertexSource,

String

fragmentSource)

{

//

Load

the

vertex

shaders

int

vertexShader

=

GLHelper.loadShader(GLES20.GL_VERTEX_SHADER,

vertexSource);

//

Load

the

fragment

shaders

int

fragmentShader

=

GLHelper.loadShader(GLES20.GL_FRAGMENT_SHADER,

fragmentSource);

//

Create

the

program

object

int

program

=

GLES20.glCreateProgram();

if

(program

==

0)

{

throw

new

RuntimeException("Error

create

program.");

}

GLES20.glAttachShader(program,

vertexShader);

GLES20.glAttachShader(program,

fragmentShader);

//

Link

the

program

GLES20.glLinkProgram(program);

int[]

linked

=

new

int[1];

//

Check

the

link

status

GLES20.glGetProgramiv(program,

GLES20.GL_LINK_STATUS,

linked,

0);

if

(linked[0]

==

0)

{

GLES20.glDeleteProgram(program);

throw

new

RuntimeException("Error

linking

program:

"

+

GLES20.glGetProgramInfoLog(program));

}

//

Free

up

no

longer

needed

shader

resources

GLES20.glDeleteShader(vertexShader);

GLES20.glDeleteShader(fragmentShader);

return

program;

}java代碼public

static

int

loadShader(int

shaderType,

String

source)

{

//

Create

the

shader

object

int

shader

=

GLES20.glCreateShader(shaderType);

if

(shader

==

0)

{

throw

new

RuntimeException("Error

create

shader.");

}

int[]

compiled

=

new

int[1];

//

Load

the

shader

source

GLES20.glShaderSource(shader,

source);

//

Compile

the

shader

GLES20.glCompileShader(shader);

//

Check

the

compile

status

GLES20.glGetShaderiv(shader,

GLES20.GL_COMPILE_STATUS,

compiled,

0);

if

(compiled[0]

==

0)

{

GLES20.glDeleteShader(shader);

throw

new

RuntimeException("Error

compile

shader:

"

+

GLES20.glGetShaderInfoLog(shader));

}

return

shader;

}為什么openGL的很多操作目標(biāo)都是int類型的?因?yàn)閛penGL只會(huì)在顯存生成或綁定地址,返回id,以后用id相當(dāng)于句柄去改變它的內(nèi)部狀態(tài)。4、加載紋理就是把圖片的數(shù)據(jù)上傳到顯存,以后再使用它。請(qǐng)注意紋理圖片的長(zhǎng)和寬***是2的N次方,不然不一定能繪制出來。java代碼static

int[]

loadTexture(String

path)

{

int[]

textureId

=

new

int[1];

//

Generate

a

texture

object

GLES20.glGenTextures(1,

textureId,

0);

int[]

result

=

null;

if

(textureId[0]

!=

0)

{

InputStream

is

=

Tools.readFromAsserts(path);

Bitmap

bitmap;

try

{

bitmap

=

BitmapFactory.decodeStream(is);

}

finally

{

try

{

is.close();

}

catch

(IOException

e)

{

throw

new

RuntimeException("Error

loading

Bitmap.");

}

}

result

=

new

int[3];

result[TEXTURE_ID]

=

textureId[0];

//

TEXTURE_ID

result[TEXTURE_WIDTH]

=

bitmap.getWidth();

//

TEXTURE_WIDTH

result[TEXTURE_HEIGHT]

=

bitmap.getHeight();

//

TEXTURE_HEIGHT

//

Bind

to

the

texture

in

OpenGL

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,

textureId[0]);

//

Set

filtering

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

GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,

GLES20.GL_TEXTURE_WRAP_S,

GLES20.GL_CLAMP_TO_EDGE);

GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,

GLES20.GL_TEXTURE_WRAP_T,

GLES20.GL_CLAMP_TO_EDGE);

//

Load

the

bitmap

into

the

bound

texture.

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,

0,

bitmap,

0);

//

Recycle

the

bitmap,

since

its

data

has

been

loaded

into

OpenGL.

bitmap.recycle();

}

else

{

throw

new

RuntimeException("Error

loading

texture.");

}

return

result;

}這里使用了android的工具類吧bitmap直接轉(zhuǎn)換成openGL紋理需要的格式了。過程是,先生成一個(gè)紋理的id在顯卡上的,以后根據(jù)id上傳紋理數(shù)據(jù),以后保存這個(gè)id就可以操作這個(gè)紋理了。至于紋理的一些過濾特性設(shè)置,將來再說?,F(xiàn)在貌似就剩下繪制了,準(zhǔn)備好了頂點(diǎn)信息,頂點(diǎn)對(duì)應(yīng)的紋理坐標(biāo)。初始化了著色器,上傳了紋理圖片。接下來就已把他們合起來繪制了。java代碼public

void

onDrawFrame(GL10

gl)

{

//

clear

screen

to

black

GLES20.glClearColor(0.0f,

0.0f,

0.0f,

0.0f);

GLES20.glClear(GLES20.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論