简单记录一下在OSG中使用OpenGL函数(以及glad库)绘制自定义图形。

源码:

#include <osgViewer/viewer>
#include <osg/Geode>#include "CustomDrawable.h"int main()
{osg::ref_ptr<osg::Geode> root = new osg::Geode;root->addDrawable(new CustomDrawable);osgViewer::Viewer viewer;viewer.setSceneData(root);viewer.realize();viewer.getCamera()->getGraphicsContext()->getState()->resetVertexAttributeAlias(false);viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);viewer.getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);return viewer.run();
}
#include <osg/Drawable>class CustomDrawable:public osg::Drawable
{public:CustomDrawable();~CustomDrawable();protected:osg::BoundingBox computeBoundingBox() const override;void drawImplementation(osg::RenderInfo& renderInfo) const override;private:GLfloat* vertices = nullptr;GLuint* indices = nullptr;mutable unsigned int vao;mutable unsigned int vbo;mutable unsigned int ebo;mutable bool doOnce = true;
};
#include "CustomDrawable.h"CustomDrawable::CustomDrawable()
{this->setUseDisplayList(false);this->setUseVertexBufferObjects(true);vertices = new GLfloat[2 * 2 * 3];vertices[0] = 1.0;vertices[1] = 1.0;vertices[2] = 0.0;vertices[3] = 1.0;vertices[4] = -1.0;vertices[5] = 0.0;vertices[6] = -1.0;vertices[7] = -1.0;vertices[8] = 0.0;vertices[9] = -1.0;vertices[10] = 1.0;vertices[11] = 0.0;indices = new GLuint[6];indices[0] = 0;indices[1] = 1;indices[2] = 2;indices[3] = 2;indices[4] = 3;indices[5] = 0;
}CustomDrawable::~CustomDrawable()
{}osg::BoundingBox CustomDrawable::computeBoundingBox() const
{return osg::BoundingBox(osg::Vec3f(-1.0, -1.0, -1.0), osg::Vec3f(1.0, 1.0, 1.0));
}void CustomDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
{auto ext = renderInfo.getState()->get<osg::GLExtensions>();if (doOnce) {ext->glGenVertexArrays(1, &vao);ext->glBindVertexArray(vao);ext->glGenBuffers(1, &vbo);ext->glBindBuffer(GL_ARRAY_BUFFER_ARB, vbo);ext->glBufferData(GL_ARRAY_BUFFER_ARB, 2 * 2 * 3 * 4, vertices, GL_STATIC_DRAW);ext->glGenBuffers(1, &ebo);ext->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, ebo);ext->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, 6 * 4, indices, GL_STATIC_DRAW);ext->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);ext->glEnableVertexAttribArray(0);doOnce = false;}ext->glBindVertexArray(vao);ext->glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0, 1);
}

运行效果:

--------------------------------------------------- 12月7日更新 ---------------------------------------------------
使用着色器:
主要是drawImplementation函数内的改动。
需要注意的是似乎这样直接调用OpenGL函数绘制,并使用着色器的话,内置的osg_ModelViewProjectionMatrix变量就失效了,需要自行获取ModelViewMatrix和ProjectionMatrix输入着色器。

void CustomDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
{auto ext = renderInfo.getState()->get<osg::GLExtensions>();//获取ModelViewMatrix和ProjectionMatrixauto mvMatrix = renderInfo.getState()->getModelViewMatrix();auto proMatrix = renderInfo.getState()->getProjectionMatrix();auto mvValue = mvMatrix.ptr();auto proValue = proMatrix.ptr();float _mvMatrix[16];float _proMatrix[16];for (int i = 0; i < 16; i++) {_mvMatrix[i] = (float)mvValue[i];_proMatrix[i] = (float)proValue[i];}if (doOnce) {ext->glGenVertexArrays(1, &vao);ext->glBindVertexArray(vao);ext->glGenBuffers(1, &vbo);ext->glBindBuffer(GL_ARRAY_BUFFER_ARB, vbo);ext->glBufferData(GL_ARRAY_BUFFER_ARB, N * N * 3 * 4, vertices, GL_STATIC_DRAW);ext->glGenBuffers(1, &ebo);ext->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, ebo);ext->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, (N - 1) * (N - 1) * 6 * 4, indices, GL_STATIC_DRAW);ext->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);ext->glEnableVertexAttribArray(0);//Shader为自己简单封装的一个类,内容跟OpenGL中使用Shader一致vfShader = new Shader(ext, "./Test.vert", "./Test.frag");doOnce = false;}vfShader->Bind();vfShader->SetMat4("modelViewMatrix", _mvMatrix);vfShader->SetMat4("projectionMatrix", _proMatrix);ext->glBindVertexArray(vao);ext->glDrawElementsInstanced(GL_TRIANGLES, (N - 1) * (N - 1) * 6, GL_UNSIGNED_INT, (void*)0, 1);
}

顶点着色器:

