我终于在Android上使用OpenGL ES 2.0绘制了一些几何图形,当我绘制一个正方形时,它最终看起来像一个矩形。
在3D中,您可以计算投影矩阵的纵横比,但我只是在进行2D绘图,所以我需要设置一些不具有“拉伸”几何体的东西吗?
由于
矩形:
public Rectangle(float width, float height) {
_width = width;
_height = height;
float halfWidth = _width * 0.5f;
float halfHeight = _height * 0.5f;
float[] vertices = new float[] {
-halfWidth, halfHeight, 0.0f, 0.0f, 0.0f,
-halfWidth, -halfHeight, 0.0f, 0.0f, 1.0f,
halfWidth, -halfHeight, 0.0f, 1.0f, 1.0f,
halfWidth, halfHeight, 0.0f, 1.0f, 0.0f
};
_vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
_vertexBuffer.put(vertices).position(0);
short[] indices = new short[] {
0, 1, 2, 0, 2, 3
};
_indexBuffer = ByteBuffer.allocateDirect(indices.length * 2)
.order(ByteOrder.nativeOrder())
.asShortBuffer();
_indexBuffer.put(indices).position(0);
}
public void draw(Shader shader, Vector2 pos, Texture2D texture)
{
int shaderId = shader.getProgramId();
int vertexPosId = GLES20.glGetAttribLocation(shaderId, "vPosition");
int texCoordId = GLES20.glGetAttribLocation(shaderId, "vTexCoord");
int textureLoc = GLES20.glGetUniformLocation(shaderId, "texture");
int positionId = GLES20.glGetUniformLocation(shaderId, "mPosition");
_vertexBuffer.position(0);
GLES20.glVertexAttribPointer(vertexPosId, 3, GLES20.GL_FLOAT, false, 5 * 4, _vertexBuffer);
_vertexBuffer.position(3);
GLES20.glVertexAttribPointer(texCoordId, 2, GLES20.GL_FLOAT, false, 5 * 4, _vertexBuffer);
GLES20.glEnableVertexAttribArray(vertexPosId);
GLES20.glEnableVertexAttribArray(texCoordId);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
texture.bind();
GLES20.glUniform1i(textureLoc, 0);
GLES20.glUniform2fv(positionId, 1, pos.getArray(), 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, _indexBuffer);
GLES20.glDisableVertexAttribArray(vertexPosId);
GLES20.glDisableVertexAttribArray(texCoordId);
}
GLRenderer:
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
_shader = Shader.createShaderProgram(Shader.VERT_2D_TEX, Shader.FRAG_TEX);
_rect = new Rectangle(1.0f, 1.0f);
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
public void onDrawFrame(GL10 unused) {
GLES20.glViewport(0, 0, _width, _height);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
_rect.draw(_shader, _pos, _texture);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
_width = width;
_height = height;
}
顶点着色器:
public static final String VERT_2D_TEX =
"uniform vec3 mPosition;" +
"attribute vec3 vPosition;" +
"attribute vec2 vTexCoord;" +
"varying vec2 uv;" +
"void main()" +
"{" +
" uv = vTexCoord;" +
" gl_Position = vec4(mPosition + vPosition, 1.0);" +
"}";
答案 0 :(得分:4)
该方面与3D与2D无关。目前,您不使用任何trasnformation矩阵,而只是通过添加一些位置向量来转换顶点。由于您使用1作为w组件,因此剪辑空间与规范化设备空间不同。因此,square [-1,1] x [-1,1]将映射到您的窗口。如果窗口不是方形,则输入坐标中的方形将最终为矩形。您应该更正顶点转换阶段中的方面。通常,人们使用某种正交投影矩阵来校正该方面。但这里不需要完整的矩阵。您需要做的就是将方面作为一个均匀的方向转发到顶点着色器,并使用它沿x(或y)缩放。
答案 1 :(得分:0)
Here是一个关于OpenGL ES 2.0和Android入门的精彩教程。阅读关于矩阵的说明,并记下如何在顶点着色器中使用模型,视图和投影矩阵。