我正在尝试创建一个使用OpenGL显示文本的应用程序.当我尝试使用Matrix.translateM将指定对象移动到特定位置时,我得到了意外的行为.所有其他转换矩阵都像我期望的那样工作.
这是我调用Matrix.translateM(model_matrix,-1.0f,0)时得到的结果:
这是没有翻译的图片:
这是我的渲染器代码.
- @Override
- public void onSurfaceCreated(GL10 unused,EGLConfig config) {
- GLES20.glClearColor(0.5f,0.5f,1.0f);
- GLES20.glDisable(GLES20.GL_DEPTH_TEST);
- GLES20.glEnable(GLES20.GL_BLEND);
- GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA,GLES20.GL_ONE_MINUS_SRC_ALPHA);
- // create programs
- simple_texture = new SimpleTexture();
- // create shapes
- square = new Square();
- // create debug text handlers
- text_fps = new Text(this.font,this.text_scale);
- text_fps.setSize(50);
- text_fps.setText("Test\nLonger line");
- // set camera position
- final float eyeX = 0.0f;
- final float eyeY = 0.0f;
- final float eyeZ = -3.0f;
- final float lookX = 0.0f;
- final float lookY = 0.0f;
- final float lookZ = 0.0f;
- final float upX = 0.0f;
- final float upY = 1.0f;
- final float upZ = 0.0f;
- Matrix.setLookAtM(view_matrix,eyeX,eyeY,eyeZ,lookX,lookY,lookZ,upX,upY,upZ);
- }
- @Override
- public void onSurfaceChanged(GL10 unused,int width,int height) {
- GLES20.glViewport(0,width,height);
- // set projection matrix
- float ratio = (float) width / height;
- Matrix.orthoM(projection_matrix,-ratio,ratio,-1,1,3,7);
- setScreenRatio(ratio);
- setScreenHeight(height);
- }
- @Override
- public void onDrawFrame(GL10 unused) {
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- // calculate projection and view transformation
- Matrix.multiplyMM(vp_matrix,projection_matrix,view_matrix,0);
- // if we are connected to debugger draw statistics
- drawStatistics(vp_matrix);
- }
- // use predefined program
- GLES20.glUseProgram(program);
- // get attribute positions
- attr_matrix = GLES20.glGetUniformLocation(program,"u_Matrix");
- attr_position = GLES20.glGetAttribLocation(program,"a_Position");
- attr_texture_position = GLES20.glGetAttribLocation(program,"a_TexturePosition");
- attr_texture = GLES20.glGetUniformLocation(program,"u_Texture");
- // set program parameters
- GLES20.glEnableVertexAttribArray(attr_position);
- GLES20.glVertexAttribPointer(attr_position,2,GLES20.GL_FLOAT,false,2 * 4,square_buffer);
- // set texture parameters
- GLES20.glEnableVertexAttribArray(attr_texture_position);
- GLES20.glVertexAttribPointer(attr_texture_position,texture_buffer);
- // set matrix
- float[] result = new float[16];
- float ratio = (float) texture_height / texture_width;
- float screen_scale = (float) texture_height / PageRenderer.getScreenHeight();
- Matrix.setIdentityM(model_matrix,0);
- Matrix.translateM(model_matrix,0);
- Matrix.scaleM(model_matrix,screen_scale,screen_scale * ratio,screen_scale);
- Matrix.setIdentityM(result,0);
- Matrix.multiplyMM(result,matrix,model_matrix,0);
- GLES20.glUniformMatrix4fv(attr_matrix,result,0);
- // assign texture
- GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,index);
- GLES20.glUniform1i(attr_texture,0);
- // perform drawing
- GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,4);
- // disable vertex array
- GLES20.glDisableVertexAttribArray(attr_position);
- GLES20.glDisableVertexAttribArray(attr_texture_position);
着色器:
- int vertex_shader = PageRenderer.loadShader(
- GLES20.GL_VERTEX_SHADER,"uniform mat4 u_Matrix;" +
- "attribute vec4 a_Position;" +
- "attribute vec2 a_TexturePosition;" +
- "varying vec2 v_TexturePosition;" +
- "void main() {" +
- " gl_Position = a_Position * u_Matrix;" +
- " v_TexturePosition = a_TexturePosition;" +
- "}"
- );
- int fragment_shader = PageRenderer.loadShader(
- GLES20.GL_FRAGMENT_SHADER,"precision mediump float;" +
- "varying vec2 v_TexturePosition;" +
- "uniform sampler2D u_Texture;" +
- "void main() {" +
- " gl_FragColor = texture2D(u_Texture,v_TexturePosition);" +
- "}"
- );
按预期缩放和旋转工作,但我无法弄清楚为什么翻译不会.
请注意,我最近才使用OpenGL.
我期待translateM将文本移动到左侧,而不是“旋转”它.
解决方法
计算gl_Position时的变量顺序很重要!世界矩阵首先是顶点坐标,然后是顶点坐标.在提问时我确实知道这一点,但由于着色器代码来自Android OpenGL教程,所以没有注意.是有趣的人.教程不正确!
更正着色器代码:
- int vertex_shader = PageRenderer.loadShader(
- GLES20.GL_VERTEX_SHADER,"uniform mat4 u_Matrix;" +
- "attribute vec4 a_Position;" +
- "attribute vec2 a_TexturePosition;" +
- "varying vec2 v_TexturePosition;" +
- "void main() {" +
- " gl_Position = u_Matrix * a_Position;" +
- " v_TexturePosition = a_TexturePosition;" +
- "}"
- );
- int fragment_shader = PageRenderer.loadShader(
- GLES20.GL_FRAGMENT_SHADER,v_TexturePosition);" +
- "}"
- );