Specify the needed opengl version centrally

This commit is contained in:
Kovid Goyal 2016-10-26 12:24:24 +05:30
parent 7161406ff3
commit 8c76596f5c
3 changed files with 67 additions and 94 deletions

View File

@ -6,29 +6,9 @@ import glfw
import OpenGL.GL as gl
import sys
from kitty.shaders import ShaderProgram, array
from kitty.shaders import ShaderProgram, array, GL_VERSION
from kitty.fonts import set_font_family, render_cell, cell_size
vertex_shader = """
# version 410
in vec2 vertex;
void main() {
gl_Position = vec4(vertex, 0, 1);
}
"""
fragment = """
# version 410
out vec4 final_color;
void main(void)
{
final_color = vec4(1.0);
}
"""
def key_callback(key, action):
""" Sample keyboard callback function """
@ -45,16 +25,37 @@ def gl_get_unicode(k):
return ans
def on_resize(window, w, h):
gl.glViewport(0, 0, w, h)
class Renderer:
def __init__(self, w, h):
self.w, self.h = w, h
self.do_layout()
self.program = rectangle_texture()
print(gl.glGetIntegerv(gl.GL_MAX_VERTEX_UNIFORM_COMPONENTS))
print(gl.glGetIntegerv(gl.GL_MAX_UNIFORM_BLOCK_SIZE))
print(gl.glGetIntegerv(gl.GL_MAX_ARRAY_TEXTURE_LAYERS))
def on_resize(self, window, w, h):
gl.glViewport(0, 0, w, h)
self.w, self.h = w, h
self.do_layout()
def do_layout(self):
# Divide into cells
cell_width, cell_height = cell_size()
self.cells_per_line = self.w // cell_width
self.lines_per_screen = self.h // cell_height
def render(self):
rectangle_texture(self.program)
def _main():
# These Window hints are used to specify
# which opengl version to use and other details
# for the opengl context that will be created
glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MAJOR, 4)
glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MINOR, 1)
glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MAJOR, GL_VERSION[0])
glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MINOR, GL_VERSION[1])
glfw.glfwWindowHint(glfw.GLFW_OPENGL_PROFILE,
glfw.GLFW_OPENGL_CORE_PROFILE)
glfw.glfwWindowHint(glfw.GLFW_OPENGL_FORWARD_COMPAT, True)
@ -65,7 +66,6 @@ def _main():
raise SystemExit("glfwCreateWindow failed")
glfw.glfwMakeContextCurrent(window)
glfw.glfwSwapInterval(1)
glfw.glfwSetFramebufferSizeCallback(window, on_resize)
# If everything went well the following calls
# will display the version of opengl being used
@ -74,21 +74,19 @@ def _main():
print('GLSL Version: %s' % (gl_get_unicode(gl.GL_SHADING_LANGUAGE_VERSION)))
print('Renderer: %s' % (gl_get_unicode(gl.GL_RENDERER)))
r = Renderer(1024, 1024)
glfw.glfwSetFramebufferSizeCallback(window, r.on_resize)
try:
gl.glClearColor(0.5, 0.5, 0.5, 0)
rectangle_texture(window)
while not glfw.glfwWindowShouldClose(window):
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
r.render()
glfw.glfwSwapBuffers(window)
glfw.glfwWaitEvents()
finally:
glfw.glfwDestroyWindow(window)
def triangle_vertices(width=0.8, height=0.8):
return array(
0.0, height,
-width, -height,
width, -height,
)
def rectangle_vertices(left=-0.8, top=0.8, right=0.8, bottom=-0.8):
vertex_data = array(
right, top,
@ -109,37 +107,8 @@ def rectangle_vertices(left=-0.8, top=0.8, right=0.8, bottom=-0.8):
return vertex_data, texture_coords
def rectangle(window):
program = ShaderProgram(vertex_shader, fragment)
with program:
program.set_attribute_data('vertex', rectangle_vertices()[0])
while not glfw.glfwWindowShouldClose(window):
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
with program:
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
glfw.glfwSwapBuffers(window)
glfw.glfwWaitEvents()
def triangle(window):
program = ShaderProgram(vertex_shader, fragment)
with program:
program.set_attribute_data('vertex', triangle_vertices())
while not glfw.glfwWindowShouldClose(window):
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
with program:
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)
glfw.glfwSwapBuffers(window)
glfw.glfwWaitEvents()
textured_shaders = (
'''
#version 410
'''\
in vec2 vertex;
in vec2 texture_position;
out vec2 texture_position_for_fs;
@ -150,8 +119,7 @@ void main() {
}
''',
'''
#version 410
'''\
uniform sampler2D tex;
in vec2 texture_position_for_fs;
out vec4 final_color;
@ -172,23 +140,20 @@ def texture_data():
return cell, w, h
def rectangle_texture(window):
program = ShaderProgram(*textured_shaders)
img_data, w, h = texture_data()
with program:
program.set_2d_texture('tex', img_data, w, h)
rv, texc = rectangle_vertices()
program.set_attribute_data('vertex', rv)
program.set_attribute_data('texture_position', texc)
while not glfw.glfwWindowShouldClose(window):
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
def rectangle_texture(program=None):
if program is None:
program = ShaderProgram(*textured_shaders)
img_data, w, h = texture_data()
with program:
program.set_2d_texture('tex', img_data, w, h)
rv, texc = rectangle_vertices()
program.set_attribute_data('vertex', rv)
program.set_attribute_data('texture_position', texc)
return program
else:
with program:
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
glfw.glfwSwapBuffers(window)
glfw.glfwWaitEvents()
def on_error(code, msg):
if isinstance(msg, bytes):

View File

@ -13,6 +13,7 @@ from .config import load_config
from .constants import appname, str_version, config_dir
from .boss import Boss
from .utils import fork_child, hangup
from .shaders import GL_VERSION
import glfw
@ -34,8 +35,8 @@ def option_parser():
def setup_opengl():
glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MAJOR, 3)
glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MINOR, 2)
glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MAJOR, GL_VERSION[0])
glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MINOR, GL_VERSION[1])
glfw.glfwWindowHint(glfw.GLFW_OPENGL_PROFILE, glfw.GLFW_OPENGL_CORE_PROFILE)
glfw.glfwWindowHint(glfw.GLFW_OPENGL_FORWARD_COMPAT, True)
glfw.glfwWindowHint(glfw.GLFW_SAMPLES, 0)

View File

@ -7,28 +7,28 @@ from functools import lru_cache
from OpenGL.arrays import ArrayDatatype
import OpenGL.GL as gl
GL_VERSION = (4, 1)
VERSION = GL_VERSION[0] * 100 + GL_VERSION[1] * 10
class ShaderProgram:
""" Helper class for using GLSL shader programs """
def __init__(self, vertex: str, fragment: str):
def __init__(self, vertex, fragment):
"""
Create a shader program.
:param vertex: The vertex shader
:param fragment: The fragment shader
"""
self.program_id = gl.glCreateProgram()
self.texture_id = None
self.is_active = False
vs_id = self.add_shader(vertex, gl.GL_VERTEX_SHADER)
frag_id = self.add_shader(fragment, gl.GL_FRAGMENT_SHADER)
gl.glAttachShader(self.program_id, vs_id)
gl.glAttachShader(self.program_id, frag_id)
gl.glLinkProgram(self.program_id)
frag_id = self.add_shader(fragment, gl.GL_FRAGMENT_SHADER)
gl.glAttachShader(self.program_id, frag_id)
gl.glLinkProgram(self.program_id)
if gl.glGetProgramiv(self.program_id, gl.GL_LINK_STATUS) != gl.GL_TRUE:
info = gl.glGetProgramInfoLog(self.program_id)
gl.glDeleteProgram(self.program_id)
@ -52,6 +52,7 @@ class ShaderProgram:
def add_shader(self, source: str, shader_type: int) -> int:
' Compile a shader and return its id, or raise an exception if compilation fails '
shader_id = gl.glCreateShader(shader_type)
source = '#version {}\n{}'.format(VERSION, source)
try:
gl.glShaderSource(shader_id, source)
gl.glCompileShader(shader_id)
@ -90,6 +91,10 @@ class ShaderProgram:
def set_2d_texture(self, var_name, data, width, height, data_type='red',
min_filter=gl.GL_LINEAR, mag_filter=gl.GL_LINEAR,
swrap=gl.GL_CLAMP_TO_EDGE, twrap=gl.GL_CLAMP_TO_EDGE):
if not self.is_active:
raise RuntimeError('The program must be active before you can add buffers')
if self.texture_id is not None:
gl.glDeleteTextures([self.texture_id])
texture_id = self.texture_id = gl.glGenTextures(1)
self.texture_var = self.uniform_location(var_name)
gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1 if data_type == 'red' else 4)
@ -107,14 +112,16 @@ class ShaderProgram:
0, external_format, gl.GL_UNSIGNED_BYTE, data)
return texture_id
def set_attribute_data(self, attribute_name, data, items_per_attribute_value=2, volatile=False, normalize=False):
def set_attribute_data(self, attribute_name, data, items_per_attribute_value=2, normalize=False):
if not self.is_active:
raise RuntimeError('The program must be active before you can add buffers')
if len(data) % items_per_attribute_value != 0:
raise ValueError('The length of the data buffer is not a multiple of the items_per_attribute_value')
buf_id = self.attribute_buffers[attribute_name] = gl.glGenBuffers(1)
buf_id = self.attribute_buffers.get(attribute_name) # glBufferData auto-deletes previous data
if buf_id is None:
buf_id = self.attribute_buffers[attribute_name] = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buf_id)
gl.glBufferData(gl.GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(data), data, gl.GL_STREAM_DRAW if volatile else gl.GL_STATIC_DRAW)
gl.glBufferData(gl.GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(data), data, gl.GL_STATIC_DRAW)
loc = self.attribute_location(attribute_name)
gl.glEnableVertexAttribArray(loc)
typ = {