OSG与Shader的结合使用
1. 概述
以往在OpenGL中学习渲染管线的时候,是依次按照申请数据、传送缓冲区、顶点着色器、片元着色器这几个步骤编程的。OSG是OpenGL的一些顶层的封装,使用shader的时候看不到这些步骤了,所以有点不习惯。这里我总结了两个最简单的例子。
2. 固定管线着色
OSG一个最简单的示例是展示自带的数据glider.osg:
#include <iostream>
#include <Windows.h>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
using namespace std;
int main()
{
osg::ref_ptr<osg::Group> root= new osg::Group();
string osgPath = "D:/Work/OSGBuild/OpenSceneGraph-Data/glider.osg";
osg::Node * node = osgDB::readNodeFile(osgPath);
root->addChild(node);
osgViewer::Viewer viewer;
viewer.setSceneData(root);
viewer.setUpViewInWindow(100, 100, 800, 600);
return viewer.run();
}
显示的结果是一个简单的滑翔机:

用文本的方式打开glider.osg这个数据,里面记录的是其顶点信息:

这个数据应该是通过固定管线渲染出来的,那么可以为这个场景加入Shader:
#include <iostream>
#include <Windows.h>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
using namespace std;
//设置纹理着色
static void ColorShader(osg::ref_ptr<osg::Node> node)
{
const char * vertexShader = {
"void main(void ){\n"
" gl_FrontColor = gl_Color;\n"
" gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;\n"
"}\n"
};
const char * fragShader = {
"void main(void){\n"
" gl_FragColor = gl_Color;\n"
"}\n"
};
osg::StateSet * ss = node->getOrCreateStateSet();
osg::ref_ptr<osg::Program> program = new osg::Program();
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragShader));
program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShader));
ss->setAttributeAndModes(program, osg::StateAttribute::ON);
}
int main()
{
osg::ref_ptr<osg::Group> root= new osg::Group();
string osgPath = "D:/Work/OSGBuild/OpenSceneGraph-Data/glider.osg";
osg::Node * node = osgDB::readNodeFile(osgPath);
root->addChild(node);
ColorShader(node);
osgViewer::Viewer viewer;
viewer.setSceneData(root);
viewer.setUpViewInWindow(100, 100, 800, 600);
return viewer.run();
}
这段着色器代码是什么意思呢?其实很简单,当使用固定管线的glColor函数后,该颜色值就以作为内置gl_Color变量传入顶点着色器, 顶点着色器计算通过gl_FontColor和gl_BackColor保存正面和反面的值;而继续传入到片元着色器之后,gl_Color则会变成一个由FontColor和BackColor插值计算出来的变量。最终gl_FragColor接受到的就是固定管线渲染得到的值。运行的结果如下:

最终的结果与之前的结果有所差异,这是osgViewer的默认场景中是有灯光效果的,可编程管线的渲染效果覆盖了固定管线的效果。可以在之前固定管线渲染的例子中加入一句代码
root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
去除光照效果,两者的渲染效果就完全一致了。
3. 纹理着色
另一个例子是通过OSG加载一个带纹理的OSGB模型:
#include <iostream>
#include <Windows.h>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
using namespace std;
int main()
{
osg::ref_ptr<osg::Group> root= new osg::Group();
string osgPath = "D:/Data/scene/Dayanta_OSGB/Data/MultiFoderReader.osgb";
osg::Node * node = osgDB::readNodeFile(osgPath);
root->addChild(node);
osgViewer::Viewer viewer;
viewer.setSceneData(root);
viewer.setUpViewInWindow(100, 100, 800, 600);
return viewer.run();
}
运行结果会发现某些视角下场景发暗,这同样也是由于场景中的默认光线造成的:

采取同样的方式,通过shader覆盖固定管线的渲染效果:
//设置纹理着色
static void TextureShader(osg::ref_ptr<osg::Node> node)
{
const char * vertexShader = {
"void main(void ){\n"
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
" gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;\n"
"}\n"
};
const char * fragShader = {
"uniform sampler2D baseTexture;\n"
"void main(void){\n"
" vec2 coord = gl_TexCoord[0].xy;\n"
" vec4 C = texture2D(baseTexture, coord)\n;"
" gl_FragColor = C;\n"
"}\n"
};
osg::StateSet * ss = node->getOrCreateStateSet();
osg::ref_ptr<osg::Program> program = new osg::Program();
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragShader));
program->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShader));
ss->setAttributeAndModes(program, osg::StateAttribute::ON);
}
int main()
{
osg::ref_ptr<osg::Group> root= new osg::Group();
string osgPath = "D:/Data/scene/Dayanta_OSGB/Data/MultiFoderReader.osgb";
osg::Node * node = osgDB::readNodeFile(osgPath);
root->addChild(node);
TextureShader(node);
osgViewer::Viewer viewer;
viewer.setSceneData(root);
viewer.setUpViewInWindow(100, 100, 800, 600);
return viewer.run();
}
这段shader代码也比较简单,在顶点着色器中,gl_MultiTexCoord0表示在启用多重纹理时的0号纹理单元的坐标顶点,将其保存在预先定义的纹理坐标gl_TexCoord[0]中。gl_TexCoord[0]经过插值后传入片元着色器,通过自定义的纹理单元变量sampler2D baseTexture,使用texture2D函数获取像素值。最终的渲染效果如下:

