LearnOpenGL学习笔记——立方体贴图

Unity Shader(四) 数据类型 Cg/HLSL中的数据类型 几种常见的数据类型: 1:float、half、fixed(三个都是浮点型 只是精度不一样) 2:integer(整型) 3:sampler2D(2D纹理) 4:samplerCUBE(3D纹理) float 高精度类型,32位,通常用于世界坐标下的位置,纹理UV,或涉及复杂函数的标量计算,如三角函数、幂运算等。 half 中精度类型,1... 阅读详情

立方体贴图

在本节中,我们将讨论的是将多个纹理组合起来映射到一张纹理上的一种纹理类型:立方体贴图(Cube Map)。简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面:一个有纹理的立方体。你可能会奇怪,这样一个立方体有什么用途呢?为什么要把6张纹理合并到一张纹理中,而不是直接使用6个单独的纹理呢?立方体贴图有一个非常有用的特性,它可以通过一个方向向量来进行索引/采样。假设我们有一个1x1x1的单位立方体,方向向量的原点位于它的中心。使用一个橘黄色的方向向量来从立方体贴图上采样一个纹理值会像是这样:
在这里插入图片描述

方向向量的大小并不重要,只要提供了方向,OpenGL就会获取方向向量(最终)所击中的纹素,并返回对应的采样纹理值。

如果我们假设将这样的立方体贴图应用到一个立方体上,采样立方体贴图所使用的方向向量将和立方体(插值的)顶点位置非常相像。这样子,只要立方体的中心位于原点,我们就能使用立方体的实际位置向量来对立方体贴图进行采样了。接下来,我们可以将所有顶点的纹理坐标当做是立方体的顶点位置。最终得到的结果就是可以访问立方体贴图上正确面(Face)纹理的一个纹理坐标。

创建立方体贴图
立方体贴图是和其它纹理一样的,所以如果想创建一个立方体贴图的话,我们需要生成一个纹理,并将其绑定到纹理目标上,之后再做其它的纹理操作。这次要绑定到GL_TEXTURE_CUBE_MAP:

unsigned int textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

因为立方体贴图包含有6个纹理,每个面一个,我们需要调用glTexImage2D函数6次,参数和之前教程中很类似。但这一次我们将纹理目标(target)参数设置为立方体贴图的一个特定的面,告诉OpenGL我们在对立方体贴图的哪一个面创建纹理。这就意味着我们需要对立方体贴图的每一个面都调用一次glTexImage2D。由于我们有6个面,OpenGL给我们提供了6个特殊的纹理目标,专门对应立方体贴图的一个面。
GL_TEXTURE_CUBE_MAP_POSITIVE_X 右
GL_TEXTURE_CUBE_MAP_NEGATIVE_X 左
GL_TEXTURE_CUBE_MAP_POSITIVE_Y 上
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 下
GL_TEXTURE_CUBE_MAP_POSITIVE_Z 后
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 前
和OpenGL的很多枚举(Enum)一样,它们背后的int值是线性递增的,所以如果我们有一个纹理位置的数组或者vector,我们就可以从GL_TEXTURE_CUBE_MAP_POSITIVE_X开始遍历它们,在每个迭代中对枚举值加1,遍历了整个纹理目标:

int width, height, nrChannels;
unsigned char *data;  
for(unsigned int i = 0; i < textures_faces.size(); i++)
{
    data = stbi_load(textures_faces[i].c_str(), &width, &height, &nrChannels, 0);
    glTexImage2D(
        GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 
        0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data
    );
}

因为立方体贴图和其它纹理没什么不同,我们也需要设定它的环绕和过滤方式:

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

不要被GL_TEXTURE_WRAP_R吓到,它仅仅是为纹理的R坐标设置了环绕方式,它对应的是纹理的第三个维度(和位置的z一样)。我们将环绕方式设置为GL_CLAMP_TO_EDGE,这是因为正好处于两个面之间的纹理坐标可能不能击中一个面(由于一些硬件限制),所以通过使用GL_CLAMP_TO_EDGE,OpenGL将在我们对两个面之间采样的时候,永远返回它们的边界值。

