Я инициализирую свою шейдерную программу следующим образом:
def __init__(self, vertex_file: str, fragment_file: str):
self.__vertex_shader_id = self.load_shader(vertex_file, GL_VERTEX_SHADER)
self.__fragment_shader_id = self.load_shader(fragment_file, GL_FRAGMENT_SHADER)
self.__program_id = glCreateProgram() # create program
glAttachShader(self.__program_id, self.__vertex_shader_id) # attach the shader to the program
glAttachShader(self.__program_id, self.__fragment_shader_id) # attach the shader to the program
self.bind_attributes()
glLinkProgram(self.__program_id) # link the program to the shaders
glValidateProgram(self.__program_id) # validate the program
# glUseProgram(self.__program_id)
self.get_all_uniform_locations()
(использование glUseProgram() не решает проблему)
и вызывая glGetUniformLocation() следующим образом:
def get_uniform_location(self, uniform_name: str):
return glGetUniformLocation(self.get_program_id, uniform_name)
В качестве аргумента для uniform_name я передаю «transformation_matrix».
Мой vertexShader.txt выглядит так:
#version 400 core
in vec3 position;
in vec2 texture_coords;
out vec2 pass_texture_coords;
uniform mat4 transformation_matrix;
void main(void){
gl_Position = transformation_matrix * vec4(position, 1.0);
pass_texture_coords = texture_coords;
}
Я не понимаю, как можно было передать неправильный тип, поскольку program_id — это целое число, аuniform_name — это строка, именно так, как это указано в документации. Кроме того, форма является (или должна быть) активной в VertexShader, так что это не может быть так.
Полная трассировка ошибки:
File "...\3DEngine\__main__.py", line 56, in <module>
main()
File "...\3DEngine\__main__.py", line 43, in main
shader = StaticShader()
File "...\3DEngine\shaders\static_shader.py", line 11, in __init__
super().__init__(self.get_vertex_file(), self.get_fragment_file())
File "...\3DEngine\shaders\shader_program.py", line 20, in __init__
self.get_all_uniform_locations()
File "...\3DEngine\shaders\static_shader.py", line 18, in get_all_uniform_locations
self.set_location_transformation_matrix(super().get_uniform_location(b"transformation_matrix"))
File "C...\3DEngine\shaders\shader_program.py", line 28, in get_uniform_location
return glGetUniformLocation(self.get_program_id, uniform_name)
File "C:\Users\Andreas\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\OpenGL\latebind.py", line 63, in __call__
return self.wrapperFunction( self.baseFunction, *args, **named )
File "C:\Users\Andreas\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\OpenGL\GL\VERSION\GL_2_0.py", line 430, in glGetUniformLocation
return baseOperation( program, name )
File "C:\Users\Andreas\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\OpenGL\platform\baseplatform.py", line 415, in __call__
return self( *args, **named )
ctypes.ArgumentError: argument 1: TypeError: wrong type
Минимальный воспроизводимый пример:
from OpenGL.GL import *
from OpenGL.GLUT import *
vertexShader = """#version 400 core
in vec3 position;
in vec2 texture_coords;
out vec2 pass_texture_coords;
uniform mat4 transformation_matrix;
void main(void){
gl_Position = transformation_matrix * vec4(position, 1.0);
pass_texture_coords = texture_coords;
}"""
fragmentShader = """#version 400 core
in vec2 pass_texture_coords;
out vec4 out_color;
uniform sampler2D texture_sampler;
void main(void){
out_color = texture(texture_sampler, pass_texture_coords);
}"""
def load_shader(file: str, shader_type: int):
try:
shader_source = ''.join(file) # create a continuous string
except Exception as e:
print(e) # print exception
raise SystemExit
shader_id = glCreateShader(shader_type) # create the shader
glShaderSource(shader_id, shader_source) # load the shader source code
glCompileShader(shader_id) # compile the shader
if glGetShaderiv(shader_id, GL_COMPILE_STATUS) == GL_FALSE:
print(glGetShaderInfoLog(shader_id)) # print the info log if it didn't compile correctly
print("Could not compile shader.")
raise SystemExit
return shader_id
def init(vertex_file: str, fragment_file: str):
vertex_shader_id = load_shader(vertex_file, GL_VERTEX_SHADER)
fragment_shader_id = load_shader(fragment_file, GL_FRAGMENT_SHADER)
program_id = glCreateProgram() # create program
glAttachShader(program_id, vertex_shader_id) # attach the shader to the program
glAttachShader(program_id, fragment_shader_id) # attach the shader to the program
glLinkProgram(program_id) # link the program to the shaders
glValidateProgram(program_id) # validate the program
glUseProgram(program_id)
get_all_uniform_locations()
def get_uniform_location(uniform_name: str):
return glGetUniformLocation(3, uniform_name) # hard coded the program ID
def get_all_uniform_locations():
get_uniform_location("transformation_matrix")
def update_display():
glClearColor(1, 0, 0, 1) # set backdrop color to red
glClear(GL_COLOR_BUFFER_BIT) # Remove everything from screen (i.e. displays all white)
glLoadIdentity() # Reset all graphic/shape's position
def create_display(window_name):
glutInit()
glutInitDisplayMode(GLUT_RGBA) # initialize colors
glutInitWindowSize(1280, 720) # set windows size
glutInitWindowPosition(0, 0) # set window position
glutCreateWindow(f"{window_name}") # create window (with a name) and set window attribute
glutSetWindow(1) # hard coded
glutDisplayFunc(update_display)
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS) # prevent program from stopping
create_display("Please work ffs")
init(vertexShader, fragmentShader)
@Rabbid76 идентификатор текущей программы, который, по-видимому, равен 3.
@NicolBolas Я не знаю. Если он начинается с нуля, это будет аргумент «имя». Если он начинается с 1, это аргумент «программа».
Мы хотим узнать от вас, какой аргумент является аргументом 1. И я не знаю, что возвращается от get_program_id
, потому что этот код отсутствует. В любом случае используйте байтовый литерал b'transformation_matrix'
вместо 'transformation_matrix'
. (Вызов get_uniform_location
также отсутствует)
Я не знаю, что такое «аргумент 1». Также я только что проверил, что возвращает get_program_id
, и это целое число 3. Это простой метод получения def get_program_id(self): return self.__program_id
. Также все та же ошибка после изменения ее в байтовый литерал
@ Rabbid76 Вызов get_uniform_location
выполняется из класса, который наследуется от класса, в котором был определен метод get_uniform_location
. Вызов: `def get_all_uniform_locations(self): self.set_location_transformation_matrix(super().get_uniform_location("transformation_matrix"))`
@ Rabbid76 Я включил в сообщение полную трассировку ошибок, потому что она была слишком длинной для комментария.
Проблема не воспроизводима. Однако я получаю ошибку типа, если передаю None
1-му аргументу. Предлагаю добавить print(self.get_program_id, uniform_name)
Вывод, как и ожидалось, "3 transform_matrix" (или "3 b'transformation_matrix'", если это байтовый литерал)
Не могу воспроизвести проблему.
Так вы говорите, что код работает для вас? Или нужны остальные?
@ Rabbid76 Старался изо всех сил ... Тем не менее, было бы лучше просто связать это ... (Это просто для того, чтобы вы могли мне помочь, если вы ответите на вопрос, это будет полезно для всех, кто ищет это)
Я установил PyOpenGL совсем недавно. Есть ли какие-либо другие зависимости, о которых я должен знать?
Также я получаю OpenGL.error.GLError с результатом -1. Я читал, что это означает, что униформа не активна (но это, вероятно, из-за отсутствия фрагмента Shader?).
Отлично... Теперь эта минимальная программа работает просто отлично.
Я не знаком с многопоточностью, поэтому я полагаю, что нет? Но вызов сделан из другого класса в другом файле, который переопределяет там метод. Я могу быстро скопировать 2 файла, если это сделает их более понятными.
@Rabbid76 Жесткое кодирование 3 в качестве идентификатора программы исправило ошибку для меня, но почему? Может ли измениться идентификатор программы?
Я забыл абзацы. Ты можешь убить меня сейчас...
Убедитесь, что вы не забыли скобки при вызове метода.
self.get_program_id()
вместо
self.get_program_id
Вы бы сэкономили много времени, если бы включили реализацию get_program_id
в вопрос, как я просил вас в начале. Я подозревал, что get_program_id
является свойством, не ожидая, что это будет функция.
Я прокомментировал это после того, как вы попросили об этом.
Это трудно читать, и я все еще думал, что это свойство (@property
def get_program_id(self):
). Я даже создаю пример со свойством. В любом случае, никогда не добавляйте дополнительную информацию в комментарии, а редактируйте вопрос.
Сделаю в следующий раз!
Я также попросила вас print(self.get_program_id, uniform_name)
. Вы этого не сделали, потому что иначе бы осознали свою ошибку. Так ты приходишь сюда за советом, а потом его игнорируешь?
@ Rabbid76 Мне очень жаль, что мы потратили впустую наше время, поверьте мне. Я действительно пытался это сделать, но из-за автодополнения скобки автоматически добавлялись, чего я не заметил. Опять же, извините.
Какой аргумент является «аргументом 1»?