Android 使用 Open GL ES 开发曲棍球游戏 二

增加颜色和着色

1. 创建新的Activit和渲染器

    1. 创建新的 AirHockey2 代码和之前一样。
    1. 创建AirHockeyRender2

这一节主要为游戏桌面增加平滑着色。在前一部分,我们使用的单一颜色绘制物体。其实还可以绘制变化的颜色,也就是平滑着色。平滑着色其实是通过定点来完成的。比如三角形状,三个顶点各一个颜色,这样一个点到另外一个点之前颜色就是变化的。
之前我们只能绘画三角形,线,和点。这一节,要引入一个三角扇形。

三星扇形,就是以一个中心点。以两个相邻的点创建一个三角形状。然后每增加一个点。就创建出了一个三角形。最后以起始汇合,形成一个闭环。
AirHockeyRenderer2 类里面的坐标点变成这样:

float[] tableVerticesWithTriangles = {
                //Triagle Fan
                0,0,1f,1f,1f,
                -0.5f,-0.5f,0.7f,0.7f,0.7f,
                0.5f,-0.5f,0.7f,0.7f,0.7f,
                0.5f,0.5f,0.7f,0.7f,0.7f,
                -0.5f,0.5f,0.7f,0.7f,0.7f,
                -0.5f,-0.5f,0.7f,0.7f,0.7f,

                // Line 1
                -0.5f,0f,1f,0f,0f,
                0.5f,0f,1f,0f,0f,

                // Mallets
                0f,-0.25f,0f,0f,1f,
                0f,0.25f,1f,0f,0f
        };

没一个点,包括x,y,r,g,b,构成一个顶点的位置和颜色。前面6个点就是定义三角扇形的。

接下来,重新创建了simple_vertex_shader2,simple_fragment_shader2作为渲染器

  • 顶点着色器 simple_vertex_shader2:
attribute vec4 a_Position;
attribute vec4 a_Color;

varying vec4 v_Color;
void main(){
    v_Color = a_Color;

    gl_Position = a_Position;
    gl_PointSize = 10.0;
}

增加了a_Color 颜色属性。增加了一个特殊变量v_Color,varying类型,他会把给它的值进行混合,并把这些混合后的值发送给片段着色器。

  • 片段着色器 simple_fragment_shader2:
precision mediump float;
varying vec4 v_Color;

void main(){
    gl_FragColor = v_Color;
}

颜色换成了varying变量,如果片段属于一个三角形,那么OpengGL会用构成三角形的三个顶点计算器混合颜色。如果是一条直线,那么OpengGL会用构成直线的两个顶点计算器混合后的颜色。

  • varying 颜色的计算是线性的。就是说不通位置,计算的混合颜色是不一样的。

使用和渲染

  1. 增加常量和位置,还要增加一个跨距。
private static final String A_COLOR = "a_Color";
    private int aColorLocation;
    private static final int COLOR_COMPONENT_COUNT = 3;
    private static final int STRIDE = (POSITION_COMPONENT_COUNT+COLOR_COMPONENT_COUNT)*BYTES_PER_FLOAT;

去掉之前的u_Color相关的。

获取新颜色属性的位置:

aColorLocation = glGetAttribLocation(program,A_COLOR);

告诉OpenGL 顶点中数据与着色器中的a_Color 联系起来

vertexData.position(POSITION_COMPONENT_COUNT);
glVertexAttribPointer(aColorLocation,COLOR_COMPONENT_COUNT,GL_FLOAT,false,STRIDE,vertexData);
//告诉OpenGL 把定点数据与做色漆中的a_Color 关联起来
glEnableVertexAttribArray(aColorLocation);

最后绘画方法里是这样的:

glClear(GL_COLOR_BUFFER_BIT);
//绘制三角扇形

glDrawArrays(GL_TRIANGLE_FAN,0,6);
//绘制分割线

glDrawArrays(GL_LINES,6,2);
//绘制点
glDrawArrays(GL_POINTS,8,1);
glDrawArrays(GL_POINTS,9,1);

不需要给片段颜色,会使用顶点颜色。

调整屏幕宽高比

1. 创建新的Activit和渲染器

    1. 创建AirHockey3
    1. 创建渲染器 AirHockeyRenderer3

OpengGL 里面的Postion使用的是归一化坐标。不论屏幕尺寸是多少。OpengGL 里面的坐标都是-1到1,这样在不同分辨率下。就显示效果不是预期的,导致我们的桌面显示在横竖屏下,效果不一致,不是我们想要的。所以我们改成使用虚拟化坐标空间。然后就需要找到一种把我们用的虚拟化坐标转化为归一化坐标的方法。
我们想要的这种操作叫做正交投影。使用方法就是用orthoM方法创建一个正交投影矩阵,然后用这个矩阵乘以虚拟坐标。就可以得到归一化坐标了。

首先修改着色器程序。新的定点色器程序为 simple_vertex_shader3:

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;
    gl_PointSize = 10.0;
}

增加了一个新的uniform 定义 u_Marix,mat4类型,也就是一个4*4的矩阵。最终gl_Position使用的就是矩阵和虚拟化坐标的乘积。

AirHockeyRenderer3 里面增加定义,矩阵属性,uniform位置,uniform名字

private static final String U_MATRIX = "u_Matrix";
private int uMatrixLocation;
private final float[] projectionMatrix = new float[16];

获得uniform位置。

uMatrixLocation = glGetUniformLocation(program,U_MATRIX);

在onSurfaceChanged里面我们创建正交矩阵

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    glViewport(0,0,width,height);
    final float aspectRatio = width > height ? (float)width/(float)height: (float)height/(float)width;

    //在不同屏幕尺寸下创建正交矩阵
    if(width > height){
        //LandScape
        orthoM(projectionMatrix,0,-aspectRatio,aspectRatio,-1f,1f,-1f,1f);
    }else{
        orthoM(projectionMatrix,0,-1f,1f,-aspectRatio,aspectRatio,-1f,1f);
    }
}

这段代码会创建一个正交投影矩阵,这个矩阵会把屏幕当前方向计算在内。它会建立一个虚拟坐标空间。

最后在绘画里面更新矩阵数据
glUniformMatrix4fv(uMatrixLocation,1,false,projectionMatrix,0);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355