GlGetUniformLocation() выдает 'ctypes.ArgumentError: аргумент 1: TypeError: неправильный тип'

Я инициализирую свою шейдерную программу следующим образом:

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)

Какой аргумент является «аргументом 1»?

Nicol Bolas 03.02.2023 17:57

@Rabbid76 идентификатор текущей программы, который, по-видимому, равен 3.

Andreas Sabelfeld 03.02.2023 17:59

@NicolBolas Я не знаю. Если он начинается с нуля, это будет аргумент «имя». Если он начинается с 1, это аргумент «программа».

Andreas Sabelfeld 03.02.2023 18:00

Мы хотим узнать от вас, какой аргумент является аргументом 1. И я не знаю, что возвращается от get_program_id, потому что этот код отсутствует. В любом случае используйте байтовый литерал b'transformation_matrix' вместо 'transformation_matrix'. (Вызов get_uniform_location также отсутствует)

Rabbid76 03.02.2023 18:02

Я не знаю, что такое «аргумент 1». Также я только что проверил, что возвращает get_program_id, и это целое число 3. Это простой метод получения def get_program_id(self): return self.__program_id. Также все та же ошибка после изменения ее в байтовый литерал

Andreas Sabelfeld 03.02.2023 18:08

@ Rabbid76 Вызов get_uniform_location выполняется из класса, который наследуется от класса, в котором был определен метод get_uniform_location. Вызов: `def get_all_uniform_locations(self): self.set_location_transformation_matrix(super().get_uniform_‌​location("transforma‌​tion_matrix"))`

Andreas Sabelfeld 03.02.2023 18:15

@ Rabbid76 Я включил в сообщение полную трассировку ошибок, потому что она была слишком длинной для комментария.

Andreas Sabelfeld 03.02.2023 18:19

Проблема не воспроизводима. Однако я получаю ошибку типа, если передаю None 1-му аргументу. Предлагаю добавить print(self.get_program_id, uniform_name)

Rabbid76 03.02.2023 19:26

Вывод, как и ожидалось, "3 transform_matrix" (или "3 b'transformation_matrix'", если это байтовый литерал)

Andreas Sabelfeld 03.02.2023 19:45

Не могу воспроизвести проблему.

Rabbid76 03.02.2023 19:46

Так вы говорите, что код работает для вас? Или нужны остальные?

Andreas Sabelfeld 03.02.2023 19:55

@ Rabbid76 Старался изо всех сил ... Тем не менее, было бы лучше просто связать это ... (Это просто для того, чтобы вы могли мне помочь, если вы ответите на вопрос, это будет полезно для всех, кто ищет это)

Andreas Sabelfeld 03.02.2023 20:16

Я установил PyOpenGL совсем недавно. Есть ли какие-либо другие зависимости, о которых я должен знать?

Andreas Sabelfeld 03.02.2023 20:28

Также я получаю OpenGL.error.GLError с результатом -1. Я читал, что это означает, что униформа не активна (но это, вероятно, из-за отсутствия фрагмента Shader?).

Andreas Sabelfeld 03.02.2023 20:30

Отлично... Теперь эта минимальная программа работает просто отлично.

Andreas Sabelfeld 03.02.2023 20:34

Я не знаком с многопоточностью, поэтому я полагаю, что нет? Но вызов сделан из другого класса в другом файле, который переопределяет там метод. Я могу быстро скопировать 2 файла, если это сделает их более понятными.

Andreas Sabelfeld 03.02.2023 20:38

@Rabbid76 Жесткое кодирование 3 в качестве идентификатора программы исправило ошибку для меня, но почему? Может ли измениться идентификатор программы?

Andreas Sabelfeld 03.02.2023 20:56

Я забыл абзацы. Ты можешь убить меня сейчас...

Andreas Sabelfeld 03.02.2023 20:58
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
18
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Убедитесь, что вы не забыли скобки при вызове метода.

self.get_program_id()

вместо

self.get_program_id

Вы бы сэкономили много времени, если бы включили реализацию get_program_id в вопрос, как я просил вас в начале. Я подозревал, что get_program_id является свойством, не ожидая, что это будет функция.

Rabbid76 03.02.2023 21:03

Я прокомментировал это после того, как вы попросили об этом.

Andreas Sabelfeld 03.02.2023 21:05

Это трудно читать, и я все еще думал, что это свойство (@propertydef get_program_id(self):). Я даже создаю пример со свойством. В любом случае, никогда не добавляйте дополнительную информацию в комментарии, а редактируйте вопрос.

Rabbid76 03.02.2023 21:07

Сделаю в следующий раз!

Andreas Sabelfeld 03.02.2023 21:08

Я также попросила вас print(self.get_program_id, uniform_name). Вы этого не сделали, потому что иначе бы осознали свою ошибку. Так ты приходишь сюда за советом, а потом его игнорируешь?

Rabbid76 04.02.2023 11:32

@ Rabbid76 Мне очень жаль, что мы потратили впустую наше время, поверьте мне. Я действительно пытался это сделать, но из-за автодополнения скобки автоматически добавлялись, чего я не заметил. Опять же, извините.

Andreas Sabelfeld 04.02.2023 13:12

Другие вопросы по теме