openGL es2.0 创建纹理灯光球
一、Java代码:
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;
}
}
二、顶点着色器:
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;//将接收的纹理坐标传递给片元着色器
}
三、片源着色器:
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;
}
还没有评论,来说两句吧...