在绘制使用立方体贴图的物体之前,我们要先激活对应的纹理单元,并绑定立方体贴图,这和普通的2D纹理没什么区别。在片段着色器中,我们使用了一个不同类型的采样器,samplerCube,我们将使用texture函数使用它进行采样,但这次我们将使用一个vec3的方向向量而不是vec2。使用立方体贴图的片段着色器会像是这样的:

in vec3 textureDir; // 代表3D纹理坐标的方向向量
uniform samplerCube cubemap; // 立方体贴图的纹理采样器
void main()
{             
    FragColor = texture(cubemap, textureDir);
}

天空盒

在这里插入图片描述

立方体贴图能完美满足天空盒的需求:我们有一个6面的立方体,每个面都需要一个纹理。在上面的图片中,他们使用了夜空的几张图片,让玩家产生其位于广袤宇宙中的错觉,但实际上他只是在一个小小的盒子当中。
在这里插入图片描述
加载天空盒
因为天空盒本身就是一个立方体贴图,加载天空盒和之前加载立方体贴图时并没有什么不同。为了加载天空盒,我们将使用下面的函数,它接受一个包含6个纹理路径的vector:

vector<std::string> faces
{
    "right.jpg",
    "left.jpg",
    "top.jpg",
    "bottom.jpg",
    "front.jpg",
    "back.jpg"
};
unsigned int loadCubemap(vector<std::string> faces)
{
    unsigned int textureID;
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

    int width, height, nrChannels;
    for (unsigned int i = 0; i < faces.size(); i++)
    {
        unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
        if (data)
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 
                         0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data
            );
            stbi_image_free(data);
        }
        else
        {
            std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;
            stbi_image_free(data);
        }
    }
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    return textureID;
}
unsigned int cubemapTexture = loadCubemap(faces);

现在我们就将这个天空盒加载为一个立方体贴图了,它的id是cubemapTexture。我们可以将它绑定到一个立方体中,替换掉用了很长时间的难看的纯色背景。

显示天空盒
由于天空盒是绘制在一个立方体上的,和其它物体一样,我们需要另一个VAO、VBO以及新的一组顶点。你可以在这里找到它的顶点数据。用于贴图3D立方体的立方体贴图可以使用立方体的位置作为纹理坐标来采样。当立方体处于原点(0, 0, 0)时,它的每一个位置向量都是从原点出发的方向向量。这个方向向量正是获取立方体上特定位置的纹理值所需要的。正是因为这个,我们只需要提供位置向量而不用纹理坐标了。要渲染天空盒的话,我们需要一组新的着色器,它们都不是很复杂。因为我们只有一个顶点属性,顶点着色器非常简单:

#version 330 core
layout (location = 0) in vec3 aPos;

out vec3 TexCoords;

uniform mat4 projection;
uniform mat4 view;

void main()
{
    TexCoords = aPos;
    gl_Position = projection * view * vec4(aPos, 1.0);
}

注意,顶点着色器中很有意思的部分是,我们将输入的位置向量作为输出给片段着色器的纹理坐标。片段着色器会将它作为输入来采样samplerCube:

#version 330 core
out vec4 FragColor;

in vec3 TexCoords;
uniform samplerCube skybox;

void main()
{    
    FragColor = texture(skybox, TexCoords);
}

片段着色器非常直观。我们将顶点属性的位置向量作为纹理的方向向量,并使用它从立方体贴图中采样纹理值。有了立方体贴图纹理,渲染天空盒现在就非常简单了,我们只需要绑定立方体贴图纹理,skybox采样器就会自动填充上天空盒立方体贴图了。绘制天空盒时,我们需要将它变为场景中的第一个渲染的物体,并且禁用深度写入。这样子天空盒就会永远被绘制在其它物体的背后了。

glDepthMask(GL_FALSE);
skyboxShader.use();
// ... 设置观察和投影矩阵
glBindVertexArray(skyboxVAO);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glDepthMask(GL_TRUE);
// ... 绘制剩下的场景

天空盒都不会变近,让玩家产生周围环境非常大的印象。然而,当前的观察矩阵会旋转、缩放和位移来变换天空盒的所有位置,所以当玩家移动的时候,立方体贴图也会移动!我们希望移除观察矩阵中的位移部分,让移动不会影响天空盒的位置向量。我们通过取4x4矩阵左上角的3x3矩阵来移除变换矩阵的位移部分。我们可以将观察矩阵转换为3x3矩阵(移除位移),再将其转换回4x4矩阵,来达到类似的效果:

