【问题标题】:pygame pyopengl texture a changing polygon with many sidespygame pyopengl 纹理一个变化多端的多边形
【发布时间】:2020-12-23 23:07:11
【问题描述】:

所以在这个网站的帮助下,我最近在 pygame/pyopengl 中制作了一个 2d 水模拟的东西。我现在正在继续使用我制作的水纹理对这个水模拟进行纹理化。但是,当我尝试这样做时,无论我做什么,纹理似乎都无法正确显示。它在那里,但它全都伸展而无序。我希望纹理平铺且不被破坏,如何获得?

这是我的代码:

import pygame
import random
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

def loadTexture():
    textureSurface = pygame.image.load('test_image.png')
    textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
    width = textureSurface.get_width()
    height = textureSurface.get_height()

    glEnable(GL_TEXTURE_2D)
    texid = glGenTextures(1)

    glBindTexture(GL_TEXTURE_2D, texid)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
                 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData)

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

    return texid


def draw_water(polygon_points):
    glBegin(GL_POLYGON)
    for i in polygon_points:
        glTexCoord2f(*i)
        glVertex2f(*i)
    glEnd()

class surface_water_particle():
    
    def __init__(self, x,y):
        self.x_pos = x
        self.y_pos = y
        self.target_y = y
        self.velocity = 0
        self.k = 0.04  
        self.d = 0.08
        self.time = 1

    def update(self):
        x =  self.y_pos - self.target_y
        a = -(self.k * x + self.d * self.velocity)

        if self.y_pos > self.target_y:
            self.y_pos -= 0.1
        if self.y_pos < self.target_y:
            self.y_pos += 0.1
        self.velocity = round(self.velocity)

        self.y_pos += self.velocity
        self.velocity += a

        self.time += 1

class water_tile():
    def __init__(self, x_start, x_end, y_start, y_end, segment_length):
        self.springs = []
        self.x_start = x_start
        self.y_start = y_start
        self.x_end = x_end
        self.y_end = y_end - 10
        for i in range(abs(x_end - x_start) // segment_length):
            self.springs.append(surface_water_particle(i * segment_length + x_start, y_end))

    def update(self, spread):
        passes = 4  # more passes = more splash spreading
        for i in range(len(self.springs)):
            self.springs[i].update() 

        leftDeltas = [0] * len(self.springs)
        rightDeltas = [0] * len(self.springs)
        for p in range(passes):  
            for i in range(0, len(self.springs)):
                if i > 0:  
                    leftDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i - 1].y_pos)
                    self.springs[i - 1].velocity += leftDeltas[i]
                if i < len(self.springs):
                    rightDeltas[i] = spread * (self.springs[i].y_pos - self.springs[(i + 1)%len(self.springs)].y_pos)
                    self.springs[(i + 1)%len(self.springs)].velocity += rightDeltas[i]

            for i in range(0, len(self.springs)):
                if round (leftDeltas[i],12) == 0 or round (rightDeltas[i],12) == 0:
                    self.springs[i - 1].y_pos = self.y_end+10
                if i > 0:
                    self.springs[i - 1].y_pos += leftDeltas[i]  
                if i < len(self.springs):
                    self.springs[(i + 1)%len(self.springs)].y_pos += rightDeltas[i]
                
    def splash(self, index, speed):
        if index >= 0 and index < len(self.springs):
            self.springs[index].velocity = speed 

    def draw(self):
        water_surface = pygame.Surface((abs(self.x_end-self.x_start), abs(self.y_start - self.y_end)), depth=8).convert_alpha()
        water_surface.fill((0,0,0,100))
        water_surface.set_colorkey((0,0,0,0))
        polygon_points = []
        polygon_points.append((self.x_start, 360-self.y_start))
        for spring in range(len(self.springs)):
            polygon_points.append((self.springs[spring].x_pos, 360-self.springs[spring].y_pos))
        polygon_points.append((self.springs[len(self.springs) - 1].x_pos, 360-self.y_start))

        return polygon_points
        

class water_object:
    def __init__(self, x_start, x_end, y_start, y_end, segment_length, x_pos, y_pos):
        self.water = water_tile(x_start,x_end,y_start,y_end,segment_length)

    def update(self):
        self.water.update(0.1)
        self.polypoints = self.water.draw()
        
water_list = [water_object(0,276+16,64,0,16,0,20)]

def main():
    pygame.init()
    display = (640, 360)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0, display[0], 0, display[1], -1, 1)

    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    loadTexture()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == MOUSEBUTTONDOWN:
                print (len(water.water.springs))
                water.water.splash(random.randint(0, len(water.water.springs) - 1),50)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
       
        for water in water_list:
            water.update()
            draw_water(water.polypoints)
        pygame.display.flip()
        pygame.time.wait(10)

if __name__ == "__main__":
    main()

下面是我的纹理

