使用 Java 或 C# 在 Y 轴上打开 GL Translation
Open GL Translation on Y axis using Java or C#
我是 OpenGL 的新手,我有一个创建到我的 surfaceView 的三角形,它依次显示在我的屏幕上。我已经能够添加 Rotation 来使我的 Triangle 旋转,但这不是我需要的。我一直在仔细研究 OpenGL,阅读了 Transformation,然后阅读了 Translation,我认为这对于向我的三角形添加垂直移动是正确的,但是根据我目前的理解,我无法实现这一点。
示例:
三角形在屏幕顶部创建,并沿 Y 轴向下移动到屏幕底部。
这个翻译是有角度的,但它表达了我的意思,我只想在 y 轴上移动。
我有一个渲染如下:
public class MyGLRenderer implements GLSurfaceView.Renderer {
//Project Matrix
private float mMatrix[] = new float[16];
private Triangle mTriangle;
private final float[] mMVPMatrix = new float[16];
private final float[] mModelMatrix = new float[16];
private float[] mTempMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
// Called once to set up the view's opengl es environment
public void onSurfaceCreated(GL10 unused, EGLConfig config){
//Set the background frame color
GLES30.glClearColor(208.0f,208.0f,208.0f,1.0f);
mTriangle= new Triangle();
}
// Called for each redraw of the view
public void onDrawFrame(GL10 gl){
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//Redraw background color
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
// Apply transformation, start with translation
Matrix.setIdentityM(mModelMatrix, 0); // initialize to identity matrix
Matrix.translateM(mModelMatrix, 0, -0.5f, 0, 0); // translation to the left
// Create a rotation transformation for the triangle
long time = SystemClock.uptimeMillis() % 4000L;
float mAngle = 0.090f * ((int) time);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
Matrix.orthoM(mMatrix, 0, -1, 1, -1, 1, -1, 1);
// Combine Rotation and Translation matrices
mTempMatrix = mModelMatrix.clone();
Matrix.multiplyMM(mModelMatrix, 0, mTempMatrix, 0, mRotationMatrix, 0);
// Combine the model matrix with the projection and camera view
mTempMatrix = mMVPMatrix.clone();
Matrix.multiplyMM(mMVPMatrix, 0, mTempMatrix, 0, mModelMatrix, 0);
mTriangle.draw(mMatrix);
}
// Called if the geometry of the view changes (example is when the screen orientation changes from landscape to portrait
public void onSurfaceChanged(GL10 unused, int width, int height){
// Called if the geometry of the viewport changes
GLES30.glViewport(0, 0, width, height);
}
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES30.GL_VERTEX_SHADER)
// or a fragment shader type (GLES30.GL_FRAGMENT_SHADER)
int shader = GLES30.glCreateShader(type);
// add the source code to the shader and compile it
GLES30.glShaderSource(shader, shaderCode);
GLES30.glCompileShader(shader);
return shader;
}
}
我有一个三角形如下:
public class Triangle {
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private final FloatBuffer vertexBuffer;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = {
// in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f };
/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
// prepare shaders and OpenGL program
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables
}
/**
* Encapsulates the OpenGL ES instructions for drawing this shape.
*
* @param mvpMatrix - The Model View Project matrix in which to draw
* this shape.
*/
public void draw(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "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(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
我的表面视图如下:
public class MyGLSurfaceView extends GLSurfaceView {
private final MyGLRenderer mRenderer;
public MyGLSurfaceView(Context context, AttributeSet attrs){
super(context, attrs);
//Create an OpenGl 3.0 context
setEGLContextClientVersion(3);
mRenderer = new MyGLRenderer();
//Set the Renderer for drawing on the GLSurfaceView
setRenderer(mRenderer);
}
}
我正在寻找可以完成在 y 轴上移动绘制的三角形的基本框架 example/answer/URL(我假设使用平移)。
我已阅读并尝试实现以下链接(超出我目前的理解)。
- http://www.swiftless.com/tutorials/opengl/rotation.html
- http://www.songho.ca/opengl/gl_transform.html
- https://open.gl/transformations
- http://www.informit.com/articles/article.aspx?p=2111395&seqNum=3
- http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/
以及其他一些资源,但这些似乎是我找到的最好的资源。
是的,这将是一个翻译。很简单,只需要在Triangle
.
的draw()
方法中修改mvpMatrix
即可
但是,重要的是要跟踪三角形的位置以使其移动。您可以将私有成员添加到 class,类似于:
private Point mPosition;
请记住,该代码中的 Point
是一个简单的 point/vector class 我假设你有,因为我很确定这是在 android 上?查看 this class.
然后,您需要在每一帧中增加三角形的 y 位置。您可以在 draw()
中执行此操作,但我会添加另一种移动方法。
mPosition.y += 0.01;
注意:我看到你有一个 MVP 矩阵作为 draw
的参数。现在,因为这是 2D 和正交的,所以它不是那么重要,但是考虑将你的旋转从 onDrawFrame()
函数移动到 Triangle.draw()
,因为 M 代表模型,通常是每个 model/triangle。通常,您只会将 VP(视图和投影)传递给 Triangle.draw()
方法。检查 this。
最后,您将通过三角形的位置平移 Triangle.draw()
方法中的 mvp 矩阵。因此,在将矩阵传递给着色器之前(GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
之前),对其进行翻译:
Matrix.translateM(mvpMatrix, mPosition.x, mPosition.y);
// Or whatever translate method you have, I am not sure
我是 OpenGL 的新手,我有一个创建到我的 surfaceView 的三角形,它依次显示在我的屏幕上。我已经能够添加 Rotation 来使我的 Triangle 旋转,但这不是我需要的。我一直在仔细研究 OpenGL,阅读了 Transformation,然后阅读了 Translation,我认为这对于向我的三角形添加垂直移动是正确的,但是根据我目前的理解,我无法实现这一点。
示例:
三角形在屏幕顶部创建,并沿 Y 轴向下移动到屏幕底部。
这个翻译是有角度的,但它表达了我的意思,我只想在 y 轴上移动。
我有一个渲染如下:
public class MyGLRenderer implements GLSurfaceView.Renderer {
//Project Matrix
private float mMatrix[] = new float[16];
private Triangle mTriangle;
private final float[] mMVPMatrix = new float[16];
private final float[] mModelMatrix = new float[16];
private float[] mTempMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
// Called once to set up the view's opengl es environment
public void onSurfaceCreated(GL10 unused, EGLConfig config){
//Set the background frame color
GLES30.glClearColor(208.0f,208.0f,208.0f,1.0f);
mTriangle= new Triangle();
}
// Called for each redraw of the view
public void onDrawFrame(GL10 gl){
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//Redraw background color
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
// Apply transformation, start with translation
Matrix.setIdentityM(mModelMatrix, 0); // initialize to identity matrix
Matrix.translateM(mModelMatrix, 0, -0.5f, 0, 0); // translation to the left
// Create a rotation transformation for the triangle
long time = SystemClock.uptimeMillis() % 4000L;
float mAngle = 0.090f * ((int) time);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
Matrix.orthoM(mMatrix, 0, -1, 1, -1, 1, -1, 1);
// Combine Rotation and Translation matrices
mTempMatrix = mModelMatrix.clone();
Matrix.multiplyMM(mModelMatrix, 0, mTempMatrix, 0, mRotationMatrix, 0);
// Combine the model matrix with the projection and camera view
mTempMatrix = mMVPMatrix.clone();
Matrix.multiplyMM(mMVPMatrix, 0, mTempMatrix, 0, mModelMatrix, 0);
mTriangle.draw(mMatrix);
}
// Called if the geometry of the view changes (example is when the screen orientation changes from landscape to portrait
public void onSurfaceChanged(GL10 unused, int width, int height){
// Called if the geometry of the viewport changes
GLES30.glViewport(0, 0, width, height);
}
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES30.GL_VERTEX_SHADER)
// or a fragment shader type (GLES30.GL_FRAGMENT_SHADER)
int shader = GLES30.glCreateShader(type);
// add the source code to the shader and compile it
GLES30.glShaderSource(shader, shaderCode);
GLES30.glCompileShader(shader);
return shader;
}
}
我有一个三角形如下:
public class Triangle {
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private final FloatBuffer vertexBuffer;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = {
// in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f };
/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
// prepare shaders and OpenGL program
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables
}
/**
* Encapsulates the OpenGL ES instructions for drawing this shape.
*
* @param mvpMatrix - The Model View Project matrix in which to draw
* this shape.
*/
public void draw(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "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(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
我的表面视图如下:
public class MyGLSurfaceView extends GLSurfaceView {
private final MyGLRenderer mRenderer;
public MyGLSurfaceView(Context context, AttributeSet attrs){
super(context, attrs);
//Create an OpenGl 3.0 context
setEGLContextClientVersion(3);
mRenderer = new MyGLRenderer();
//Set the Renderer for drawing on the GLSurfaceView
setRenderer(mRenderer);
}
}
我正在寻找可以完成在 y 轴上移动绘制的三角形的基本框架 example/answer/URL(我假设使用平移)。
我已阅读并尝试实现以下链接(超出我目前的理解)。
- http://www.swiftless.com/tutorials/opengl/rotation.html
- http://www.songho.ca/opengl/gl_transform.html
- https://open.gl/transformations
- http://www.informit.com/articles/article.aspx?p=2111395&seqNum=3
- http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/
以及其他一些资源,但这些似乎是我找到的最好的资源。
是的,这将是一个翻译。很简单,只需要在Triangle
.
draw()
方法中修改mvpMatrix
即可
但是,重要的是要跟踪三角形的位置以使其移动。您可以将私有成员添加到 class,类似于:
private Point mPosition;
请记住,该代码中的 Point
是一个简单的 point/vector class 我假设你有,因为我很确定这是在 android 上?查看 this class.
然后,您需要在每一帧中增加三角形的 y 位置。您可以在 draw()
中执行此操作,但我会添加另一种移动方法。
mPosition.y += 0.01;
注意:我看到你有一个 MVP 矩阵作为 draw
的参数。现在,因为这是 2D 和正交的,所以它不是那么重要,但是考虑将你的旋转从 onDrawFrame()
函数移动到 Triangle.draw()
,因为 M 代表模型,通常是每个 model/triangle。通常,您只会将 VP(视图和投影)传递给 Triangle.draw()
方法。检查 this。
最后,您将通过三角形的位置平移 Triangle.draw()
方法中的 mvp 矩阵。因此,在将矩阵传递给着色器之前(GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
之前),对其进行翻译:
Matrix.translateM(mvpMatrix, mPosition.x, mPosition.y);
// Or whatever translate method you have, I am not sure