How to read in python the KTX file format used in the book Superbible OpenGL? part 2 of an example

主宰稳场 提交于 2019-12-11 15:08:18

问题


In part 1 we read the SBM file format successfully, this is part 2 on how to read the KTX file format.

Update: June 25, 2019, the below code to read the ktx file format does work. The file is ktxloader.py Though the code is still a work in progress. Any comments on it would be appreciated.

The code below is a working example to create and modify ktxloader.py

Files required: pattern1.ktx is our KTX file, to be read this program torus_nrms_tc.sbm is our SBM file solved in part1 in a folder called 'shared' in the same directory as the program sbmath.py and from part1 the sbmloader.py from part2, this post: ktxloader.py this is our KTX file format loader.

The source code for the program, sbmktx.py is:

import sys
import time 
import os
import math
import ctypes

currentWDir = os.getcwd()
print( 'current working directory: {}'.format( str(currentWDir) ) )
fileDir = os.path.dirname(os.path.abspath(__file__)) # det the directory of this file
print( 'current location of self: {}'.format( str(fileDir) ) )
parentDir = os.path.abspath(os.path.join(fileDir, os.pardir)) # get the parent directory of this file
sys.path.insert(0, parentDir)
print( 'insert system directory: {}'.format( str(parentDir) ) )
os.chdir( fileDir )
baseWDir = os.getcwd()
print( 'changed current working directory: {}'.format( str(baseWDir) ) )
print ( '' )

sys.path.append("./shared")

from sbmloader import SBMObject    # location of sbm file format loader
from ktxloader import KTXObject    # location of ktx file format loader

from sbmath import m3dDegToRad, m3dRadToDeg, m3dTranslateMatrix44, m3dRotationMatrix44, m3dMultiply, m3dOrtho, m3dPerspective, rotation_matrix, translate

fullscreen = True

import numpy.matlib 
import numpy as np 

try:
    from OpenGL.GLUT import *
    from OpenGL.GL import *
    from OpenGL.GLU import *
    #from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, glBindVertexArray
except:
    print ('''
    ERROR: PyOpenGL not installed properly.
        ''')
    sys.exit()


# Vertex program
vs_source = '''
#version 420 core
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
layout (location = 0) in vec4 position;
layout (location = 4) in vec2 tc;
out VS_OUT
{
    vec2 tc;
} vs_out;
void main(void)
{
    vec4 pos_vs = mv_matrix * position;
    vs_out.tc = tc;
    gl_Position = proj_matrix * pos_vs;
}
'''

# Fragment program
fs_source = '''
#version 420 core
layout (binding = 0) uniform sampler2D tex_object;
in VS_OUT
{
    vec2 tc;
} fs_in;
out vec4 color;
void main(void)
{
    color = texture(tex_object, fs_in.tc * vec2(3.0, 1.0));
}
'''

identityMatrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]

render_prog = GLuint(0)

uniforms_mv_matrix = (GLfloat * 16)(*identityMatrix)
uniforms_proj_matrix = (GLfloat * 16)(*identityMatrix)

tex_index = 0
tex_object = []


def load_shaders():
        global render_prog
        global uniforms_mv_matrix
        global uniforms_proj_matrix

        if (render_prog):
            glDeleteProgram(render_prog);

        fs = glCreateShader(GL_FRAGMENT_SHADER);

        glShaderSource(fs, fs_source);
        glCompileShader(fs);

        vs = glCreateShader(GL_VERTEX_SHADER);

        glShaderSource(vs, vs_source);
        glCompileShader(vs);

        render_prog = glCreateProgram();
        glAttachShader(render_prog, vs);
        glAttachShader(render_prog, fs);
        glLinkProgram(render_prog);

        glDeleteShader(vs);
        glDeleteShader(fs);

        uniforms_mv_matrix = glGetUniformLocation(render_prog, "mv_matrix");
        uniforms_proj_matrix = glGetUniformLocation(render_prog, "proj_matrix");