【问题讨论】:

  • 抱歉,您缺少基础知识。您误解了 OpenGL primitives 和纹理坐标的基本概念(请参阅 How do opengl texture coordinates work?)。我建议阅读一个好的 OpenGL 教程(例如LearnOpenGL)。无论如何,当您使用旧版 OpenGL 固定功能管道时,必须启用纹理 (glEnable(GL_TEXTURE_2D))
  • @Rabbid76 您好,感谢您提供的链接,我会尽快查看。我知道我缺少很多知识,包括大部分基础知识。说实话,我昨天才开始使用 openGL,目前我正在翻阅一本关于它的书/试图通过实践来学习。这本质上就是这样,只是我试图把一些东西放在一起。我有学习障碍,并且与书籍和东西斗争(即使我尽力阅读它们),所以我发现这种混乱的练习和从错误中学习很有用。它是如何开始学习 Python 的。

标签: opengl pygame textures pyopengl


【解决方案1】:

如果你想用颜色填充水线下的区域,那么我建议生成一个GL_TRIANGLE_STRIPprimitive

def draw_polygon(polygon_points):
    glBegin(GL_TRIANGLE_STRIP)
    for pt in polygon_points:
        glVertex2f(*pt)
        glVertex2f(pt[0], WINDOW_SIZE[1])
    glEnd()

看例子:

import pygame, random
import math as m

from pygame import *
from OpenGL import *
from OpenGL.GLU import *
from OpenGL.GL import *

pygame.init()

WINDOW_SIZE = (640, 480)
 
screen = pygame.display.set_mode(WINDOW_SIZE, flags=DOUBLEBUF|OPENGL, depth=32, display=0) # initiate the window
clock = pygame.time.Clock()

def draw_polygon(polygon_points):
    glBegin(GL_TRIANGLE_STRIP)
    for pt in polygon_points:
        glVertex2f(*pt)
        glVertex2f(pt[0], WINDOW_SIZE[1])
    glEnd()
    
class surface_water_particle():
    
    def __init__(self, x,y):
        self.x_pos = x
        self.y_pos = y
        self.target_y = y
        self.velocity = 0
        self.k = 0.04  
        self.d = 0.08
        self.time = 1

    def update(self):
        x =  self.y_pos - self.target_y
        a = -(self.k * x + self.d * self.velocity)

        if self.y_pos > self.target_y:
            self.y_pos -= 0.1
        if self.y_pos < self.target_y:
            self.y_pos += 0.1
        self.velocity = round(self.velocity)

        self.y_pos += self.velocity
        self.velocity += a

        self.time += 1

class water():
    
    def __init__(self, x_start, x_end, y_start, y_end, segment_length):
        self.springs = []
        self.x_start = x_start
        self.y_start = y_start
        self.x_end = x_end
        self.y_end = y_end - 10
        for i in range(abs(x_end - x_start) // segment_length):
            self.springs.append(surface_water_particle(i * segment_length + x_start, y_end))

    def update(self, spread):
        passes = 4  # more passes = more splash spreading
        for i in range(len(self.springs)):
            self.springs[i].update() 

        leftDeltas = [0] * len(self.springs)
        rightDeltas = [0] * len(self.springs)
        for p in range(passes):  
            for i in range(0, len(self.springs) -1 ):
                if i > 0:  
                    leftDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i - 1].y_pos)
                    self.springs[i - 1].velocity += leftDeltas[i]
                if i < len(self.springs) - 1:
                    rightDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i + 1].y_pos)
                    self.springs[i + 1].velocity += rightDeltas[i]

            for i in range(0, len(self.springs) -1):
                if i > 0:
                    self.springs[i - 1].y_pos += leftDeltas[i]  # you were updating velocity here!
                if i < len(self.springs) - 1:
                    self.springs[i + 1].y_pos += rightDeltas[i]

               
                
    def splash(self, index, speed):
        if index > 0 and index < len(self.springs) :
            self.springs[index].velocity = speed
                
    def draw(self):
        water_surface = pygame.Surface((abs(self.x_start - self.x_end), abs(self.y_start - self.y_end))).convert_alpha()
        water_surface.fill((0,0,0,0))
        water_surface.set_colorkey((0,0,0,0))
        polygon_points = []
        polygon_points.append((self.x_start, self.y_start))
        for spring in range(len(self.springs)):
            polygon_points.append((self.springs[spring].x_pos, self.springs[spring].y_pos))
        polygon_points.append((self.springs[len(self.springs) - 1].x_pos, self.y_start))

        glColor3f(0, 0, 1)
        draw_polygon(polygon_points)
        
water_test = water(0,800,200,200, 3)

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, WINDOW_SIZE[0], WINDOW_SIZE[1], 0, -1, 1)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

glClearColor(1, 1, 1, 1)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
        if event.type == MOUSEBUTTONDOWN:
            water_test.splash(50, 100)
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    
    water_test.update(0.025)
    water_test.draw()

    pygame.display.flip()
    clock.tick(60)

【讨论】:

    猜你喜欢
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多