glm::mat4 view = glm::mat4(glm::mat3(camera.GetViewMatrix()));

优化

目前我们是首先渲染天空盒,之后再渲染场景中的其它物体。这样子能够工作,但不是非常高效。如果我们先渲染天空盒,我们就会对屏幕上的每一个像素运行一遍片段着色器,即便只有一小部分的天空盒最终是可见的。可以使用提前深度测试(Early Depth Testing)轻松丢弃掉的片段能够节省我们很多宝贵的带宽。

所以,我们将会最后渲染天空盒,以获得轻微的性能提升。这样子的话,深度缓冲就会填充满所有物体的深度值了,我们只需要在提前深度测试通过的地方渲染天空盒的片段就可以了,很大程度上减少了片段着色器的调用。问题是,天空盒只是一个1x1x1的立方体,它很可能会不通过大部分的深度测试,导致渲染失败。不用深度测试来进行渲染不是解决方案,因为天空盒将会复写场景中的其它物体。我们需要欺骗深度缓冲,让它认为天空盒有着最大的深度值1.0,只要它前面有一个物体,深度测试就会失败。

在坐标系统小节中我们说过,透视除法是在顶点着色器运行之后执行的,将gl_Position的xyz坐标除以w分量。我们又从深度测试小节中知道,相除结果的z分量等于顶点的深度值。使用这些信息,我们可以将输出位置的z分量等于它的w分量,让z分量永远等于1.0,这样子的话,当透视除法执行之后,z分量会变为w / w = 1.0。

void main()
{
    TexCoords = aPos;
    vec4 pos = projection * view * vec4(aPos, 1.0);
    gl_Position = pos.xyww;
}

最终的标准化设备坐标将永远会有一个等于1.0的z值:最大的深度值。结果就是天空盒只会在没有可见物体的地方渲染了(只有这样才能通过深度测试,其它所有的东西都在天空盒前面)。

我们还要改变一下深度函数,将它从默认的GL_LESS改为GL_LEQUAL。深度缓冲将会填充上天空盒的1.0值,所以我们需要保证天空盒在值小于或等于深度缓冲而不是小于时通过深度测试。

环境映射

我们现在将整个环境映射到了一个纹理对象上了,能利用这个信息的不仅仅只有天空盒。通过使用环境的立方体贴图,我们可以给物体反射和折射的属性。这样使用环境立方体贴图的技术叫做环境映射(Environment Mapping),其中最流行的两个是反射(Reflection)和折射(Refraction)。
反射

反射这个属性表现为物体(或物体的一部分)反射它周围环境,即根据观察者的视角,物体的颜色或多或少等于它的环境。镜子就是一个反射性物体:它会根据观察者的视角反射它周围的环境。

反射的原理并不难。下面这张图展示了我们如何计算反射向量,并如何使用这个向量来从立方体贴图中采样:
在这里插入图片描述
我们根据观察方向向量I¯和物体的法向量N¯,来计算反射向量R¯。我们可以使用GLSL内建的reflect函数来计算这个反射向量。最终的R¯向量将会作为索引/采样立方体贴图的方向向量,返回环境的颜色值。最终的结果是物体看起来反射了天空盒。因为我们已经在场景中配置好天空盒了,创建反射效果并不会很难。我们将会改变箱子的片段着色器,让箱子有反射性:

	#version 330 core
	out vec4 FragColor;
	in vec3 Normal;
	in vec3 Position;
	uniform vec3 cameraPos;
	uniform samplerCube skybox;
	void main()
	{             
    	vec3 I = normalize(Position - cameraPos);
    	vec3 R = reflect(I, normalize(Normal));
    	FragColor = vec4(texture(skybox, R).rgb, 1.0);
	}

我们先计算了观察/摄像机方向向量I,并使用它来计算反射向量R,之后我们将使用R来从天空盒立方体贴图中采样。注意,我们现在又有了片段的插值Normal和Position变量,所以我们需要更新一下顶点着色器。

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

out vec3 Normal;
out vec3 Position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    Normal = mat3(transpose(inverse(model))) * aNormal;
    Position = vec3(model * vec4(aPos, 1.0));
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

