Android 更改 OpenGL 坐标系
Android Changing OpenGL Coordinate System
好的,所以我找到了这个 thread,这是我认为我需要做的。但是,我没有使用 GL10
,而是 GLES20
。 glOrthof
不是 GLES20
API.
的一部分
我想要做的是改变坐标系的范围从[-1, 1] 到 [ 0,1]。
这是正常系统。
我想改成这样(下)
屏幕中心0.5f,0.5f,左下角0f,0f等只有2D
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 aPosition;" +
"attribute vec2 aTexCoordinate;" +
"varying vec2 vTexCoordinate;" +
"void main() {" +
" gl_Position = uMVPMatrix * aPosition;" +
" vTexCoordinate = aTexCoordinate;" +
"}";
这是我的渲染器class
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;
import com.matt.world.World;
public class OpenGLRenderer implements GLSurfaceView.Renderer {
private static final String TAG = "OpenGLRenderer"; // Tag for the logcat error message
private final float[] mMVPMatrix = new float[16]; // mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
private final float[] mTranslationMatrix = new float[16];
private World mWorld; // World object
private long mStartTime; // Start time
public volatile float mPlayerInputX; // Variable to receive player coordinate input
public volatile float mPlayerInputY; // Variable to receive player coordinate input
public volatile boolean mFireWeapon = false; // Variable to handle player fire commands
public volatile boolean mToggleShield = false; // Variable to handle player shield toggle
public volatile boolean mToggleLaser = false; // Variable to handle player laser toggle
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Called once when the surface is created
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set the background frame color
GLES20.glEnable(GLES20.GL_TEXTURE_2D); // Enable textures
mWorld = new World(this); // Initialize World object
}
@Override
public void onDrawFrame(GL10 unused) { // Called every frame
float[] scratch = new float[16]; // Container for matrix manipulations
float decimal = 1000000000.0f; // Divisor to move the decimal point for delta time
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | // Draw background color
GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, // Set the camera position (View matrix)
0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, // Calculate the projection and view transformation
0, mProjectionMatrix, 0, mViewMatrix, 0);
float deltaTime = (System.nanoTime()-mStartTime)/decimal; // Calculate delta time
mStartTime = System.nanoTime(); // Get the time now for next frame calculations
mWorld.update(mMVPMatrix, deltaTime); // Update World
mWorld.draw(); // Draw World
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0,0, width, height); // Adjust the viewport based on geometry changes,
float ratio = (float) height / width; // such as screen rotation
Matrix.setIdentityM(mProjectionMatrix, 0); // Set this matrix to the identity matrix
Matrix.frustumM(mProjectionMatrix, // this projection matrix is applied to object coordinates
0,-ratio, ratio, 0, 1, 3, 7); // in the onDrawFrame() method*/
mStartTime = System.nanoTime(); // keep record of what the current time is
}
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type); // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
GLES20.glShaderSource(shader, shaderCode); // add the source code to the shader and
GLES20.glCompileShader(shader); // compile it
return shader;
}
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
}
Ortho
仍然是一种方法,但您需要使用矩阵。因此,在您的着色器中,您将使用矩阵作为统一,然后乘以输入位置。
一般来说,您根本无法更改坐标系。 openGL 使用归一化坐标,所以无论你做什么,缓冲区的中心总是有一个 0,边界从左到右,从下到上为 [-1, 1],使用 depth 时深度也是如此缓冲区。
所以正交矩阵所做的是将您的输入坐标缩放到 openGL 内部坐标系,这是甚至 ES1 所做的过程,但不同之处在于已经为您生成了矩阵并且所有坐标都相乘你在固定管道中。
好的,所以我找到了这个 thread,这是我认为我需要做的。但是,我没有使用 GL10
,而是 GLES20
。 glOrthof
不是 GLES20
API.
我想要做的是改变坐标系的范围从[-1, 1] 到 [ 0,1]。 这是正常系统。
我想改成这样(下)
屏幕中心0.5f,0.5f,左下角0f,0f等只有2D
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 aPosition;" +
"attribute vec2 aTexCoordinate;" +
"varying vec2 vTexCoordinate;" +
"void main() {" +
" gl_Position = uMVPMatrix * aPosition;" +
" vTexCoordinate = aTexCoordinate;" +
"}";
这是我的渲染器class
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;
import com.matt.world.World;
public class OpenGLRenderer implements GLSurfaceView.Renderer {
private static final String TAG = "OpenGLRenderer"; // Tag for the logcat error message
private final float[] mMVPMatrix = new float[16]; // mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
private final float[] mTranslationMatrix = new float[16];
private World mWorld; // World object
private long mStartTime; // Start time
public volatile float mPlayerInputX; // Variable to receive player coordinate input
public volatile float mPlayerInputY; // Variable to receive player coordinate input
public volatile boolean mFireWeapon = false; // Variable to handle player fire commands
public volatile boolean mToggleShield = false; // Variable to handle player shield toggle
public volatile boolean mToggleLaser = false; // Variable to handle player laser toggle
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Called once when the surface is created
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set the background frame color
GLES20.glEnable(GLES20.GL_TEXTURE_2D); // Enable textures
mWorld = new World(this); // Initialize World object
}
@Override
public void onDrawFrame(GL10 unused) { // Called every frame
float[] scratch = new float[16]; // Container for matrix manipulations
float decimal = 1000000000.0f; // Divisor to move the decimal point for delta time
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | // Draw background color
GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, // Set the camera position (View matrix)
0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, // Calculate the projection and view transformation
0, mProjectionMatrix, 0, mViewMatrix, 0);
float deltaTime = (System.nanoTime()-mStartTime)/decimal; // Calculate delta time
mStartTime = System.nanoTime(); // Get the time now for next frame calculations
mWorld.update(mMVPMatrix, deltaTime); // Update World
mWorld.draw(); // Draw World
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0,0, width, height); // Adjust the viewport based on geometry changes,
float ratio = (float) height / width; // such as screen rotation
Matrix.setIdentityM(mProjectionMatrix, 0); // Set this matrix to the identity matrix
Matrix.frustumM(mProjectionMatrix, // this projection matrix is applied to object coordinates
0,-ratio, ratio, 0, 1, 3, 7); // in the onDrawFrame() method*/
mStartTime = System.nanoTime(); // keep record of what the current time is
}
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type); // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
GLES20.glShaderSource(shader, shaderCode); // add the source code to the shader and
GLES20.glCompileShader(shader); // compile it
return shader;
}
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
}
Ortho
仍然是一种方法,但您需要使用矩阵。因此,在您的着色器中,您将使用矩阵作为统一,然后乘以输入位置。
一般来说,您根本无法更改坐标系。 openGL 使用归一化坐标,所以无论你做什么,缓冲区的中心总是有一个 0,边界从左到右,从下到上为 [-1, 1],使用 depth 时深度也是如此缓冲区。
所以正交矩阵所做的是将您的输入坐标缩放到 openGL 内部坐标系,这是甚至 ES1 所做的过程,但不同之处在于已经为您生成了矩阵并且所有坐标都相乘你在固定管道中。