Part I 空气曲棍球 Chapter4 (4.4 Rendering with the New Color Attribute)

4.4 使用新的颜色进行渲染(Rendering with the New Color Attribute)

    现在我们已经在顶点数据中增加了一个颜色属性数据并且已经更新了相应的顶点着色器及片元着色器,下一步是移除老的使用uniform类型数据进行绘制的代码并且告诉OpenGL使用顶点属性颜色进行绘制。


4.4.1 更新常量(Updating Constants)


    在AirHockeyRenderer的开始处添加如下常量:

//AirHockey2/src/com/airhockey/android/AirHockeyRenderer.java
private static final String A_COLOR = "a_Color";
private static final int COLOR_COMPONENT_COUNT = 3;
private static final int STRIDE =
(POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;

    同时也增加一个变量存储a_Color着色器变量的位置引用,代码如下:

//AirHockey2/src/com/airhockey/android/AirHockeyRenderer.java
private int aColorLocation;

    现在我们可以移除与u_Color关联的一些常量及变量了。
    你注意到我们添加了一个特殊的常量STRIDE了吗?因为我们现在在同一个数组中存储了顶点位置数据及属性颜色数据,OpenGL在读取位置数据的时候不能再认为每一个顶点位置数据都是相邻的,一旦OpenGL已经读取了一个顶点位置数据,如果它还想读取下一个位置数据那么必须跳过当前位置的颜色属性数据。 这里我们使用stride(步长)告诉OpenGL在相邻两个顶点之间间隔多少字节,这样OpenGL才知道要跳过多少字节的数据。
    如下图1展示了颜色与顶点位置数据是如何存储在同一个数组中的,stride(步长)告诉OpenGL每两个相邻的顶点或者颜色数据之前的间隔是多少。如果你不喜欢这种方式,你也可以针对每个属性使用一个数组进行数据存储,就如下图2所示一样,当然使用同一个数组会理高效,但是当我们想要使用同一个偏移量进行顶点数据或者颜色数据的更新时或许使用多个数组会更有意义。

图 1(单个数组存储数据)
图 2(多个数组进行存储数据)

4.4.2 更新onSurfaceCreated(Updating onSurfaceCreated())

 

    下一步是更新onSurfaceCreated()使用新的颜色属性,第一步是得到颜色属性的位置引用,所以先把与u_Color变量相关的代码去掉并且增加如下代码:

//AirHockey2/src/com/airhockey/android/AirHockeyRenderer.java
aColorLocation = glGetAttribLocation(program, A_COLOR);

    同时也需要更新对glVertexAttribPointer()的调用以使用stride参数:

//AirHockey2/src/com/airhockey/android/AirHockeyRenderer.java
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);

    现在我们需要告诉OpenGL将颜色数据与着色器变量a_Color更新关联,在OnSurfaceCreated()最后增加如下代码:

//AirHockey2/src/com/airhockey/android/AirHockeyRenderer.java
vertexData.position(POSITION_COMPONENT_COUNT);
glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
glEnableVertexAttribArray(aColorLocation);

    这段代码相当重要,所以让我们来稍微理解下:
    1)首先把vertexData 的位置更新为 值为2的常量POSITION_COMPONENT_COUNT,为什么要做这一步呢?因为当OpenGL开始读取颜色数据的时候是从第一人颜色数据开始读取而不是从第一个顶点数据开始读取。
    因为我们需要跳过第一个顶点数据,因此我把位置设置为POSITION_COMPONENT_COUNT, 这样的话当OpenGLd 在读取颜色数据的时候就会读取到第一个颜色数据而不是第一个顶点数据。如果我们把位置设置成0,那么OpenGL就会把第一个位置数据当成颜色数据进行使用,这样的结果肯定是不对的。
    2)然后调用glVertexAttribPointer() 把数组中的颜色数据与着色器变量a_Color进行关联,同样的stride参数告诉OpenGL在每两个颜色之间间隔多少个字节,这样的话当OpenGL在读取颜色数据的时候才会知道下一个顶点的颜色数据要跳过字节,很关键的一点是stride因子是以字节为单位计算的。
    即使在OpenGL中的颜色是用四个分量进行表示的,我们也并不需要指定所有的分量。不像uniform类型的颜色变量,OpenGL会把没有指定的分量指定为默认值:RGB分别指定为0,A指定为1。
    3)最后就像顶点属性一样,我们开启对颜色属性的使用(enable the vertex attribute for the color attribute)


4.4.3 更新onDrawFrame(Updating onDrawFrame)


    最后一步就是删除glUniform4f()的调用,因为我们已经不需要了。我们已经把颜色数组与a_Color进行关联,现在需要调用的是glDrawArrays(),这样OpenGL就可以从数组中读取颜色数据了。

4.4.4 运行结果(Putting It All Together)


    现在运行代码将会看到如下效果图:


    现在我们的球台桌面看起来比之前更好了,而且也可以清楚的看到桌面的中心更明亮边缘更暗。然而我们也可以清楚的辨认出每一个三角形的大体轮廓,这是因为线性混合的方向也三角形有关,因此虽然三角形的颜色看起来更平滑,但我们也可以看出哪个三角形在哪里开始哪个三角形在哪里结束。
    要减少或者消除这种效应,我们可以使用更多的三角形或者使用光照算法计算每个片元的颜色值,在第13章中将会学习光照算法相关知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值