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

建设网站几种方法建筑工程信息平台

建设网站几种方法,建筑工程信息平台,跨境c2c电商平台有哪些,博客网站需求分析一.纹理是什么#xff1f; 纹理是一个2D图片#xff08;甚至也有1D和3D的纹理#xff09;#xff0c;它可以用来添加物体的细节#xff1b;类似于图像一样#xff0c;纹理也可以被用来储存大量的数据#xff0c;这些数据可以发送到着色器上。 采样是指用纹理坐标来获取纹…一.纹理是什么 纹理是一个2D图片甚至也有1D和3D的纹理它可以用来添加物体的细节类似于图像一样纹理也可以被用来储存大量的数据这些数据可以发送到着色器上。 采样是指用纹理坐标来获取纹理颜色的过程。 纹理坐标在x和y轴上范围为0到1之间注意我们使用的是2D纹理图像。纹理坐标起始于(0, 0)也就是纹理图片的左上角终始于(1, 1)即纹理图片的右下角。这里与原作者的教案对不上我通过自己的论证得到的坐标。原作者说的(0,0)坐标是在左下角(1,1)坐标是右上角。大家有兴趣可以验证下与我沟通也可能是中文翻译出了问题。正确的是这样 float texCoords[] {0.0f, 0.0f, // 左上角1.0f, 0.0f, // 右上角1.0f, 1.0f, // 右下角0.0f, 1.0f // 左下角 }; 纹理坐标的范围通常是从(0, 0)到(1, 1)那如果我们把纹理坐标设置在范围之外会发生什么OpenGL默认的行为是重复这个纹理图像我们基本上忽略浮点纹理坐标的整数部分但OpenGL提供了更多的选择纹理环绕方式 环绕方式描述GL_REPEAT对纹理的默认行为。重复纹理图像。GL_MIRRORED_REPEAT和GL_REPEAT一样但每次重复图片是镜像放置的。GL_CLAMP_TO_EDGE纹理坐标会被约束在0到1之间超出的部分会重复纹理坐标的边缘产生一种边缘被拉伸的效果。GL_CLAMP_TO_BORDER超出的坐标为用户指定的边缘颜色。 设置纹理环绕的方式用的函数是glTexParameter第一个参数指定了纹理目标我们使用的是2D纹理因此纹理目标是GL_TEXTURE_2D第二个参数需要我们指定设置的选项与应用的纹理轴。我们打算配置的是WRAP选项并且指定S和T轴(如何是3D纹理的话还有一个参数是r)最后一个参数需要我们传递一个环绕方式。如下 设置x轴glTexParamteriGL_TEXTURE_2DGL_TEXT_WRAP_SGL_MIRRORED_REPEAT 设置y轴glTexParamteri GL_TEXTURE_2DGL_TEXT_WRAP_TGL_MIRRORED_REPEAT 设置边框 float borderColor[] { 1.0f, 1.0f, 0.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 纹理过滤是在物体很大而相对于纹理的分辨率又很低时你需要使用它。opengl需要知道怎样将纹理的像素映射到纹理的坐标。纹理坐标是我们上面提供传入的顶点数组。纹理像素是把图像放大到像素级别时单个像素的颜色。源作者给你的解释 你可以想象你打开一张.jpg格式图片不断放大你会发现它是由无数像素点组成的这个点就是纹理像素注意不要和纹理坐标搞混纹理坐标是你给模型顶点设置的那个数组OpenGL以这个顶点的纹理坐标数据去查找纹理图像上的像素然后进行采样提取纹理像素的颜色。 好了回归到纹理过滤上来主要分为两种邻近过滤(GL_NEAREST默认的方式)和线性过滤GL_LINEAR。 邻近过滤OpenGL会选择中心点最接近纹理坐标的那个像素。如图号表示纹理坐标所以蓝色的中心点离它最近返回蓝色。 线性过滤OpenGL会基于纹理坐标附近的纹理像素计算出一个插值近似出这些纹理像素之间的颜色。一个纹理像素的中心距离纹理坐标越近那么这个纹理像素的颜色对最终的样本颜色的贡献越大。说明白点的话就是离号越近的颜色点与最终样本的颜色越接近。 邻近过滤                                                 线性过滤 两种纹理过滤方式的视觉效果 GL_NEAREST产生了颗粒状的图案我们能够清晰看到组成纹理的像素而GL_LINEAR能够产生更平滑的图案很难看出单个的纹理像素。GL_LINEAR可以产生更真实的输出但有些开发者更喜欢8-bit风格所以他们会用GL_NEAREST选项。 你可以在纹理被缩小的时候使用邻近过滤被放大时使用线性过滤。设置放大和缩小时的纹理过滤方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 现在我们针对的是一个物体假如有多个物体时为了让纹理更真实。OpenGL使用一种叫做多级渐远纹理(Mipmap)的概念来解决这个问题它简单来说就是一系列的纹理图像后一个纹理图像是前一个的二分之一。多级渐远纹理背后的理念很简单距观察者的距离超过一定的阈值OpenGL会使用不同的多级渐远纹理即最适合物体的距离的那个。由于距离远解析度不高也不会被用户注意到。同时多级渐远纹理另一加分之处是它的性能非常好。 手工为每个纹理图像创建一系列多级渐远纹理很麻烦幸好OpenGL有一个glGenerateMipmaps函数在创建完一个纹理后调用它OpenGL就会承担接下来的所有工作了。 在渲染中切换多级渐远纹理级别(Level)时OpenGL在两个不同级别的多级渐远纹理层之间会产生不真实的生硬边界。就像普通的纹理过滤一样切换多级渐远纹理级别时你也可以在两个不同多级渐远纹理级别之间使用NEAREST和LINEAR过滤。为了指定不同多级渐远纹理级别之间的过滤方式你可以使用下面四个选项中的一个代替原有的过滤方式  过滤方式描述GL_NEAREST_MIPMAP_NEAREST使用最邻近的多级渐远纹理来匹配像素大小并使用邻近插值进行纹理采样GL_LINEAR_MIPMAP_NEAREST使用最邻近的多级渐远纹理级别并使用线性插值进行采样GL_NEAREST_MIPMAP_LINEAR在两个最匹配像素大小的多级渐远纹理之间进行线性插值使用邻近插值进行采样GL_LINEAR_MIPMAP_LINEAR在两个邻近的多级渐远纹理之间使用线性插值并使用线性插值进行采样 一个常见的错误是将放大过滤的选项设置为多级渐远纹理过滤选项之一。这样没有任何效果因为多级渐远纹理主要是使用在纹理被缩小的情况下的纹理放大不会使用多级渐远纹理为放大过滤设置多级渐远纹理的选项会产生一个GL_INVALID_ENUM错误代码。  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 二.加载和创建纹理 要使纹理加载到应用程序中我们使用图像加载库stb_image.h库。下面是实操我就不粘贴原作者的教案和博客了当然重要的东西还是会用原作者原始文案方便后续复查。 1.第一步先用stb_image.h将图片加载到内存。如下 int width, height, nrChannels; unsigned char *data stbi_load(container.jpg, width, height, nrChannels, 0); 这个函数首先接受一个图像文件的位置作为输入。接下来它需要三个int作为它的第二、第三和第四个参数stb_image.h将会用图像的宽度、高度和颜色通道的个数填充这三个变量。我们之后生成纹理的时候会用到的图像的宽度和高度的。 2.第二步生成纹理创建纹理ID绑定纹理生成纹理释放内存编写。生成纹理函数 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); 第一个参数指定了纹理目标(Target)。设置为GL_TEXTURE_2D意味着会生成与当前绑定的纹理对象在同一个目标上的纹理任何绑定到GL_TEXTURE_1D和GL_TEXTURE_3D的纹理不会受到影响。第二个参数为纹理指定多级渐远纹理的级别如果你希望单独手动设置每个多级渐远纹理的级别的话。这里我们填0也就是基本级别。第三个参数告诉OpenGL我们希望把纹理储存为何种格式。我们的图像只有RGB值因此我们也把纹理储存为RGB值。第四个和第五个参数设置最终的纹理的宽度和高度。我们之前加载图像的时候储存了它们所以我们使用对应的变量。下个参数应该总是被设为0历史遗留的问题。第七第八个参数定义了源图的格式和数据类型。我们使用RGB值加载这个图像并把它们储存为char(byte)数组我们将会传入对应值。最后一个参数是真正的图像数据。 当调用glTexImage2D时当前绑定的纹理对象就会被附加上纹理图像。然而目前只有基本级别(Base-level)的纹理图像被加载了如果要使用多级渐远纹理我们必须手动设置所有不同的图像不断递增第二个参数。或者直接在生成纹理之后调用glGenerateMipmap。这会为当前绑定的纹理自动生成所有需要的多级渐远纹理。 这里将创建绑定生成释放四个过程用单独的类来进行管理包括第一步的stb_image.h库的包含。如下 texture.h #ifndef TEXTURE_H #define TEXTURE_H #define STB_IMAGE_IMPLEMENTATIONclass Texture { public:// 纹理IDunsigned int ID;Texture(const char* imagePath);unsigned int getTextID() const { return ID; } };#endif // TEXTURE_Htexture.cpp #include texture.h #include stb_image.h #include glad/glad.h #include string #include fstream #include sstream #include iostreamTexture::Texture(const char* imagePath) {// 创建纹理glGenTextures(1, ID);// 绑定纹理glBindTexture(GL_TEXTURE_2D, ID);// 为当前绑定的纹理对象设置环绕、过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 加载并生成纹理int width, height, nrChannels;unsigned char *data stbi_load(imagePath, width, height, nrChannels, 0);if (data){glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);}else{std::cout Failed to load texture std::endl;}stbi_image_free(data); }3.第三步就是应用纹理。首先前面我们知道VAO(顶点数组对象)在内存中的存放规则我们需要将纹理也添加到顶点的属性当中这里respect一下原作者写教案真是用心了一环扣一环环环相应。先看下面的结构 告诉opengl我们的顶点格式   原作者是正方形我们是六边形下面看数据格式排版代码(如果你是一个上下对称的图像原作者的代码没有问题如果不是原作者的坐标是有问题的。可参照六边形的设定上面讲过纹理的坐标计算) float vertices[] { // ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上 }; 四边形的四个顶点  float vertices[] {-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f,0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f};unsigned int indices[] {0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5}; 六边形的六个顶点   设置属性 // 位置属性glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// 颜色属性glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);// 纹理属性glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));glEnableVertexAttribArray(2); 4.第四步就是编辑我们的两个着色器                     #version 330 core layout (location 0) in vec3 aPos; layout (location 1) in vec3 aColor; layout (location 2) in vec2 aTexCoord; out vec3 vertexColor; out vec2 TexCoord; void main() {gl_Position vec4(aPos, 1.0);vertexColor aColor;TexCoord aTexCoord; } 顶点着色器 #version 330 core out vec4 FragColor; in vec3 vertexColor; in vec2 TexCoord; uniform sampler2D ourTexture;void main() {FragColor texture(ourTexture, TexCoord); }片段着色器 片段着色器能访问纹理对象但是我们怎样能把纹理对象传给片段着色器呢GLSL有一个供纹理对象使用的内建数据类型叫做采样器(Sampler)它以纹理类型作为后缀比如sampler1D、sampler3D或在我们的例子中的sampler2D。我们可以简单声明一个uniform sampler2D把一个纹理添加到片段着色器中上面我们把纹理赋值给这个uniform。 我们使用GLSL内建的texture函数来采样纹理的颜色它第一个参数是纹理采样器第二个参数是对应的纹理坐标。texture函数会使用之前设置的纹理参数对相应的颜色值进行采样。这个片段着色器的输出就是纹理的插值纹理坐标上的(过滤后的)颜色。 5.第五步就是如何绘制了在绘制之前绑定我们的纹理id就可以了。text是上面我们建立的纹理类创建的对象传入一张jpeg的图像参数得到这个对象。通过调用纹理ID绑定。 // bind Texture glBindTexture(GL_TEXTURE_2D, text.getTextID());// 3. 绘制物体 glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0); 6.操作完后你会得到这样的一个效果 原图是这样的 7.上面我们还未使用颜色值我们还可以把得到的纹理颜色与顶点颜色混合来获得更有趣的效果。我们只需把纹理颜色与顶点颜色在片段着色器中相乘来混合二者的颜色 FragColor texture(ourTexture, TexCoord) * vec4(vertexColor, 1.0); 得到下面的效果 8.纹理单元 你可能会奇怪为什么sampler2D变量是个uniform我们却不用glUniform给它赋值。使用glUniform1i我们可以给纹理采样器分配一个位置值这样的话我们能够在一个片段着色器中设置多个纹理。一个纹理的位置值通常称为一个纹理单元(Texture Unit)。一个纹理的默认纹理单元是0它是默认的激活纹理单元所以教程前面部分我们没有分配一个位置值。 纹理单元的主要目的是让我们在着色器中可以使用多于一个的纹理。通过把纹理单元赋值给采样器我们可以一次绑定多个纹理只要我们首先激活对应的纹理单元。就像glBindTexture一样我们可以使用glActiveTexture激活纹理单元传入我们需要使用的纹理单元 glActiveTexture(GL_TEXTURE0); // 在绑定纹理之前先激活纹理单元         glBindTexture(GL_TEXTURE_2D, texture); 激活纹理单元之后接下来的glBindTexture函数调用会绑定这个纹理到当前激活的纹理单元纹理单元GL_TEXTURE0默认总是被激活所以我们在前面的例子里当我们使用glBindTexture的时候无需激活任何纹理单元。 OpenGL至少保证有16个纹理单元供你使用也就是说你可以激活从GL_TEXTURE0到GL_TEXTRUE15。它们都是按顺序定义的所以我们也可以通过GL_TEXTURE0 8的方式获得GL_TEXTURE8这在当我们需要循环一些纹理单元的时候会很有用。 #version 330 core out vec4 FragColor; in vec3 vertexColor; in vec2 TexCoord; uniform sampler2D texture1; uniform sampler2D texture2;void main() {FragColor mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2) * vec4(vertexColor, 1.0); }GLSL内建的mix函数需要接受两个值作为参数并对它们根据第三个参数进行线性插值。如果第三个值是0.0它会返回第一个输入如果是1.0会返回第二个输入值。0.2会返回80%的第一个输入颜色和20%的第二个输入颜色即返回两个纹理的混合色。 激活纹理 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texture2); 设置纹理采集 我们还要通过使用glUniform1i设置每个采样器的方式告诉OpenGL每个着色器采样器属于哪个纹理单元。我们只需要设置一次即可所以这个会放在渲染循环的前面 ourShader.use(); // 不要忘记在设置uniform变量之前激活着色器程序 glUniform1i(glGetUniformLocation(ourShader.ID, texture1), 0); // 手动设置 ourShader.setInt(texture2, 1); // 或者使用着色器类设置 得到的效果如下 最后说下坐标的问题 原来原作者没有错误作者最后说了句std_image.h库默认会上下翻转图像数据。下面是原话 你可能注意到纹理上下颠倒了这是因为OpenGL要求y轴0.0坐标是在图片的底部的但是图片的y轴0.0坐标通常在顶部。很幸运stb_image.h能够在图像加载时帮助我们翻转y轴只需要在加载任何图像前加入以下语句即可 stbi_set_flip_vertically_on_load(true); 那么我们纹理的坐标理解应该是左下角(0,0)右上角(1,1)。这里不管是咋样也不想求证了可以用一个第三方库加载图像来验证纹理的坐标。到这里基本学习了纹理。 三.学习地址(感谢原作者的讲解) 纹理 - LearnOpenGL CN (learnopengl-cn.github.io) 四.demo地址 learningOpengl: 一起学习opengl
http://www.dnsts.com.cn/news/268053.html

