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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM