2008-10-08 88 views
1

我需要从纹理中获取特定坐标的颜色。有两种方法可以做到这一点,通过获取并查看原始png数据,或者通过对我生成的opengl纹理进行采样。是否有可能在一个给定的UV或XY坐标上采样opengl纹理来获取颜色(RGBA)?如果是这样,怎么样?Open GL中的纹理采样

回答

2

关闭我的头顶,你的选择是

  1. 取使用glGetTexImage(整个纹理),并检查你感兴趣的纹理像素
  2. 平局。您感兴趣的纹理元素(例如,通过渲染GL_POINTS基元),然后使用glReadPixels获取从帧缓冲区渲染它的像素。
  3. 方便地保留纹理图像的副本,并将OpenGL保留在其外面。

选项1和2的效率非常低(尽管通过使用像素缓冲区对象并异步执行副本,速度可能会有所提高)。所以我最喜欢的是FAR选项3

编辑:如果有GL_APPLE_client_storage扩展名(即您是Mac或iPhone上。)那么这就是选择4这是一个很长的路要走赢家。

+0

外保持PixelData取出方便(浪费内存虽然)

  • 做它的副本,你需要一个基于texcoords的抽样方法,但这是一个很难的部分 - 这在我的答案中有所描述。 – 2008-10-08 08:39:06

  • 2

    我发现最有效的方法是访问纹理数据(您应该将我们的PNG解码为纹理),并在纹理之间进行插值。假设您的texcoords为[0,1],请将texwidth u和texheight v相乘,然后使用它来查找纹理上的位置。如果它们是整数,则直接使用该像素,否则使用int部分来查找边界像素并根据小数部分进行插值。

    这里有一些类似HLSL的伪码。应该是相当清楚的:

    float3 sample(float2 coord, texture tex) { 
        float x = tex.w * coord.x; // Get X coord in texture 
        int ix = (int) x; // Get X coord as whole number 
        float y = tex.h * coord.y; 
        int iy = (int) y; 
    
        float3 x1 = getTexel(ix, iy); // Get top-left pixel 
        float3 x2 = getTexel(ix+1, iy); // Get top-right pixel 
        float3 y1 = getTexel(ix, iy+1); // Get bottom-left pixel 
        float3 y2 = getTexel(ix+1, iy+1); // Get bottom-right pixel 
    
        float3 top = interpolate(x1, x2, frac(x)); // Interpolate between top two pixels based on the fractional part of the X coord 
        float3 bottom = interpolate(y1, y2, frac(x)); // Interpolate between bottom two pixels 
    
        return interpolate(top, bottom, frac(y)); // Interpolate between top and bottom based on fractional Y coord 
    } 
    
    0

    正如其他人所建议的,从VRAM回读纹理效率非常低,如果您甚至对性能感兴趣,应该像瘟疫一样避免。据

    两个可行的解决方案,因为我知道:

    1. 使用着色器选项2的