gpt4 book ai didi

python - 接近 1 的纹理坐标表现异常

转载 作者:太空狗 更新时间:2023-10-30 01:02:08 28 4
gpt4 key购买 nike

我正在使用 (Py)OpenGL 显示 256 色索引图像。我将着色器与包含调色板的一维纹理一起使用。这是片段着色器代码:

#version 330
uniform sampler2D texture;
uniform sampler1D palette;

void main()
{
vec2 uv = gl_TexCoord[0].xy;
vec4 color = texture2D(texture, uv);
gl_FragColor = texture1D(palette, color.a) ;
}

为避免舍入错误,所有 MAG 和 MIN 过滤器都设置为 NEAREST。

我看到一维纹理的纹理坐标的方式是:

  • 颜色 0 位于区间 [0 ; 1/256[
  • 颜色 1 位于区间 [1/256 ; 2/256[...
  • 颜色 255 位于区间 [255/256 ; 1[

我将自己的整数索引转换为 0 和 1 之间的 float ,以确保发生了什么,使用公式 x_float = (x_int + .4)/256,即 x_float 在前面提到的区间内,稍早于它中心(以避免结果在区间的错误一侧四舍五入)。

但它不起作用。我制作了一个包含 256 个单元格的棋盘,颜色索引从 0 到 255 和一个灰度级调色板(从 0x000000 到 0xFFFFFF)。代码如下。然后我制作了一个屏幕快照并在 Paint.NET 中对其进行了编辑以查看颜色是否正确,并注意到颜色 0xE0 处有一个跳跃:我得到两倍颜色 0xDF,从这个开始,所有内容都移动了一个:最后一个颜色改为 0xFE 0xFF 的。

我怀疑存在某种舍入错误,但不知道如何...

完整代码如下:

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

from OpenGL.arrays import vbo
from OpenGL.GL import shaders
from numpy import *

def checkboard(size = 512, cell = 32):
bitmap = zeros(size * size, 'u8')
bitmap.shape = (size, size)
current_color = 0

for y in range(0, size, cell):
for x in range(0, size, cell):
bitmap[y : y + cell, x : x + cell] = current_color
current_color += 1

palette = array([[a, a, a, 255] for a in range(256)], 'u8')

return bitmap, palette

def reshape(w, h):
glutDisplayFunc(lambda: display(w, h))
glutPostRedisplay();

glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(512, 512)
glutCreateWindow("Hello World :'D")

### init code

# vbo
quad = (0.0, 0.0, 512.0, 512.0)
tex = (0., 0., 1., 1.)

my_vbo = vbo.VBO(
array( [
( quad[0], quad[1], 0, tex[0], tex[1]),
( quad[0], quad[3], 0, tex[0], tex[3]),
( quad[2], quad[3], 0, tex[2], tex[3]),
( quad[2], quad[1], 0, tex[2], tex[1])
],'f,f,f,f,f')
)

# texture
bitmap, palette = checkboard()
height, width = bitmap.shape
f_image = (array(bitmap, 'f') + .4) / 256.0

# Image to be displayed
image_id = glGenTextures(1)
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, image_id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
GL_ALPHA, GL_FLOAT, f_image)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glActiveTexture(GL_TEXTURE0)

# palette
f_palette = (palette / float32(255))

palette_id = glGenTextures(1)
glEnable(GL_TEXTURE_1D)
glBindTexture(GL_TEXTURE_1D, palette_id)
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0,
GL_RGBA, GL_FLOAT, f_palette)
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
#glActiveTexture(GL_TEXTURE1)

# shaders
VERTEX_SHADER = shaders.compileShader("""#version 330

layout(location = 0) in vec4 position;
uniform vec2 offset ;

void main()
{
gl_FrontColor = gl_Color;
gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
gl_Position = vec4((offset.x + position.x - 256) / 256, (256 - offset.y - position.y)/256, 0.0, 1.0);
}""", GL_VERTEX_SHADER)

FRAGMENT_SHADER = shaders.compileShader("""#version 330
uniform sampler2D texture;
uniform sampler1D palette;

void main()
{
vec2 uv = gl_TexCoord[0].xy;
vec4 color = texture2D(texture, uv);
gl_FragColor = texture1D(palette, color.a) ;
}""", GL_FRAGMENT_SHADER)

shader = shaders.compileProgram(VERTEX_SHADER,FRAGMENT_SHADER)

# uniform variables
offset_uniform_loc = glGetUniformLocation(shader, "offset")
texture_uniform_loc = glGetUniformLocation(shader, 'texture' )
palette_uniform_loc = glGetUniformLocation(shader, 'palette' )


def display(w, h):
"""Render the geometry for the scene."""
glViewport(0, 0, w, h)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, w, 0, h, -1, 1)

glMatrixMode(GL_MODELVIEW);
glLoadIdentity()

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

glEnable( GL_TEXTURE_2D )
glActiveTexture( GL_TEXTURE0 )
glBindTexture( GL_TEXTURE_2D, image_id)

glEnable( GL_TEXTURE_1D )
glActiveTexture( GL_TEXTURE1 )

shaders.glUseProgram(shader)
shaders.glUniform1i(texture_uniform_loc, 0)
shaders.glUniform1i(palette_uniform_loc, 1)
shaders.glUniform2f(offset_uniform_loc, 0, 0)

try:
my_vbo.bind()
try:
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
glVertexPointer(3, GL_FLOAT, 20, my_vbo)
glTexCoordPointer(2, GL_FLOAT, 20, my_vbo + 12)

glBindTexture( GL_TEXTURE_1D, palette_id)
glDrawArrays(GL_QUADS, 0, 4)
finally:
my_vbo.unbind()
glDisableClientState(GL_TEXTURE_COORD_ARRAY)
glDisableClientState(GL_VERTEX_ARRAY)
finally:
shaders.glUseProgram( 0 )

glutSwapBuffers()


glutReshapeFunc(reshape)
glutIdleFunc(glutPostRedisplay)
glutMainLoop()

最佳答案

使用 GL_CLAMP_TO_EDGE 作为纹理的 GL_TEXTURE_WRAP_S

出现此问题的部分原因是纹理坐标 1.0 引用的位置超出了最后一个纹素的中心。夹紧到边缘将使您的坐标在 S 方向上夹紧到边缘纹素的中心。

当对纹理进行采样时,如果坐标不指向确切的纹素中心,则过滤模式和环绕行为将决定从何处获取纹素。默认情况下,OpenGL 使用重复模式,因此纹理坐标接近 1.0 的最近邻居(最近的纹素中心)可能来自纹理的另一侧(重复)。对于普通图像,您甚至可能不会注意到这种行为,但是当您环绕到查找表的另一侧时,不连续性会非常明显。

下图说明了这一点:

http://i.msdn.microsoft.com/dynimg/IC83860.gif

注意到纹理坐标 1.0 实际上是指调色板条目 30 之间的边界吗?

简短的版本是,如果您的范围是从 0.01.0,那么您的纹理坐标都没有引用纹素中心,您很容易结束采样错误的纹素。你需要调整你的坐标,这样你就不会为每个调色板条目使用纹素边界。


或者,由于您使用的是 GLSL ≥ 130,您可以使用 texelFetch (...) 并完全跳过所有这些标准化纹理坐标废话。如果您想使用其 a 组件获取纹理的调色板条目,请尝试如下操作:

gl_FragColor = texelFetch (palette, (int)(texture2D (texture, uv).a * 255.0), 0);

这将显式获取由整数索引给出的纹素。您不必担心最近的邻居、环绕模式、过滤等。

关于python - 接近 1 的纹理坐标表现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19323188/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com