osg for android (二) 几何物体的颜色显示以及纹理贴图

        上篇的代码仅仅是将图形显示,并通过gl_FragColor=vec4(0.4,0.4,0.8,1.0),简单粗暴的上色,其实在createNode()中创建四边

的时候有创建了几何体的纹理坐标、法线坐标和颜色坐标。下面分别讲颜色的加载和纹理的加载。

 1.颜色的加载

       颜色的加载有两种方式,一种是通过vertext shader的内建变量gl_Color直接来加载,另外一种是将颜色信息通过attribute传递到

shader里边。如下所示:

      (1)通过vertext shader的内建变量gl_Color

       vertext shader

 C++ Code 
1
2
3
4
5
6
static  const  char gVertexShader[] =
     "varying vec4 col;                                                      \n"
     "void main() {                                                          \n"
     "    col   = gl_Color;                                                  \n"
     "    gl_Position  = gl_ModelViewProjectionMatrix * gl_Vertex;           \n"
     "}                                                                      \n";

         fragment shader

 C++ Code 
1
2
3
4
5
static  const  char gFragmentShader[] =
     "varying  mediump vec4 col;                             \n"
     "void main() {                                          \n"
     "   gl_FragColor = col;                                 \n"
     "}                                                      \n";

         修改createNode()

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//创建一个四边形节点
osg::ref_ptr<osg::Node> OsgMainApp::createNode() {

     //创建一个叶节点对象
    osg::ref_ptr<osg::Geode> geode =  new osg::Geode();
     //创建一个几何体对象
    osg::ref_ptr<osg::Geometry> geom =  new osg::Geometry();
     //添加顶点数据 注意顶点的添加顺序是逆时针
    osg::ref_ptr<osg::Vec3Array> v =  new osg::Vec3Array();
     //添加数据
    v->push_back(osg::Vec3( 000));
    v->push_back(osg::Vec3( 100));
    v->push_back(osg::Vec3( 101));
    v->push_back(osg::Vec3( 001));

     //设置顶点数据
    geom->setVertexArray(v.get());

     //创建纹理订点数据
    osg::ref_ptr<osg::Vec2Array> vt =  new osg::Vec2Array();
     //添加纹理坐标
    vt->push_back(osg::Vec2( 00));
    vt->push_back(osg::Vec2( 10));
    vt->push_back(osg::Vec2( 11));
    vt->push_back(osg::Vec2( 01));

     //设置纹理坐标
    geom->setTexCoordArray( 0, vt.get());

     //创建颜色数组
    osg::ref_ptr<osg::Vec4Array> vc =  new osg::Vec4Array();
     //添加数据
    vc->push_back(osg::Vec4( 1001));
    vc->push_back(osg::Vec4( 0101));
    vc->push_back(osg::Vec4( 0011));
    vc->push_back(osg::Vec4( 1101));

     //设置颜色数组
    geom->setColorArray(vc.get());
     //设置颜色的绑定方式为单个顶点
    geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
     //创建法线数组
    osg::ref_ptr<osg::Vec3Array> nc =  new osg::Vec3Array();
     //添加法线
    nc->push_back(osg::Vec3( 0, - 10));
     //设置法线
    geom->setNormalArray(nc.get());
     //设置法绑定为全部顶点
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
     //添加图元
    geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::QUADS,  04));

     //添加到叶子节点
    geode->addDrawable(geom.get());
    osg::StateSet* stateset =  new osg::StateSet;

     return geode.get();
}

        (2)将颜色信息通过attribute传递到shader里边

          vertext shader

 C++ Code 
1
2
3
4
5
6
7
static  const  char gVertexShader[] =
     "attribute vec4 a_col;                                          \n"
     "varying vec4 col;                                              \n"
     "void main() {                                                  \n"
     "    col   = a_col;                                             \n"
     "    gl_Position  = gl_ModelViewProjectionMatrix * gl_Vertex;   \n"
     "}                                                              \n";

      fragment shader代码

 C++ Code 
1
2
3
4
5
6

static  const  char gFragmentShader[] =
     "varying  mediump vec4 col;                         \n"
     "void main() {                                      \n"
     "    gl_FragColor = col;                            \n"
     "}                                                  \n";

         修改createNode()

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//创建一个四边形节点
osg::ref_ptr<osg::Node> OsgMainApp::createNode() {

     //创建一个叶节点对象
    osg::ref_ptr<osg::Geode> geode =  new osg::Geode();
     //创建一个几何体对象
    osg::ref_ptr<osg::Geometry> geom =  new osg::Geometry();
     //添加顶点数据 注意顶点的添加顺序是逆时针
    osg::ref_ptr<osg::Vec3Array> v =  new osg::Vec3Array();
     //添加数据
    v->push_back(osg::Vec3( 000));
    v->push_back(osg::Vec3( 100));
    v->push_back(osg::Vec3( 101));
    v->push_back(osg::Vec3( 001));

     //设置顶点数据
    geom->setVertexArray(v.get());

     //创建纹理订点数据
    osg::ref_ptr<osg::Vec2Array> vt =  new osg::Vec2Array();
     //添加纹理坐标
    vt->push_back(osg::Vec2( 00));
    vt->push_back(osg::Vec2( 10));
    vt->push_back(osg::Vec2( 11));
    vt->push_back(osg::Vec2( 01));

     //设置纹理坐标
    geom->setTexCoordArray( 0, vt.get());

     //创建颜色数组
    osg::ref_ptr<osg::Vec4Array> vc =  new osg::Vec4Array();
     //添加数据
    vc->push_back(osg::Vec4( 1001));
    vc->push_back(osg::Vec4( 0101));
    vc->push_back(osg::Vec4( 0011));
    vc->push_back(osg::Vec4( 1101));

     //设置颜色的绑定方式为单个顶点
     //geom->setVertexAttribBinding(1, osg::Geometry::BIND_PER_VERTEX);
     //geom->setVertexAttribArray(1, vc.get());//颜色的地址//不要用0,2,3
     //创建法线数组
    osg::ref_ptr<osg::Vec3Array> nc =  new osg::Vec3Array();
     //添加法线
    nc->push_back(osg::Vec3( 0, - 10));
     //设置法线
    geom->setNormalArray(nc.get());
     //设置法绑定为全部顶点
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
     //添加图元
    geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::QUADS,  04));

     //添加到叶子节点
    geode->addDrawable(geom.get());
    osg::StateSet* stateset =  new osg::StateSet;

     return geode.get();
}

           此外还得在loadModels()中的Program将颜色的地址传入

 C++ Code 
