osg内置shader变量

Posted 酷熊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了osg内置shader变量相关的知识,希望对你有一定的参考价值。

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\n"
    "// the App updates uniforms \"slowly\" (eg once per frame) for animation.\n"
    "uniform float Sine;\n"
    "const vec3 LightPosition = vec3(0.0, 0.0, 4.0);\n"
    "const float BlockScale = 0.30;\n"
    "// varyings are written by vert shader, interpolated, and read by frag shader.\n"
    "varying float LightIntensity;\n"
    "varying vec2  BlockPosition;\n"
    "void main(void)\n"
    "{\n"
    "    // per-vertex diffuse lighting\n"
    "    vec4 ecPosition    = gl_ModelViewMatrix * gl_Vertex;\n"
    "    vec3 tnorm         = normalize(gl_NormalMatrix * gl_Normal);\n"
    "    vec3 lightVec      = normalize(LightPosition - vec3 (ecPosition));\n"
    "    LightIntensity     = max(dot(lightVec, tnorm), 0.0);\n"
    "    // blocks will be determined by fragment‘s position on the XZ plane.\n"
    "    BlockPosition  = gl_Vertex.xz / BlockScale;\n"
    "    // scale the geometry based on an animation variable.\n"
    "    vec4 vertex    = gl_Vertex;\n"
    "    vertex.w       = 1.0 + 0.4 * (Sine + 1.0);\n"
    "    gl_Position    = gl_ModelViewProjectionMatrix * vertex;\n"
    "}\n"
};

static const char *blockyFragSource = {
    "// blocky.frag - an GLSL fragment shader with animation\n"
    "// the App updates uniforms \"slowly\" (eg once per frame) for animation.\n"
    "uniform float Sine;\n"
    "const vec3 Color1 = vec3(1.0, 1.0, 1.0);\n"
    "const vec3 Color2 = vec3(0.0, 0.0, 0.0);\n"
    "// varyings are written by vert shader, interpolated, and read by frag shader.\n"
    "varying vec2  BlockPosition;\n"
    "varying float LightIntensity;\n"
    "void main(void)\n"
    "{\n"
    "    vec3 color;\n"
    "    float ss, tt, w, h;\n"
    "    ss = BlockPosition.x;\n"
    "    tt = BlockPosition.y;\n"
    "    if (fract(tt * 0.5) > 0.5)\n"
    "        ss += 0.5;\n"
    "    ss = fract(ss);\n"
    "    tt = fract(tt);\n"
    "    // animate the proportion of block to mortar\n"
    "    float blockFract = (Sine + 1.1) * 0.4;\n"
    "    w = step(ss, blockFract);\n"
    "    h = step(tt, blockFract);\n"
    "    color = mix(Color2, Color1, w * h) * LightIntensity;\n"
    "    gl_FragColor = vec4 (color, 1.0);\n"
    "}\n"
};

///////////////////////////////////////////////////////////////////////////
// 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*/

 

以上是关于osg内置shader变量的主要内容,如果未能解决你的问题,请参考以下文章

osg使用shader动态修改纹理坐标

shader的内置矩阵和一些变量

shader内置变量

初识OpenGL 片段着色器(Fragment Shader)

初识OpenGL 片段着色器(Fragment Shader)

Shader预处理宏内置状态变量多版本编译等