OpenGL ES初探(二) – 用OpenGL画一个三角形(2)
目录
OpenGL中的投影转化
承接上一篇博客
OpenGL ES初探(一) – 用OpenGL画一个三角形(1)
在上篇最后留了一个问题:
OpenGL 坐标单位非长度的问题
那么如何解决这个问题呢?
我们继续使用上篇博客的测试代码
其实我们大可不必去想如何改变OpenGL的视口单位规则
我们可以考虑如何以一种巧妙的形式去将我们的单位转化成OpenGL使用的单位
那么如何转化呢?
数学上有一个非常巧妙神奇的东西 – 矩阵
通过矩阵与向量的乘法我们可以实现各种几何坐标的变换,比如平移,旋转,伸缩,切换投影方式等.
引入正交投影矩阵
将triangle_vertex_shader.glsl
更新如下
uniform mat4 u_Matrix;
attribute vec4 a_Position;
void main() {
gl_Position = u_Matrix * a_Position;
}
在MyRenderer
中添加全局变量和常量如下
//19,定义正交矩阵相关常量和变量
private static final String U_MATRIX = "u_Matrix";
private static final float[] projectionMatrix = new float[16];
private int uMatrixLocation;
在MyRenderer.onSurfaceChanged
的末尾添加
//20,创建正交投影矩阵
final float aspectRatio = height / (float) width;
orthoM(projectionMatrix, 0, -1f, 1f,
-aspectRatio, aspectRatio, -1f, 1f);
在MyRenderer.onSurfaceCreated
的注释16上面添加如下代码
//22,获取u_Matrix在顶点着色器中的位置
uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
现在我们已经有了正交投影矩阵projectionMatrix
和顶点着色器中u_Matrix的位置uMatrixLocation
传递矩阵给着色器
在MyRenderer.onDrawFrame
中glClear下面添加如下方法
//23,将正交投影矩阵传递给顶点着色器
glUniformMatrix4fv(uMatrixLocation, 1, false, projectionMatrix, 0);
我们再运行下程序看看,会发现已经变成下图这样了,真的成了一个直角三角形了
给着色器增加颜色属性
白色的三角形是不是显得非常单调?
其实OpenGL是支持非常强大的颜色渲染的,接下来让我们让三角形变得绚烂多彩吧
更新triangle_vertex_shader.glsl
如下
uniform mat4 u_Matrix;
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
v_Color = a_Color;
gl_Position = u_Matrix * a_Position;
}
更新triangle_fragment_shader.glsl
如下
precision mediump float;
varying vec4 v_Color;
void main(){
gl_FragColor = v_Color;
}
简单解释下,我们在triangle_vertex_shader
中添加了aColor
和v_Color
,接下来我们将会把我们想设置的颜色传递给a_Color
,然后a_Color
传递给v_Color
,varying修饰的在片段着色器和顶点着色器中同名变量,片段着色器将获得顶点着色器中的值并混合,所以triangle_fragment_shader
中的v_Color
即拥有了我们传给三个顶点a_Color
的颜色混合值,然后片段着色器将混合值赋值给了gl_FragColor
更新MyRenderer
的关于triangleVertices
初始化部分如下
//24,注释掉注释6的修改
/*//6,设置三角形的三个顶点坐标: 左下(-0.5f,0f),右下(0.5f,0f),中上(0f,0.5f) private float[] triangleVertices = { -0.5f,0f, 0.5f,0f, 0f,0.5f, };*/
//25,给triangleVertices增加颜色数组
private float[] triangleVertices = {
-0.5f, 0f,1f,0f,0f,//red
0.5f, 0f,0f,0f,1f,//blue
0f, 0.5f,1f,1f,1f,//white
};
在MyRenderer
中添加如下全局属性
//26,定义a_Color常量及位置变量
private static final String A_COLOR = "a_Color";
private int aColorLocation;
//27,定义颜色值所需数字数量
private static final int COLOR_COMPONENT_COUNT = 3;
//28,定义数组中相邻点的字节数间隔
private static final int STRIDE = (POSITION_COMPONENT_COUNT +
COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;
更新MyRenderer.onSurfaceCreated
如下
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//2,设置清空屏幕用的颜色
glClearColor(0f, 1f, 0f, 0f);
//9,读取shader源文件
String vertexShaderSource = CommonUtils.readTextFromResource(context, R.raw.triangle_vertex_shader);
String fragmentShaderSource = CommonUtils.readTextFromResource(context, R.raw.triangle_fragment_shader);
//10,编译shader 源文件
int vertexShader = CommonUtils.compileVertexShader(vertexShaderSource);
int fragmentShader = CommonUtils.compileFragmentShader(fragmentShaderSource);
//12,将shader添加进program,并获得Program的Id
program = CommonUtils.linkProgram(vertexShader, fragmentShader);
//13,使用这个program
glUseProgram(program);
//15,获得u_Color和a_Position的位置
//一个Uniform,一个Attribute别搞错了
uColorLocation = glGetUniformLocation(program, U_COLOR);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
//22,获取u_Matrix在顶点着色器中的位置
uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
//29,增加对a_Color位置的获取
aColorLocation = glGetAttribLocation(program, A_COLOR);
//30,注释掉16的操作
/*//16,根据a_Position的位置将顶点数据传给a_Position vertexData.position(0); glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, 0, vertexData);*/
//31,更新跨距
vertexData.position(0);
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
//17,激活顶点数组
glEnableVertexAttribArray(aPositionLocation);
//32,传输颜色数据给a_Color
vertexData.position(POSITION_COMPONENT_COUNT);
glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
//33,激活颜色数组
glEnableVertexAttribArray(aColorLocation);
}
片段着色器的u_Color
属性已经被我们删除,所以在MyRenderer
中,删除和u_Color
相关的属性和方法.
详细操作不再赘述.
运行程序
会获得下图效果