我对opengl es很新。现在我正试图制作一个简单的场景,不同大小的矩形正在倒下并绕着自己的轴旋转。
(我想要的插图)
我为它创建了矩形类,着色器助手,还创建了一个简单的顶点和片段着色器(只是通过vec4着色,没有什么特别的,我不会发布代码)。
嗯,所有这些东西都是这样的:
矩形对象
public class RectObject{
private static final int POSITION_COMPONENT_COUNT = 2;
private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
private static final int STRIDE = (POSITION_COMPONENT_COUNT
+ TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT;
private final VertexArray vertexArray;
public RectObject(float x, float y, float size){
float[] newCoordinates = {
x, y, 0.5f, 0.5f,
(x-size), (y-size),0f, 1.0f,
(x+size), (y-size),1f, 1.0f,
(size + x), (size + y),1f, 0.1f,
(x-size), (size + y),0f, 0.1f,
(x-size), (y-size), - 0f, 1.0f
};
vertexArray = new VertexArray(newCoordinates);
}
public void bindData(RectShaderProgram textureProgram) {
vertexArray.setVertexAttribPointer(
0,
textureProgram.getPositionAttributeLocation(),
POSITION_COMPONENT_COUNT,
STRIDE);
}
public void draw(RectShaderProgram shader, float velocity) {
glUniform4f(shader.getMoveLocation(), 0.0f, velocity, 0.0f, 0.0f);
glUniform1f(shader.getTimerLocation(), (float)(System.nanoTime()/10000000000.0f));
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
}
}
顶点着色器:
attribute vec4 a_Position;
uniform vec4 u_Move;
uniform mat4 u_Matrix;
uniform float timer;
void main()
{
mat4 rotation = mat4(
cos(timer), -sin(timer), 0.0, 0.0,
sin( timer), cos(timer), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
gl_Position = u_Matrix * rotation* ((a_Position /*+ u_Move*/)) ;
}
着色器助手
public class RectShaderProgram extends ShaderProgram{
private final int uMatrixLocation;
private final int uMoveLocation;
private final int TimerLocation;
// Attribute locations
private final int aPositionLocation;
public RectShaderProgram(Context context ) {
super(context, R.raw.rect_vertex_shader,
R.raw.rect_fragment_shader);
// TODO Auto-generated constructor stub
// Retrieve uniform locations for the shader program.
// Retrieve attribute locations for the shader program.
aPositionLocation = glGetAttribLocation(program, A_POSITION);
uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
uMoveLocation= glGetUniformLocation(program, U_MOVE);
TimerLocation = glGetUniformLocation(program, TIMER);
}
public void setUniforms(float[] matrix) {
glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);
}
public int getPositionAttributeLocation() {
return aPositionLocation;
}
public int getMoveLocation() {
return uMoveLocation;
}
public int getTimerLocation() {
return TimerLocation;
}
}
但问题是整个场景都在旋转!
我得到了什么
那么,如何正确地做到这一点? 这是渲染器类
public class ProjectRenderer implements Renderer{
private final float[] projectionMatrix = new float[16];
private final float[] modelMatrix = new float[16];
private int uMatrixLocation;
private Background wall;
//private RectObject myobject, myobject2;
private TextureShaderProgram textureProgram;
private ColorShaderProgram colorProgram;
private RectShaderProgram rectProgram;
private int texture;
private float velocity, time;
private ArrayList<RectObject> rlist = new ArrayList<RectObject>();
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
glClearColor(0.0f,0.0f,0.0f,0.0f);
velocity = 0.1f;
wall = new Background();
//myobject = new RectObject(0.1f,0.1f, 0.1f);
//myobject2 = new RectObject(0.2f,0.4f, 0.1f);
Random rand = new Random();
for (int i = 0; i < 15; i++){
rlist.add(new RectObject( (float)0.2*rand.nextInt(15)-1, (float)0.2*rand.nextInt(15)-1, (float)0.1*rand.nextInt(3)));
}
textureProgram = new TextureShaderProgram(context);
colorProgram = new ColorShaderProgram(context);
rectProgram = new RectShaderProgram(context);
texture = TextureHelper.loadTexture(context, R.drawable.sas);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
glViewport(0, 0, width, height);
// Construct the projection matrix
MatrixHelper.perspectiveM(projectionMatrix,45,(float)width
/(float)height,1f,10f);
// Make the modelMatrix identity matrix
setIdentityM(modelMatrix,0);
// Add offset of 2.5 in direction of z axle
translateM(modelMatrix,0,0f,0f,-2.0f);
// Rotation by 60 degrees in direction of x axle
//rotateM(modelMatrix,0,-60f,1f,0f,0f);
// Projection matrix * model matrix
final float[] temp=new float[16];
multiplyMM(temp,0,projectionMatrix,0,modelMatrix,0);
System.arraycopy(temp,0,projectionMatrix,0,temp.length);
}
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw the table.
textureProgram.useProgram();
textureProgram.setUniforms(projectionMatrix, texture);
wall.bindData(textureProgram);
wall.draw();
velocity = velocity - 0.005f;
rectProgram.useProgram();
rectProgram.setUniforms(projectionMatrix);
for(Iterator<RectObject> i = rlist.iterator(); i.hasNext(); ) {
RectObject item = i.next();
item.bindData(rectProgram);
item.draw(rectProgram, velocity);
}
}
public ProjectRenderer(Context context){
this.context = context;
}
答案 0 :(得分:2)
案例在于您将矩形的坐标存储在世界坐标中。换句话说,您将平移变换应用于顶点并将它们存储为变换。因此,如果具有一个全局原点的单个帧,则表示所有矩形。
旋转矩阵以围绕原点旋转此点的方式变换给定点的坐标。要在空间中围绕任意轴旋转点,需要更复杂的数学运算。因此,通常每个对象用适当的局部帧表示,这允许相对于对象的本地原点执行一些变换(即旋转,缩放)。此本地原点(有时称为轴点)通常位于对象的中心。
任何运动都可以表示为两种不同类型运动的组合:平移运动和旋转运动。任意运动都有无限的分解方式,因此选择最方便的运动是合理的。应该选择局部(固定到对象)框架,考虑到它在全局框架中的原点(枢轴点)位置不会受到旋转变换的影响。
因此,总结以上所有内容,您应该重写 RectObject 的构造函数,如下所示:
public RectObject(float x, float y, float size){
float[] newCoordinates = {
0, 0, 0.5f, 0.5f,
-size, -size, 0f, 1.0f,
size, -size, 1f, 1.0f,
size, size, 1f, 0.1f,
-size, size, 0f, 0.1f,
-size, -size, - 0f, 1.0f
};
vertexArray = new VertexArray(newCoordinates);
}
原点位于矩形的中心(准确地说是方形)。
此外,我建议您不要直接将大小应用于矩形的顶点,而是将其作为均匀参数传递到顶点着色器并应用为缩放变换。因此,您可以为所有矩形使用相同的顶点数组。对于这种情况,顶点的坐标应该构造为单位尺寸矩形。
如何将变换传递给顶点着色器?通常由转换矩阵完成,该转换矩阵作为统一参数传递。该变换矩阵通常是所有中间变换(例如平移,旋转和缩放)的乘法的结果。因此,您的顶点着色器应更改如下:
attribute vec2 a_Position;
uniform mat4 u_Matrix;
void main()
{
gl_Position = u_Matrix * vec4(a_Position, vec2(0.0, 1.0));
}
请注意,您已将 a_Position 属性定义为两个组件向量,因此必须将其用作双组件向量。在上面的着色器中,使用 a_Position 属性构造了一个四分量向量。
另请注意,如果您要使用紫外线坐标,则需要将它们添加到顶点着色器中。
由于投影,平移和旋转矩阵的相乘,您需要计算 u_Matrix 矩阵。构造这些矩阵取决于您使用的数学库。请阅读this,this和this,了解如何执行此操作。
一般而言,对于您的情况,转换矩阵可以按如下方式计算:
Translation Rotation
| | | | | 1 0 0 0 | | cos(alpha) -sin(alpha) 0 0 |
| Transformation | = | Projection | X | 0 1 0 0 | X | sin(alpha) cos(alpha) 0 0 |
| matrix | | matrix | | 0 0 1 0 | | 0 0 1 0 |
| | | | | x y 0 1 | | 0 0 0 1 |
其中: