OSG使用顶点着色器和片元着色器(基于GLSL430版本)

一、前言

网上已经有很多OSG使用顶点着色器和片元着色器的方法,但是绝大多都是基于GLSL120、140等版本,对于现有网上OpenGL的Shader资料(基于GLSL330版本往后)都太过老了,偶尔有基于330版本的,但是又因为部分设置没有细说导致没能成功使用,在此经过自己测试做个记录。

参考资料:杨石兴大佬的文章 https://blog.csdn.net/FreeSouthS/article/details/118971243
基于OSG版本:3.6.3

二、代码

先直接上代码:

#include <osgViewer/viewer>
#include <osgDB/ReadFile>
#include <osg/Texture2D>
#include <osg/BindImageTexture>
#include <osg/DispatchCompute>
#include <osg/PolygonMode>

int main()
{
    
    
    auto node = osgDB::readNodeFile("./objects/rock/rock.obj");

    osg::ref_ptr<osg::Group> scene = new osg::Group;
    scene->addChild(node);

    //use Shader
    osg::ref_ptr<osg::StateSet> ss = node->getOrCreateStateSet();
    ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    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);
    vertShader->loadShaderSourceFromFile("./Test.vert");
    fragShader->loadShaderSourceFromFile("./Test.frag");
    program->addShader(vertShader);
    program->addShader(fragShader);
    ss->setAttributeAndModes(program);

    osgViewer::Viewer viewer;
    viewer.setSceneData(scene);
    viewer.realize();
    //三句话
    viewer.getCamera()->getGraphicsContext()->getState()->resetVertexAttributeAlias(false);//1
    viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);//2
    viewer.getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);//3
    return viewer.run();
}

顶点着色器:

#version 430

uniform mat4 osg_ModelViewProjectionMatrix;
in vec4 osg_Vertex;
in vec3 osg_Normal;

out vec3 color;

void main()
{
    
    
	float theta = dot(osg_Normal, normalize(vec3(0.0, 1.0, 0.0)));
	color = vec3(0.0, 1.0, 0.0)*theta;

	gl_Position = osg_ModelViewProjectionMatrix*osg_Vertex;
}

片元着色器:

#version 430

in vec3 color;

out vec4 FragColor;

void main()
{
    
    
	FragColor = vec4(color, 1.0);
}

不使用着色器效果:

在这里插入图片描述

使用着色器效果:

在这里插入图片描述

三、记录

0、 最重要的就是代码中最下面做了标记的三句话。
1、 在默认情况下,OSG主要使用的是OpenGL2.0及之前版本(固定管线)的GLSL语法(具有gl_Vertex、gl_Normal、gl_ModelViewProjectionMatrix、ftransform()等内置变量和函数),当使用OpenGL3.3及之后版本(可编程管线)的GLSL语法,上述的内置变量和函数就已经被淘汰掉了,导致没办法通过上述内置变量和函数取到载入模型的顶点、法线、场景变换矩阵等。
2、 因为1,所以在OSG中内置了变量进行替换,如gl_Vertex替换成了osg_Vertex,gl_Normal替换成了osg_Normal,gl_ModelViewProjectionMatrix替换成了osg_ModelViewProjectionMatrix,ftransform()替换成了osg_ModelViewProjectionMatrix*osg_Vertex等。
3、 如果按照替换变量直接写高版本的Shader,结果会是模型显示不出来,原因是OSG没有将场景变换矩阵赋值,需要调用setUseModelViewAndProjectionUniforms为true,osg_ModelViewProjectionMatrix等变换矩阵才会生效,注意此设置仅使变换矩阵生效。
4、 在3的基础上,如果Shader中有使用osg_Normal、osg_Color等除osg_Vertex以外的其他内置变量,会发现它们并没有值,这里分两种情况。
4.1、 不使用osg内置变量,shader中将

in vec4 osg_Vertex;
in vec3 osg_Normal;

改为:

layout(location = 0) in vec3 vPos;
layout(location = 2) in vec3 vNormal;

这样。
4.2、 调用setUseVertexAttributeAliasing为true,根据参考的大佬的文章
在这里插入图片描述
这里最重要的是Shader中默认location会发生改变,文章中所说N卡下默认是vertex-0 normal-2 color-3等,设置后变为vertex-0 normal-1 color-2等。但是会产生一个问题,因为默认索引的改变,所以当载入的模型不使用Shader时(因为是由GraphicsContext的State调用,所以是全局生效会影响到不使用Shader的模型节点),会关联不上法线、材质坐标等从而变成灰模。

在这里插入图片描述

5、 在4.2的基础上,调用resetVertexAttributeAlias为false(注意查看OSG源码中这个函数的注释,这个函数只能在开始渲染之前调用才有效,测试后发现还必须在setUseVertexAttributeAliasing之前调用),调用后发现不使用Shader时,模型正常载入不会出现灰模问题,OSG内置变量也正常取到值。查看源码发现,此函数是将OSG内置变量和OpenGL内置变量做了个别名和索引的映射,调用是在State类的构造里,默认为true,此时osg_Vertex、osg_Normal、osg_Color分别为0、1、2,当为false时为0、2、3对应4.2中的改变。

在这里插入图片描述

6、 所以setUseVertexAttributeAliasing启用的是resetVertexAttributeAlias中所做的映射。
7、 经过测试,使用4.1的写法
当不调用setUseVertexAttributeAliasing,此时normal的location为2。
当调用setUseVertexAttributeAliasing为true,不调用resetVertexAttributeAlias,此时normal的location为1。
当调用setUseVertexAttributeAliasing为true,调用resetVertexAttributeAlias为false,此时normal的location为2。
这里猜测底层固定管线默认索引为4.2中所述(我用的N卡),但是当启用了setUseVertexAttributeAliasing后,上层索引就由resetVertexAttributeAlias所做的映射来接手决定了,默认(在State的构造中调用)的情况下normal的location为1,与底层索引不匹配,所以导致不使用Shader时取不到模型除顶点以外的数据从而成灰模。

猜你喜欢

转载自blog.csdn.net/qq_45523399/article/details/128173906
今日推荐