我在OpenGL中绘制一个三角形,如:
MyGLRenderer( )
{
fSampleVertices = ByteBuffer.allocateDirect( fSampleVerticesData.length * 4 )
.order ( ByteOrder.nativeOrder( ) ).asFloatBuffer( );
fSampleVertices.put( fSampleVerticesData ).position ( 0 );
Log.d( TAG, "MyGLRender( )" );
}
private FloatBuffer fSampleVertices;
private final float[] fSampleVerticesData =
{ .8f, .8f, 0.0f, -.8f, .8f, 0.0f, -.8f, -.8f, 0.0f };
public void onDrawFrame( GL10 unused )
{
GLES30.glViewport ( 0, 0, mWidth, mHeight );
GLES30.glClear ( GLES30.GL_COLOR_BUFFER_BIT );
GLES30.glUseProgram ( dProgramObject1 );
GLES30.glVertexAttribPointer ( 0, 3, GLES30.GL_FLOAT, false, 0, fSampleVertices );
GLES30.glEnableVertexAttribArray ( 0 );
GLES30.glDrawArrays( GLES30.GL_TRIANGLES, 0, 3 );
//Log.d( TAG, "onDrawFrame( )" );
}
因为我已经尝试过坐标,所以不需要花很长时间才能弄清楚屏幕的可见区域 介于-1,1之间。那么三角形占据屏幕的80%。我也确定了我的像素尺寸 GLSurfaceView的宽度为2560,高度为1600。
然后给出一个带有这些基于像素的坐标的三角形(fBoardOuter):
1112.0f
800.0f
0.0f
-1280.0f
800.0f
0.0f
-1280.0f
-800.0f
0.0f
我必须将这些像素坐标转换为-1,1之间的某个坐标,或者找出一种方法来转换那些坐标 在他们被吸引的时候?由于我是OpenGL的新手,我正在寻找一些指导来做到这一点?
我的顶点着色器就像:
String sVertexShader1 =
"#version 300 es \n"
+ "in vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vPosition; \n"
+ "} \n";
我会说基于像素的系统会被称为世界坐标吗?我现在想做的只是一些棋盘游戏的2D绘图。
我发现Android具有此功能:
orthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)
然而,到目前为止,我所阅读的文档中没有任何内容可以解释矩阵的用法,该矩阵用于如何将带有像素坐标的float []转换为GLES30中与该矩阵的标准化坐标。
我也在这里找到了文档:
http://developer.android.com/guide/topics/graphics/opengl.html
根据我试图创建示例的文档:
在pastebin示例fSampleVertices中,我认为它会小得多,位于屏幕的中心,但它几乎不是整个屏幕,如果我尝试将fBoardOuter显示为黑屏把它放进glDrawArray。
答案 0 :(得分:1)
您可能需要找一本书或一些好的教程才能掌握其中的一些概念。但是由于你的问题中有一些特定的项目,我会尝试在这种格式下解释它们。
您发现的坐标系在x和y坐标方向上的范围是[-1.0,1.0],正式称为标准化设备坐标,通常缩写为NDC。这与您提出的名称非常相似,因此一些OpenGL术语实际上非常合乎逻辑。 :)
至少只要你处理2D坐标,这就是你的顶点着色器需要产生的坐标范围。即您为内置gl_Position
变量指定的坐标必须在此范围内才能在输出中可见。如果您正在处理3D坐标并应用透视投影,事情会变得稍微复杂一点,但我们暂时会跳过这部分。
现在,正如您已经猜到的,如果您想在不同的坐标系中指定坐标,则有两个主要选项:
选项2显然是更好的选择,因为GPU在执行此工作时非常有效。
在一个非常简单的层面上,这意味着您可以修改顶点着色器中的坐标。如果你看一下非常简单的第一个顶点着色器:
in vec4 vPosition;
void main()
{
gl_Position = vPosition;
}
您可以在vPosition
输入变量中获取应用代码提供的坐标,并将相同的坐标分配给顶点着色器输出gl_Position
。
如果要使用不同的坐标系,可以在顶点着色器代码中处理输入坐标,并将这些处理过的坐标分配给输出。
现在版本的OpenGL实际上并没有这些坐标系的名称。当一些东西仍然硬连线到固定管道时,曾经有“模型坐标”和“世界坐标”。现在,这是通过可编程着色器代码完成的,从OpenGL的角度来看,这些概念不再相关。所有它关心的是从顶点着色器出来的坐标。之前发生的一切都是你自己的事。
应用线性变换的规范方法,包括您的预期用途所需的平移和缩放,是通过将坐标与变换矩阵相乘。如果您不想自己编写(简单)代码,那么您已经发现了android.opengl.Matrix
包,其中包含一些用于构建转换矩阵的实用函数。
获得变换矩阵后,将其作为 uniform 变量传递到顶点着色器中,并在着色器代码中应用矩阵。它在着色器代码中的显示方式例如是:
in vec4 vPosition;
uniform mat4 TransformMat;
void main()
{
gl_Position = TransformMat * vPosition;
}
要设置此矩阵的值,您需要在使用着色器程序prog
链接着色器后获取统一变量的位置:
GLint transformLoc = GLES20.glGetUniformLocation(prog, "TransformMat");
然后,至少一次,每次想要更改矩阵时,请调用:
GLES20.glUniformMatrix4fv(transformLoc, 1, GL_FALSE, mat, 0);
其中mat
是您自己构建的矩阵,或来自android.opengl.Matrix
中的一个效用函数。请注意,此调用需要 之后才能使程序与glUseProgram()
保持同步。