查看: 4696|回复: 6

用1D纹理实现查找表操作

[复制链接]

该用户从未签到

发表于 2009-12-30 09:43:28 | 显示全部楼层 |阅读模式
varying vec4 colorIn;
uniform sampler1D lut;
void main()
{
   vec4 colorOut ;
colorOut=colorIn;
colorOut.r = texture1D(lut,colorIn.r).r;
  colorOut.g = texture1D(lut,colorIn.g).g;
colorOut.b = texture1D(lut,colorIn.b).b;
  colorOut.a = texture1D(lut,colorIn.a).a;
  gl_FragColor = colorOut;
}
在书中看到的相关代码,不知道在应用程序中应该传递一个什么样的参数?
osg::ref_ptr<osg::Uniform> unif=new osg::Uniform();
root->getOrCreateStateSet()->addUniform(unif.get());
还有osg::Uniform中setArray函数设置的数组值是用来干什么的?

该用户从未签到

发表于 2009-12-30 10:44:25 | 显示全部楼层
这里唯一的一致变量就是sampler1D lut,因此,首先您要保证应用程序中有一个Texture1D对象,并且通过setTextureAttributeAndModes设置给了某个节点的渲染状态集。然后,如果这个对象位于纹理单元0的话,那么addUniform( new Uniform("lut", 0) )就可以将它绑定到GLSL了。我和FlySky的书中,以及已经停载的《你所不知的OSG》中都有相关的介绍,osg自己也有多个着色器相关的例子

该用户从未签到

 楼主| 发表于 2009-12-30 14:25:32 | 显示全部楼层
我想知道的是一维纹理实现查找表映射和一维纹理贴图原理相同吗?我的理解是lut相当于一个一维数组,里面存储的是新的颜色值。
shader通过  colorOut.b = texture1D(lut,colorIn.b).b;
找到本来颜色colorIn所对应的新颜色值,做颜色调整。这样的话,如果传的是一个一维纹理,那colorIn和colorOut还有区别吗?

该用户从未签到

发表于 2009-12-30 14:45:12 | 显示全部楼层
原理相同。由于GLSL能够传入的一致变量,也就是与应用程序的数据接口数量有限,因此,使用纹理查找表(lookup table)可以极大地增加用户数据的导入量,例如一个1024x1的一维纹理就相当于给着色器额外提供了1024个用户参数——这才是它的真正意义所在。

该用户从未签到

发表于 2009-12-31 10:24:33 | 显示全部楼层
如果仅仅是colorOut.b = texture1D(lut,colorIn.b).b似乎意义并不大,但这仅是一个演示,它表达的是一种方法,正如array所说的,“一个1024x1的一维纹理就相当于给着色器额外提供了1024个用户参数——这才是它的真正意义所在”!
呵呵 学习了

该用户从未签到

 楼主| 发表于 2010-1-4 11:31:51 | 显示全部楼层
麻烦帮我看一下我这个程序什么错误,运行出来一片黑。
(1)把查找表数据存成一张图片作为一维纹理
osg::ref_ptr<osg::Image> image = new osg::Image;

    image->allocateImage(768,1,1,GL_RGBA,GL_FLOAT);
    image->setInternalTextureFormat(GL_RGBA);

    osg::Vec4* dataPtr = (osg::Vec4*)image->data();
    for(int i=0;i<256;i++)  //红色0-255对应的新值
    {
        *dataPtr++ = osg::Vec4(lutR[i],0.0,0.0,1.0f);
    }
    for(int i=0;i<256;i++)//绿色0-255对应的新值
    {
        *dataPtr++ = osg::Vec4(0.0,lutG[i],0.0,1.0f);
    }
    for(int i=0;i<256;i++)//蓝色0-255对应的新值

    {
        *dataPtr++ = osg::Vec4(0.0,0.0,lutB[i],1.0f);
    }

    osg::ref_ptr<osg::Texture1D> texture = new osg::Texture1D;
    texture->setWrap(osg::Texture1D::WRAP_S,osg::Texture1D::MIRROR);
    texture->setFilter(osg::Texture1D::MIN_FILTER,osg::Texture1D:INEAR);
        texture->setImage(image.get());
(2)传参给着色器
osg::ref_ptr<osg::StateSet> state=new osg::StateSet(); //此状态集用来给着色器传参数,没有和任何节点关联,目的只是把查找表传给着色器
state->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
state->setTextureAttribute(0,texture,osg::StateAttribute::ON);
state->setTextureMode(0,GL_TEXTURE_1D,osg::StateAttribute::ON);
addVertexAndFragmentShaderFromFile("minimal.vert","minimal.frag", root.get());  //将着色器给根结点
state->addUniform(new osg::Uniform("lut",0));
(3)着色器内容
colorOut.r = texture1D(lut,colorIn.r).r;
colorOut.g = texture1D(lut,colorIn.g+256).g;
colorOut.b = texture1D(lut,colorIn.b+512).b;
colorOut.a = 1.0;

gl_FragColor = colorOut;

该用户从未签到

发表于 2010-1-4 12:49:44 | 显示全部楼层
“此状态集用来给着色器传参数,没有和任何节点关联”,这样的话,它永远都不会加入到场景的遍历中来,换句话说,您等于什么都没有做;必须把StateSet设置给某个节点
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表