我如何在 python 中使用 glDrawArraysInstanced?
How could I use glDrawArrayInstanced in python?
我有一个 python OpenGL 应用程序,我试图在其中同时渲染多个对象,但没有任何运气。出于某种原因,无论我如何更改偏移量,都只会绘制一个对象。这是我的片段着色器:
self.vertex_shader_source = b"""
#version 330
in layout(location = 0) vec3 positions;
in layout(location = 1) vec2 textureCoords;
in layout(location = 2) vec3 normals;
uniform mat4 light;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 rotate;
uniform mat4 translate;
uniform mat4 scale;
uniform vec2 offsets[2];
out vec2 textures;
out vec3 fragNormal;
void main()
{
fragNormal = (light * vec4(normals, 0.0f)).xyz;
vec2 offset = offsets[gl_InstanceID];
gl_Position = projection * view * model * rotate * translate * scale * vec4(positions + (offset, 0), 1.0f);
textures = vec2(textureCoords.x, 1 - textureCoords.y);
}
"""
self.fragment_shader_source = b"""
#version 330
in vec2 textures;
in vec3 fragNormal;
uniform sampler2D sampTexture;
out vec4 outColor;
void main()
{
vec3 ambientLightIntensity = vec3(0.9f, 0.9f, 0.9f);
vec3 sunLightIntensity = vec3(0.0f, 0.2f, 0.0f);
vec3 sunLightDirection = normalize(vec3(0.0f, 0.0f, 0.0f));
vec4 texel = texture(sampTexture, textures);
vec3 lightIntensity = ambientLightIntensity + sunLightIntensity * fragNormal * max(dot(fragNormal, sunLightDirection), 0.0f);
outColor = vec4(texel.rgb * lightIntensity, texel.a);
}
"""
在编译它们之后,我是这样设置环境的:
self.vertex_array_object = glGenVertexArrays(1)
glBindVertexArray(self.vertex_array_object)
vertex_buffer_object = GLuint(0)
glGenBuffers(1, vertex_buffer_object)
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object)
glBufferData(GL_ARRAY_BUFFER, len(self.object.model) * 4, self.object.c_model, GL_STATIC_DRAW)
# vertices
vertex_offset = 0
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.object.model.itemsize * 3, ctypes.c_void_p(vertex_offset))
glEnableVertexAttribArray(0)
# textures
texture_offset = len(self.object.vertex_index) * 12
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, self.object.model.itemsize * 2, ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# normals
normal_offset = texture_offset + len(self.object.texture_index) * 8
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, self.object.model.itemsize * 3, ctypes.c_void_p(normal_offset))
glEnableVertexAttribArray(2)
/* texture mapping … */
view = pyrr.matrix44.create_from_translation(pyrr.Vector3([0.0, 0.0, -3.0])).flatten()
projection = pyrr.matrix44.create_perspective_projection_matrix(80.0, 1280 / 720, 0.1, 100.0).flatten()
model = pyrr.matrix44.create_from_translation(pyrr.Vector3([2.0, -0.5, -1.7])).flatten()
translate = pyrr.matrix44.create_from_translation(pyrr.Vector3([0, -0.15, 0])).flatten()
scale = pyrr.matrix44.create_from_scale(pyrr.Vector3([0, 0, 0])).flatten()
light = pyrr.matrix44.create_from_translation(pyrr.Vector3([2.0, 10.5, 1.7])).flatten()
self.rot_y = pyrr.Matrix44.from_y_rotation(0).flatten()
c_view = (GLfloat * len(view))(*view)
c_projection = (GLfloat * len(projection))(*projection)
c_model = (GLfloat * len(model))(*model)
c_translate = (GLfloat * len(translate))(*translate)
c_scale = (GLfloat * len(translate))(*translate)
c_rotate = (GLfloat * len(self.rot_y))(*self.rot_y)
c_light = (GLfloat * len(light))(*light)
self.rotate_location = glGetUniformLocation(self.shader, b"rotate")
self.translate_location = glGetUniformLocation(self.shader, b"translate")
self.scale_location = glGetUniformLocation(self.shader, b"scale")
self.view_location = glGetUniformLocation(self.shader, b"view")
self.proj_location = glGetUniformLocation(self.shader, b"projection")
self.model_location = glGetUniformLocation(self.shader, b"model")
self.light_location = glGetUniformLocation(self.shader, b"light")
self.offset_location = glGetUniformLocation(self.shader, b"offsets")
glUniformMatrix4fv(self.view_location, 1, GL_FALSE, c_view)
glUniformMatrix4fv(self.proj_location, 1, GL_FALSE, c_projection)
glUniformMatrix4fv(self.model_location, 1, GL_FALSE, c_model)
glUniformMatrix4fv(self.translate_location, 1, GL_FALSE, c_translate)
glUniformMatrix4fv(self.scale_location, 1, GL_FALSE, c_scale)
glUniformMatrix4fv(self.rotate_location, 1, GL_FALSE, c_rotate)
glUniformMatrix4fv(self.light_location, 1, GL_FALSE, c_light)
我试过像
这样设置偏移向量
offset = [(0, 0), (10, 10)]
并使用 glUniform2fv 将它传递给着色器,但这只显示一个对象(我现在只需要 2 个)。这就是我绘制对象的方式:
glBindVertexArray(self.vertex_array_object)
glDrawArraysInstanced(GL_TRIANGLES, 0, len(self.object.vertex_index), 2)
glBindVertexArray(0)
顶点着色器在语义上不正确。您必须从类型为 vec2
:
的变量 offset 构造一个 vec3
vec4(positions + (offset, 0), 1.0f)
vec4(positions + vec3(offset, 0.0), 1.0)
实际上您已经使用了序列 (,
) 运算符。见 GLSL 4.60 - Expressions:
[...] The sequence (,) operator that operates on expressions by returning the type and value of the right-most expression in a comma separated list of expressions.
因此positions + (offset, 0)
的结果与positions + 0
的结果相同。
使用glUniform2fv
设置制服:
self.offset_location = glGetUniformLocation(self.shader, b"offsets")
glUniform2fv(self.offset_location, 2, [x0, y0, x1, y1])
或者你可以单独设置数组中的制服:
self.offset_0_location = glGetUniformLocation(self.shader, b"offsets[0]")
glUniform2f(self.offset_0_location, x0, y0)
self.offset_1_location = glGetUniformLocation(self.shader, b"offsets[1]")
glUniform2f(self.offset_1_location, x1, y1)
此外,(0, 0, 0) 的比例完全没有意义,因为它意味着所有顶点都变成 (0, 0, 0)。将比例更改为 (1, 1, 1):
scale = pyrr.matrix44.create_from_scale(pyrr.Vector3([1, 1, 1])).flatten()
我有一个 python OpenGL 应用程序,我试图在其中同时渲染多个对象,但没有任何运气。出于某种原因,无论我如何更改偏移量,都只会绘制一个对象。这是我的片段着色器:
self.vertex_shader_source = b"""
#version 330
in layout(location = 0) vec3 positions;
in layout(location = 1) vec2 textureCoords;
in layout(location = 2) vec3 normals;
uniform mat4 light;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 rotate;
uniform mat4 translate;
uniform mat4 scale;
uniform vec2 offsets[2];
out vec2 textures;
out vec3 fragNormal;
void main()
{
fragNormal = (light * vec4(normals, 0.0f)).xyz;
vec2 offset = offsets[gl_InstanceID];
gl_Position = projection * view * model * rotate * translate * scale * vec4(positions + (offset, 0), 1.0f);
textures = vec2(textureCoords.x, 1 - textureCoords.y);
}
"""
self.fragment_shader_source = b"""
#version 330
in vec2 textures;
in vec3 fragNormal;
uniform sampler2D sampTexture;
out vec4 outColor;
void main()
{
vec3 ambientLightIntensity = vec3(0.9f, 0.9f, 0.9f);
vec3 sunLightIntensity = vec3(0.0f, 0.2f, 0.0f);
vec3 sunLightDirection = normalize(vec3(0.0f, 0.0f, 0.0f));
vec4 texel = texture(sampTexture, textures);
vec3 lightIntensity = ambientLightIntensity + sunLightIntensity * fragNormal * max(dot(fragNormal, sunLightDirection), 0.0f);
outColor = vec4(texel.rgb * lightIntensity, texel.a);
}
"""
在编译它们之后,我是这样设置环境的:
self.vertex_array_object = glGenVertexArrays(1)
glBindVertexArray(self.vertex_array_object)
vertex_buffer_object = GLuint(0)
glGenBuffers(1, vertex_buffer_object)
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object)
glBufferData(GL_ARRAY_BUFFER, len(self.object.model) * 4, self.object.c_model, GL_STATIC_DRAW)
# vertices
vertex_offset = 0
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.object.model.itemsize * 3, ctypes.c_void_p(vertex_offset))
glEnableVertexAttribArray(0)
# textures
texture_offset = len(self.object.vertex_index) * 12
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, self.object.model.itemsize * 2, ctypes.c_void_p(texture_offset))
glEnableVertexAttribArray(1)
# normals
normal_offset = texture_offset + len(self.object.texture_index) * 8
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, self.object.model.itemsize * 3, ctypes.c_void_p(normal_offset))
glEnableVertexAttribArray(2)
/* texture mapping … */
view = pyrr.matrix44.create_from_translation(pyrr.Vector3([0.0, 0.0, -3.0])).flatten()
projection = pyrr.matrix44.create_perspective_projection_matrix(80.0, 1280 / 720, 0.1, 100.0).flatten()
model = pyrr.matrix44.create_from_translation(pyrr.Vector3([2.0, -0.5, -1.7])).flatten()
translate = pyrr.matrix44.create_from_translation(pyrr.Vector3([0, -0.15, 0])).flatten()
scale = pyrr.matrix44.create_from_scale(pyrr.Vector3([0, 0, 0])).flatten()
light = pyrr.matrix44.create_from_translation(pyrr.Vector3([2.0, 10.5, 1.7])).flatten()
self.rot_y = pyrr.Matrix44.from_y_rotation(0).flatten()
c_view = (GLfloat * len(view))(*view)
c_projection = (GLfloat * len(projection))(*projection)
c_model = (GLfloat * len(model))(*model)
c_translate = (GLfloat * len(translate))(*translate)
c_scale = (GLfloat * len(translate))(*translate)
c_rotate = (GLfloat * len(self.rot_y))(*self.rot_y)
c_light = (GLfloat * len(light))(*light)
self.rotate_location = glGetUniformLocation(self.shader, b"rotate")
self.translate_location = glGetUniformLocation(self.shader, b"translate")
self.scale_location = glGetUniformLocation(self.shader, b"scale")
self.view_location = glGetUniformLocation(self.shader, b"view")
self.proj_location = glGetUniformLocation(self.shader, b"projection")
self.model_location = glGetUniformLocation(self.shader, b"model")
self.light_location = glGetUniformLocation(self.shader, b"light")
self.offset_location = glGetUniformLocation(self.shader, b"offsets")
glUniformMatrix4fv(self.view_location, 1, GL_FALSE, c_view)
glUniformMatrix4fv(self.proj_location, 1, GL_FALSE, c_projection)
glUniformMatrix4fv(self.model_location, 1, GL_FALSE, c_model)
glUniformMatrix4fv(self.translate_location, 1, GL_FALSE, c_translate)
glUniformMatrix4fv(self.scale_location, 1, GL_FALSE, c_scale)
glUniformMatrix4fv(self.rotate_location, 1, GL_FALSE, c_rotate)
glUniformMatrix4fv(self.light_location, 1, GL_FALSE, c_light)
我试过像
这样设置偏移向量offset = [(0, 0), (10, 10)]
并使用 glUniform2fv 将它传递给着色器,但这只显示一个对象(我现在只需要 2 个)。这就是我绘制对象的方式:
glBindVertexArray(self.vertex_array_object)
glDrawArraysInstanced(GL_TRIANGLES, 0, len(self.object.vertex_index), 2)
glBindVertexArray(0)
顶点着色器在语义上不正确。您必须从类型为 vec2
:
vec3
vec4(positions + (offset, 0), 1.0f)
vec4(positions + vec3(offset, 0.0), 1.0)
实际上您已经使用了序列 (,
) 运算符。见 GLSL 4.60 - Expressions:
[...] The sequence (,) operator that operates on expressions by returning the type and value of the right-most expression in a comma separated list of expressions.
因此positions + (offset, 0)
的结果与positions + 0
的结果相同。
使用glUniform2fv
设置制服:
self.offset_location = glGetUniformLocation(self.shader, b"offsets")
glUniform2fv(self.offset_location, 2, [x0, y0, x1, y1])
或者你可以单独设置数组中的制服:
self.offset_0_location = glGetUniformLocation(self.shader, b"offsets[0]")
glUniform2f(self.offset_0_location, x0, y0)
self.offset_1_location = glGetUniformLocation(self.shader, b"offsets[1]")
glUniform2f(self.offset_1_location, x1, y1)
此外,(0, 0, 0) 的比例完全没有意义,因为它意味着所有顶点都变成 (0, 0, 0)。将比例更改为 (1, 1, 1):
scale = pyrr.matrix44.create_from_scale(pyrr.Vector3([1, 1, 1])).flatten()