周围的天空盒被完美地反射在箱子上。
在这里插入图片描述
折射
环境映射的另一种形式是折射,它和反射很相似。折射是光线由于传播介质的改变而产生的方向变化。在常见的类水表面上所产生的现象就是折射,光线不是直直地传播,而是弯曲了一点。将你的半只胳膊伸进水里,观察出来的就是这种效果。

折射是通过斯涅尔定律(Snell’s Law)来描述的,使用环境贴图的话看起来像是这样:
在这里插入图片描述
同样,我们有一个观察向量I¯,一个法向量N¯,而这次是折射向量R¯。可以看到,观察向量的方向轻微弯曲了。弯折后的向量R¯将会用来从立方体贴图中采样。

折射可以使用GLSL的内建refract函数来轻松实现,它需要一个法向量、一个观察方向和两个材质之间的折射率(Refractive Index)。

折射率决定了材质中光线弯曲的程度,每个材质都有自己的折射率。一些最常见的折射率可以在下表中找到:

材质 折射率
空气 1.00
水 1.33
冰 1.309
玻璃 1.52
钻石 2.42

我们使用这些折射率来计算光传播的两种材质间的比值。在我们的例子中,光线/视线从空气进入玻璃(如果我们假设箱子是玻璃制的),所以比值为1.001.52=0.658。

我们已经绑定了立方体贴图,提供了顶点数据和法线,并设置了摄像机位置的uniform。唯一要修改的就是片段着色器:

void main()
{             
    float ratio = 1.00 / 1.52;
    vec3 I = normalize(Position - cameraPos);
    vec3 R = refract(I, normalize(Normal), ratio);
    FragColor = vec4(texture(skybox, R).rgb, 1.0);
}

通过改变折射率,你可以创建完全不同的视觉效果。编译程序并运行,但结果并不是很有趣,因为我们只使用了一个简单的箱子,它不太能显示折射的效果,现在看起来只是有点像一个放大镜。对纳米装使用相同的着色器却能够展现出了我们期待的效果:一个类玻璃的物体。
在这里插入图片描述

动态环境贴图

现在我们使用的都是静态图像的组合来作为天空盒,看起来很不错,但它没有在场景中包括可移动的物体。我们一直都没有注意到这一点,因为我们只使用了一个物体。如果我们有一个镜子一样的物体,周围还有多个物体,镜子中可见的只有天空盒,看起来就像它是场景中唯一一个物体一样。

通过使用帧缓冲,我们能够为物体的6个不同角度创建出场景的纹理,并在每个渲染迭代中将它们储存到一个立方体贴图中。之后我们就可以使用这个(动态生成的)立方体贴图来创建出更真实的,包含其它物体的,反射和折射表面了。这就叫做动态环境映射(Dynamic Environment Mapping),因为我们动态创建了物体周围的立方体贴图,并将其用作环境贴图。

虽然它看起来很棒,但它有一个很大的缺点:我们需要为使用环境贴图的物体渲染场景6次,这是对程序是非常大的性能开销。现代的程序通常会尽可能使用天空盒,并在可能的时候使用预编译的立方体贴图,只要它们能产生一点动态环境贴图的效果。虽然动态环境贴图是一个很棒的技术,但是要想在不降低性能的情况下让它工作还是需要非常多的技巧的.

知识点总结

1.什么是立方体贴图,如何加载立方体贴图
2.用立方体贴图做天空盒
3.如何使用反射和折射反射或者折射天空盒的信息

https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/06%20Cubemaps/

【LearnOpenGL学习笔记】——18.立方体贴图 文章目录1.立方体贴图?2.立方体贴图创建 1.立方体贴图? 包含6个2D纹理 用处:将该贴图应用到某个立方体上,并将立方体移动到原点,就能利用立方体的实际位置向量进行采样,可以将顶点的纹理坐标当成位置坐标直接使用 2.立方体贴图创建 unsigned int textureID; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); 和OpenGL的很多枚举(Enum)一样,它们背后的int 阅读详情

相关推荐

【LearnOpenGL 学习笔记】高级OpenGL

LearnOpenGL 学习笔记 高级OpenGL

weixin_42489848的博客 557

LearnOpenGL笔记——四、高级OpenGL:4.6“立方体贴图”