1
2
3
4

    prog->addShader(vshader);
    prog->addShader(fshader);
    prog->addBindAttribLocation( "a_col"1);

         运行结果


2.纹理的加载

         由于之前的android,mk 中没有将jpeg的库引入,故要正确加载纹理,必须在android.mk加上-ljpeg 和 -losgdb_jpeg纹理的加

载是通过OSG中的Uniform变量来加载,注意要在sdcard中的osg文件夹放入texture.jpg文件。

      vertext shader

 C++ Code 
1
2
3
4
5
6
static  const  char gVertexShader[] =
     "varying vec2 v_texCoord;                                         \n"
     "void main() {                                                    \n"
     "    gl_Position  = gl_ModelViewProjectionMatrix * gl_Vertex;     \n"
     "    v_texCoord   = gl_MultiTexCoord0.xy;                           \n"
     "}                                                                \n";

       fragment shader

 C++ Code 
1
2
3
4
5
6
static  const  char gFragmentShader[] =
     "varying  mediump vec2 v_texCoord;                      \n"
     "uniform sampler2D sam;                                 \n"
     "void main() {                                          \n"
     "    gl_FragColor = texture2D(sam, v_texCoord);         \n"
     "}                                                      \n";

       修改createNode()

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//创建一个四边形节点
osg::ref_ptr<osg::Node> OsgMainApp::createNode() {

     //创建一个叶节点对象
    osg::ref_ptr<osg::Geode> geode =  new osg::Geode();
     //创建一个几何体对象
    osg::ref_ptr<osg::Geometry> geom =  new osg::Geometry();
     //添加顶点数据 注意顶点的添加顺序是逆时针
    osg::ref_ptr<osg::Vec3Array> v =  new osg::Vec3Array();
     //添加数据
    v->push_back(osg::Vec3( 000));
    v->push_back(osg::Vec3( 100));
    v->push_back(osg::Vec3( 101));
    v->push_back(osg::Vec3( 001));

     //设置顶点数据
    geom->setVertexArray(v.get());

     //创建纹理订点数据
    osg::ref_ptr<osg::Vec2Array> vt =  new osg::Vec2Array();
     //添加纹理坐标
    vt->push_back(osg::Vec2( 00));
    vt->push_back(osg::Vec2( 10));
    vt->push_back(osg::Vec2( 11));
    vt->push_back(osg::Vec2( 01));

     //设置纹理坐标
    geom->setTexCoordArray( 0, vt.get());

     //创建颜色数组
    osg::ref_ptr<osg::Vec4Array> vc =  new osg::Vec4Array();
     //添加数据
    vc->push_back(osg::Vec4( 1001));
    vc->push_back(osg::Vec4( 0101));
    vc->push_back(osg::Vec4( 0011));
    vc->push_back(osg::Vec4( 1101));

     //设置颜色数组
    geom->setColorArray(vc.get());
     //设置颜色的绑定方式为单个顶点
    geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
     //创建法线数组
    osg::ref_ptr<osg::Vec3Array> nc =  new osg::Vec3Array();
     //添加法线
    nc->push_back(osg::Vec3( 0, - 10));
     //设置法线
    geom->setNormalArray(nc.get());
     //设置法绑定为全部顶点
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
     //添加图元
    geom->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::QUADS,  04));

     //添加到叶子节点
    geode->addDrawable(geom.get());
    osg::StateSet* stateset =  new osg::StateSet;
    osg::Texture2D* texture =  new osg::Texture2D();
    texture->setDataVariance(osg::Object::DYNAMIC);
    texture->setImage(osgDB::readImageFile( "/sdcard/osg/texture.jpg"));
    osg::Uniform* samUniform =  new osg::Uniform(osg::Uniform::SAMPLER_2D,  "sam");
    samUniform->set( 0); //设置纹理单元
    stateset->addUniform(samUniform);
    stateset->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON);

    geode->setStateSet(stateset);

     return geode.get();
}

      运行结果



3 几点注意:

       (1)由于移动平台GPU的强弱,shader中有的支持高精度的变量,有的仅支持中等精度

      vertext shader中可以不声明,默认为highp

        fragment shader必须声明,opengles 规范没有强制要求fragment shader 必须支持highp,所以如果GPU支持,宏

GL_FRAGMENT_PRECISION_HIGH肯定会被定义,所以可以用下面的语句做为shader的开始 

 C++ Code 
1
2
3
4
5
#ifdef GL_FRAGMENT_PRECISION_HIGH  
precision highp  float;  
#else  
precision mediump  float;  
#endif

     2)由于桌面平台的闲置,shader中有些内置变量不支持(例如gl_TexCoord[x]),OpenGL ES的着色器里规范里面没有这

变量,它们都是通过用户自定义的着色器来替代的。《OpenGL ES Programming Guide》里面有详细的讲解。嵌入式版本的规

范与计算机版本的规范存在很大的差异性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值