当前位置: 首页 > news >正文

全球网站排名现在从深圳回来需要隔离吗?

全球网站排名,现在从深圳回来需要隔离吗?,珠海做网站报价,session WordPressOverload的场景视图区有拾取鼠标功能#xff0c;单击拾取物体后会显示在Inspector面板中。本文来分析鼠标拾取这个功能背后的原理。 一、OpenGL的FrameBuffer 实现鼠标拾取常用的方式有两种#xff1a;渲染id到纹理、光线投射求交。Overload使用的是渲染id到纹理#xff0c…     Overload的场景视图区有拾取鼠标功能单击拾取物体后会显示在Inspector面板中。本文来分析鼠标拾取这个功能背后的原理。 一、OpenGL的FrameBuffer 实现鼠标拾取常用的方式有两种渲染id到纹理、光线投射求交。Overload使用的是渲染id到纹理其实现需借助OpenGL的帧缓冲FrameBuffer所以要先了解一下OpenGL的帧缓冲。 我们一般讨论的缓存默认指窗口缓存直接显示在窗口中。我们也可以创建一个自定义的缓存让GPU管线渲染到纹理当中之后在其他地方可以使用这张纹理。并且纹理中的数据只是二进制值不一定非得是颜色可以写入任意有意义的数据。 如果我们要创建帧缓存对象需要调用glGenFramebuffers()得到一个未使用的标识符。在使用帧缓存的时候需要先调用glBindFramebuffer(GL_FRAMEBUFFER, bufferID)绑定。如果要渲染到纹理贴图需调用glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENTi, textureId, level)将纹理贴图的level层级关联到帧缓存附件上。如果渲染还需要深度缓存、模板缓存那么还需要渲染缓存。 渲染缓存同样也是OpenGL所管理的一处高效内存区域它可以存储特定格式的数据其只有关联到一个帧缓存才有意义。调用glGenRenderbuffers可以创建渲染缓存操作它的时候同样需要绑定操作。绑定的时候使用glBindRenderbuffer。 看到这里是不是觉得帧缓存使用起来太复杂了其实帧缓存的设置都是固定格式的代码套路基本一样先用伪代码串一下。假设我们的程序是面向过程设计的先用调用init函数进行初始化之后主循环不断调用display函数进行渲染大致伪代码如下 init() {glGenFramebuffers(1, m_bufferID);  // 生成帧缓存glGenTextures(1, m_renderTexture)  // 生成纹理对象// 设置纹理格式glBindTexture(GL_TEXTURE_2D, m_renderTexture);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glBindTexture(GL_TEXTURE_2D, 0);// 将纹理作为颜色附件绑定到帧缓存上glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_renderTexture, 0);glGenRenderbuffers(1, m_depthStencilBuffer); // 生成渲染对象// 设置渲染对象数据格式glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, p_width, p_height);// 配置成帧缓存的深度缓冲与模板缓冲附件glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);}display() {// 1. 绑定帧缓存glBindFramebuffer(GL_FRAMEBUFFER, m_bufferID);// 2. 渲染物体到帧缓存glClearColor();glClear();draw();// 3. 解绑帧缓存glBindFramebuffer(GL_FRAMEBUFFER, 0);// 4. 使用帧缓存渲染出来的纹理...glActiveTexture();glBindTexture(GL_TEXTURE_2D, id);} init函数中的代码基本保持不变。                                        二、Overload对FrameBuffer的封装 Overload将FrameBuffer封装成类Framebuffer代码位于Framebuffer.h、Framebuffer.cpp中。先看Framebuffer.h文件Framebuffer类的定义如下如果对注释中的名词不太熟悉需学习一下OpenGL。 class Framebuffer{public:/*** 构造函数会直接创建一个帧缓冲* param p_width 帧缓冲的宽* param p_height 帧缓存的高*/Framebuffer(uint16_t p_width 0, uint16_t p_height 0);/*** 析构函数*/~Framebuffer();/*** 绑定帧缓冲对其进行操作*/void Bind();/*** 解除绑定*/void Unbind();/*** 对帧缓冲的大小进行改变* param p_width 新的帧缓冲宽度* param p_height 新的帧缓冲高度*/void Resize(uint16_t p_width, uint16_t p_height);/*** 帧缓冲的id*/uint32_t GetID();/*** 返回OpenGL纹理附件的id*/uint32_t GetTextureID();/*** 返回渲染缓存的id这个方法在Overload中其他地方没有使用*/uint32_t GetRenderBufferID();private:uint32_t m_bufferID 0; // 帧缓冲的iduint32_t m_renderTexture 0; // 纹理附件的iduint32_t m_depthStencilBuffer 0; // 渲染缓存的id}; 先来看其构造函数的实现 OvRendering::Buffers::Framebuffer::Framebuffer(uint16_t p_width, uint16_t p_height) {/* Generate OpenGL objects */glGenFramebuffers(1, m_bufferID); // 生成帧缓冲idglGenTextures(1, m_renderTexture); // 生成颜色缓冲纹理glGenRenderbuffers(1, m_depthStencilBuffer); // 生成渲染缓存// 设置m_renderTexture纹理参数glBindTexture(GL_TEXTURE_2D, m_renderTexture);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glBindTexture(GL_TEXTURE_2D, 0);/* Setup framebuffer */Bind();// 将纹理设置为渲染目标glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_renderTexture, 0);Unbind();Resize(p_width, p_height); } 构造中直接生成帧缓存、纹理、渲染缓存对象并将纹理作为颜色附件关联到帧缓存上。再看resize方法。 void OvRendering::Buffers::Framebuffer::Resize(uint16_t p_width, uint16_t p_height) {/* Resize texture */// 设置纹理的大小glBindTexture(GL_TEXTURE_2D, m_renderTexture);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, p_width, p_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);glBindTexture(GL_TEXTURE_2D, 0);/* Setup depth-stencil buffer (24 8 bits) */glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, p_width, p_height);glBindRenderbuffer(GL_RENDERBUFFER, 0);/* Attach depth and stencil buffer to the framebuffer */Bind();// 配置深度缓冲与模板缓冲glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);Unbind(); } 这俩方法加起来跟前面的伪代码init函数基本一致只是用面向对象的方式进行了封装而已。 三、鼠标拾取原理 Overload中鼠标拾取是先将物体的id渲染到纹理中根据鼠标位置读取这张图上的对应的像素值之后解码获取对象的id。下图红框中是这个函数的关键三个步骤 我们先来看RenderSceneForActorPicking这个函数。这个函数是把场景中的物体、摄像机、灯光进行渲染。他们三者的渲染方式很类似以渲染摄像机为例代码如下 /* Render cameras */for (auto camera : m_context.sceneManager.GetCurrentScene()-GetFastAccessComponents().cameras){auto actor camera-owner;if (actor.IsActive()){// 对摄像机的id进行编码设置到Shader的unfiorm中PreparePickingMaterial(actor, m_actorPickingMaterial);auto model *m_context.editorResources-GetModel(Camera);auto modelMatrix CalculateCameraModelMatrix(actor);// 绘制摄像机其覆盖区域的像素全部是其idm_context.renderer-DrawModelWithSingleMaterial(model, m_actorPickingMaterial, modelMatrix);}} 这里有一个特殊函数PreparePickingMaterial将id的三个字节变成颜色保持到u_Diffuse变量中这个变量Shader中会使用。核心代码见下图红框这种编码方式是将信息写入图像常用的方式可以直接拿来借鉴参考。 要想在FrameBuffer中绘制肯定需要Shader。Overload的Shader是封装成了材料对于拾取需要特殊的材料RenderSceneForActorPicking函数中变量m_actorPickingMaterial就保存的这种材料。我们跟踪代码找这个变量的初始化可以找到以下代码 /* Picking Material */ auto unlit m_context.shaderManager[:Shaders\\Unlit.glsl]; m_actorPickingMaterial.SetShader(unlit); m_actorPickingMaterial.Set(u_Diffuse, FVector4(1.f, 1.f, 1.f, 1.0f)); m_actorPickingMaterial.SetOvRendering::Resources::Texture*(u_DiffuseMap, nullptr); m_actorPickingMaterial.SetFrontfaceCulling(false); m_actorPickingMaterial.SetBackfaceCulling(false); 看来这个Shader是保存在文件Unlit.glsl中的同时注意u_DiffuseMap设成了null记住这一点这是故意为之魔鬼都隐藏在这些细节当中。 我们打开这个文件分析这个Shader #shader vertex #version 430 corelayout (location 0) in vec3 geo_Pos; layout (location 1) in vec2 geo_TexCoords; layout (location 2) in vec3 geo_Normal;layout (std140) uniform EngineUBO {mat4 ubo_Model;mat4 ubo_View;mat4 ubo_Projection;vec3 ubo_ViewPos;float ubo_Time; };out VS_OUT {vec2 TexCoords; } vs_out;void main() {vs_out.TexCoords geo_TexCoords;gl_Position ubo_Projection * ubo_View * ubo_Model * vec4(geo_Pos, 1.0); }#shader fragment #version 430 coreout vec4 FRAGMENT_COLOR;in VS_OUT {vec2 TexCoords; } fs_in;uniform vec4 u_Diffuse vec4(1.0, 1.0, 1.0, 1.0); uniform sampler2D u_DiffuseMap; uniform vec2 u_TextureTiling vec2(1.0, 1.0); uniform vec2 u_TextureOffset vec2(0.0, 0.0);void main() {FRAGMENT_COLOR texture(u_DiffuseMap, u_TextureOffset vec2(mod(fs_in.TexCoords.x * u_TextureTiling.x, 1), mod(fs_in.TexCoords.y * u_TextureTiling.y, 1))) * u_Diffuse; } 这个GPU程序的Vertex Shader没啥可说的计算一下网格的NDC坐标完事。令人费解的是Fragment Shader的最后一行代码我这里先说结论这行代码等价于FRAGMENT_COLOR  u_Diffuse。 至于为什么简单来说应用程序中将u_DiffuseMap设成了null但传给CPU的时候会将值是null的纹理设置成空纹理。这个空纹理大小一个像素值是纯白色那么对其采样结果都是1.0 。 空文理初始化见以下代码 看看是不是只有一个像素而且值都是1.0。 说道这里拾取需要的纹理渲染核心细节基本说完了。我们再来看看如何读取这个纹理的。 先获取以下鼠标位置。由于是用imgui绘制的需要对鼠标的绝对位置变换到图像的相对位置上。 先绑定FrameBuffer使用glReadPixels读取像素注意图片格式是RGB跟初始化FrameBuffer进行的设置一致这些细节都得注意玄机很多。最后对像素进行解码操作获取场景物体的id。 读代码就是要将这些细节看明白才能照猫画虎用到我们自己的项目中
http://www.hkea.cn/news/14272092/