四、高级OpenGL:4.6“立方体贴图” 立方体贴图(Cube Map):将多个纹理组合起来映射到一张纹理上的一种纹理类型。 简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面:一个有纹理的立方体。 立方体贴图有一个非常有用的特性,它可以通过一个方向向量来进行索引/采样。假设我们有一个1x1x1的单位立方体,方向向量的原点位于它的中心。使用一个橘黄色的方向向量来从立方体贴图上采样一个纹理值会像是这样: 创建立方体贴图 直接贴代码unsigned int loa

weixin_44478658的博客 1166

LearnOpenGL 高级OpenGL—立方体贴图

文章目录写在前面立方体贴图创建立方体贴图天空盒加载天空盒显示天空盒优化环境映射反射折射动态环境贴图总结 写在前面 原文链接。原文应该是github上的一个项目,本文主要用来记录一些知识点和自己遇到的问题。 立方体贴图 我们已经使用2D纹理很长时间了,但除此之外仍有更多的纹理类型等着我们探索。在本节中,我们将讨论的是将多个纹理组合起来映射到一张纹理上的一种纹理类型:立方体贴图(Cube Map)。 简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面:一个有纹理的立方体。你

xiji333的博客 719

unity shader texCUBE,对cubemap进行采样

Cubemap是一个由六个独立的正方形纹理组成的集合,它将多个纹理组合起来映射到一个单一纹理。 基本上说CubeMap包含6个2D纹理,这每个2D纹理是一个立方体(cube)的一个面,也就是说它是一个有贴图的立方体。 CubeMap通常被用来作为具有反射属性物体的反射源。 你可能会奇怪这样的立方体有什么用?为什么费事地把6个独立纹理结合为一个单独的纹理,只使用6个各自独立的不行吗?这是因为cubemap有自己特有的属性,可以使用方向向量对它们索引和采样。 想象一下,我们有一个1×1×1的单位立方体

zengjunjie59的博客 4815

LearnOpenGL——法线贴图、视差贴图学习笔记

我们将观察方向变化到切线空间中,所以P向量的x和y分量会与表面切线和副切线对齐,由于切线和副切线向量与表面纹理坐标的方向相同,我们可以用P的x和y元素作为纹理坐标的偏移量。目前,如果我们让平面竖直面对我们,此时效果正常,因为法线贴图中的法线方向指向z正方向并且平面的法线也指向z轴正方向。将法线向量的x、y、z元素储存到纹理中,代替颜色的r、g、b元素,因为法线向量的范围在[-1,1],所以我们要先将其映射到[0,1],变换为RGB颜色元素。法线向量从z轴方向也有向其他方向的偏差,颜色也就发生了轻微的变化。

weixin_70073176的博客 1902

【OpenGL】LearnOpenGL学习笔记25 - 法线贴图 NormalMap

LearnOpenGL学习笔记 - 法线贴图 NormalMap

Duo1J的随笔 1327

LearnOpenGL学习笔记—高级OpenGL 06:立方体贴图

LearnOpenGL学习笔记—高级OpenGL 06:立方体贴图1 立方体贴图概述2 创建立方体贴图3 实现:天空盒3.1 加载天空盒3.2 显示天空盒3.3 优化4 环境映射4.1 反射 本节对应官网学习内容:立方体贴图 1 立方体贴图概述 我们已经使用2D纹理很长时间了,但除此之外仍有更多的纹理类型等着我们探索 比如在games101的课程中,记录的这一节shading笔记中提到的各种纹理贴图。 在本节中,我们将讨论的是将多个纹理组合起来映射到一张纹理上的一种纹理类型:立方体贴图(Cube Map)。

清清!的博客 2642

【OpenGL4.6】VS2022安装OpenGL4.6的全过程

我这里用python完成OpenGL的开发,目前存在一个问题是:OpenGL4.6到目前还没看到python版本。有时需要OpenGL4.6,不能再等,于是只能安装一个C++版的OpenGL4.6试用。以下为安装过程全记录。

gongdiwudu的专栏 6292

(自用)learnOpenGL学习总结-高级OpenGL-立方体贴图

ok终于来到了立方体贴图了,在这里面我们可以加入好看的天空包围盒,这样的画我们的背景就不再是黑色的了!首先,立方体贴图和前面的sampler2D贴图一样,不过是6个2D组成的立方体而已。那么为什么要把6个组合在一起呢?立方体贴图可以通过一个方向向量来进行索引(或者说采样)。什么意思?我们类比一下,之前在一个2D面上我们通过uv纹理坐标来找到对应的纹理值对吧。这里也一样,不过是通过一个方向向量来获得。

