#python #opengl #glsl #glfw #pyopengl
#python #opengl #glsl #glfw #pyopengl
Вопрос:
Я написал этот код на Python, который нарисует треугольник в окне, созданном с использованием GLFW:
import glfw
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import numpy as np
vertex_src = """
# version 330 core
in vec3 a_position;
void main() {
gl_position = vec4(a_position, 1.0);
}
"""
fragment_src = """
# version 330 core
out vec4 out_color;
void main() {
out_color = vec4(1.0, 0.0, 0.0, 1.0);
}
"""
if not glfw.init():
print("Cannot initialize GLFW")
exit()
window = glfw.create_window(320, 240, "OpenGL window", None, None)
if not window:
glfw.terminate()
print("GLFW window cannot be creted")
exit()
glfw.set_window_pos(window, 100, 100)
glfw.make_context_current(window)
vertices = [-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0]
colors = [1, 0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0]
vertices = np.array(vertices, dtype=np.float32)
colors = np.array(colors, dtype=np.float32)
shader = compileProgram(compileShader(
vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))
buff_obj = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, buff_obj)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
position = glGetAttribLocation(shader, "a_position")
glEnableVertexAttribArray(position)
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
glUseProgram(shader)
glClearColor(0, 0.1, 0.1, 1)
while not glfw.window_should_close(window):
glfw.poll_events()
glfw.swap_buffers(window)
glfw.terminate()
При запуске программы я получил эту ошибку:
Traceback (most recent call last):
File "opengl.py", line 43, in <module>
shader = compileProgram(compileShader(
File "/usr/local/lib/python3.8/dist-packages/OpenGL/GL/shaders.py", line 235, in compileShader
raise ShaderCompilationError(
OpenGL.GL.shaders.ShaderCompilationError: ("Shader compile failure (0): b'0:2(10): error: GLSL 3.30 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES, and 3.00 ES\n'", [b'n# version 330 corenin vec3 a_position;nvoid main() {n gl_position = vec4(a_position, 1.0);n}n'], GL_VERTEX_SHADER)
Это ясно указывает на то, что GLSL 3.30 не поддерживается. Но это работает в C, устанавливая оконные подсказки:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
Как я могу установить эти оконные подсказки в Python?
Ответ №1:
С синтаксисом Python это
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
Обратите внимание, в вашем фрагментном шейдере есть опечатка. GLSL чувствителен к регистру. Это должно быть gl_Position
, а не gl_position
.
В контексте OpenGL основного профиля вы должны использовать именованный объект массива вершин, потому что объект массива вершин по умолчанию (0) недопустим:
vao = glGenVertexArrays(1) # <----
glBindVertexArray(vao) # <----
position = glGetAttribLocation(shader, "a_position")
glEnableVertexAttribArray(position)
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
Наконец, вы пропустили рисование геометрии. Очистите буфер фрейма и нарисуйте массив:
while not glfw.window_should_close(window):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDrawArrays(GL_TRIANGLES, 0, 3)
glfw.poll_events()
glfw.swap_buffers(window)
Полный пример:
import glfw
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import numpy as np
vertex_src = """
# version 330 core
in vec3 a_position;
void main() {
gl_Position = vec4(a_position, 1.0);
}
"""
fragment_src = """
# version 330 core
out vec4 out_color;
void main() {
out_color = vec4(1.0, 0.0, 0.0, 1.0);
}
"""
if not glfw.init():
print("Cannot initialize GLFW")
exit()
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
window = glfw.create_window(320, 240, "OpenGL window", None, None)
if not window:
glfw.terminate()
print("GLFW window cannot be creted")
exit()
glfw.set_window_pos(window, 100, 100)
glfw.make_context_current(window)
vertices = [-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0]
colors = [1, 0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0]
vertices = np.array(vertices, dtype=np.float32)
colors = np.array(colors, dtype=np.float32)
shader = compileProgram(compileShader(
vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))
buff_obj = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, buff_obj)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
position = glGetAttribLocation(shader, "a_position")
glEnableVertexAttribArray(position)
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
glUseProgram(shader)
glClearColor(0, 0.1, 0.1, 1)
while not glfw.window_should_close(window):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDrawArrays(GL_TRIANGLES, 0, 3)
glfw.poll_events()
glfw.swap_buffers(window)
glfw.terminate()