我尝试渲染一些2D对象,但我能够做到这一点,但现在我尝试在opengl中渲染一些图像,但它没有显示任何内容。这是我的图像渲染代码。
package com.example.androidinternalmaps;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
public class ImageObject
{
private final Context mActivityContext;
private final FloatBuffer mCubeTextureCoordinates;
private int mTextureUniformHandle;
private int mTextureCoordinateHandle;
private final int mTextureCoordinateDataSize = 2;
private int mTextureDataHandle;
private final String VerShader =
"uniform mat4 u_Matrix;"+
"attribute vec4 a_Position;"+
"attribute vec2 a_TextureCoordinates;"+
"varying vec2 v_TextureCoordinates;"+
"void main()"+
"{"+
"v_TextureCoordinates = a_TextureCoordinates;"+
"gl_Position = u_Matrix * a_Position;"+
"}";
private final String FragShader =
"precision mediump float;"+
"uniform sampler2D u_TextureUnit;"+
"varying vec2 v_TextureCoordinates;"+
"void main()"+
"{"+
"gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);"+
"}";
private final int shaderProgram;
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
static final int COORDS_PER_VERTEX = 2;
static float spriteCoords[] = { -0.5f, 0.5f, // top left
-0.5f, -0.5f, // bottom left
0.5f, -0.5f, // bottom right
0.5f, 0.5f }; //top right
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; //Order to draw vertices
private final int vertexStride = COORDS_PER_VERTEX * 4; //Bytes per vertex
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
public ImageObject(final Context activityContext)
{
mActivityContext = activityContext;
ByteBuffer bb = ByteBuffer.allocateDirect(spriteCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(spriteCoords);
vertexBuffer.position(0);
final float[] cubeTextureCoordinateData =
{
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f
};
mCubeTextureCoordinates = ByteBuffer.allocateDirect(cubeTextureCoordinateData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
mCubeTextureCoordinates.put(cubeTextureCoordinateData).position(0);
//Initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(spriteCoords.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, VerShader);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, FragShader);
shaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(shaderProgram, vertexShader);
GLES20.glAttachShader(shaderProgram, fragmentShader);
//Texture Code
GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate");
GLES20.glLinkProgram(shaderProgram);
//Load the texture
mTextureDataHandle = loadTexture(mActivityContext, R.drawable.air_hockey_surface);
}
public void Draw(float[] mvpMatrix)
{
//Add program to OpenGL ES Environment
GLES20.glUseProgram(shaderProgram);
//Get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
//Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
//Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
//Get Handle to Fragment Shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(shaderProgram, "vColor");
//Set the Color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//Set Texture Handles and bind Texture
mTextureUniformHandle = GLES20.glGetAttribLocation(shaderProgram, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(shaderProgram, "a_TexCoordinate");
//Set the active texture unit to texture unit 0.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
//Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLES20.glUniform1i(mTextureUniformHandle, 0);
//Pass in the texture coordinate information
mCubeTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
//Get Handle to Shape's Transformation Matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
//Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
//Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
//Disable Vertex Array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
public static int loadTexture(final Context context, final int resourceId)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
}
没有显示任何内容。只是空白屏幕。我不知道我做错了什么。需要帮忙。谢谢。
我的渲染器类
package com.example.androidinternalmaps;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
public class MyGLRenderer implements GLSurfaceView.Renderer {
private FloorPolygon floorPolygon;
private ImageObject imageObject;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
private float originX = 0.0f, originY = 0.0f;
private float translationDx=0.0f,translationDy=0.0f;
private float originScaleX = 2.5f, originScaleY = 2.5f;
private float scaleDx = 1.0f, scaleDy = 1.0f;
private float surfaceViewWidth, surfaceViewHeight;
private Context mContext;
public MyGLRenderer(Context context)
{
mContext = context;
}
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
floorPolygon = new FloorPolygon();
imageObject = new ImageObject(mContext);
}
public void onDrawFrame(GL10 unused)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.translateM(mMVPMatrix, 0, originX+translationDx, originY+translationDy, 0.0f);
Matrix.scaleM(mMVPMatrix, 0, scaleDx*originScaleX, scaleDy*originScaleY, 0.0f);
imageObject.Draw(mMVPMatrix);
}
public void onSurfaceChanged(GL10 unused, int width, int height)
{
surfaceViewHeight = height;
surfaceViewWidth = width;
GLES20.glViewport(0, 0, width, height);
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
public static int loadShader(int type, String shaderCode)
{
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void setTranslationPoints(float translationDx, float translationDy)
{
this.translationDx = ((translationDx/surfaceViewWidth)*2);
this.translationDy = -((translationDy/surfaceViewHeight)*2);
}
public void setScalePoints(float scaleDx, float scaleDy)
{
this.scaleDx = scaleDx;
this.scaleDy = scaleDy;
}
}
答案 0 :(得分:1)
我认为有一个问题是:
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
您的外观向量是(0,0,0),它不描述方向。您的眼睛位置是(0,0,5),表示从原点沿z轴朝向您的位置。所以你的外观矢量需要远离你回到原点。因此,请尝试将外观向量更改为(0,0,-1):
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, -1f, 0f, 1.0f, 0.0f);
编辑:
对于初学者来说,将其移到onSurfaceChanged,因为你不需要在每一帧上调用它,就像表面构造一样:
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0f, 0f, -1f, 0f, 1.0f, 0.0f);
现在为ImageObject类。在顶点着色器中,将“a_TextureCoordinates”更改为“a_TexCoordinate”,以使该名称与您在构造函数代码中使用的名称相匹配。
在构造函数中,进行此更改:
//GLES20.glBindAttribLocation(shaderProgram, 0, "a_TexCoordinate");
GLES20.glBindAttribLocation(shaderProgram, 0, "a_Position");
GLES20.glBindAttribLocation(shaderProgram, 1, "a_TexCoordinate");
在将“a_TexCoordinate”绑定到位置0之前,它应该是位置1,因为它是着色器中的第二个属性。着色器中的第一个属性是“a_Position”,因此应绑定到位置0。
在Draw中,进行以下更改:
//mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "a_Position");
//mTextureUniformHandle = GLES20.glGetAttribLocation(shaderProgram, "u_Texture");
mTextureUniformHandle = GLES20.glGetUniformLocation(shaderProgram, "u_TextureUnit");
//mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "u_Matrix");
这是因为名称与着色器中的名称无法正确匹配。对于纹理处理程序,这是一个Uniform,而不是一个Attribute,因此你需要使用glGetUniformLocation。
我认为应该是这样。我运行了你的代码,我在屏幕上绘制了一个纹理。