相关文章:

  • 网站情况建设说明网站建设需要哪些流程
  • 新网网站空间到期停了 咋续费网站设计配色案列
  • 网站免费建站性盈盈影院国外网站dns改成什么快
  • 中英文双语网站 滑动切换阿里云 wordpress cdn
  • 要怎么做网站推广网页布局有哪些
  • 网站建设加排名要多少怎么能查到网站是哪个公司做的
  • 国内十大搜索引擎网站wordpress的登录页
  • 衡阳做网站可以直接进入网址的正能量大豆网
  • 网站推广文章怎么写便民网app下载
  • 鞍山企业做网站c asp.net 做网站
  • 南宁公司网站建设怎样制作企业的网站
  • 网页设计与网站制作视频教程科技企业网站建设模板
  • 个人网站必须备案做网站的软件叫81什么来着
  • 建设信息港网站seo网站营销
  • 深圳高端建设网站做尽调需要用到的网站
  • 品展示设计网站wordpress旺季密码
  • word 无法注册 wordpress账号新网站seo优化
  • 林甸网站建设seo优化便宜
  • 网站建设的岗位叫什么wordpress 帮助中心
  • 如何做请求队列防止网站高并发人和机械网站建设
  • 做一份完整的网站规划书中国做二手房最大的网站有哪些
  • 网站制作是什么公司WordPress批量修改文章
  • 湖南建设人力资源官方网站wordpress建站流程
  • 如何做供求网站甘肃温室大棚建设网站
  • 网站开发整体流程移动网站 制作
  • 360建筑网是什么网站织梦大气婚纱影楼网站源码 dedecms摄影工作室网站模板
  • 最近做国际网站怎么样动力无限西安网站建设
  • 浙江平台网站建设找哪家梧州建设网站
  • 做版权保护的网站温州网站建设公司电话
  • 湘潭网站建设 要选磐石网络永嘉县住房和城乡建设局网站