class Scene:
    def __init__(self, width, height):

        self.width = width
        self.height = height

        B = (0x00, 0x00, 0x00, 0x00)
        W = (0xFF, 0xFF, 0xFF, 0xFF)
        tex_data = [
            B, W, B, W, B, W, B, W, B, W, B, W, B, W, B, W,
            W, B, W, B, W, B, W, B, W, B, W, B, W, B, W, B,
            B, W, B, W, B, W, B, W, B, W, B, W, B, W, B, W,
            W, B, W, B, W, B, W, B, W, B, W, B, W, B, W, B,
            B, W, B, W, B, W, B, W, B, W, B, W, B, W, B, W,
            W, B, W, B, W, B, W, B, W, B, W, B, W, B, W, B,
            B, W, B, W, B, W, B, W, B, W, B, W, B, W, B, W,
            W, B, W, B, W, B, W, B, W, B, W, B, W, B, W, B,
            B, W, B, W, B, W, B, W, B, W, B, W, B, W, B, W,
            W, B, W, B, W, B, W, B, W, B, W, B, W, B, W, B,
            B, W, B, W, B, W, B, W, B, W, B, W, B, W, B, W,
            W, B, W, B, W, B, W, B, W, B, W, B, W, B, W, B,
            B, W, B, W, B, W, B, W, B, W, B, W, B, W, B, W,
            W, B, W, B, W, B, W, B, W, B, W, B, W, B, W, B,
            B, W, B, W, B, W, B, W, B, W, B, W, B, W, B, W,
            W, B, W, B, W, B, W, B, W, B, W, B, W, B, W, B,
        ]

        tex_object.append( glGenTextures(1) )

        #glGenTextures(1, tex_object[0]);
        glBindTexture(GL_TEXTURE_2D, tex_object[0]);
        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        tex_object.append (  glGenTextures(1) )

        ktxobj = KTXObject()

        tex_object[1] = ktxobj.ktx_load("pattern1.ktx")
        #tex_object[1] = sb7::ktx::file::load("pattern1.ktx");

        myobject.load("torus_nrms_tc.sbm");

        load_shaders();

        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);


    def display(self):

        global uniforms_mv_matrix
        global uniforms_proj_matrix

        currentTime = time.time()

        gray = [ 0.2, 0.2, 0.2, 1.0 ];
        ones = [ 1.0 ];

        glClearBufferfv(GL_COLOR, 0, gray);
        glClearBufferfv(GL_DEPTH, 0, ones);

        glViewport(0, 0, self.width, self.height);

        glBindTexture(GL_TEXTURE_2D, tex_object[tex_index]);

        glUseProgram(render_prog);

        T = (GLfloat * 16)(*identityMatrix)
        RX = (GLfloat * 16)(*identityMatrix)
        RY = (GLfloat * 16)(*identityMatrix)
        R = (GLfloat * 16)(*identityMatrix)

        # other ways to matrix multiply can be found at https://stackoverflow.com/questions/56711138/how-to-read-parse-the-sbm-file-format-from-superbible-opengl
        # Matrix multiplication is not commutative, order matters when multiplying matrices
        T  = np.matrix(translate(0.0, 0.0, -4.0)).reshape(4,4)
        RX = np.matrix(rotation_matrix( [1.0, 0.0, 0.0], currentTime * m3dDegToRad(17.0)))
        RY = np.matrix(rotation_matrix( [0.0, 1.0, 0.0], currentTime * m3dDegToRad(13.0)))
        mv_matrix = RX * RY * T

        proj_matrix = (GLfloat * 16)(*identityMatrix)
        proj_matrix = m3dPerspective(m3dDegToRad(60.0), float(self.width) / float(self.height), 0.1, 100.0);    

        glUniformMatrix4fv(uniforms_mv_matrix, 1, GL_FALSE, mv_matrix);
        glUniformMatrix4fv(uniforms_proj_matrix, 1, GL_FALSE, proj_matrix);

        myobject.render() # renders the torus

        glutSwapBuffers()

    def reshape(self, width, height):
        self.width = width
        self.height = height

    def keyboard(self, key, x, y ):
        global fullscreen
        global tex_index

        print ('key:' , key)
        if key == b'\x1b': # ESC
            sys.exit()

        elif key == b'f' or key == b'F': #fullscreen toggle

            if (fullscreen == True):
                glutReshapeWindow(self.width, self.height)
                glutPositionWindow(int((1360/2)-(512/2)), int((768/2)-(512/2)))
                fullscreen = False
            else:
                glutFullScreen()
                fullscreen = True

        elif key == b'r' or key == b'R': 
            load_shaders()

        elif key == b't' or key == b'T': 
            tex_index+=1
            if (tex_index > 1):
                tex_index = 0

        print('done')

    def init(self):
        pass

    def timer(self, blah):

        glutPostRedisplay()
        glutTimerFunc( int(1/60), self.timer, 0)
        time.sleep(1/20.0)

myobject = SBMObject()
if __name__ == '__main__':
    start = time.time()

    glutInit()
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
    glutInitWindowSize(512, 512)
    w1 = glutCreateWindow('OpenGL SuperBible - Texture Coordinates')

    fullscreen = False
    #glutFullScreen()

    scene = Scene(512, 512)
    glutReshapeFunc(scene.reshape)
    glutDisplayFunc(scene.display)
    glutKeyboardFunc(scene.keyboard)

    glutIdleFunc(scene.display)
    #glutTimerFunc( int(1/60), scene.timer, 0)

    scene.init()

glutMainLoop()

At this point the program should run, and you should see a torus or donut like the gif here, it rotates and spins and has a checkboard pattern.

When the ktx file complete the result looks like (by pressing 't' on the keyboard to switch textures): it will have a lion spotted like drops pattern.

The KTX File Format Specification are here.

Though I am porting to python the c++ code from here and am following that mostly: sb7ktx.cpp and its header here sb7ktx.h

Here is an example of a ktx file contents:

My question is that by using numpy how can I read the ktx texture file in a similar way to part1 how the sbm file was read, parsed? Any help would be greatly appreciated. Thank You.

来源:https://stackoverflow.com/questions/56749815/how-to-read-in-python-the-ktx-file-format-used-in-the-book-superbible-opengl-pa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!