问题
I want to impement a pyramid which has different texture in each side. The pyramid with the textures is correct without using an index data array. When i use the indexdata the textures get mixed with each other. Do i have to correct the AttribPointer? (My texture is a collage image of 5 different images)
*I want to keep the indexData array
Here is a part of the code
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
import numpy as np
from framework import *
from PIL import Image
from math import tan, cos, sin
# A 1-D array of 3 4-D vertices (X,Y,Z,W)
# Note that this must be a numpy array, since as of
# 170111 support for lists has not been implemented.
vertexData = np.array(
[ 0.0, 0.5, -1.3, 1.0, #0
0.3, 0.0, -1.0, 1.0, #1
-0.3, 0.0, -1.0, 1.0, #2
-0.3, 0.0, -1.6, 1.0, #3
0.3, 0.0, -1.6, 1.0, #4
0.0, 0.0, -1.3, 1.0, #5
#texture
0.8, 0.0,
1.0, 0.0,
0.8, 0.4,
0.0, 0.3,
0.3, 0.3,
0.3, 0.0,
0.5, 1.0,
0.5, 0.5,
0.6, 1.0,
0.1, 1.0,
0.4, 1.0,
0.0, 0.4,
0.0, 0.0,
0.0, 0.3,
0.3, 0.0,
0.0, 0.0,
0.0, 0.3,
0.3, 0.0,
0.0, 0.0,
0.0, 0.3, #leukos toixos
0.3, 0.0,
0.0, 0.0,
0.0, 0.3,
0.3, 0.0,
],
dtype='float32'
)
indexData = np.array(
[0,1,2,
0,2,3,
0,3,4,
0,4,1,
5,2,1,
5,1,4,
5,4,3,
5,3,2],)
vertexDim = 4
texcoordDim = 2
nVertices = 8*3
# Global variable to represent the compiled shader program, written in GLSL
theProgram = None
# Global variable to represent the buffer that will hold the position vectors
vertexBufferObject = None
sampleTexture = None
texUnitUniform = None
# Global variables to store the location of the shader's uniform variables
perspectiveMatrixUnif = None
WorldtoCameraMatrixUnif = None
# Global display variables
perspectiveMatrix = None
CameraMatrix = None
fFrustumScale = 1.0
def loadTexture(path):
img = Image.open(path).transpose(Image.FLIP_TOP_BOTTOM) #anoigoume tin eikona
#img.show()
img_data = np.frombuffer(img.tobytes(), np.uint8)
width, height = img.size
# glTexImage2D expects the first element of the image data to be the
# bottom-left corner of the image. Subsequent elements go left to right,
# with subsequent lines going from bottom to top.
# However, the image data was created with PIL Image tostring and numpy's
# fromstring, which means we have to do a bit of reorganization. The first
# element in the data output by tostring() will be the top-left corner of
# the image, with following values going left-to-right and lines going
# top-to-bottom. So, we need to flip the vertical coordinate (y).
texture = glGenTextures(1)
#glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glBindTexture(GL_TEXTURE_2D, texture)#ginetai sundesi me to antikeimeno pou ftiaxtike
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)#parametroi gia tin ufi
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)#gia na exw digrammiko filtrarisma
#glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
#glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)#sundesi twn dedomenwn
#glGenerateMipmap(GL_TEXTURE_2D)
return texture
# Set up the list of shaders, and call functions to compile them
def initializeProgram():
shaderList = []
shaderList.append(loadShader(GL_VERTEX_SHADER, "Texture.vert"))
shaderList.append(loadShader(GL_FRAGMENT_SHADER, "Texture.frag"))
global theProgram
theProgram = createProgram(shaderList)
for shader in shaderList:
glDeleteShader(shader)
global perspectiveMatrixUnif
perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix")
global WorldtoCameraMatrixUnif
WorldtoCameraMatrixUnif = glGetUniformLocation(theProgram, "cameraMatrix")
global sampleTexture
global texUnitUniform
sampleTexture = loadTexture('pic.jpg') #i eikona
texUnitUniform = glGetUniformLocation(theProgram, "texUnit")#gia na vrethei apo ton fragment shader
fzNear = 0.5
fzFar = 3.0
global CameraMatrix
CameraPos=np.array([0.8, 0.8, -1.0])
CameraTarget=np.array([1.0, 1.0, 0.0])
CameraUp=np.array([-1.0, 1.0, 0.0])
CameraTarget=CameraTarget/np.linalg.norm(CameraTarget)
CameraRight=np.cross(CameraUp, CameraTarget)
CameraRight=CameraRight/np.linalg.norm(CameraRight)
CameraUp=np.cross(CameraTarget, CameraRight)
CameraRotMatrix=np.vstack((CameraRight, CameraUp, CameraTarget,[0.0, 0.0, 0.0]))
CameraRotMatrix=np.hstack((CameraRotMatrix, [[0.0], [0.0], [0.0], [1.0]]))
CameraTranMatrix=np.eye(4)
CameraTranMatrix[0][3]=-CameraPos[0]
CameraTranMatrix[1][3]=-CameraPos[1]
CameraTranMatrix[2][3]=-CameraPos[2]
CameraMatrix=np.matmul(CameraRotMatrix,CameraTranMatrix)
global perspectiveMatrix
perspectiveMatrix = np.zeros(16, dtype='float32')
perspectiveMatrix[0] = fFrustumScale
perspectiveMatrix[5] = fFrustumScale
perspectiveMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar)
perspectiveMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar)
perspectiveMatrix[11] = -1.0
glUseProgram(theProgram)
glActiveTexture(GL_TEXTURE0)#energi tin monada ufis pou me endiaferei
glBindTexture(GL_TEXTURE_2D, sampleTexture)#sundesi tis ufis me ton stoxo
glUniform1i(texUnitUniform, 0)#sundesi tis metavlitis me tin monada 0
glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix)
glUniformMatrix4fv(WorldtoCameraMatrixUnif, 1, GL_TRUE, CameraMatrix)
glUseProgram(0)
# Set up the vertex buffer that will store our vertex coordinates for OpenGL's access
def initializeVertexBuffer():
global vertexBufferObject
vertexBufferObject = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject)
glBufferData( # PyOpenGL allows for the omission of the size parameter
GL_ARRAY_BUFFER,
vertexData,
GL_STREAM_DRAW
)
glBindBuffer(GL_ARRAY_BUFFER, 0)
indexBufferObject = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject)
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
indexData,
GL_STATIC_DRAW
)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
def computeAngleRad(fElapsedTime, fLoopDuration):
fScale = 3.14159 * 2.0 / fLoopDuration
fCurrTimeThroughLoop = fElapsedTime % fLoopDuration
return fCurrTimeThroughLoop * fScale
def rotateZ(fElapsedTime):
fAngRad = computeAngleRad(fElapsedTime, 4.0)
fCos = cos(fAngRad)
fSin = sin(fAngRad)
# Initialize the OpenGL environment
def init():
initializeProgram()
initializeVertexBuffer()
glBindVertexArray(glGenVertexArrays(1))
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glFrontFace(GL_CW)
glEnable(GL_DEPTH_TEST)
# Called to update the display.
# Because we are using double-buffering, glutSwapBuffers is called at the end
# to write the rendered buffer to the display.
def display():
glClearColor(0.0, 0.0, 0.0, 0.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glUseProgram(theProgram)
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject)
glEnableVertexAttribArray(0)
glEnableVertexAttribArray(1)
glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None)
# a ctype void pointer must be used to pass in the offset into the bound GL_ARRAY_BUFFER
# also note that python's underlying float type is usally 64-bit, but
# we have specified that our vertex array contains float32 data.
texcoordOffset = c_void_p(vertexDim*nVertices*4)
glVertexAttribPointer(1, texcoordDim, GL_FLOAT, GL_FALSE, 0, texcoordOffset)
fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 2000.0
AngRad = computeAngleRad(fElapsedTime, 2.0)
worldMatrix = np.identity(4, dtype='float32')
worldMatrix[0][0] = cos(AngRad)
worldMatrix[0][2] = sin(AngRad)
worldMatrix[2][0] = -sin(AngRad)
worldMatrix[2][2] = cos(AngRad)
matTrans1 = np.identity(4, dtype='float32')
matTrans1[2][3] = 1.3
matTrans2 = np.identity(4, dtype='float32')
matTrans2[2][3] = -1.3
newTransformA= np.matmul(worldMatrix,matTrans1)
newTransformB = np.matmul (matTrans2,newTransformA)
transformMatrix = newTransformB
glUniformMatrix4fv(WorldtoCameraMatrixUnif, 1, GL_FALSE, transformMatrix.transpose())
glDrawArrays(GL_TRIANGLES, 0, nVertices)
glDisableVertexAttribArray(0)
glDisableVertexAttribArray(1)
glUseProgram(0)
glutSwapBuffers()
glutPostRedisplay()
# keyboard input handler: exits the program if 'esc' is pressed
def keyboard(key, x, y):
if ord(key) == 27: # ord() is needed to get the keycode
glutLeaveMainLoop()
return
# Called whenever the window's size changes (including once when the program starts)
def reshape(w, h):
global perspectiveMatrix
perspectiveMatrix[0] = fFrustumScale / (w / float(h))
perspectiveMatrix[5] = fFrustumScale
glUseProgram(theProgram)
glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix)
glUseProgram(0)
glViewport(0, 0, w, h)
# The main function
def main():
glutInit()
displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL;
glutInitDisplayMode (displayMode)
width = 500;
height = 500;
glutInitWindowSize (width, height)
glutInitWindowPosition (300, 200)
window = glutCreateWindow(b"Tutorial Window")
init()
glutDisplayFunc(display)
glutReshapeFunc(reshape)
glutKeyboardFunc(keyboard)
glutMainLoop();
if __name__ == '__main__':
main()
来源:https://stackoverflow.com/questions/62495938/how-to-get-i-the-correct-texture-using-indexing-in-opengl