4. 参考
[1].GLSL下几个简单的Shader
[2].GLSL 纹理贴图
OSG与Shader的结合使用的更多相关文章
- osg使用shader动态修改纹理坐标
#include <osg/Node> #include <osg/Geometry> #include <osg/Notify> #include <osg ...
- OSG3.4内置Examples解析【目录】
opengl渲染管线 从整体上解读OpenGL的渲染流程 一 从整体上解读OpenGL的渲染流程 二 osg与animate相关示例解析 OSG3.4内置Examples(osganimate)解析 ...
- [OSG]如何用Shader得到物体的世界坐标
来自:http://www.cnblogs.com/hesicong/archive/2008/05/27/1208312.html 最近群里面有个朋友问我关于如何得到OpenGL世界坐标的问题,当时 ...
- osg内置shader变量
uniform int osg_FrameNumber:当前OSG程序运行的帧数: uniform float osg_FrameTime:当前OSG程序的运行总时间: uniform float o ...
- osg Shader 着色器
#ifdef _WIN32 #include <Windows.h> #endif // _WIN32 #include <osg/Group> #include <os ...
- osg shader 相机观察矩阵逆矩阵 求顶点世界坐标
uniform mat4 osg_ViewMatrixInverse;//osg内置uniform void main() { vec4 posWorld = osg_ViewMatrixInvers ...
- [比较老的文章]三维渲染引擎 OGRE 与 OSG 的比较综述
1 .引言随着计算机可视化.虚拟现实技术的飞速发展,人们对实时真实感渲染以及场景复杂度提出了更高的要求.传统的直接使用底层图形接口如OpenGL.DirectX开发图形应用的模式越来越暴露出开发复杂性 ...
- [OSG]OSG例子程序简介
1.example_osganimate一)演示了路径动画的使用(AnimationPath.AnimationPathCallback),路径动画回调可以作用在Camera.CameraView.M ...
- osg实例介绍
osg实例介绍 转自:http://blog.csdn.net/yungis/article/list/1 [原]osgmotionblur例子 该例子演示了运动模糊的效果.一下内容是转自网上的:原理 ...
随机推荐
- ehcache的使用 Shiro与Ehcache的结合(附:EhcacheUtils)
ehcache 缓存的使用 合理的使用缓存会极大的提高程序的运行效率.切记:缓存请勿滥用. 配置ehcache与Shiro shiro初识请查看该文章 https://blog.csdn.net/py ...
- tablayout_不能左右滑动问题小计
<android.support.design.widget.TabLayout android:id="@+id/tab_pic" android:layout_width ...
- 架构师小跟班:SSL证书免费申请及部署,解决页面样式错乱问题完整攻略
申请证书 1.登录阿里云控制台,产品与服务,选择SSL证书 2.进入SSL证书页面,点击“购买证书”,选择免费1年的证书类型,点击“立即购买” 3.返回SSL证书页面,可以看到证书列表里多了一条记录 ...
- Java简单公式计算器
最近给公司开发业务代码时,碰到一个场景,简单描述是这样的: 客户要向咱们公司定制一件产品,这个产品呢,有很多属性,那公司得根据这些属性报价呀,怎么报价呢?公司针对某种类型的产品有一个基准价,在同类产品 ...
- nodejs 获取客户端 ip 地址
应用场景: php:我们需要拿到用户客户端的ip信息,以识别用户位置,但现在我们拿到的地址永远是杭州 前端:我查一下,稍等 .... 明白了,我们加了一层 node 服务器,服务器在杭州,你们拿到的是 ...
- KNN算法实现手写体区分
KNN算法在python里面可以使用pip install指令安装,我在实现之前查看过安装的KNN算法,十分全面,包括了对于手写体数据集的处理.我这里只是实现了基础的识别方法,能力有限,没有数据处理方 ...
- get解决乱码的方式
//自定义的解决乱码方式
- IntelliJ IDEA 2019.2最新解读:性能更好,体验更优,细节处理更完美!
idea 2019.2 准备 idea 2019.2正式版是在2019年7月24号发布的,本篇文章,我将根据官方博客以及自己的理解来进行说明,总体就是:性能更好,体验更优,细节处理更完美! 支持jdk ...
- EF Core的Code First 基础
一.创建实体类与映射类 通过NuGet引用Microsoft.EntityFrameworkCore 1.创建实体类 Code First可以通过为实体类字段添加相应特性,来创建对应的字段类型等,举例 ...
- PyQt4 在Windows下安装
快来加入群[python爬虫交流群](群号570070796),发现精彩内容. 首先在网上下载sip文件下载完之后解压, 在Windows的开始菜单栏中进入sip的解压目录下: 在目录下面 ...