Java 从像素坐标到opengl坐标
正如我在opengl中看到的,坐标在-1和1之间,我想使用opengl渲染一个对象,我有第一个在像素坐标中渲染对象的位置,但我不知道如何将像素坐标转换为opengl坐标。我正在使用java开发一个android应用程序 公共类FirstOpenGLProjectRenderer实现GLSurfaceView.Renderer{Java 从像素坐标到opengl坐标,java,android,opengl-es,augmented-reality,Java,Android,Opengl Es,Augmented Reality,正如我在opengl中看到的,坐标在-1和1之间,我想使用opengl渲染一个对象,我有第一个在像素坐标中渲染对象的位置,但我不知道如何将像素坐标转换为opengl坐标。我正在使用java开发一个android应用程序 公共类FirstOpenGLProjectRenderer实现GLSurfaceView.Renderer{ private static final String A_POSITION = "a_Position"; private static final String A_
private static final String A_POSITION = "a_Position";
private static final String A_COLOR = "a_Color";
private static final int POSITION_COMPONENT_COUNT = 4;
private static final int COLOR_COMPONENT_COUNT = 3;
private static final int BYTES_PER_FLOAT = 4;
private static final int STRIDE =
(POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;
private final FloatBuffer vertexData;
private final Context context;
private int program;
private int aPositionLocation;
private int aColorLocation;
private static final String U_MATRIX = "u_Matrix";
private final float[] projectionMatrix = new float[16];
private int uMatrixLocation;
private final float[] modelMatrix = new float[16];
public FirstOpenGLProjectRenderer(Context context) {
this.context = context;
//
// Vertex data is stored in the following manner:
//
// The first two numbers are part of the position: X, Y
// The next three numbers are part of the color: R, G, B
//
float[] tableVerticesWithTriangles = {
// Order of coordinates: X, Y, R, G, B
// Triangle Fan
0f, 0f, 0f, 1.5f, 1f, 1f, 1f,
-0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
0.5f, 0.8f, 0f, 2f, 0.7f, 0.7f, 0.7f,
-0.5f, 0.8f, 0f, 2f, 0.7f, 0.7f, 0.7f,
-0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
// Line 1
-0.5f, 0f, 0f, 1.5f, 1f, 0f, 0f,
0.5f, 0f, 0f, 1.5f, 1f, 0f, 0f,
// Mallets
0f, -0.4f, 0f, 1.25f, 0f, 0f, 1f,
0f, 0.4f, 0f, 1.75f, 1f, 0f, 0f
};
vertexData = ByteBuffer
.allocateDirect(tableVerticesWithTriangles.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexData.put(tableVerticesWithTriangles);
}
@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
String vertexShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.imple_vertex_shader);
String fragmentShaderSource = TextResourceReader
.readTextFileFromResource(context, R.raw.simple_fragment_shader);
int vertexShader = ShaderHelper.compileVertexShader(vertexShaderSource);
int fragmentShader = ShaderHelper
.compileFragmentShader(fragmentShaderSource);
program = ShaderHelper.linkProgram(vertexShader, fragmentShader);
if (LoggerConfig.ON) {
ShaderHelper.validateProgram(program);
}
glUseProgram(program);
uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
aColorLocation = glGetAttribLocation(program, A_COLOR);
// Bind our data, specified by the variable vertexData, to the vertex
// attribute at location A_POSITION_LOCATION.
vertexData.position(0);
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
glEnableVertexAttribArray(aPositionLocation);
// Bind our data, specified by the variable vertexData, to the vertex
// attribute at location A_COLOR_LOCATION.
vertexData.position(POSITION_COMPONENT_COUNT);
glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
glEnableVertexAttribArray(aColorLocation);
}
@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
// Set the OpenGL viewport to fill the entire surface.
glViewport(0, 0, width, height);
MatrixHelper.perspectiveM(projectionMatrix, 45, (float) width
/ (float) height, 1f, 10f);
setIdentityM(modelMatrix, 0);
translateM(modelMatrix, 0, 0f, 0f, -2.5f);
rotateM(modelMatrix, 0, -60f, 1f, 0f, 0f);
final float[] temp = new float[16];
multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);
/
}
}首先,如果您只想在屏幕上绘制2D基本体,则不希望应用任何3D模型、视图或投影矩阵(即,使用仅通过未更改位置的着色器,或将这些矩阵设置为标识)。然后,您基本上可以指定要直接在剪辑空间中绘制的对象的坐标。剪辑空间实际上是一个平面,剪辑空间坐标实际上是四维的,但现在你不必担心这个问题。只要将第四个坐标w设置为1,剪辑空间坐标将直接对应于标准化设备坐标,这是您似乎已经熟悉的-1:1坐标系 既然这样,我们如何从像素坐标到标准化设备坐标?我们需要做的是将x和y像素索引的[0..w)和[0..h)范围映射到[-1,1]范围内的位置(其中w和h分别是x和y方向上视口/屏幕的像素数)。这里需要注意的一点是,OpenGL中的像素位置对应于采样网格单元的中心。这意味着像素(0,0)不会落在左下角,而是偏移了“1/2像素”。如果您原谅我的ASCII艺术:
| | | |
+-----+-----+-----+---
| o | o | o |
+-----+-----+-----+---
| o | o | o |
+-----+-----+-----+---
| X | o | o |
+-----+-----+-----+---
(-1, -1)
像素位置之间的距离在x方向为1/w,在y方向为1/h。因此,像素(x,y)在归一化设备坐标中的位置为:
x_ndc = 2.0f * (x + 0.5f) / w - 1.0f;
y_ndc = 2.0f * (y + 0.5f) / h - 1.0f;
要放置在该点的顶点的齐次坐标为
(x\u ndc,y\u ndc,-1.0f,1.0f)
。请注意,z坐标可以是要放置2D元素的任何深度(-1对应于近平面,+1对应于远平面).首先,如果您只想在屏幕上绘制2D基本体,则不希望应用任何3D模型、视图或投影矩阵(即,使用仅通过未更改位置的着色器,或将这些矩阵设置为标识)。然后你基本上可以直接指定要在剪辑空间中绘制的对象的坐标。剪辑空间实际上是a,剪辑空间坐标实际上是四维的,但你现在不必担心这一点。只要你将第四个坐标w设置为1,剪辑空间坐标将直接对应于标准化的设备e坐标,这是你似乎已经熟悉的-1对1坐标系
那么,我们如何从像素坐标到标准化设备坐标呢?我们需要做的是将x和y像素索引的[0..w)和[0..h)范围映射到[-1,1]范围内的位置(其中w和h分别是x和y方向上视口/屏幕的像素数)。这里需要注意的一点是,OpenGL中的像素位置对应于采样网格单元的中心。这意味着像素(0,0)不会落在左下角,而是偏移了“1/2像素”。如果您原谅我的ASCII艺术:
| | | |
+-----+-----+-----+---
| o | o | o |
+-----+-----+-----+---
| o | o | o |
+-----+-----+-----+---
| X | o | o |
+-----+-----+-----+---
(-1, -1)
像素位置之间的距离在x方向为1/w,在y方向为1/h。因此,像素(x,y)在归一化设备坐标中的位置为:
x_ndc = 2.0f * (x + 0.5f) / w - 1.0f;
y_ndc = 2.0f * (y + 0.5f) / h - 1.0f;
要放置在该点的顶点的齐次坐标是
(x\u ndc,y\u ndc,-1.0f,1.0f)
。请注意,z坐标可以是您想要放置2D元素的任何深度(-1对应于近平面,+1对应于远平面)。非常感谢@Michael Kenzel非常感谢@Michael Kenzel