Android 使用不透明度渲染的 OpenGL ES2 三角形
Android OpenGL ES2 triangles rendered with opacity
我正在从服务器以 [=27=] 格式加载模型,这是我在 Three.js BufferGeometry 中创建的,并将位置和 uv 属性存储在 JSON 文件中,当我将所有内容加载到 openGL ES2 时很好,但是如果视图有纹理,或者如果它有颜色,则在我旋转视图之前不会出现某些面孔,或者如果它有颜色则显示为半透明。
从 Three.js 生成的顶点值和顺序没有任何变化,所以我假设它们的顺序是正确的,所以它应该没有颠倒的面。
这是片段着色器:
precision mediump float;
varying vec4 v_Color;
uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;
void main() {
vec4 tex=texture2D(u_TextureUnit, v_TextureCoordinates);
gl_FragColor=v_Color+tex;
}
和渲染代码:
private static final int BYTES_PER_FLOAT = 4;
// private static final int BYTES_PER_SHORT = 2;
private static final int POSITION_COMPONENT_COUNT = 3;
private static final int COLOR_COMPONENT_COUNT = 4;
private static final int UV_COMPONENT_COUNT = 2;
private static final int ALL_COMPONENT_COUNT = POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT + UV_COMPONENT_COUNT;
private static final int STRIDE = ALL_COMPONENT_COUNT * BYTES_PER_FLOAT;
private VertexArray vertexArray;
private float[] modelMatrix = new float[16];
private final float[] modelViewProjectionMatrix = new float[16];
TextureShaderProgram shaderProgram;
int textureid;
// ShortBuffer indexBuffer;
public Geometry(Context context, JSONObject element) throws JSONException {
/*
* JSONArray indecies = element.getJSONArray("indexes"); short[] indexes
* = new short[indecies.length()]; for (int y = 0; y <
* indecies.length(); y++) { indexes[y] = (short) indecies.getInt(y); }
*/
// indexBuffer = ByteBuffer.allocateDirect(indexes.length *
// BYTES_PER_SHORT).order(ByteOrder.nativeOrder()).asShortBuffer();
// indexBuffer.put(indexes).position(0);
JSONArray vertices = element.getJSONArray("vertices");
JSONArray uvs = element.getJSONArray("uvs");
JSONArray matrix = element.getJSONArray("matrix");
for (int y = 0; y < matrix.length(); y++) {
modelMatrix[y] = (float) matrix.getDouble(y);
}
JSONObject material = element.getJSONObject("material");
int color = Color.parseColor(material.getString("color"));
String bmpString = material.getString("map");
int n = vertices.length() / 3;
float[] data;
data = new float[n * STRIDE];
int k = 0;
for (int i = 0; i < n; i++) {
data[i * ALL_COMPONENT_COUNT] = (float) vertices.getDouble(i * 3);
data[i * ALL_COMPONENT_COUNT + 1] = (float) vertices.getDouble(i * 3 + 1);
data[i * ALL_COMPONENT_COUNT + 2] = (float) vertices.getDouble(i * 3 + 2);
data[i * ALL_COMPONENT_COUNT + 3] = Color.red(color) / 255f;
data[i * ALL_COMPONENT_COUNT + 4] = Color.green(color) / 255f;
data[i * ALL_COMPONENT_COUNT + 5] = Color.blue(color) / 255f;
data[i * ALL_COMPONENT_COUNT + 6] = Color.alpha(color) / 255f;
data[i * ALL_COMPONENT_COUNT + 7] = bmpString.equals("") ? 0f : (float) uvs.getDouble(k);
data[i * ALL_COMPONENT_COUNT + 8] = bmpString.equals("") ? 0f : (float) uvs.getDouble(k + 1);
k += 2;
}
vertexArray = new VertexArray(data);
shaderProgram = new TextureShaderProgram(context, R.raw.texture_vertex_shader, R.raw.texture_fragment_shader);
textureid = bmpString.equals("") ? 0 : TextureHelper.loadTexture(TextureHelper.decodeBase64(bmpString));
}
private void bindData(TextureShaderProgram shaderProgram) {
vertexArray.setVertexAttribPointer(0, shaderProgram.getPositionAttributeLocation(), POSITION_COMPONENT_COUNT, STRIDE);
vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT, shaderProgram.getColorAttributeLocation(), COLOR_COMPONENT_COUNT, STRIDE);
vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT, shaderProgram.getTextureCoordinatesAttributeLocation(), UV_COMPONENT_COUNT, STRIDE);
}
public void draw(float[] projectionMatrix) {
multiplyMM(modelViewProjectionMatrix, 0, projectionMatrix, 0, modelMatrix, 0);
shaderProgram.useProgram();
shaderProgram.setUniforms(modelViewProjectionMatrix, textureid);
bindData(shaderProgram);
glDrawArrays(GL_TRIANGLES, 0, vertexArray.getCapacity() / ALL_COMPONENT_COUNT);
// glDrawElements(GL_TRIANGLES, indexBuffer.capacity(),
// GL_UNSIGNED_SHORT, indexBuffer);
}
顶点数据class:
private final FloatBuffer floatBuffer;
private final int capacity;
public VertexArray(float[] vertexData) {
floatBuffer = ByteBuffer.allocateDirect(vertexData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexData);
capacity = floatBuffer.capacity();
}
public void setVertexAttribPointer(int dataOffset, int attributeLocation, int componentCount, int stride) {
floatBuffer.position(dataOffset);
glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT, false, stride, floatBuffer);
glEnableVertexAttribArray(attributeLocation);
floatBuffer.position(0);
}
public final int getCapacity() {
return capacity;
}
没有设置深度函数,所以OpenGL ES是根据索引数据按照三角形的顺序绘制的。您必须启用深度测试,这将根据来自相机的深度信息对三角形进行排序。
glEnable(GL_DEPTH_TEST);
我正在从服务器以 [=27=] 格式加载模型,这是我在 Three.js BufferGeometry 中创建的,并将位置和 uv 属性存储在 JSON 文件中,当我将所有内容加载到 openGL ES2 时很好,但是如果视图有纹理,或者如果它有颜色,则在我旋转视图之前不会出现某些面孔,或者如果它有颜色则显示为半透明。
从 Three.js 生成的顶点值和顺序没有任何变化,所以我假设它们的顺序是正确的,所以它应该没有颠倒的面。
precision mediump float;
varying vec4 v_Color;
uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;
void main() {
vec4 tex=texture2D(u_TextureUnit, v_TextureCoordinates);
gl_FragColor=v_Color+tex;
}
和渲染代码:
private static final int BYTES_PER_FLOAT = 4;
// private static final int BYTES_PER_SHORT = 2;
private static final int POSITION_COMPONENT_COUNT = 3;
private static final int COLOR_COMPONENT_COUNT = 4;
private static final int UV_COMPONENT_COUNT = 2;
private static final int ALL_COMPONENT_COUNT = POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT + UV_COMPONENT_COUNT;
private static final int STRIDE = ALL_COMPONENT_COUNT * BYTES_PER_FLOAT;
private VertexArray vertexArray;
private float[] modelMatrix = new float[16];
private final float[] modelViewProjectionMatrix = new float[16];
TextureShaderProgram shaderProgram;
int textureid;
// ShortBuffer indexBuffer;
public Geometry(Context context, JSONObject element) throws JSONException {
/*
* JSONArray indecies = element.getJSONArray("indexes"); short[] indexes
* = new short[indecies.length()]; for (int y = 0; y <
* indecies.length(); y++) { indexes[y] = (short) indecies.getInt(y); }
*/
// indexBuffer = ByteBuffer.allocateDirect(indexes.length *
// BYTES_PER_SHORT).order(ByteOrder.nativeOrder()).asShortBuffer();
// indexBuffer.put(indexes).position(0);
JSONArray vertices = element.getJSONArray("vertices");
JSONArray uvs = element.getJSONArray("uvs");
JSONArray matrix = element.getJSONArray("matrix");
for (int y = 0; y < matrix.length(); y++) {
modelMatrix[y] = (float) matrix.getDouble(y);
}
JSONObject material = element.getJSONObject("material");
int color = Color.parseColor(material.getString("color"));
String bmpString = material.getString("map");
int n = vertices.length() / 3;
float[] data;
data = new float[n * STRIDE];
int k = 0;
for (int i = 0; i < n; i++) {
data[i * ALL_COMPONENT_COUNT] = (float) vertices.getDouble(i * 3);
data[i * ALL_COMPONENT_COUNT + 1] = (float) vertices.getDouble(i * 3 + 1);
data[i * ALL_COMPONENT_COUNT + 2] = (float) vertices.getDouble(i * 3 + 2);
data[i * ALL_COMPONENT_COUNT + 3] = Color.red(color) / 255f;
data[i * ALL_COMPONENT_COUNT + 4] = Color.green(color) / 255f;
data[i * ALL_COMPONENT_COUNT + 5] = Color.blue(color) / 255f;
data[i * ALL_COMPONENT_COUNT + 6] = Color.alpha(color) / 255f;
data[i * ALL_COMPONENT_COUNT + 7] = bmpString.equals("") ? 0f : (float) uvs.getDouble(k);
data[i * ALL_COMPONENT_COUNT + 8] = bmpString.equals("") ? 0f : (float) uvs.getDouble(k + 1);
k += 2;
}
vertexArray = new VertexArray(data);
shaderProgram = new TextureShaderProgram(context, R.raw.texture_vertex_shader, R.raw.texture_fragment_shader);
textureid = bmpString.equals("") ? 0 : TextureHelper.loadTexture(TextureHelper.decodeBase64(bmpString));
}
private void bindData(TextureShaderProgram shaderProgram) {
vertexArray.setVertexAttribPointer(0, shaderProgram.getPositionAttributeLocation(), POSITION_COMPONENT_COUNT, STRIDE);
vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT, shaderProgram.getColorAttributeLocation(), COLOR_COMPONENT_COUNT, STRIDE);
vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT, shaderProgram.getTextureCoordinatesAttributeLocation(), UV_COMPONENT_COUNT, STRIDE);
}
public void draw(float[] projectionMatrix) {
multiplyMM(modelViewProjectionMatrix, 0, projectionMatrix, 0, modelMatrix, 0);
shaderProgram.useProgram();
shaderProgram.setUniforms(modelViewProjectionMatrix, textureid);
bindData(shaderProgram);
glDrawArrays(GL_TRIANGLES, 0, vertexArray.getCapacity() / ALL_COMPONENT_COUNT);
// glDrawElements(GL_TRIANGLES, indexBuffer.capacity(),
// GL_UNSIGNED_SHORT, indexBuffer);
}
顶点数据class:
private final FloatBuffer floatBuffer;
private final int capacity;
public VertexArray(float[] vertexData) {
floatBuffer = ByteBuffer.allocateDirect(vertexData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexData);
capacity = floatBuffer.capacity();
}
public void setVertexAttribPointer(int dataOffset, int attributeLocation, int componentCount, int stride) {
floatBuffer.position(dataOffset);
glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT, false, stride, floatBuffer);
glEnableVertexAttribArray(attributeLocation);
floatBuffer.position(0);
}
public final int getCapacity() {
return capacity;
}
没有设置深度函数,所以OpenGL ES是根据索引数据按照三角形的顺序绘制的。您必须启用深度测试,这将根据来自相机的深度信息对三角形进行排序。
glEnable(GL_DEPTH_TEST);