如何解决OpenGL中的纹理数组
我正在一个项目上,我需要使用纹理数组来应用纹理。我已经问了很多问题,没有一个我完全满意的答案(Get access to later versions of GLSL,OpenGL: Access Array Texture in GLSL和OpenGL: How would I implement texture arrays?),所以我想问一个更广泛的问题希望得到回应。无论如何,我将如何在OpenGL中构造对象(更具体地说是PyOpenGL,但如果将答案放在C ++中就可以了)。我已经有一种加载纹理数组的方法,只是没有一种应用它的方法。这是理想的结果:
这是我目前用于加载数组纹理的内容:
def load_texture_array(path,width,height):
teximg = pygame.image.load(path)
texels = teximg.get_buffer().raw
texture = gluint(0)
layerCount = 6
mipLevelCount = 1
glGenTextures(1,texture)
glBindTexture(GL_TEXTURE_2D_ARRAY,texture)
glTexStorage3D(GL_TEXTURE_2D_ARRAY,mipLevelCount,GL_RGBA8,height,layerCount)
glTexSubImage3D(GL_TEXTURE_2D_ARRAY,layerCount,GL_RGBA,GL_UNSIGNED_BYTE,texels)
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE)
TLDR:如何使用纹理数组将纹理应用于OpenGL中的对象?
如有必要,我会很乐意提供其他信息。
解决方法
如果要对多维数据集使用2D Array Texture,则6面的6个纹理中的每一个必须具有相同的大小。
您可以通过3维纹理坐标查找纹理。纹理坐标的第三个组成部分是2d纹理数组中2d纹理的索引。
因此,这6个面的纹理坐标为
0: [(0,0),(1,1,(0,0)]
1: [(0,1),1)]
2: [(0,2),2)]
3: [(0,3),3)]
4: [(0,4),4)]
5: [(0,5),5)]
在顶点着色器中获取三维纹理坐标属性,并将其传递给片段着色器:
in a_uv;
out v_uv;
// [...]
void main()
{
v_uv = a_uv;
// [...]
}
使用3维纹理坐标在片段着色器中查找sampler2DArray
:
out v_uv;
uniform sampler2DArray u_texture;
// [...]
void main()
{
vec4 texture(u_texture,v_uv.xyz);
// [...]
}
创建一个GL_TEXTURE_2D_ARRAY
并使用glTexSubImage3D
将6个二维图像加载到2D Array Texture的6个平面上。以下image_planes
是具有6个二维图像平面的列表:
tex_obj = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D_ARRAY,self.tex_obj)
glTexImage3D(GL_TEXTURE_2D_ARRAY,GL_RGBA,sizeX,sizeY,6,GL_UNSIGNED_BYTE,None)
for i in range(6):
glTexSubImage3D(GL_TEXTURE_2D_ARRAY,i,image_planes[i])
glTexParameterf(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
查看示例:
import os,math,ctypes
import glm
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from OpenGL.arrays import *
import pygame
pygame.init()
image_path = r"images"
image_names = ["banana64.png","apple64.png","fish64.png","rocket64.png","ice64.png","boomerang64.png"]
image_planes = [
(GLubyte * 4)(255,255),(GLubyte * 4)(0,255,(GLubyte * 4)(255,255)]
image_size = (1,1)
for i,filename in enumerate(image_names):
try:
image = pygame.image.load(os.path.join(image_path,filename))
image_size = image.get_size()
image_planes[i] = pygame.image.tostring(image,'RGBA')
except:
pass
class MyWindow:
__glsl_vert = """
#version 130
in vec3 a_pos;
in vec3 a_nv;
in vec3 a_uv;
out vec3 v_pos;
out vec3 v_nv;
out vec3 v_uv;
uniform mat4 u_proj;
uniform mat4 u_view;
uniform mat4 u_model;
void main()
{
mat4 model_view = u_view * u_model;
mat3 normal = mat3(model_view);
vec4 view_pos = model_view * vec4(a_pos.xyz,1.0);
v_pos = view_pos.xyz;
v_nv = normal * a_nv;
v_uv = a_uv;
gl_Position = u_proj * view_pos;
}
"""
__glsl_frag = """
#version 130
out vec4 frag_color;
in vec3 v_pos;
in vec3 v_nv;
in vec3 v_uv;
uniform sampler2DArray u_texture;
void main()
{
vec3 N = normalize(v_nv);
vec3 V = -normalize(v_pos);
float ka = 0.1;
float kd = max(0.0,dot(N,V)) * 0.9;
vec4 color = texture(u_texture,v_uv.xyz);
frag_color = vec4(color.rgb * (ka + kd),color.a);
}
"""
def __init__(self,w,h):
self.__caption = 'OpenGL Window'
self.__vp_size = [w,h]
pygame.display.gl_set_attribute(pygame.GL_DEPTH_SIZE,24)
self.__screen = pygame.display.set_mode(self.__vp_size,pygame.DOUBLEBUF| pygame.OPENGL)
self.__program = compileProgram(
compileShader( self.__glsl_vert,GL_VERTEX_SHADER ),compileShader( self.__glsl_frag,GL_FRAGMENT_SHADER ),)
self.___attrib = { a : glGetAttribLocation (self.__program,a) for a in ['a_pos','a_nv','a_uv'] }
print(self.___attrib)
self.___uniform = { u : glGetUniformLocation (self.__program,u) for u in ['u_model','u_view','u_proj'] }
print(self.___uniform)
v = [[-1,-1,1],[1,[-1,-1],-1]]
n = [[0,0],[0,0]]
e = [[0,2,3],5,2],[5,4,7,6],[4,3,7],[3,5]]
t = [[0,1]]
index_array = [si*4+[0,3][vi] for si in range(6) for vi in range(6)]
attr_array = []
for si in range(len(e)):
for i,vi in enumerate(e[si]):
attr_array += [*v[vi],*n[si],*t[i],si]
self.__no_vert = len(attr_array) // 10
self.__no_indices = len(index_array)
vertex_attributes = (ctypes.c_float * len(attr_array))(*attr_array)
indices = (ctypes.c_uint32 * self.__no_indices)(*index_array)
self.__vao = glGenVertexArrays(1)
self.__vbo,self.__ibo = glGenBuffers(2)
glBindVertexArray(self.__vao)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,self.__ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices,GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER,self.__vbo)
glBufferData(GL_ARRAY_BUFFER,vertex_attributes,GL_STATIC_DRAW)
float_size = ctypes.sizeof(ctypes.c_float)
glVertexAttribPointer(self.___attrib['a_pos'],GL_FLOAT,False,9*float_size,None)
glVertexAttribPointer(self.___attrib['a_nv'],ctypes.c_void_p(3*float_size))
glVertexAttribPointer(self.___attrib['a_uv'],ctypes.c_void_p(6*float_size))
glEnableVertexAttribArray(self.___attrib['a_pos'])
glEnableVertexAttribArray(self.___attrib['a_nv'])
glEnableVertexAttribArray(self.___attrib['a_uv'])
glEnable(GL_DEPTH_TEST)
glUseProgram(self.__program)
glActiveTexture(GL_TEXTURE0)
sizeX,sizeY = image_size
self.tex_obj = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D_ARRAY,self.tex_obj)
glTexImage3D(GL_TEXTURE_2D_ARRAY,None)
for i in range(6):
glTexSubImage3D(GL_TEXTURE_2D_ARRAY,image_planes[i])
glTexParameterf(GL_TEXTURE_2D_ARRAY,GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D_ARRAY,GL_LINEAR)
def run(self):
self.__starttime = 0
self.__starttime = self.elapsed_ms()
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
self.__mainloop()
pygame.display.flip()
pygame.quit()
def elapsed_ms(self):
return pygame.time.get_ticks() - self.__starttime
def __mainloop(self):
proj,view,model = glm.mat4(1),glm.mat4(1),glm.mat4(1)
aspect = self.__vp_size[0]/self.__vp_size[1]
proj = glm.perspective(glm.radians(90.0),aspect,0.1,10.0)
view = glm.lookAt(glm.vec3(0,-3,glm.vec3(0,1))
angle1 = self.elapsed_ms() * math.pi * 2 / 5000.0
angle2 = self.elapsed_ms() * math.pi * 2 / 7333.0
model = glm.rotate(model,angle1,glm.vec3(1,0))
model = glm.rotate(model,angle2,0))
glUniformMatrix4fv(self.___uniform['u_proj'],GL_FALSE,glm.value_ptr(proj) )
glUniformMatrix4fv(self.___uniform['u_view'],glm.value_ptr(view) )
glUniformMatrix4fv(self.___uniform['u_model'],glm.value_ptr(model) )
glClearColor(0.2,0.3,1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDrawElements(GL_TRIANGLES,self.__no_indices,GL_UNSIGNED_INT,None)
window = MyWindow(800,600)
window.run()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。