SHIgaNatsuki的博客 1240

OpenGL4.6开发手册

这是现代图形渲染技术OpenGL4.6开发手册,共有800页,包括丰富的案例和解说,是游戏开发人员的有力助手。

具身智能端到端大模型VLA (Vision Language Action)

在语言为条件的机器人任务中,策略必须具备理解语言指令、视觉感知环境并生成适当动作的能力,这就需要VLA的。例如,在自动驾驶领域,传统的做法是将感知、预测、规划等步骤分开处理,而VLA则试图用一个统一的框架来替代这种分立的方法。另外,VLA的模型对于算力的需求很大,单片AI算力1000Tops的Thor大概率会延期发布,加上英伟达芯片的量产时间与成本挑战,以及在国内的应用情况,对车企而言是个大问题。以谷歌DeepMind推出的RT-2为例,该模型可以在新的物体、背景和环境中表现出显著改善的性能。

具身智能机器人 1万+

LearnOpenGL(二十)之立方体贴图

LearnOpenGL(二十)之立方体贴图

ckg3824278的博客 1111

基于yolov5的鸟类图像准确识别

本项目主要基于yolov5进行鸟类准确识别,主要识别白鹭家族,红脚鹬,反嘴鹬,环颈珩,小白鹭以及夜鹭六类鸟

weixin_46064184的博客 3823

LearnOpenGL——帧缓冲、立方体贴图

如果你想将你的屏幕渲染到一个更小或更大的纹理上,你需要(在渲染到你的帧缓冲之前)再次调用glViewport,使用纹理的新维度作为参数,否则只有一小部分的纹理或屏幕会被渲染到这个纹理上。由于渲染缓冲对象通常都是只写的,它们会经常用于深度和模板附件,当我们不需要从这些缓冲中采样的时候,通常都会选择渲染缓冲对象,因为它会更优化一点。,附件是一个内存位置,作为帧缓冲的其中一个缓冲,可以想象为一张图片。当把一个纹理附加到帧缓冲的时候,所有的渲染指令将会写入到这个纹理中,就像它是一个普通的颜色/深度或模板缓冲一样。

weixin_70073176的博客 1207

病理图像处理个人手札(三)WSI & MIL

1.什么是WSI? WSI全称是Whole Slide Image,也就是全视野数字切片,主要应用在病理学细胞图像领域。WSI 是利用数字扫描仪对传统的病理切片进行扫描,采集具有高分辨率的数字图像,再通过计算机将得到的碎片化图像进行无缝拼接整合,制作可视化数字图像的一项技术。与传统载玻片相比,很好地解决了传统的玻璃切片易损坏、易褪色、易丢片、检索困难的问题。 一言以蔽之,WSI是对传统载玻片进行数字化。 由于是全视野,因此它将包含多尺度的切片在一个文件上面。因此WSI将使用到金字塔模型满足其支持不同分辨率的

baiweizeng的博客 1万+

数据中心光模块升级实录:从200G QSFP56到400G QSFP-DD的踩坑指南

本文记录了数据中心从200G QSFP56升级至400G QSFP-DD光模块的完整实战经验。文章深入剖析了升级过程中面临的兼容性、链路预算、布线、散热与功耗管理等核心挑战,并提供了具体的解决方案与排坑指南,为高速网络升级提供了宝贵的实践参考。

butter的博客 479

LearnOpenGL->立方体贴图

Learn OpenGL->立方体贴图

2201_75303014的博客 448

Verilog除法器(32位无符号+带符号)

32位无符号除法器设计 恢复余数法: 恢复余数除法的基本思路是从“部分余数”中减去除数,如果结果为负(不够减),则恢复原来的部分余数,商0. 寄存器使用: reg_r 存放被除数a reg_b 存放除数b reg_r 存放余数(初始清零) 具体做法: 做减法时,减数是reg_b中的除数,被减数是reg_r中的余数左移一位,最低位由reg_q(被除数)的最高位补充。为了能够判断相减结果的正...

qq_38600065的博客 1万+

LearnOpenGL17——立方体贴图

