免费A级毛片无码专区网站-成人国产精品视频一区二区-啊 日出水了 用力乖乖在线-国产黑色丝袜在线观看下-天天操美女夜夜操美女-日韩网站在线观看中文字幕-AV高清hd片XXX国产-亚洲av中文字字幕乱码综合-搬开女人下面使劲插视频

[CG從零開(kāi)始] 4. pyopengl 繪制一個(gè)正方形

在做了 1~3 的基礎(chǔ)工作后,我們的開(kāi)發(fā)環(huán)境基本 OK 了,我們可以開(kāi)始嘗試?yán)?pyopengl 來(lái)進(jìn)行繪制了 。本文主要有三個(gè)部分

  1. 利用 glfw 封裝窗口類,并打開(kāi)窗口;
  2. 封裝 shader 類,進(jìn)行編譯、鏈接、使用;
  3. 封裝 VAO、VBO、EBO
  4. 完成主函數(shù)進(jìn)行繪制
完整的代碼在倉(cāng)庫(kù) (tag: v0.1) https://github.com/MangoWAY/CGLearner/tree/v0.1
1. 利用 glfw 封裝窗口類為了顯示我們繪制的內(nèi)容,打開(kāi)窗口是必不可少的操作,因此我們來(lái)簡(jiǎn)單封裝一個(gè)窗口類,便于我們后續(xù)的學(xué)習(xí)、調(diào)用 。我們?cè)O(shè)置 opengl 的版本,向前兼容和配置(這倆在 macOS 必須配置),這些其實(shí)可以不用太關(guān)心,并不影響我們后續(xù)的學(xué)習(xí)進(jìn)程,感興趣可以看一下 glfw 的官方關(guān)于窗口的文檔 。
# window_helper.pyimport glfw, logging, sysfrom OpenGL import GL as gllog = logging.getLogger(__name__)class Window:class Config:def __init__(self,gl_version = (3,3), size = (500,400), title = "cglearn", bgcolor = (0,0.4,0)) -> None:self.gl_version = gl_versionself.size = sizeself.title = titleself.bgcolor = bgcolordef __init__(self,config: Config) -> None:self.native_window = Noneself.config = configself.init(config)def set_background(self,r,g,b):gl.glClearColor(r, g, b, 0)def init(self, config: Config):if not glfw.init():log.error('failed to initialize GLFW')sys.exit(1)log.debug('requiring modern OpenGL without any legacy features')glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, config.gl_version[0])glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, config.gl_version[1])glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)log.debug('opening window')self.native_window = glfw.create_window(config.size[0], config.size[1], config.title, None, None)if not self.native_window:log.error('failed to open GLFW window.')sys.exit(2)glfw.make_context_current(self.native_window)log.debug('set background to dark blue')gl.glClearColor(0, config.bgcolor[0], config.bgcolor[1],config.bgcolor[2])2. 封裝 shader 類用 OpenGL 完成一次簡(jiǎn)單的繪制有一些基本的操作,
  1. 需要編寫(xiě) shader,然后創(chuàng)建 shader 程序,進(jìn)行編譯、鏈接、激活;
  2. 需要?jiǎng)?chuàng)建 VAO,VBO,EBO(可選),來(lái)管理數(shù)據(jù),傳遞給 shader 進(jìn)行計(jì)算;
  3. 在循環(huán)中調(diào)用繪制指令來(lái)進(jìn)行繪制;
這一小節(jié)我們來(lái)封裝一個(gè) shader 類,來(lái)完成 shader 的創(chuàng)建、編譯、鏈接等操作 。
創(chuàng)建一個(gè) shader 分幾個(gè)步驟:
  • 創(chuàng)建 VERTEX 和 FRAGMENT shader;
  • 傳送 shader 的代碼 (string);
  • 編譯 VERTEX 和 FRAGMENT shader;
  • 創(chuàng)建 program (shader 程序);
  • 將 VERTEX 和 FRAGMENT shader 附加到 program 上;
  • 鏈接 program;
在渲染前,還要激活 shader 程序
# shader.pyimport sysfrom OpenGL import GL as glfrom enum import Enumimport logginglog = logging.getLogger(__name__)class ShaderType(Enum):VERTEX = 0FRAGMENT = 1class Shader:def __init__(self) -> None:self.vertex_shader = ""self.fragment_shader = ""self.program_id = -1self.shader_ids = []def load_shader_source_from_string(self, shader_type: ShaderType, source: str):if shader_type == ShaderType.VERTEX:self.vertex_shader = sourceelif shader_type == ShaderType.FRAGMENT:self.fragment_shader = sourceelse:logging.error("wrong shader type !")# 從文件讀取 shader,按照普通的文本文件讀取即可 。def load_shader_source_from_path(self, shader_type: ShaderType, path: str):with open(path,"r") as f:source = f.read()self.load_shader_source_from_string(shader_type, source)# 這個(gè)主要是用來(lái)打印編譯時(shí)候出現(xiàn)的錯(cuò)誤信息,不是關(guān)鍵,這里先略去def log_shader_info(self, shader_id):...# 這個(gè)主要是用來(lái)打印鏈接時(shí)候出現(xiàn)的錯(cuò)誤信息,不是關(guān)鍵,這里先略去def log_program_info(self,program_id):...def create_program(self):# 創(chuàng)建 shader 程序self.program_id = gl.glCreateProgram()for shader_type in [gl.GL_VERTEX_SHADER, gl.GL_FRAGMENT_SHADER]:# 創(chuàng)建 VERTEX 和 FRAGMENT shadershader_id = gl.glCreateShader(shader_type)# 傳送 shader 代碼if shader_type == gl.GL_VERTEX_SHADER:gl.glShaderSource(shader_id, self.vertex_shader)else:gl.glShaderSource(shader_id, self.fragment_shader)log.debug(f'compiling the {shader_type} shader')# 編譯 VERTEX 和 FRAGMENT shadergl.glCompileShader(shader_id)self.log_shader_info(shader_id)# 將 VERTEX 和 FRAGMENT shader 附加到 program 上gl.glAttachShader(self.program_id, shader_id)self.shader_ids.append(shader_id)log.debug('linking shader program')# 鏈接 shader 程序gl.glLinkProgram(self.program_id)self.log_program_info(self.program_id)log.debug('installing shader program into rendering state')# 激活 shader 程序def use_program(self):gl.glUseProgram(self.program_id)# 刪除 shader 程序def clean_program(self):log.debug('cleaning up shader program')for shader_id in self.shader_ids:gl.glDetachShader(self.program_id, shader_id)gl.glDeleteShader(shader_id)gl.glUseProgram(0)gl.glDeleteProgram(self.program_id)

經(jīng)驗(yàn)總結(jié)擴(kuò)展閱讀