相关文章:

  • 拓者室内设计网站广告关键词
  • 建设网站宽度最好是多少钱微信做网站的弊端
  • 仿制网站建设企业注册地址变更流程
  • wordpress当下载站广州白云区新闻头条最新消息今天
  • 网站建设包含二级网站修改wordpress页脚信息
  • 泸州网站建设兼职农业科技工作服务站建站模板
  • 手机网站建设步骤建设网站一定需要云服务器么
  • 广州做网站做得比较好环保部建设项目影响登记网站
  • 亚马逊品牌网站要怎么做营销网络分布图
  • 网站域名跳转代码html2345网址导航 手机上网简单一点
  • 毕业设计网站设计大连网络推广公司哪家好
  • 全国最大网站建站公司手机网站管理
  • 功能分类模块类型网站说明设计网站开发方案流程
  • 巧家县住房和城乡建设局网站店名logo设计在线生成
  • 织梦网站栏目无法生成国际军事新闻
  • 河北省建设网和执业中心网站wordpress canvas
  • 开天猫旗舰店网站建设商标购买在哪个平台好
  • 时装网站的建设提供中小企业网站建设
  • 百度关键词查询网站wordpress移动端导航菜单加文字
  • 寻找基础微网站开发深圳市住房保障署官网登录
  • 如何做网站编辑网站权重怎么做
  • html网站首页设计烤漆 东莞网站建设
  • 夏天做那个网站能致富网站获取访问者qq号码
  • 做平面计设和网站哪个好网站建设策划书ppt
  • 北京展览馆网站建设网站开发技术路线与规范
  • 网站投票活动怎么做哪个网站可以做c语言的题
  • 旅游网站排名相关推荐wordpress自助建站系统
  • 网站建设与管理试题一科技公司网站主页设计
  • 导航网站设计方案网站注册账号
  • 平台网站怎么优化建设银行预约纪念钞网站