本文共 4870 字,大约阅读时间需要 16 分钟。
在Android OpenGLES2.0(十四)中,我们成功实现了Obj格式3D模型的加载。具体来说,我们加载了一个没有贴图和光照处理的帽子模型,通过手动添加光照来呈现立体效果。对于具有贴图和光照处理的模型,如何实现加载呢?让我们深入探讨一下。
模型加载与之前的实现类似,但这次我们需要同时加载顶点法线和贴图坐标,并将它们传递给着色器。此外,还需要提取并解析mtl文件中的材质信息。解析流程如下:
为了实现上述功能,我们设计了以下类:
public class MtlInfo { public String newmtl; public float[] Ka = new float[3]; // 阴影色 public float[] Kd = new float[3]; // 固有色 public float[] Ks = new float[3]; // 高光色 public float[] Ke = new float[3]; // Ke public float Ns; // shininess public String map_Kd; // 固有纹理贴图 public String map_Ks; // 高光纹理贴图 public String map_Ka; // 阴影纹理贴图 public int illum; // 光照模型}
public class Obj3D { public FloatBuffer vert; public int vertCount; public FloatBuffer vertNorl; public FloatBuffer vertTexture; public MtlInfo mtl; private ArrayListtempVert; private ArrayList tempVertNorl; private ArrayList tempVertTexture; public int textureSMode; public int textureTMode; public void addVert(float d) { if (tempVert == null) { tempVert = new ArrayList<>(); } tempVert.add(d); } public void addVertTexture(float d) { if (tempVertTexture == null) { tempVertTexture = new ArrayList<>(); } tempVertTexture.add(d); } public void addVertNorl(float d) { if (tempVertNorl == null) { tempVertNorl = new ArrayList<>(); } tempVertNorl.add(d); } public void dataLock() { if (tempVert != null) { setVert(tempVert); tempVert.clear(); tempVert = null; } if (tempVertTexture != null) { setVertTexture(tempVertTexture); tempVertTexture.clear(); tempVertTexture = null; } if (tempVertNorl != null) { setVertNorl(tempVertNorl); tempVertNorl.clear(); tempVertNorl = null; } } public void setVert(ArrayList data) { int size = data.size(); ByteBuffer buffer = ByteBuffer.allocateDirect(size * 4); buffer.order(ByteOrder.nativeOrder()); vert = buffer.asFloatBuffer(); for (int i = 0; i < size; i++) { vert.put(data.get(i)); } vert.position(0); vertCount = size / 3; } public void setVertNorl(ArrayList data) { int size = data.size(); ByteBuffer buffer = ByteBuffer.allocateDirect(size * 4); buffer.order(ByteOrder.nativeOrder()); vertNorl = buffer.asFloatBuffer(); for (int i = 0; i < size; i++) { vertNorl.put(data.get(i)); } vertNorl.position(0); } public void setVertTexture(ArrayList data) { int size = data.size(); ByteBuffer buffer = ByteBuffer.allocateDirect(size * 4); buffer.order(ByteOrder.nativeOrder()); vertTexture = buffer.asFloatBuffer(); for (int i = 0; i < size; i++) { vertTexture.put(data.get(i)); } vertTexture.position(0); }}
在顶点着色器中,我们需要传递以下参数到片元着色器:
attribute vec3 vPosition;attribute vec2 vCoord;uniform mat4 vMatrix;uniform vec3 vKa;uniform vec3 vKd;uniform vec3 vKs;varying vec2 textureCoordinate;attribute vec3 vNormal;varying vec4 vDiffuse;varying vec4 vAmbient;varying vec4 vSpecular;void main() { gl_Position = vMatrix * vec4(vPosition, 1); textureCoordinate = vCoord; vec3 lightLocation = vec3(0.0, -200.0, -500.0); vec3 camera = vec3(0, 200.0, 0); float shininess = 10.0; vec3 newNormal = normalize((vMatrix * vec4(vNormal + vPosition, 1)).xyz - (vMatrix * vec4(vPosition, 1)).xyz); vec3 vp = normalize(lightLocation - (vMatrix * vec4(vPosition, 1)).xyz); vDiffuse = vec4(vKd, 1.0) * max(0.0, dot(newNormal, vp)); vec3 eye = normalize(camera - (vMatrix * vec4(vPosition, 1)).xyz); vec3 halfVector = normalize(vp + eye); float nDotViewHalfVector = dot(newNormal, halfVector); float powerFactor = max(0.0, pow(nDotViewHalfVector, shininess)); vSpecular = vec4(vKs, 1.0) * powerFactor; vAmbient = vec4(vKa, 1.0);}
precision mediump float;varying vec2 textureCoordinate;uniform sampler2D vTexture;varying vec4 vDiffuse;varying vec4 vAmbient;varying vec4 vSpecular;void main() { vec4 finalColor = texture2D(vTexture, textureCoordinate); gl_FragColor = finalColor * vAmbient + finalColor * vSpecular + finalColor * vDiffuse;}
在应用程序中,我们可以按照以下步骤进行渲染:
Listmodel = ObjReader.readMultiObj(this, "assets/3dres/pikachu.obj");List filters = new ArrayList<>();for (int i = 0; i < model.size(); i++) { Obj3D obj = model.get(i); obj.dataLock(); // 添加渲染相关逻辑}
通过以上实现,我们成功地将带有贴图和光照处理的Obj格式3D模型加载到Android OpenGLES2.0环境中。整个过程包括Obj文件解析、mtl文件解析、顶点、法线和贴图数据的提取与处理,以及顶点着色器和片元着色器的实现。通过合理的数据传递和光照计算,我们能够实现高质量的3D渲染效果。
转载地址:http://yngs.baihongyu.com/