原教程地址:https://learnopengl.com/Getting-started/Textures
中文翻译地址:https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/
文件列表:
glfw3.dll: 在http://www.glfw.org/download.html 点击下载32-bit Windows binaries,解压后选择lib-vc2015/glfw3.dll
glfw.py: 在https://github.com/rougier/pyglfw文件列表中下载glfw.py
ShaderProgram.py:
1 import os 2 import sys 3 import numpy as np 4 from OpenGL.GL import (glCreateProgram, glLinkProgram, glDeleteProgram, 5 glCreateShader, glShaderSource, glCompileShader, glAttachShader, glDeleteShader, 6 glGetAttribLocation, glGetProgramiv, glGetShaderiv, 7 glGetUniformLocation, glGetShaderInfoLog, glGetProgramInfoLog, 8 GL_FLOAT, GL_TRUE, GL_FALSE, GL_COMPILE_STATUS, GL_LINK_STATUS, GL_VERTEX_SHADER, GL_FRAGMENT_SHADER) 9 10 # this class is needed to create shader program and attach shaders to it. 11 12 class ShaderProgram(object): 13 def __init__(self, vertpath="", fragpath=""): 14 # paths to files should be set correctly 15 # yep it will contain paths to shaders. 16 self.vertpath = vertpath 17 self.fragpath = fragpath 18 vflag = os.path.exists(self.vertpath) 19 fflag = os.path.exists(self.fragpath) 20 if not vflag: 21 print ("Vertex shader file (--> %s <--) doesn't exist!"%self.vertpath) 22 if not fflag: 23 print ("Fragment shader file (--> %s <--) doesn't exist!"%self.fragpath) 24 if not (fflag and vflag): 25 sys.exit(1) 26 self.initProgram() 27 28 def getShader(self, shader_source, shader_type): 29 try: 30 shader_id = glCreateShader(shader_type) 31 glShaderSource(shader_id, shader_source) 32 glCompileShader(shader_id) 33 if glGetShaderiv(shader_id, GL_COMPILE_STATUS) != GL_TRUE: 34 info = glGetShaderInfoLog(shader_id) 35 raise RuntimeError('Shader compilation failed:\n %s'%info) 36 return shader_id 37 except: 38 glDeleteShader(shader_id) 39 raise 40 41 def loadShader(self, path): 42 source_file = open(path) 43 shader_source = source_file.read() 44 source_file.close() 45 return shader_source 46 47 def initProgram(self): 48 # create unique shader program id 49 self.program_id = glCreateProgram() 50 # load and compile individual shaders 51 vertsource = self.loadShader(self.vertpath) 52 fragsource = self.loadShader(self.fragpath) 53 vert_id = self.getShader(vertsource, GL_VERTEX_SHADER) 54 frag_id = self.getShader(fragsource, GL_FRAGMENT_SHADER) 55 # if it's ok, attach them to shader program 56 glAttachShader(self.program_id, vert_id) 57 glAttachShader(self.program_id, frag_id) 58 # link program means make program obj with created executables for different programmable processors for shaders, 59 # that were attached. 60 glLinkProgram(self.program_id) 61 # if something went wrong 62 if glGetProgramiv(self.program_id, GL_LINK_STATUS) != GL_TRUE: 63 info = glGetProgramInfoLog(self.program_id) 64 glDeleteProgram(self.program_id) 65 # they should be deleted anyway 66 glDeleteShader(vert_id) 67 glDeleteShader(frag_id) 68 raise RuntimeError("Error in program linking: %s"%info) 69 # shaders are attached, program is linked -> full shader program with compiled executables is ready, 70 # no need in individual shaders ids, i suppose 71 glDeleteShader(vert_id) 72 glDeleteShader(frag_id) 73 74 def attribLocation(self, name): 75 return glGetAttribLocation(self.program_id, name) 76 77 def uniformLocation(self, name): 78 return glGetUniformLocation(self.program_id, name)
texture.py:
1 #! /usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 import os, sys 5 6 import OpenGL.GL as gl 7 import glfw 8 from ShaderProgram import ShaderProgram 9 import numpy as np 10 from ctypes import c_void_p 11 from PIL import Image 12 13 class MyShaderProgram(ShaderProgram): 14 def __init__(self, vertPath="vertexShader.glsl", fragPath="fragmentShader.glsl"): 15 super().__init__(vertPath, fragPath) 16 17 def use(self): 18 gl.glUseProgram(self.program_id) 19 20 WIN_WIDTH = 800 21 WIN_HEIGHT = 600 22 23 vertices = np.array([0.5, 0.5, 0, 1.0, 0.0, 0.0, 1.0, 1.0, 24 0.5,-0.5, 0, 0.0, 1.0, 0.0, 1.0, 0.0, 25 -0.5,-0.5, 0, 0.0, 0.0, 1.0, 0.0, 0.0, 26 -0.5, 0.5, 0, 1.0, 1.0, 0.0, 0.0, 1.0], dtype = np.float32) 27 28 indices = np.array([0, 1, 3, 29 1, 2, 3], dtype = np.uint32) 30 31 def framebuffer_size_callback(window, width, height): 32 gl.glViewport(0, 0, width, height) 33 34 def processInput(window): 35 if glfw.glfwGetKey(window, glfw.GLFW_KEY_ESCAPE) == glfw.GLFW_PRESS: 36 glfw.glfwSetWindowShouldClose() 37 38 if glfw.glfwGetKey(window, glfw.GLFW_KEY_LEFT) == glfw.GLFW_PRESS: 39 gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL) 40 41 if glfw.glfwGetKey(window, glfw.GLFW_KEY_RIGHT) == glfw.GLFW_PRESS: 42 gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE) 43 44 def main(): 45 glfw.glfwInit() 46 glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MAJOR, 3) 47 glfw.glfwWindowHint(glfw.GLFW_CONTEXT_VERSION_MINOR, 3) 48 glfw.glfwWindowHint(glfw.GLFW_OPENGL_PROFILE, glfw.GLFW_OPENGL_CORE_PROFILE) 49 50 window = glfw.glfwCreateWindow(WIN_WIDTH, WIN_HEIGHT, "学习OpenGL".encode(), 0, 0) 51 if window == 0: 52 print("failed to create window") 53 glfw.glfwTerminate() 54 55 glfw.glfwMakeContextCurrent(window) 56 glfw.glfwSetFramebufferSizeCallback(window, framebuffer_size_callback) 57 58 myShaderProg = MyShaderProgram() 59 60 VAO = gl.glGenVertexArrays(1) 61 VBO, EBO = gl.glGenBuffers(2) 62 63 gl.glBindVertexArray(VAO) 64 gl.glBindBuffer(gl.GL_ARRAY_BUFFER, VBO) 65 gl.glBufferData(gl.GL_ARRAY_BUFFER, sys.getsizeof(vertices), vertices, gl.GL_STATIC_DRAW) 66 gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, EBO) 67 gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, sys.getsizeof(indices), indices, gl.GL_STATIC_DRAW) 68 69 gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 32, c_void_p(0)) 70 gl.glEnableVertexAttribArray(0) 71 gl.glVertexAttribPointer(1, 3, gl.GL_FLOAT, gl.GL_FALSE, 32, c_void_p(12)) 72 gl.glEnableVertexAttribArray(1) 73 gl.glVertexAttribPointer(2, 2, gl.GL_FLOAT, gl.GL_FALSE, 32, c_void_p(24)) 74 gl.glEnableVertexAttribArray(2) 75 76 texture = gl.glGenTextures(1) 77 gl.glBindTexture(gl.GL_TEXTURE_2D, texture) 78 gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT) 79 gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT) 80 gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) 81 gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) 82 83 img = Image.open("container.jpg") 84 width, height = img.size 85 data = np.array(list(img.getdata()), dtype=np.uint8) 86 87 gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, width, height, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, data) 88 gl.glGenerateMipmap(gl.GL_TEXTURE_2D) 89 90 gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) 91 gl.glBindVertexArray(0) 92 93 while not glfw.glfwWindowShouldClose(window): 94 processInput(window) 95 gl.glClearColor(0.2, 0.3, 0.3, 1.0) 96 gl.glClear(gl.GL_COLOR_BUFFER_BIT) 97 98 myShaderProg.use() 99 100 gl.glBindVertexArray(VAO) 101 gl.glDrawElements(gl.GL_TRIANGLES, len(indices), gl.GL_UNSIGNED_INT, None) 102 103 glfw.glfwSwapBuffers(window) 104 glfw.glfwPollEvents() 105 106 glfw.glfwTerminate() 107 108 if __name__ == "__main__": 109 main()
vertexShader.glsl:
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; layout (location = 2) in vec2 aTexCoord; out vec3 ourColor; out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0); ourColor = aColor; TexCoord = aTexCoord; }
fragmentShader.glsl:
#version 330 core out vec4 FragColor; in vec3 ourColor; in vec2 TexCoord; uniform sampler2D ourTexture; void main() { FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 1.0); }
container.jpg:
最终程序执行效果: