openGL es2.0 创建纹理灯光球
package com.gzdxid.utils; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.ArrayList; import android.opengl.GLES20; public class DrawBallTextureLight { int mProgram; int muMVPMatrixHandle; int muMMatrixHandle; int muLightLocationHandle; int muCameraHandle; int maPositionHandle; int maNormalHandle; int maTexCoorHandle; FloatBuffer mVertexBuffer; FloatBuffer mTexCoorBuffer; FloatBuffer mNormalBuffer; int vCount = 0; final float UNIT_SIZE = 1f; final float angleSpan = 10f; float R = 0; public float roateX; public float roateY; public DrawBallTextureLight(float r,int mProgram) { initVertex(r); initShader(mProgram); } private void initVertex(float r) { R = r; ArrayList<Float> alVertix = new ArrayList<Float>(); for (float vAngle = 90; vAngle > -90; vAngle -= angleSpan) { for (float hAngle = 360; hAngle > 0; hAngle -= angleSpan) { float x1 = getCoor(0, vAngle, hAngle); float y1 = getCoor(1, vAngle, hAngle); float z1 = getCoor(2, vAngle, hAngle); float x2 = getCoor(0, vAngle - angleSpan, hAngle); float y2 = getCoor(1, vAngle - angleSpan, hAngle); float z2 = getCoor(2, vAngle - angleSpan, hAngle); float x3 = getCoor(0, vAngle - angleSpan, hAngle - angleSpan); float y3 = getCoor(1, vAngle - angleSpan, hAngle - angleSpan); float z3 = getCoor(2, vAngle - angleSpan, hAngle - angleSpan); float x4 = getCoor(0, vAngle, hAngle - angleSpan); float y4 = getCoor(1, vAngle, hAngle - angleSpan); float z4 = getCoor(2, vAngle, hAngle - angleSpan); alVertix.add(x1); alVertix.add(y1); alVertix.add(z1); alVertix.add(x2); alVertix.add(y2); alVertix.add(z2); alVertix.add(x4); alVertix.add(y4); alVertix.add(z4); // 构建第二三角形 alVertix.add(x4); alVertix.add(y4); alVertix.add(z4); alVertix.add(x2); alVertix.add(y2); alVertix.add(z2); alVertix.add(x3); alVertix.add(y3); alVertix.add(z3); } } vCount = alVertix.size() / 3; float vertices[] = new float[vCount * 3]; for (int i = 0; i < alVertix.size(); i++) { vertices[i] = alVertix.get(i); } ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); mVertexBuffer = vbb.asFloatBuffer(); mVertexBuffer.put(vertices); mVertexBuffer.position(0); float[] texCoor = generateTexCoor(// 获取切分整图的纹理数组 (int) (360 / angleSpan), // 纹理图切分的列数 (int) (180 / angleSpan) // 纹理图切分的行数 ); ByteBuffer llbb = ByteBuffer.allocateDirect(texCoor.length * 4); llbb.order(ByteOrder.nativeOrder());// 设置字节顺序 mTexCoorBuffer = llbb.asFloatBuffer(); mTexCoorBuffer.put(texCoor); mTexCoorBuffer.position(0); mNormalBuffer=mVertexBuffer; } private void initShader(int mProgram) { this.mProgram=mProgram; muMVPMatrixHandle=GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); muMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix"); muLightLocationHandle=GLES20.glGetUniformLocation(mProgram, "uLightLocation"); muCameraHandle=GLES20.glGetUniformLocation(mProgram, "uCamera"); maPositionHandle=GLES20.glGetAttribLocation(mProgram, "aPosition"); maNormalHandle= GLES20.glGetAttribLocation(mProgram, "aNormal"); maTexCoorHandle=GLES20.glGetAttribLocation(mProgram, "aTexCoor"); } public void drawSelf(int texId){ MatrixState.rotate(roateX, 1, 0, 0); MatrixState.rotate(roateY, 0, 1, 0); GLES20.glUseProgram(mProgram); GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0); GLES20.glUniformMatrix4fv(muMMatrixHandle, 1, false, MatrixState.getMMatrix(), 0); GLES20.glUniform3fv(muLightLocationHandle, 1, MatrixState.lightPositionFB); GLES20.glUniform3fv(muCameraHandle, 1, MatrixState.cameraFB); GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, mVertexBuffer); GLES20.glVertexAttribPointer(maTexCoorHandle, 2, GLES20.GL_FLOAT, false, 2 * 4, mTexCoorBuffer); GLES20.glVertexAttribPointer(maNormalHandle, 3, GLES20.GL_FLOAT, false, 3*4, mNormalBuffer); GLES20.glEnableVertexAttribArray(maPositionHandle); GLES20.glEnableVertexAttribArray(maNormalHandle); GLES20.glEnableVertexAttribArray(maTexCoorHandle); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount); } private float getCoor(int which, float vAngle, float hAngle) { switch (which) { case 0:// x return (float) (R * UNIT_SIZE * Math.cos(Math.toRadians(vAngle)) * Math.cos(Math.toRadians(hAngle))); case 1:// y return (float) (R * UNIT_SIZE * Math.sin(Math.toRadians(vAngle))); case 2:// z return (float) (R * UNIT_SIZE * Math.cos(Math.toRadians(vAngle)) * Math.sin(Math.toRadians(hAngle))); } return 0; } // 自动切分纹理产生纹理数组的方法 public float[] generateTexCoor(int bw, int bh) { float[] result = new float[bw * bh * 6 * 2]; float sizew = 1.0f / bw;// 列数 float sizeh = 1.0f / bh;// 行数 int c = 0; for (int i = 0; i < bh; i++) { for (int j = 0; j < bw; j++) { // 每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标 float s = j * sizew; float t = i * sizeh; result[c++] = s; result[c++] = t; result[c++] = s; result[c++] = t + sizeh; result[c++] = s + sizew; result[c++] = t; result[c++] = s + sizew; result[c++] = t; result[c++] = s; result[c++] = t + sizeh; result[c++] = s + sizew; result[c++] = t + sizeh; } } return result; } }
<span style="font-family: Arial; font-size: 14px; line-height: 26px;">二、顶点着色器:</span>
<span style="font-family: Arial; font-size: 14px; line-height: 26px;"></span><pre name="code" class="cpp">uniform mat4 uMVPMatrix; //总变换矩阵 uniform mat4 uMMatrix; //变换矩阵 uniform vec3 uLightLocation; //光源位置 uniform vec3 uCamera; //摄像机位置 attribute vec3 aPosition; //顶点位置 attribute vec3 aNormal; //顶点法向量 attribute vec2 aTexCoor; //顶点纹理坐标 //用于传递给片元着色器的变量 varying vec4 vAmbient; varying vec4 vDiffuse; varying vec4 vSpecular; varying vec2 vTextureCoord; //定位光光照计算的方法 void pointLight( //定位光光照计算的方法 in vec3 normal, //法向量 inout vec4 ambient, //环境光最终强度 inout vec4 diffuse, //散射光最终强度 inout vec4 specular, //镜面光最终强度 in vec3 lightLocation, //光源位置 in vec4 lightAmbient, //环境光强度 in vec4 lightDiffuse, //散射光强度 in vec4 lightSpecular //镜面光强度 ){ ambient=lightAmbient; //直接得出环境光的最终强度 vec3 normalTarget=aPosition+normal; //计算变换后的法向量 vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz; newNormal=normalize(newNormal); //对法向量规格化 //计算从表面点到摄像机的向量 vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz); //计算从表面点到光源位置的向量vp vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz); vp=normalize(vp);//格式化vp vec3 halfVector=normalize(vp+eye); //求视线与光线的半向量 float shininess=50.0; //粗糙度,越小越光滑 float nDotViewPosition=max(0.0,dot(newNormal,vp)); //求法向量与vp的点积与0的最大值 diffuse=lightDiffuse*nDotViewPosition; //计算散射光的最终强度 float nDotViewHalfVector=dot(newNormal,halfVector); //法线与半向量的点积 float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess)); //镜面反射光强度因子 specular=lightSpecular*powerFactor; //计算镜面光的最终强度 } void main() { gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置 vec4 ambientTemp, diffuseTemp, specularTemp; //存放环境光、散射光、镜面反射光的临时变量 pointLight(normalize(aNormal),ambientTemp,diffuseTemp,specularTemp,uLightLocation, vec4(0.8,0.8,0.8,1.0),vec4(0.8,0.8,0.8,1.0),vec4(1.0,1.0,1.0,1.0)); vAmbient=ambientTemp; vDiffuse=diffuseTemp; vSpecular=specularTemp; vTextureCoord = aTexCoor;//将接收的纹理坐标传递给片元着色器 }
三、片源着色器:
<span style="font-family: Arial; font-size: 14px; line-height: 26px;"><span style="font-family: Arial; font-size: 14px; line-height: 26px;"></span></span><pre name="code" class="cpp">precision mediump float; uniform sampler2D sTexture;//纹理内容数据 //接收从顶点着色器过来的参数 varying vec4 vAmbient; varying vec4 vDiffuse; varying vec4 vSpecular; varying vec2 vTextureCoord; void main() { //将计算出的颜色给此片元 vec4 finalColor=texture2D(sTexture, vTextureCoord); //给此片元颜色值 gl_FragColor = finalColor*vAmbient+finalColor*vSpecular+finalColor*vDiffuse; }