廊坊網(wǎng)站關(guān)鍵詞優(yōu)化seo關(guān)鍵詞是什么
效果展示
本篇博文會實現(xiàn)一個混色旋轉(zhuǎn)的3D球體
一.球體解析
前面幾篇博文講解了如何使用OpenGLES實現(xiàn)不同的3D圖形
本篇博文講解怎樣實現(xiàn)3D世界的代表圖形:一個混色旋轉(zhuǎn)的3D球體
1.1 極限正多面體
如果有學(xué)習(xí)過我前幾篇3D圖形繪制的博文,就知道要想繪制一個3D圖形,首先要做的第一步就是將要繪制的3D圖形進(jìn)行拆解,拆解成能夠使用單位圖元——三角形進(jìn)行繪制的各種子圖形
然而懂點微積分的都知道,球體本身就可以看作是一個被極限分解的正多面體
所以球面本身就可以使用三角形進(jìn)行繪制,并不需要拆解成其他子圖形
那么,現(xiàn)在要做的就是如何求解球體的頂點坐標(biāo)。
1.2 求解球體頂點坐標(biāo)
眾所周知,地球上任何一個地方都能用經(jīng)緯度進(jìn)行標(biāo)識
以此類推,先給球體設(shè)置一個經(jīng)緯度
根據(jù)經(jīng)緯度就將球體分解成四邊形,再將四邊形分解成三角形。
那么求解球體的坐標(biāo),就只需要求出四邊形的坐標(biāo)即可。
1.3 球體頂點坐標(biāo)公式
根據(jù)上述講解和圖示,很容易就能得出球體頂點坐標(biāo)公式:
- x0 = R?* cos(a) * sin(b)
- y0 = R?* sin(a))
- z0 = R * cos(a) * cos(b)
二.Render:變量定義
2.1 常規(guī)變量定義
還是常見的幾個變量,跟其他3D圖形的常規(guī)變量并無差別
//MVP矩陣
private float[] mMVPMatrix = new float[16];//著色器程序/渲染器
private int shaderProgram;//返回屬性變量的位置
//MVP變換矩陣屬性
private int mvpMatrixLoc;
//位置屬性
private int aPositionLocation;
//顏色屬性
private int aColorLocation;//surface寬高比
private float ratio;
2.2 定義頂點坐標(biāo)數(shù)組和緩沖
前文中已經(jīng)講解,對于球體,并不需要拆解出子圖形,而且顏色混合我會在著色器代碼中實現(xiàn),并不會在Render代碼中動態(tài)加載實現(xiàn),因此只需要定義一個數(shù)組和緩沖,就是頂點坐標(biāo)。
//球體頂點坐標(biāo)數(shù)組
private float vertexData[];
//頂點緩沖
private FloatBuffer vertexBuffer;
2.3?定義MVP矩陣
//MVP矩陣
private float[] mMVPMatrix = new float[16];
三.Render:著色器、內(nèi)存分配等
3.1 著色器創(chuàng)建、鏈接、使用
3.2 著色器屬性獲取、賦值
3.3 緩沖內(nèi)存分配
這幾個部分的代碼實現(xiàn)2D圖形繪制基本一致
可參考以前2D繪制的相關(guān)博文,里面都有詳細(xì)的代碼實現(xiàn)
不再重復(fù)展示代碼
四.Render:動態(tài)創(chuàng)建頂點
創(chuàng)建頂點時需要傳入半徑:0.85f
createBallPositions(0.85f);
球體渲染的關(guān)鍵函數(shù):?
createBallPositions(float r):
private void createBallPositions(float r) {// 存放頂點坐標(biāo)的ArrayListArrayList<Float> alVertix = new ArrayList<Float>();// 將球進(jìn)行單位切分的角度final int angleSpan = 5;// 緯度angleSpan度一份for (int wAngle = -90; wAngle < 90; wAngle = wAngle + angleSpan) {// 經(jīng)度angleSpan度一份for (int jAngle = 0; jAngle <= 360; jAngle = jAngle + angleSpan) {// 縱向橫向各到一個角度后計算對應(yīng)的此點在球面上的坐標(biāo)float x0 = (float) (r * Math.cos(Math.toRadians(wAngle)) * Math.sin(Math.toRadians(jAngle)));float y0 = (float) (r * Math.sin(Math.toRadians(wAngle)));float z0 = (float) (r * Math.cos(Math.toRadians(wAngle)) * Math.cos(Math.toRadians(jAngle)));float x1 = (float) (r * Math.cos(Math.toRadians(wAngle)) * Math.sin(Math.toRadians(jAngle + angleSpan)));float y1 = (float) (r * Math.sin(Math.toRadians(wAngle)));float z1 = (float) (r * Math.cos(Math.toRadians(wAngle)) * Math.cos(Math.toRadians(jAngle + angleSpan)));float x2 = (float) (r * Math.cos(Math.toRadians(wAngle + angleSpan)) * Math.sin(Math.toRadians(jAngle + angleSpan)));float y2 = (float) (r * Math.sin(Math.toRadians(wAngle + angleSpan)));float z2 = (float) (r * Math.cos(Math.toRadians(wAngle + angleSpan)) * Math.cos(Math.toRadians(jAngle + angleSpan)));float x3 = (float) (r * Math.cos(Math.toRadians(wAngle + angleSpan)) * Math.sin(Math.toRadians(jAngle)));float y3 = (float) (r * Math.sin(Math.toRadians(wAngle + angleSpan)));float z3 = (float) (r * Math.cos(Math.toRadians(wAngle + angleSpan)) * Math.cos(Math.toRadians(jAngle)));// 將計算出來的XYZ坐標(biāo)加入存放頂點坐標(biāo)的ArrayListalVertix.add(x1);alVertix.add(y1);alVertix.add(z1);alVertix.add(x0);alVertix.add(y0);alVertix.add(z0);alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);/*2---------------3| / || / || / || / || / |1---------------0*/}}float f[] = new float[alVertix.size()];for (int i = 0; i < f.length; i++) {f[i] = alVertix.get(i);}vertexData = f;
}
五.Render:繪制
5.1 MVP矩陣
//MVP矩陣賦值
mMVPMatrix = TransformUtils.getBallMVPMatrix(ratio);
//將變換矩陣傳入頂點渲染器
glUniformMatrix4fv(mvpMatrixLoc, 1, false, mMVPMatrix, 0);
getBallMVPMatrix(float ratio)
依然采用的是視椎體透視投影:
public static float[] getBallMVPMatrix(float ratio) {float[] modelMatrix = getIdentityMatrix(16, 0); //模型變換矩陣float[] modelMatrix0 = getIdentityMatrix(16, 0); //模型變換矩陣float[] viewMatrix = getIdentityMatrix(16, 0); //觀測變換矩陣/相機矩陣float[] projectionMatrix = getIdentityMatrix(16, 0); //投影變換矩陣mBallRotateAgree = (mBallRotateAgree + 1.0f) % 360;Matrix.setRotateM(modelMatrix, 0, mBallRotateAgree, 1, 0, 1);Matrix.translateM(modelMatrix0,0,0.0f,0.3f,0.3f);Matrix.multiplyMM(modelMatrix, 0, modelMatrix, 0, modelMatrix0, 0);Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 1, 10);float[] tmpMatrix = new float[16];float[] mvpMatrix = new float[16];Matrix.multiplyMM(tmpMatrix, 0, viewMatrix, 0, modelMatrix, 0);Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, tmpMatrix, 0);return mvpMatrix;
}
5.2 繪制球體
//準(zhǔn)備頂點坐標(biāo)內(nèi)存
glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, false, 0, vertexBuffer);
//繪制
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexData.length / 3);
六.著色器代碼
(1).ball_vertex_shader.glsl
#version 300 eslayout (location = 0) in vec4 vPosition;
layout (location = 1) in vec4 aColor;uniform mat4 u_Matrix;out vec4 vColor;void main() {gl_Position = u_Matrix*vPosition;float x = vPosition.x;float y = vPosition.y;float z = vPosition.z;//效果較真實vColor = vec4(x, y, z, 0.0);
}
(2).ball_fragtment_shader.glsl
#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision mediump float;in vec4 vColor;out vec4 outColor;void main(){outColor = vColor;
}
八.結(jié)束語
混色旋轉(zhuǎn)3D球體的繪制過程到此講解結(jié)束了
最終實現(xiàn)出來的效果如同開頭效果展示