编辑6 - 完成与评论/正在进行的研究相关的重写
编辑7 - 添加投影/视图矩阵.....
由于我没有达到这个目的,我在Google演示中添加了视图/投影矩阵 - 请参阅下面的代码:如果有人能够指出我出错的地方,我真的很感激,因为我是当我把“”gl_position = a_position * uMVPMatrix;“+放到我的顶点着色器中时(”gl_position = a_position;“+我的四边形至少显示.......)
在班级宣布:(四级)
private final float[] rotationMat = new float[16];
private FloatBuffer flotRotBuf;
ByteBuffer rotBuf;
private int muRotationHandle = -1; // Handle to the rotation matrix in the vertex shader called "uRotate"
在类杠杆上声明:(渲染器类)
private final float[] mVMatrix = new float[16];
private final float[] mProjMatrix = new float[16];
private final float[] mMVPMatrix = new float[16];
设置纹理和做(或应该做)旋转的例程(这是我的Quad类
public void setTexture(GLSurfaceView view, Bitmap imgTexture, float[] mvpMatrix){
this.imgTexture=imgTexture;
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(iProgId, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Matrix.setRotateM(rotationMat, 0, 45f, 0, 0, 1.0f); //Set rotation matrix with angle and (z) axis
// rotBuf = ByteBuffer.allocateDirect(rotationMat.length * 4);
// use the device hardware's native byte order
// rotBuf.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
// flotRotBuf = rotBuf.asFloatBuffer();
// add the coordinates to the FloatBuffer
// flotRotBuf.put(rotationMat);
// set the buffer to read the first coordinate
// flotRotBuf.position(0);
// muRotationHandle = GLES20.glGetUniformLocation(iProgId, "uRotation"); // grab the variable from the shader
// GLES20.glUniformMatrix4fv(muRotationHandle, 1, false, flotRotBuf); //Pass floatbuffer contraining rotation matrix info into vertex shader
//GLES20.glUniformMatrix4fv(muRotationHandle, 1, false, rotationMat, 1); //Also tried this ,not use floatbuffer
//Vertex shader
String strVShader =
// "uniform mat4 uRotation;" +
"uniform mat4 uMVPMatrix;" +
"attribute vec4 a_position;\n"+
"attribute vec2 a_texCoords;" +
"varying vec2 v_texCoords;" +
"void main()\n" +
"{\n" +
"gl_Position = a_Position * uMVPMatrix;"+ //This is where it all goes wrong....
"v_texCoords = a_texCoords;" +
"}";
//Fragment shader
String strFShader =
"precision mediump float;" +
"varying vec2 v_texCoords;" +
"uniform sampler2D u_baseMap;" +
"void main()" +
"{" +
"gl_FragColor = texture2D(u_baseMap, v_texCoords);" +
"}";
iProgId = Utils.LoadProgram(strVShader, strFShader);
iBaseMap = GLES20.glGetUniformLocation(iProgId, "u_baseMap");
iPosition = GLES20.glGetAttribLocation(iProgId, "a_position");
iTexCoords = GLES20.glGetAttribLocation(iProgId, "a_texCoords");
texID = Utils.LoadTexture(view, imgTexture);
}
来自我的渲染器类:
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
//Set viewport size based on screen dimensions
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
//Paint the screen the colour defined in onSurfaceCreated
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
quad1.setTexture(curView, myBitmap, mMVPMatrix); //SetTexture now modified to take a float array (See above) - Note I know it's not a good idea to have this in my onDrawFrame method - will move it once I have it working!
quad1.drawBackground();
}
我现在已经删除了所有旋转相关的东西,现在我只是试图在顶点着色器中应用uMVPMatrix后显示静态四边形。但仍然没有: - (
如果我只是将该行更改回“默认”:
"gl_Position = a_position;\n"+
然后我至少显示我的纹理四边形(显然没有旋转,我希望如此)。
另外要指出的是,mvpMatrix绝对被完整地接收到setTexture方法中是有效的(包含与我从Google开发人员代码中记录mvpMatrix内容时出现的相同数据)。我不确定如何检查着色器是否完好无损?我没有理由相信它不是。
真的很感激和所有的帮助 - 我必须在某个地方出错,但我无法发现它。谢谢!
编辑2 :在为这个问题添加了赏金之后,我想知道如何旋转我的纹理四元精灵(2D),保持我必须将其渲染为基础的代码。 (即,为了旋转我需要添加什么以及为什么)。谢谢!
编辑3 N / A
编辑4 重写/简化问题
编辑5 添加了错误屏幕截图
答案 0 :(得分:0)
围绕z旋转的旋转矩阵:
cos a -sin a 0
sin a cos a 0
0 0 1
如何记住如何构建它:
a是以弧度表示的角度,对于a = 0,矩阵产生单位矩阵。 cos必须在对角线上。在一个罪恶面前必须有一个符号,切换符号反转旋转的方向。
同样可以构建围绕x和y的旋转:
1 0 0
0 cos a sin a
0 -sin a cos a
cos a 0 sin a
0 1 0
-sin a 0 cos a
如果你不熟悉矩阵运算,这里有一些代码:
for (int i=0; i<4; i++) {
vertices_new[i*5+0] = cos(a) * vertices[i*5+0] - sin(a) * vertices[i*5+1]; // cos(a) * v[i].x - sin(a) * v[i].y + 0 * v[i].z
vertices_new[i*5+1] = sin(a) * vertices[i*5+0] + cos(a) * vertices[i*5+1]; // sin(a) * v[i].x + cos(a) * v[i].y + 0 * v[i].z
vertices_new[i*5+2] = vertices[i*5+2]; // 0 * v[i].x + 0 * v[i].y + 1 * v[i].z
vertices_new[i*5+3] = vertices[i*5+3]; // copy texture u
vertices_new[i*5+4] = vertices[i*5+4]; // copy texture v
}
答案 1 :(得分:0)
编辑:已编辑为使用Android SDK支持Java。
正如Tobias指出的那样,OpenGL中任何顶点变换的惯用解决方案都是通过矩阵运算来实现的。如果您计划继续使用OpenGL进行开发,那么您(最终)理解矩阵运算中涉及的基础线性代数非常重要,但通常最好利用数学库将线性代数计算抽象为更易读的格式。在android环境下,你应该使用[matrix] [1]类操作float数组来创建一个这样的旋转矩阵:
// initialize rotation matrix
float[16] rotationMat;
Matrix.setIdentityM(rotationMat,0);
// angle in degrees to rotate
float angle = 90;
// axis to rotate about (z axis in your case)
float[3] axis = { 0.0,0.0,1.0};
// For your case, rotate angle (in degrees) about the z axis.
Matrix.rotateM(rotationMat,0,angle,axis[0],axis[1],axis[2]);
然后你可以将旋转矩阵绑定到这样的着色器程序:
// assuming shader program is currently bound ...
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(shaderProgramID, "uRotation"), 1, GL_FALSE, rotationMat);
你的顶点着色器(传递的程序rotationMat
)看起来像:
precision mediump float;
uniform mat4 uMVPMatrix;
uniform mat4 uRotation;
attribute vec2 a_texCoords;
attribute vec3 a_position;
varying v_texCoord;
void main(void)
{
v_texCoord = a_texCoords;
gl_Position = uMVPMatrix* uRotation * vec4(a_position,1.0f);
}
或者,您可以在此着色器程序之外预乘uMVPMatrix* uRotation
并将结果传递给着色器程序,以避免过多的重复计算。
一旦您习惯使用此更高级别的API进行矩阵运算,您可以通过阅读this撰写的Nicol Bolas精彩教程来研究内部操作的执行方式。