#version 430layout(location = 0) in vec3 vPos;//uniform mat4 osg_ModelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;void main()
{gl_Position = projectionMatrix*modelViewMatrix*vec4(vPos,1.0);
}

片元着色器:

#version 430out vec4 FragColor;void main()
{FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

另外computeBoundingBox函数中设置的包围盒大小一定要大于等于图形的大小,不然会产生裁切问题,如下图,包围盒顶点的值是±1.0,图形顶点的值是±256.0,垂直在一定角度范围内是正常的,但是再继续倾斜就会发生裁切。另外,包围盒的大小也会影响程序刚运行时初始视角离图形的远近,例如包围盒设置±512.0就会比设置±256.0的初始视角要远。

嵌入glad库:(还在尝试)
glad+glfw库是很多OpenGL资料中非常常见的一种搭配,因为在查询OSG使用OpenGL绘制自定义图形的资料时,找到了在OSG中用glut库的glutSolidTeapot函数绘制teapot,所以想既然glut都能嵌入使用,那glad是不是也可以呢?因为很多OpenGL资料都是用的glad,如果能够找到办法嵌入使用,那么就可以直接挪到OSG中而不用想办法转换实现。

先说结论:理论上似乎是可以,但是glGetString不知道为什么获取不到,并且文件包含比较麻烦。 可以。

1、首先glad头文件的包含问题
因为OSG底层包含了系统的gl.h文件,其中当没有定义__gl_h_这个宏的时候会定义这个宏,所以当这个宏已经被定义了的时候,glad会报错:

然后就需要把glad.h的包含放在整个代码的最前面,像下面这样
在CustomDrawable.h中放在最前面

然后把CustomDrawable.h的包含放在main.cpp最前面

这样就不会报这个错了。

2、glad的初始化
glad库使用时先需要对glad进行初始化,在glad+glfw库的使用中,glad的初始化是由gladLoadGLLoader函数来完成的。

由glfwGetProcAddress的名称、注释以及接口参数可以得知,这是一个通过传入名称来获取函数地址的函数。
通过gladLoadGLLoader的源码可以得知,glad通过传入的glfwGetProcAddress函数来初始化自身的函数指针接口。
所以我需要在OSG中找到一个能够通过名称来获取函数地址的函数。
因为OSG的OpenGL相关函数主要都在GLExtensions类中,所以就先在它的头文件中寻找,然后发现有一个在类外的函数叫做getGLExtensionFuncPtr正好是我需要的,在doOnce中加入如下代码:

结果发现并不能初始化成功,单步跟入gladLoadGLLoader函数内,发现是在第一步获取glGetString时返回为空。

然后尝试单独调用getGLExtensionFuncPtr,发现确实无法获取到glGetString,但是像glGenBuffers什么的都是可以获取到的。
查看getGLExtensionFuncPtr的源码,发现它是通过调用wingdi.h中的wglGetProcAddress来获取函数地址,目前暂不清楚为什么wglGetProcAddress获取不到glGetString的函数地址…

--------------------------------------------------- 12月8日更新 ---------------------------------------------------
查找资料发现wglGetProcAddress这个函数只能获取OpenGL 1.1+的拓展,而glGetString是OpenGL 1.0的,所以这个函数无法获取到glGetString的函数地址。
接着在StackOverFlow上找到了关于wgl+glad的提问,里面提到了用gladLoadGL()进行初始化,这是glad的另一个初始化函数。
这里需要注意如果调用gladLoadGL()返回false有可能是因为没有添加opengl32.lib,需要在附加依赖项中添加这个lib,原因查看glad源码可知。

主要是drawImplementation函数内的改动。

void CustomDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
{//获取ModelViewMatrix和ProjectionMatrixauto mvMatrix = renderInfo.getState()->getModelViewMatrix();auto proMatrix = renderInfo.getState()->getProjectionMatrix();auto mvValue = mvMatrix.ptr();auto proValue = proMatrix.ptr();float _mvMatrix[16];float _proMatrix[16];for (int i = 0; i < 16; i++) {_mvMatrix[i] = (float)mvValue[i];_proMatrix[i] = (float)proValue[i];}if (doOnce) {if (!gladLoadGL()){std::cout << "Failed to initialize GLAD" << std::endl;}glGenVertexArrays(1, &vao);glBindVertexArray(vao);glGenBuffers(1, &vbo);glBindBuffer(GL_ARRAY_BUFFER, vbo);glBufferData(GL_ARRAY_BUFFER, N * N * 3 * 4, vertices, GL_STATIC_DRAW);glGenBuffers(1, &ebo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, (N - 1) * (N - 1) * 6 * 4, indices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);vfShader = new Shader("./Test.vert", "./Test.frag");doOnce = false;}glUseProgram(vfShader->id);auto modelViewLoc = glGetUniformLocation(vfShader->id, "modelViewMatrix");auto projectionLoc = glGetUniformLocation(vfShader->id, "projectionMatrix");glUniformMatrix4fv(modelViewLoc, 1, GL_FALSE, _mvMatrix);glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, _proMatrix);glBindVertexArray(vao);//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);glDrawElements(GL_TRIANGLES, (N - 1) * (N - 1) * 6, GL_UNSIGNED_INT, (void*)0);
}

运行效果:

OSG使用OpenGL(以及glad库)绘制自定义图形相关推荐

  1. 【OpenGL】使用OpenGL的GLU库绘制BSpline曲线

    [OpenGL]使用OpenGL的GLU库绘制BSpline曲线. 1.绘制目标 2.核心代码 3.运行结果 1.绘制目标 使用OpenGL的GLU库绘制BSpline曲线. 2.核心代码 /// T ...

  2. Python之PIL之绘图:基于Python的PIL库绘制各种图形、添加文字等

    Python之PIL之绘图:基于Python的PIL库绘制各种图形.添加文字等 目录 一.绘制各种形状各种案例 1.绘制矩形 2.绘制圆形.弧线形

  3. Python之Turtle库绘制简单图形

    Python之Turtle库绘制简单图形 来绘制正方形.三角形.五边形.五角形 import turtle #引入turtle库pen=turtle.Turtle() #创建turtle类型的画笔 # ...

  4. python的turtle怎么画曲线_利用 turtle库绘制简单图形

    turtle库是python的基础绘图库,这个库被介绍为一个最常用的用来介绍编程知识的方法库,其主要是用于程序设计入门,是标准库之一,利用turtle可以制作很多复杂的绘图. turtle名称含义为& ...

  5. python如何画贝塞尔曲线_Python使用matplotlib实现绘制自定义图形功能示例

    本文实例讲述了Python使用matplotlib实现绘制自定义图形功能.分享给大家供大家参考,具体如下: 一 代码 from matplotlib.path importPath from matp ...

  6. python编程题2.2:turtle库绘制风轮图形

    turtle库绘制风轮图形 使用turtle库,绘制一个风轮效果,其中,每个风轮内角为45度,风轮边长150像素. import turtle as t #设置画笔 t.setup(600,600) ...

  7. python turtle画有趣的图形_Python turtle库绘制简单图形

    一.简介 Python中的turtle库是一个直观有趣的图形绘制函数库.turtle库绘制图形有一个基本框架:一个小海龟在坐标系中爬行,其爬行轨迹形成了绘制图形. 二.简单的图形列举 1.绘制4个不同 ...

  8. 软件项目技术点(7)——在canvas上绘制自定义图形

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 图形种类 目前我们软件可以绘制出来的形状有如下这几种,作为开发者我们一直想支持用户可以拖拽的类似word里面图形库,但目前还没有找到比 ...

  9. OpenGL与3D开发-绘制3D图形

    绘制3D图形 文章目录 绘制3D图形 1.立方体 2.圆形 3.球形 3.1.球面顶点坐标计算 使用OpenGL ES绘制3D图形的方法与绘制2D图形的步骤大致相同,只是绘制3D图形需要定义更多的顶点 ...

最新文章

  1. JavaSE_NIO_ByteBuffer
  2. spring cloud config将配置存储在数据库中 1
  3. KDD 2021 | 小红书推荐多样性解决方案:SSD在质量、多样性之间获得较好权衡
  4. vue中用的swiper轮播图的用法及github的地址
  5. vector的基本用法 (详解 + 代码演示)
  6. opencv--图像金字塔
  7. 赠书 | 什么是 Knative?
  8. 用python计算列表元素之和_python实现计算列表元素之和
  9. Golang官方限流器的用法详解
  10. 利用pil库处理图像
  11. php pdf压缩工具,在线压缩PDF文件的工具
  12. 计算机网络考研知识点总结,2020计算机专业考研的计算机网络部分知识点
  13. java无头浏览器_Java + Selenium 无头浏览器模式
  14. centos oracle卸载
  15. Unity StanderShader系列1---ForwardBase源码解析
  16. Ubuntu修改/home下各目录为英文
  17. 一位想学习编程拯救他人的初中生
  18. 验证码—基本功能实现02_点击重新获取验证码
  19. 39.(前端)欢迎页面的设置
  20. 【图像处理】卷积算法

热门文章

  1. 电脑计算机硬盘怎么新建,电脑如何新建一个本地磁盘
  2. 哈,我终于成功量产:因写保护无法格式化的U盘。
  3. 内存不能为读的解决办法
  4. 关于汽油清洁剂,到底该不该加
  5. OpenCV中图像的深度
  6. 商场室内地图导航如何实现,便捷、低成本智慧商业综合体一站式解决方案
  7. php weixin provider,14、ABPZero系列教程之拼多多卖家工具 新建微信公众号模块
  8. R作图配色---颜色提取及色彩搭配
  9. 微信小程序云函数安装wx-server-sdk依赖
  10. vue原生js打印插件