法线贴图

法线贴图

http://blog.csdn.net/zp373860147/article/details/6758828


案例:


water.vert

varying vec3 lightdir;           //切线空间灯光向量;
varying vec3 eyedir;             //切线空间眼点向量;
varying vec4 ambient, diffuse, specular;
attribute vec3 tangent;          //顶点切线;
uniform float time;                       //时间更新;
uniform vec3  lightPos;         //灯光的位置;
void main()
{
         vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
         vec3 L = normalize(lightPos - vVertex);                 //定点到光源向量;
         vec3 E = normalize(-vVertex);                                     //定点到眼点向量;
         vec3 N = normalize(gl_NormalMatrix * gl_Normal);
         vec3 H = normalize(L + E);
         //获取漫反射, 镜面反射量;
         ambient = vec4(1.0,1.0,1.0,1.0);
         diffuse = vec4(1.0,1.0,1.0,1.0);
         specular = vec4(1.0,1.0,1.0,1.0);
         float _diffuse = max(dot(L, N), 0.0);
         if(_diffuse > 0.0)
         {
                 diffuse = diffuse * _diffuse;
                 float _specular = max(dot(H,N),0.0);
                 specular = specular * pow(_specular , 64.0);
         }
         //计算切线空间量;
         vec3 T = normalize(vec3(gl_NormalMatrix * tangent));
         vec3 B = normalize(cross(N,T));
 
         lightdir.x = dot(L,T);
         lightdir.y = dot(L,B);
         lightdir.z = dot(L,N);
         lightdir = normalize(lightdir);
 
         eyedir.x = dot(E,T);
         eyedir.y = dot(E,B);
         eyedir.z = dot(E,N);
         lightdir = normalize(eyedir);
 
         gl_TexCoord[0] = gl_MultiTexCoord0;
        
         //根据时间获取法线纹理位置;
         gl_TexCoord[1].x = gl_TexCoord[0].x + time * 0.05;
         gl_TexCoord[1].y = gl_TexCoord[0].y + time * 0.05;
 
         gl_Position  = ftransform();
}


water.frag

varying vec3 lightdir;
varying vec3 eyedir;
varying vec4 ambient, diffuse, specular;
uniform sampler2D baseTex;
uniform sampler2D normTex;
void main()
{
vec3 L = normalize(lightdir);
        vec3 E = normalize(eyedir);
        vec4 _baseColor = texture2D(baseTex, gl_TexCoord[0].xy);
        vec3 _normColor = texture2D(normTex, gl_TexCoord[1].xy).xyz;
        
        _baseColor = texture2D(baseTex, gl_TexCoord[0].xy + _normColor * 0.35); //调制底面纹理波动;
        _normColor = texture2D(normTex, gl_TexCoord[1].xy + _normColor * 0.02).xyz;
        vec3 N = normalize(_normColor * 2.0 - vec3(1.0));     //将法线转到[-1,1]范围;
        float _diff = max(dot(L,N),0.0);
        float _spec = max(dot(E,N),0.0);
        if(_diff > 0.0)
        {
_spec = pow(_spec, 64.0);
        }
gl_FragColor = vec4(ambient.xyz * _baseColor.xyz + diffuse.xyz * _diff * _baseColor.xyz + specular * _spec, 1.0);
}


#include "StdAfx.h"
#include "osg/Geode"
#include "osg/Geometry"
#include "osg/Texture2D"
#include "osgDB/ReadFile"
#include "osgViewer/Viewer"
#include "osgGA/TrackballManipulator"


osg::ref_ptr<osg::Geode> createPlane(int _w, int _h)
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
geode->addDrawable(geom);
osg::ref_ptr<osg::Vec3Array> vArr = new osg::Vec3Array;
vArr->push_back(osg::Vec3(-_w/2.0,0,-_h/2.0));
vArr->push_back(osg::Vec3(-_w/2.0,0,_h/2.0));
vArr->push_back(osg::Vec3(_w/2.0,0,_h/2.0));
vArr->push_back(osg::Vec3(_w/2.0,0,-_h/2.0));
geom->setVertexArray(vArr);
osg::ref_ptr<osg::Vec2Array> tArr = new osg::Vec2Array;
tArr->push_back(osg::Vec2(0.0,0.0));
tArr->push_back(osg::Vec2(0.0,1.0));
tArr->push_back(osg::Vec2(1.0,1.0));
tArr->push_back(osg::Vec2(1.0,0.0));
geom->setTexCoordArray(0, tArr);
osg::ref_ptr<osg::Vec3Array> nArr = new osg::Vec3Array;
nArr->push_back(osg::Vec3(0.0,-1.0,1.0));
geom->setNormalArray(nArr);
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
return geode;
}


int main(int argc, char *argv[])
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
osg::ref_ptr<osg::Group> _root = new osg::Group;
osg::ref_ptr<osg::Geode>  _waterPanle = createPlane(500,500);
_root->addChild(_waterPanle);
//背景图片;
osg::ref_ptr<osg::Texture2D> baseTex = new osg::Texture2D;
baseTex->setImage(osgDB::readImageFile("water.jpg"));
baseTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
baseTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
//法线图;
osg::ref_ptr<osg::Texture2D> normTex = new osg::Texture2D;
normTex->setImage(osgDB::readImageFile("water.jpg"));
normTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
normTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
_waterPanle->getOrCreateStateSet()->setTextureAttributeAndModes(0, baseTex, 1);
_waterPanle->getOrCreateStateSet()->setTextureAttributeAndModes(1, normTex, 1);


osg::ref_ptr<osg::Program> program = new osg::Program;
osg::ref_ptr<osg::Shader>  vertShader = new osg::Shader(osg::Shader::VERTEX);
osg::ref_ptr<osg::Shader>  fragShader = new osg::Shader(osg::Shader::FRAGMENT);
program->addShader(vertShader);
program->addShader(fragShader);
if(!vertShader->loadShaderSourceFromFile("water.vert"))
{
printf("load vertex shader error !\n");
}
if(!fragShader->loadShaderSourceFromFile("water.frag"))
{
printf("load fragment shader error !\n");
}
_waterPanle->getOrCreateStateSet()->setAttribute(program, 1);
_waterPanle->getOrCreateStateSet()->addUniform(new osg::Uniform("time", float(0.0)));
_waterPanle->getOrCreateStateSet()->addUniform(new osg::Uniform("baseTex", 0));
_waterPanle->getOrCreateStateSet()->addUniform(new osg::Uniform("normTex", 1));
_waterPanle->getOrCreateStateSet()->addUniform(new osg::Uniform("lightPos", osg::Vec3(0.0,0.0,0.0)));//lightPos


viewer->setSceneData(_root);
viewer->setCameraManipulator(new osgGA::TrackballManipulator);
while(!viewer->done())
{
float _time = viewer->getFrameStamp()->getSimulationTime();
_waterPanle->getOrCreateStateSet()->getUniform("time")->set(_time);
osg::Matrix _mmt = viewer->getCamera()->getViewMatrix();
_waterPanle->getOrCreateStateSet()->getUniform("lightPos")->set(_mmt.getTrans());
viewer->frame();
}
}

资源图:


效果图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值