Я тестирую рисование текстурированного спрайта с помощью opengl es 2.0.на андроид.Демо отлично работает, когда я устанавливаю ортопроекцию от - scr_w / 2 до + scr_w / 2 и от - scr_h / до + scr_h / 2 с началом координат в середине экрана.
Однако, если я перевожу на то, что ожидаю: 480ширина (scr_w) и 720 (scr_h) высота системы координат + начало координат в верхнем левом углу экрана.тогда рендеринг текстуры идет не так.
Matrix.orthoM(mProjectionMatrix, 0, 0, scr_w,0, scr_h, -1, 1); //then texture rendering doesn't work ?
Я попытался установить Matrix.setLookAtM по-другому, чтобы указать от (240 360,5) до (240 360,0)
//Matrix.setLookAtM(mViewMatrix, 0, scr_w/2, scr_h/2, 5, scr_w/2, scr_h/2, 0f, 0f, 1.0f, 0.0f); // then texture rendering doesn't work ?
Класс Renderer:
public class SimpleRenderer implements GLSurfaceView.Renderer{
private final Context ctx;
static int scr_w = 480;
static int scr_h = 720;
private final float[] mViewMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mMVPMatrix = new float[16];
private Sprite spt1;
SimpleRenderer(final Context context)
{
this.ctx = context;
}
public void onSurfaceCreated(GL10 unused, EGLConfig config)
{
//Set the background color
GLES20.glClearColor(0.0f, 0.0f, 2.0f, 1.0f);
//Disable depth test
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
// Set alpha blend on
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
spt1 = new Sprite(ctx);
}
public void onSurfaceChanged(GL10 unused, int width, int height)
{
GLES20.glViewport(0, 0, width, height);
Matrix.orthoM(mProjectionMatrix, 0, -scr_w/2, scr_w/2,-scr_h/2, scr_h/2, -1, 1);
// Matrix.orthoM(mProjectionMatrix, 0, 0, scr_w,0, scr_h, -1, 1); // DOESNT WORK ?
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0, 0, 0f, 0f, 1.0f, 0.0f);
//Matrix.setLookAtM(mViewMatrix, 0, scr_w/2, scr_h/2, 5, scr_w/2, scr_h/2, 0f, 0f, 1.0f, 0.0f); // DOESN'T WORK
// Mix the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
}
public void onDrawFrame(GL10 unused)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
spt1.Draw(mMVPMatrix);
}}
Может ли класс Sprite связываться с шейдером или фрагментом в 2D-координатах?
public class Sprite
{
//Reference to Activity Context
private final Context mActivityContext;
//Added for Textures
private final FloatBuffer mCubeTextureCoordinates;
private int mTextureUniformHandle;
private int mTextureCoordinateHandle;
private final int mTextureCoordinateDataSize = 2;
private int mTextureDataHandle;
private final String vertexShaderCode =
"attribute vec2 a_TexCoordinate; \n" +
"varying vec2 v_TexCoordinate; \n" +
"uniform mat4 uMVPMatrix; \n" +
"attribute vec4 vPosition; \n" +
"void main() { \n" +
" gl_Position = vPosition * uMVPMatrix; \n" +
" v_TexCoordinate = a_TexCoordinate; \n" +
"} \n";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"uniform sampler2D u_Texture;" +
"varying vec2 v_TexCoordinate;" +
"void main() {" +
"gl_FragColor = (vColor * texture2D(u_Texture, v_TexCoordinate));" +
"}";
private final int shaderProgram;
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 2;
static float spriteCoords[] = {
-50f, 50f, // top left
-50f, -50f, // bottom left
50f, -50f, // bottom right
50f, 50f //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[] = { 1f, 1f, 1f, 1.0f };
public Sprite(final Context activityContext)
{
mActivityContext = activityContext;
//Initialize Vertex Byte Buffer
ByteBuffer bb = ByteBuffer.allocateDirect(spriteCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(spriteCoords);
vertexBuffer.position(0);
final float[] TextureCoordinate =
{
1f, 0f,
1f, 1f,
0f, 1f,
0f, 0f
};
mCubeTextureCoordinates = ByteBuffer.allocateDirect(TextureCoordinate.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
mCubeTextureCoordinates.put(TextureCoordinate).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 = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
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.cathead);
}
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);
GLES20.glEnable(GLES20.GL_BLEND_COLOR);
GLES20.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLES20.glDepthMask(false);
//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];
}
public static int loadShader(int type, String shaderCode)
{
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}