在前边几节,纹理坐标数组是在生成geometry前指定的。
这里在shader里计算,
一,注释掉geometry中的纹理坐标
//osg::ref_ptr<osg::Vec2Array> texCoord = new osg::Vec2Array;
//texCoord->push_back(osg::Vec2(0.0, 0.0));
//texCoord->push_back(osg::Vec2(1.0, 0.0));
//texCoord->push_back(osg::Vec2(1.0, 1.0));
//texCoord->push_back(osg::Vec2(0.0, 1.0));
//geom->setTexCoordArray(0, texCoord);
二,由于位置坐标是[-1,1],纹理坐标是[0,1],所以可以在顶点着色器里凑个公式,以满足位置坐标和纹理坐标的关系。
"vec2 coord = sign(gl_Vertex.xy);"
"texCoord.x = coord.x * 0.5 + 0.5;"
"texCoord.y = coord.y * 0.5 + 0.5;"
三,由于纹理坐标是在顶点着色器中计算的,还要传递给片元着色器,所以要加上
“varying vec2 texCoord;”
四,在应用程序中,由于颜色缓冲区的纹理设置为第0个,所以对第0个纹理进行采样。在shader中传递0过去。(这里用N表示普适性)
stateset_panelGeode->setTextureAttributeAndModes(N, tex);
osg::ref_ptr<osg::Uniform> tex1 = new osg::Uniform("tex1", N);
stateset_panelGeode->addUniform(tex1);
"uniform sampler2D tex1;"
五,在片元着色器中采样,(这里只采样,没进行其他操作,所以图像不变)
"gl_FragColor = texture2D(tex1,texCoord);"
运行结果如下
代码如下:
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>
#include <osg/Switch>
#include <osg/Types>
#include <osgText/Text>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>
#include <osgGA/Device>
#include <osg/Shader>
osg::ref_ptrosg::Texture2D createFloatRectangleTexture(int width, int height)
{
osg::ref_ptrosg::Texture2D tex2D = new osg::Texture2D;
tex2D->setTextureSize(width, height);
tex2D->setInternalFormat(GL_RGBA16F_ARB);
tex2D->setSourceFormat(GL_RGBA);
tex2D->setSourceType(GL_FLOAT);
return tex2D.release();
}
osg::ref_ptrosg::Geode createTexturePanelGeode()
{
osg::ref_ptrosg::Vec3Array vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(-1.0f, -1.0f, 0.0f));
vertices->push_back(osg::Vec3(1.0f, -1.0f, 0.0f));
vertices->push_back(osg::Vec3(1.0f, 1.0f, 0.0f));
vertices->push_back(osg::Vec3(-1.0f, 1.0f, 0.0f));
//osg::ref_ptr<osg::Vec2Array> texCoord = new osg::Vec2Array;
//texCoord->push_back(osg::Vec2(0.0, 0.0));
//texCoord->push_back(osg::Vec2(1.0, 0.0));
//texCoord->push_back(osg::Vec2(1.0, 1.0));
//texCoord->push_back(osg::Vec2(0.0, 1.0));
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
geom->setVertexArray(vertices);
//geom->setTexCoordArray(0, texCoord);
geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(geom);
osg::ref_ptr<osg::StateSet> set1 = geode->getOrCreateStateSet();
set1->setMode(GL_LIGHTING, osg::StateAttribute::OFF); //设置不受光照影响,不然太暗了就看不清楚
return geode;
}
static const char * vertexShader =
{
“varying vec2 texCoord;” //顶点坐标到纹理坐标的转换
“void main(void)\n”
“{\n”
" gl_Position = ftransform();\n"
“vec2 coord = sign(gl_Vertex.xy);”
“texCoord.x = coord.x * 0.5 + 0.5;”
“texCoord.y = coord.y * 0.5 + 0.5;”
“}\n”
};
static const char *psShader =
{
“varying vec2 texCoord;” //顶点坐标(-1,1)到纹理坐标(0,1)的转换
“uniform sampler2D tex1;”
“void main(void)\n”
“{\n”
“gl_FragColor = texture2D(tex1,texCoord);”
“}\n”
};
int main()
{
osg::ref_ptrosgViewer::Viewer viewer = new osgViewer::Viewer;
//各个pass的根
osg::ref_ptrosg::Group passRoot = new osg::Group();
//场景根
osg::ref_ptrosg::Group sceneRoot = new osg::Group();
std::string strFileName = “D:/OpenSceneGraph-master/OpenSceneGraph-Data-master/cow.osg”;
osg::ref_ptrosg::Node node = osgDB::readNodeFile(strFileName);
sceneRoot->addChild(node);
//获取系统分辨率
unsigned int screenWidth, screenHeight;
osg::GraphicsContext::WindowingSystemInterface * wsInterface = osg::GraphicsContext::getWindowingSystemInterface();
if (!wsInterface)
{
return -1;
}
wsInterface->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), screenWidth, screenHeight);
int texWidth = screenWidth;
int texHeight = screenHeight;
osg::ref_ptr<osg::Texture2D> tex = createFloatRectangleTexture(texWidth, texHeight);
//绑定pass1采样摄像机
osg::ref_ptr<osg::Camera> sampleCamera = new osg::Camera;
{
sampleCamera->addChild(sceneRoot);
sampleCamera->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
sampleCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); //这句话使内容不渲染到屏幕上
sampleCamera->attach(osg::Camera::COLOR_BUFFER0, tex); //关联采样贴图
sampleCamera->setViewport(0, 0, texWidth, texHeight);//摄像机视口投影到纹理大小
}
osg::ref_ptr<osg::Geode> panelGeode = createTexturePanelGeode();
osg::ref_ptr<osg::StateSet> stateset_panelGeode = panelGeode->getOrCreateStateSet();
stateset_panelGeode->setTextureAttributeAndModes(0, tex);
#if 1
//对场景进行处理
osg::ref_ptrosg::Shader vs1 = new osg::Shader(osg::Shader::VERTEX, vertexShader);
osg::ref_ptrosg::Shader ps1 = new osg::Shader(osg::Shader::FRAGMENT, psShader);
osg::ref_ptrosg::Program program1 = new osg::Program;
program1->addShader(vs1);
program1->addShader(ps1);
osg::ref_ptrosg::Uniform tex1 = new osg::Uniform(“tex1”, 0);
stateset_panelGeode->addUniform(tex1);
stateset_panelGeode->setAttribute(program1, osg::StateAttribute::ON);
#endif
//final
osg::ref_ptr<osg::Camera> finalCamera = new osg::Camera;
{
finalCamera->addChild(panelGeode);
finalCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
}
passRoot->addChild(sampleCamera); //将摄像机加入场景
passRoot->addChild(finalCamera);
viewer->setSceneData(passRoot);
viewer->run();
return 0;
}