uniform int osg_FrameNumber:当前OSG程序运行的帧数; uniform float osg_FrameTime:当前OSG程序的运行总时间; uniform float osg_DeltaFrameTime:当前OSG程序运行每帧的间隔时间; uniform mat4 osg_ViewMatrix:当前OSG摄像机的观察矩阵; uniform mat4 osg_ViewMatrixInverse:当前OSG摄像机观察矩阵的逆矩阵。 uniform mat4 osg_ModelViewMatrix:内置gl_ModelViewMatrix uniform mat4 osg_ModelViewProjectionMatrix:内置gl_ModelViewProjectionMatrix uniform mat4 osg_ProjectionMatrix:内置gl_ProjectionMatrix uniform mat3 osg_NormalMatrix:内置gl_NormalMatrix
- attribute:应用程序与顶点着色器的接口,使用顶点属性定义函数进行定义;
- uniform:应用程序与所有着色器的接口,定义不随顶点变化的“一致变量”;
- varying:着色器之间的“易变变量”接口,用于传递插值得到的顶点数据;
- const:用于声明常量数据;
- in:作为函数形参进行传递,函数返回时不保留改变,只保留传入值;
- out:作为函数形参进行传递,本身未定义,函数返回时保留改变值;
- inout:作为函数形参进行传递,可以定义传入值,也会保留返回时的改变值。
- uniform mat4 gl_NormalMatrix:法线变换矩阵;
- uniform mat4 gl_ModelViewMatrix:模型视点变换矩阵;
- attribute vec4 gl_Vertex:顶点坐标属性;
- attribute vec4 gl_MultiTexCoord0:纹理单元0的纹理坐标属性;
- varying vec4 gl_TexCoord[0]:纹理单元0的实际纹理坐标。
-
实现片元着色器的一段示例代码如下: uniform sampler2D texture; varying vec3 tangent; void main( void ) { gl_FragColor = texture2D( texture, gl_TexCoord[0] ); }
着色器一致变量的接口类。对于OpenGL着色语言而言,一致变量(uniform)是用户应用程序与着色器的主要交互接口。Uniform类支持绑定多种类型的一致变量,并使用set()和setArray()更新变量或变量数组的值。而为了实现一致变量的每帧变化,进而达到顶点和片元的各种动画特效,Uniform类还提供了相应的回调工具:使用setUpdateCallback设置自定义的回调类,并在其中更新这个一致变量的值,以实现所需的效果。
#include <osgViewer/Viewer> #include <osg/ShapeDrawable> #include <osg/Geode> #include <osg/Vec3> #include <osg/Program> #include <osg/Shader> #include <osg/Uniform> using namespace osg; /////////////////////////////////////////////////////////////////////////// // in-line GLSL source code static const char *blockyVertSource = { "// blocky.vert - an GLSL vertex shader with animation " "// the App updates uniforms "slowly" (eg once per frame) for animation. " "uniform float Sine; " "const vec3 LightPosition = vec3(0.0, 0.0, 4.0); " "const float BlockScale = 0.30; " "// varyings are written by vert shader, interpolated, and read by frag shader. " "varying float LightIntensity; " "varying vec2 BlockPosition; " "void main(void) " "{ " " // per-vertex diffuse lighting " " vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex; " " vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal); " " vec3 lightVec = normalize(LightPosition - vec3 (ecPosition)); " " LightIntensity = max(dot(lightVec, tnorm), 0.0); " " // blocks will be determined by fragment's position on the XZ plane. " " BlockPosition = gl_Vertex.xz / BlockScale; " " // scale the geometry based on an animation variable. " " vec4 vertex = gl_Vertex; " " vertex.w = 1.0 + 0.4 * (Sine + 1.0); " " gl_Position = gl_ModelViewProjectionMatrix * vertex; " "} " }; static const char *blockyFragSource = { "// blocky.frag - an GLSL fragment shader with animation " "// the App updates uniforms "slowly" (eg once per frame) for animation. " "uniform float Sine; " "const vec3 Color1 = vec3(1.0, 1.0, 1.0); " "const vec3 Color2 = vec3(0.0, 0.0, 0.0); " "// varyings are written by vert shader, interpolated, and read by frag shader. " "varying vec2 BlockPosition; " "varying float LightIntensity; " "void main(void) " "{ " " vec3 color; " " float ss, tt, w, h; " " ss = BlockPosition.x; " " tt = BlockPosition.y; " " if (fract(tt * 0.5) > 0.5) " " ss += 0.5; " " ss = fract(ss); " " tt = fract(tt); " " // animate the proportion of block to mortar " " float blockFract = (Sine + 1.1) * 0.4; " " w = step(ss, blockFract); " " h = step(tt, blockFract); " " color = mix(Color2, Color1, w * h) * LightIntensity; " " gl_FragColor = vec4 (color, 1.0); " "} " }; /////////////////////////////////////////////////////////////////////////// // callback for animating various Uniforms (currently only the SIN uniform) class AnimateCallback : public osg::UniformCallback { public: enum Operation { SIN }; AnimateCallback(Operation op) : _operation(op) {} virtual void operator() (osg::Uniform* uniform, osg::NodeVisitor* nv) { float angle = 2.0 * nv->getFrameStamp()->getSimulationTime(); float sine = sinf(angle); // -1 -> 1 switch (_operation) { case SIN: uniform->set(sine); break; } } private: Operation _operation; }; int main(int, char **) { // construct the viewer. osgViewer::Viewer viewer; // use a geode with a Box ShapeDrawable osg::Geode* basicModel = new osg::Geode(); basicModel->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 0.0f), 1.0f))); // create the "blocky" shader, a simple animation test osg::StateSet *ss = basicModel->getOrCreateStateSet(); osg::Program* program = new osg::Program; program->setName("blocky"); //program->addShader(new osg::Shader(osg::Shader::VERTEX, blockyVertSource)); //program->addShader(new osg::Shader(osg::Shader::FRAGMENT, blockyFragSource)); program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, "blocky.vert")); program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, "blocky.frag")); ss->setAttributeAndModes(program, osg::StateAttribute::ON); // attach some animated Uniform variable to the state set osg::Uniform* SineUniform = new osg::Uniform("Sine", 0.0f); ss->addUniform(SineUniform); SineUniform->setUpdateCallback(new AnimateCallback(AnimateCallback::SIN)); // run the osg::Viewer using our model viewer.setSceneData(basicModel); return viewer.run(); } /*EOF*/