什么是立方体贴图 简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面,我们知道如果将一张贴图赋给一个立方体模型,那么这个立方体的六个面都显示该贴图,但是对于立方体贴图,我们就能对立方体各个面都使用不同的贴图附在立方体上,如图:每个面展示的图片都不一样。 立方体贴图原理 下图展示纹理映射的原理 对于立方体贴图,也使用了类似的映射原理,核心是对立方体的面进行展开,处理成2D纹理,然后再进行对应的纹理映射。如图:将立方体六个面展开成平面后进行纹理映射: 立方体贴图应用—

白小飞 619

【驭风计划 算法训练营】周测4:习题11-4、8-4、12-4

给出 nn 个非负整数 x1,x2,⋯,xnx1,x2,⋯,xn,有 qq 个询问,第 jj 个询问给出一个非负整数 yjyj,求其中,xor 表示按位异或运算。

Mege1的博客 1043

Happycapy深度解析:AI智能体的“iPhone时刻“来了?

从理论到实践深度解析了融合OpenClaw和ClaudeCode优点的超强智能体工具Happycapy

program哲学 457

LearnOpenGL——高级OpenGL(六)立方体贴图

立方体贴图是一种包含6个2D纹理的特殊纹理类型,构成立方体的6个面。相比单独使用6个纹理,立方体贴图可以通过方向向量进行索引采样,简化了纹理操作。文章详细介绍了创建立方体贴图的步骤,包括绑定纹理目标、加载6个面的图像以及设置纹理参数。特别介绍了天空盒的应用,即用立方体贴图模拟大型场景效果。通过加载6张环境图片作为立方体贴图,将其绑定到立方体上,并使用方向向量采样,可以实现逼真的天空背景效果。最后给出了加载天空盒纹理和渲染天空盒的具体代码实现。

QQ805009795的博客 596

手把手教你学Simulink——四开关 Buck‑Boost(FSBB)变换器的无缝模式切换仿真

本文详细介绍了四开关Buck-Boost(FSBB)变换器的Simulink仿真方法,重点解决模式切换时的直通风险和输出电压波动问题。通过统一电压PI控制、迟滞比较模式仲裁(Buck/Boost/Pass-Through)和200ns死区设计,实现了Vin从26V到22V变化时Vout稳定在12V±0.15V。关键步骤包括:搭建功率级电路、Stateflow模式判断、PI控制器输出占空比映射(Buck模式D≈Vo/Vin,Boost模式D≈1-Vo/Vin),以及带死区的PWM信号分配。仿真验证了切换过程中

MHD0815的博客 115

LearnOpenGL学习(高级OpenGL --> 帧缓冲,立方体贴图,高级数据)

当把一个纹理附加到帧缓冲的时候,所有的渲染指令将会写入到这个纹理中,就像它是一个普通的颜色/深度或模板缓冲一样。创建一个渲染缓冲对象和纹理对象类似,不同的是这个对象是专门被设计作为帧缓冲附件使用的,而不是纹理那样的通用数据缓冲(General Purpose Data Buffer)。我们将会将场景渲染到一个附加到帧缓冲对象上的颜色纹理中,之后将在一个横跨整个屏幕的四边形上绘制这个纹理。帧缓冲(FrameBuffer)是所有屏幕缓冲(包括颜色缓冲,深度缓冲,模板缓冲)的集合。的渲染缓冲上进行的。

zaizai1007的博客 1345

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

深度探索LearnOpenGL高级特性:帧缓冲、立方体贴图与实例化渲染

LearnOpenGL是一个全面的OpenGL学习资源库,提供了从基础到高级的OpenGL编程教程和示例代码。本文将深入探讨LearnOpenGL中的三个高级特性:帧缓冲、立方体贴图和实例化渲染,帮助开发者掌握这些技术以创建更复杂、更高效的3D图形应用。 ## 帧缓冲:打造高级渲染效果的核心技术 帧缓冲(Framebuffer)是OpenGL中一个强大的工具,它允许开发者将渲染结果绘制到离屏缓

gitblog_00648的博客 1004

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【OpenGL】LearnOpenGL学习笔记26 - 视差贴图 Parallax Map

LearnOpenGL学习笔记 - 视差贴图 Parallax Map

Duo1J的随笔 1333

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

上一篇: LearnOpenGL学习笔记——帧缓冲
下一篇: LearnOpenGL学习笔记——高级数据
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值