如何使用GL_REPEAT仅重复纹理图集的选择?(OpenGL)

如何使用GL_REPEAT仅重复纹理图集的选择?(OpenGL),opengl,graphics,textures,texture-mapping,Opengl,Graphics,Textures,Texture Mapping,如何重复纹理图谱的选择? 例如,我的精灵(选择)位于纹理坐标内: GLfloat textureCoords[]= { .1f, .1f, .3f, .1f, .1f, .3f, .3f, .3f }; 然后,我想将该精灵重复N次,直到一个三角形条带(或四边形),其定义如下: GLfloat vertices[]= { -100.f, -100.f, 100.f, -100.f, -100.f, 100.f, 100.f,

如何重复纹理图谱的选择?

例如,我的精灵(选择)位于纹理坐标内:

GLfloat textureCoords[]=
{
    .1f,  .1f,
    .3f,  .1f,
    .1f,  .3f,
    .3f,  .3f
};
然后,我想将该精灵重复N次,直到一个三角形条带(或四边形),其定义如下:

GLfloat vertices[]=
{
   -100.f, -100.f,
    100.f, -100.f,
   -100.f,  100.f,
    100.f,  100.f
};
我知道这与
GL\u REPEAT
和纹理词通过范围
[0,1]
有关。但是,这不起作用:(尝试重复N=10)

我们看到完整的纹理图谱被重复


我该怎么做才能正确呢?我不确定你能不能做到。我认为OpenGL的纹理坐标模式只适用于整个纹理。使用atlas时,您使用的是“子纹理”,因此纹理坐标永远不会接近0和1,即发生缠绕和夹紧的法线限制

可能会有扩展来处理这个问题,我还没有检查

编辑:通常,要重复纹理,您需要绘制一个比纹理所暗示的“大”的多边形。例如,如果你有一个正方形的纹理,你想在一个更大的区域重复几次(比如说六次),你会画一个矩形,它的宽度是它的高度的六倍。然后将纹理坐标设置为(0,0)-(6,1),纹理模式设置为“重复”。在多边形上插值时,由于启用了“重复”,超过1的纹理坐标将在纹理中“环绕”,从而使纹理在矩形上映射六次

没有图像的解释有点粗糙


无论如何,当您仅使用纹理的一部分进行纹理处理时,无法指定更大的纹理坐标,从而使OpenGL仅在子矩形内重复该坐标。

无法完成…

没有任何纹理包裹模式支持您正在寻找的操作类型,即它们都映射到完整的[0,1]范围,不是任意的子集。你基本上有两个选择:要么创建一个新的纹理,只包含你需要的来自现有纹理的精灵,要么编写一个GLSL像素程序来适当地映射纹理坐标。

这不能按照问题中描述的方式完成。OpenGL的纹理坐标模式仅适用于整个纹理

通常,要重复纹理,您需要绘制一个比纹理所暗示的“大”的多边形。例如,如果你有一个正方形的纹理,你想在一个更大的区域重复几次(比如说六次),你会画一个矩形,它的宽度是它的高度的六倍。然后将纹理坐标设置为(0,0)-(6,1),纹理模式设置为“重复”。在多边形上插值时,由于启用了“重复”,超过1的纹理坐标将在纹理中“环绕”,从而使纹理在矩形上映射六次


没有任何纹理包裹模式支持问题中描述的操作类型,即它们都映射到完整的[0,1]范围,而不是某个任意子集。当您仅使用纹理的一部分进行纹理处理时,无法指定更大的纹理坐标,从而使OpenGL仅在子矩形内重复该坐标


您基本上有两种选择:要么创建一个新纹理,该纹理仅包含现有纹理中所需的精灵,要么编写一个GLSL顶点程序来适当地映射纹理坐标。

这可能是一个旧主题;以下是我最终如何做到这一点:

解决方法是创建多个网格,将包含纹理UV子集的网格粘在一起

例如: 我有一个激光纹理包含在一个更大的纹理图集中,在U[0.05-0.1]&V[0.05-0.1]

然后我将构造N个网格,每个网格都有U[0.05-0.1]和V[0.05-0.1]坐标。 (N=长度/texture.height;高度是我想要重复的纹理的维度。或者更简单:我想要重复纹理的次数。)

此解决方案比一个纹理接着一个纹理重新加载更具成本效益。 尤其是当您批处理所有渲染调用时(您应该这样做)


(OpenGL ES 1.0,1.1,2.0-移动硬件2011)

可以在着色器中使用tex坐标的模来完成。国防部将重复您的子范围协调。

我在处理同一问题时遇到了您的问题-尽管是在HLSL和DirectX中。我还需要mip映射并解决相关的纹理出血问题

我是这样解决的:

min16float4 sample_atlas(Texture2D<min16float4> atlasTexture, SamplerState samplerState, float2 uv, AtlasComponent atlasComponent)
{
  //Get LOD
  //Never wrap these as that will cause the LOD value to jump on wrap
  //xy is left-top, zw is width-height of the atlas texture component
  float2 lodCoords = atlasComponent.Extent.xy + uv * atlasComponent.Extent.zw;  
  uint lod = ceil(atlasTexture.CalculateLevelOfDetail(samplerState, lodCoords));

  //Get texture size
  float2 textureSize;
  uint levels;
  atlasTexture.GetDimensions(lod, textureSize.x, textureSize.y, levels);
  
  //Calculate component size and calculate edge thickness - this is to avoid bleeding
  //Note my atlas components are well behaved, that is they are all power of 2 and mostly similar size, they are tightly packed, no gaps
  float2 componentSize = textureSize * atlasComponent.Extent.zw;
  float2 edgeThickness = 0.5 / componentSize;

  //Calculate texture coordinates
  //We only support wrap for now
  float2 wrapCoords = clamp(wrap(uv), edgeThickness, 1 - edgeThickness);
  float2 texCoords = atlasComponent.Extent.xy + wrapCoords * atlasComponent.Extent.zw;
  return atlasTexture.SampleLevel(samplerState, texCoords, lod);
}
min16float4样本图谱(纹理2D图谱、采样器状态采样器状态、float2 uv、图谱组件图谱组件)
{
//获取详细等级
//永远不要包装这些,因为这样会导致LOD值在包装时跳转
//xy是左上角,zw是atlas纹理组件的宽度和高度
float2 lodCoords=atlasComponent.Extent.xy+uv*atlasComponent.Extent.zw;
uint lod=ceil(AtlastTexture.CalculateLevelOfDetail(samplerState,lodCoords));
//获取纹理大小
漂浮2纹理化;
单位水平;
获取维度(lod、textureSize.x、textureSize.y、级别);
//计算部件尺寸和边缘厚度-这是为了避免出血
//请注意,我的atlas组件性能良好,即它们都是2的幂次型,大小基本相同,它们紧密封装,没有间隙
float2 componentSize=textureSize*atlasComponent.Extent.zw;
浮动2边缘厚度=0.5/部件尺寸;
//计算纹理坐标
//我们现在只支持wrap
float2-wrapCoords=夹具(包裹(uv),边缘厚度,1-边缘厚度);
float2 texCoords=atlasComponent.Extent.xy+wrapCoords*atlasComponent.Extent.zw;
返回AtlastTexture.SampleLevel(SampleState、texCoords、lod);
}

请注意,限制在于mip级别是以这种方式混合的,但在我们的用例中,这是完全正确的。

Hmm,例如GL_-CLAMP会影响您描述的子纹理,这使我想到“理想纹理坐标模式”确实适用于纹理图集的部分。还是我在工作
min16float4 sample_atlas(Texture2D<min16float4> atlasTexture, SamplerState samplerState, float2 uv, AtlasComponent atlasComponent)
{
  //Get LOD
  //Never wrap these as that will cause the LOD value to jump on wrap
  //xy is left-top, zw is width-height of the atlas texture component
  float2 lodCoords = atlasComponent.Extent.xy + uv * atlasComponent.Extent.zw;  
  uint lod = ceil(atlasTexture.CalculateLevelOfDetail(samplerState, lodCoords));

  //Get texture size
  float2 textureSize;
  uint levels;
  atlasTexture.GetDimensions(lod, textureSize.x, textureSize.y, levels);
  
  //Calculate component size and calculate edge thickness - this is to avoid bleeding
  //Note my atlas components are well behaved, that is they are all power of 2 and mostly similar size, they are tightly packed, no gaps
  float2 componentSize = textureSize * atlasComponent.Extent.zw;
  float2 edgeThickness = 0.5 / componentSize;

  //Calculate texture coordinates
  //We only support wrap for now
  float2 wrapCoords = clamp(wrap(uv), edgeThickness, 1 - edgeThickness);
  float2 texCoords = atlasComponent.Extent.xy + wrapCoords * atlasComponent.Extent.zw;
  return atlasTexture.SampleLevel(samplerState, texCoords, lod);
}