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

  • Post author:
  • Post category:其他


上篇的代码仅仅是将图形显示,并通过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<:node> OsgMainApp::createNode() {

//创建一个叶节点对象    osg::ref_ptr<:geode> geode = new osg::Geode();

//创建一个几何体对象    osg::ref_ptr<:geometry> geom = new osg::Geometry();

//添加顶点数据 注意顶点的添加顺序是逆时针    osg::ref_ptr<:vec3array> v = new osg::Vec3Array();

//添加数据    v->push_back(osg::Vec3(0, 0, 0));

v->push_back(osg::Vec3(1, 0, 0));

v->push_back(osg::Vec3(1, 0, 1));

v->push_back(osg::Vec3(0, 0, 1));

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

//创建纹理订点数据    osg::ref_ptr<:vec2array> vt = new osg::Vec2Array();

//添加纹理坐标    vt->push_back(osg::Vec2(0, 0));

vt->push_back(osg::Vec2(1, 0));

vt->push_back(osg::Vec2(1, 1));

vt->push_back(osg::Vec2(0, 1));

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

//创建颜色数组    osg::ref_ptr<:vec4array> vc = new osg::Vec4Array();

//添加数据    vc->push_back(osg::Vec4(1, 0, 0, 1));

vc->push_back(osg::Vec4(0, 1, 0, 1));

vc->push_back(osg::Vec4(0, 0, 1, 1));

vc->push_back(osg::Vec4(1, 1, 0, 1));

//设置颜色数组    geom->setColorArray(vc.get());

//设置颜色的绑定方式为单个顶点    geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

//创建法线数组    osg::ref_ptr<:vec3array> nc = new osg::Vec3Array();

//添加法线    nc->push_back(osg::Vec3(0, -1, 0));

//设置法线    geom->setNormalArray(nc.get());

//设置法绑定为全部顶点    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

//添加图元    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

//添加到叶子节点    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<:node> OsgMainApp::createNode() {

//创建一个叶节点对象    osg::ref_ptr<:geode> geode = new osg::Geode();

//创建一个几何体对象    osg::ref_ptr<:geometry> geom = new osg::Geometry();

//添加顶点数据 注意顶点的添加顺序是逆时针    osg::ref_ptr<:vec3array> v = new osg::Vec3Array();

//添加数据    v->push_back(osg::Vec3(0, 0, 0));

v->push_back(osg::Vec3(1, 0, 0));

v->push_back(osg::Vec3(1, 0, 1));

v->push_back(osg::Vec3(0, 0, 1));

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

//创建纹理订点数据    osg::ref_ptr<:vec2array> vt = new osg::Vec2Array();

//添加纹理坐标    vt->push_back(osg::Vec2(0, 0));

vt->push_back(osg::Vec2(1, 0));

vt->push_back(osg::Vec2(1, 1));

vt->push_back(osg::Vec2(0, 1));

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

//创建颜色数组    osg::ref_ptr<:vec4array> vc = new osg::Vec4Array();

//添加数据    vc->push_back(osg::Vec4(1, 0, 0, 1));

vc->push_back(osg::Vec4(0, 1, 0, 1));

vc->push_back(osg::Vec4(0, 0, 1, 1));

vc->push_back(osg::Vec4(1, 1, 0, 1));

//设置颜色的绑定方式为单个顶点    //geom->setVertexAttribBinding(1, osg::Geometry::BIND_PER_VERTEX);    //geom->setVertexAttribArray(1, vc.get());//颜色的地址//不要用0,2,3    //创建法线数组    osg::ref_ptr<:vec3array> nc = new osg::Vec3Array();

//添加法线    nc->push_back(osg::Vec3(0, -1, 0));

//设置法线    geom->setNormalArray(nc.get());

//设置法绑定为全部顶点    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

//添加图元    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

//添加到叶子节点    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);

运行结果

b7244587310fdde2aec96c651af1dbc2.png

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<:node> OsgMainApp::createNode() {

//创建一个叶节点对象    osg::ref_ptr<:geode> geode = new osg::Geode();

//创建一个几何体对象    osg::ref_ptr<:geometry> geom = new osg::Geometry();

//添加顶点数据 注意顶点的添加顺序是逆时针    osg::ref_ptr<:vec3array> v = new osg::Vec3Array();

//添加数据    v->push_back(osg::Vec3(0, 0, 0));

v->push_back(osg::Vec3(1, 0, 0));

v->push_back(osg::Vec3(1, 0, 1));

v->push_back(osg::Vec3(0, 0, 1));

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

//创建纹理订点数据    osg::ref_ptr<:vec2array> vt = new osg::Vec2Array();

//添加纹理坐标    vt->push_back(osg::Vec2(0, 0));

vt->push_back(osg::Vec2(1, 0));

vt->push_back(osg::Vec2(1, 1));

vt->push_back(osg::Vec2(0, 1));

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

//创建颜色数组    osg::ref_ptr<:vec4array> vc = new osg::Vec4Array();

//添加数据    vc->push_back(osg::Vec4(1, 0, 0, 1));

vc->push_back(osg::Vec4(0, 1, 0, 1));

vc->push_back(osg::Vec4(0, 0, 1, 1));

vc->push_back(osg::Vec4(1, 1, 0, 1));

//设置颜色数组    geom->setColorArray(vc.get());

//设置颜色的绑定方式为单个顶点    geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

//创建法线数组    osg::ref_ptr<:vec3array> nc = new osg::Vec3Array();

//添加法线    nc->push_back(osg::Vec3(0, -1, 0));

//设置法线    geom->setNormalArray(nc.get());

//设置法绑定为全部顶点    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

//添加图元    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

//添加到叶子节点    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();

}

运行结果

89f322921d9bf6fd6b8c390653445b59.png

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》里面有详细的讲解。嵌入式版本的规

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