pygame光栅化三角形 用像素填充三角形

参考文章
DirectX C++ 3D编程基础 5 [三角形光栅化] 自制中字

这次用像素填充三角形,是为了下次用图片做纹理填充三角形做准备。
前面的文章说了根据直线方程求出已知两点间任意一点的坐标,现在来试试用像素填充三角形。
首先画一个三角形
pygame光栅化三角形 用像素填充三角形_第1张图片

pygame.draw.polygon(screen, color, ((ax,ay), (bx, by), (cx, cy)))#左,中,右
                                        #(70, 580), (160, 300), (200, 580)

abc三点坐标为a(70,580) b(160,300) c(200,500)
首先计算点a至点b这条线的斜率
公式为zk=(ay-by)/(ax-bx)#左边斜率
计算求得k=-(280/90)
接下来求截距

jiejuz=(bx*zk)-by#截距

公式y=kx+b, 将点b(160,300)带入公式(带入哪个点都行)
b=(71800/90)
这里做个判断,因为计算b的时候公式为-b=kx-y
要将结果正负转换(这个后续可能还得改)

jz=0
    if jiejuz<0:
        jz=abs(jiejuz)
    else:
        jz=-abs(jiejuz)

现在做个测试,看看对不对
x取值在70-200,y取值在300-580
y取400,看看x在不在这条线上
因为要求x,所以公示改变为-kx=b-y,变化下-x=(b-y)/k
x=127.85714285714288
下图橙色线
pygame光栅化三角形 用像素填充三角形_第2张图片
这是三角形左边线的斜率,我们同理求出右边的斜率
现在就可以根据y求出两边直线sx,ex的坐标
pygame光栅化三角形 用像素填充三角形_第3张图片

zk=(ay-by)/(ax-bx)#左边斜率
    yk=(by-cy)/(bx-cx)
    #y=kx+b -b=kx-y 但是没法用-b当变量,下面就-abs手动转负数
    jiejuz=(bx*zk)-by#截距
    jz=0
    if jiejuz<0:
        jz=abs(jiejuz)
    else:
        jz=-abs(jiejuz)
    #print(jiejuz,jz)
    '''yz=zk*(70+0.5)+jz
    #y1 = zk * 90 + jieju
    #print(int(46600/90),int(y1), int(yz))
    pygame.Surface.set_at(screen, (90, int(46600/90)), (255,0,0))
    pygame.Surface.set_at(screen, (int(70+0.5), int(yz)), (255,0, 0))
'''
    # (70, 580), (160, 300), (200, 580)

    
    jiejuy=(bx*yk)-by#截距

    jy = 0
    if jiejuy < 0:
        jy = abs(jiejuy)
    else:
        jy = -abs(jiejuy)

    

   
   
    xz = (jz - 300) /zk
    zuoxianx=abs(xz)
    xy=(jy-300)/yk
    youxianx=abs(xy)
    # y1 = zk * 90 + jieju
    # print(int(46600/90),int(y1), int(yz))
    pygame.Surface.set_at(screen, (int(youxianx), 300), (255, 0, 0))
    pygame.Surface.set_at(screen, (int(zuoxianx), 300), (255, 0, 0))

pygame光栅化三角形 用像素填充三角形_第4张图片
眼神好的能看见,这两点都画了一个红色像素,现在将这两点连起来

c=int(youxianx)-int(zuoxianx)
    for i in range(c):
        pygame.Surface.set_at(screen, (70+i, int(580)), (0, 255, 0))

pygame光栅化三角形 用像素填充三角形_第5张图片
画出了一条绿色线。现在只需要知道高度,就可以将白色三角形填充起来了。
a(70, 580),b (160, 300), c(200, 580)
高度就是580-300
循环280次,从上面开始,也就是从300开始。每次加1,首个数字gao是0。ex = abs(xy1)+2#加2是为了填补空白这个如果不加2个像素会有空白边

xcishu=ex-sx

计算x循环几次,终点x也就是右边的x-左边x

pygame.Surface.set_at(screen, (int(sx) + i, 300+gao), (255, 0, 0))

sx就是当前高度左边x的坐标,x每次加循环次数(xcishu=ex-sx),y是从300开始,每次加gao,也就是高度循环次数

    for gao in range(280):

        xz1 = (jz - (gao+300)) / zk
        sx = abs(xz1)
        xy1 = (jy - (gao+300)) / yk
        ex = abs(xy1)+2#加2是为了填补空白
        xcishu=ex-sx
        print("gao==",gao,"第一次循环",int(sx),int(ex))
        for i in range(int(xcishu)):
            print("i==",i,"第二次循环",int(sx),int(ex))

            # pygame.Surface.set_at(screen, (i, int(580)), (0, 255, 0))
            pygame.Surface.set_at(screen, (int(sx) + i, 300+gao), (255, 0, 0))

pygame光栅化三角形 用像素填充三角形_第6张图片
如果没加2的话是这样的
pygame光栅化三角形 用像素填充三角形_第7张图片
下面是完整代码

import pygame
import sys
from pygame import gfxdraw

(width, height) = (600, 600)
pygame.init()
screen = pygame.display.set_mode((width, height))
image = pygame.image.load("1.png").convert_alpha()
masked_result = image.copy()

white_color = (255, 255, 255)
polygon =[(0, 0), (800, 600), (0, 600)]
#(260,0),(200,0),(200,130),(260,130)

#[(0.0, 307.6923076923077), (723.0769230769231, 307.6923076923077), (972.4137931034483, 413.7931034482759), (0.0, 413.7931034482759)]
image = pygame.image.load("1.png")
car = pygame.transform.scale(image, (100, 100))


#screen.fill((0,0,0))
#screen.blit(image, (140,140))
screensurf = pygame.display.get_surface()#获取当前显示的 Surface 对象
color=(255, 255, 255)

img=pygame.image.load("1.png").convert_alpha()
ix=0#纹理坐标
iy=0
px=310#画出来填充像素坐标
py=310

ax=70
ay=580
bx=160
by=300
cx=200
cy=580
#(70, 580), (160, 300), (200, 580)
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouse = pygame.mouse.get_pos()
            '''pxarray = pygame.PixelArray(screensurf)
            pixel = pygame.Color(pxarray[mouse[0], mouse[1]])#获取像素
            print (pixel)
            print (screensurf.get_at(mouse))#颜色
            print(mouse[0], mouse[1],mouse)#点击坐标
            print(img.get_at(mouse))#颜色'''
            #pygame.Surface.set_at(screen, (140, 140), (img.get_at(mouse)))
            print(mouse[0], mouse[1], mouse)  # 点击坐标
    #gfxdraw.pixel(screen, 90, 90, color)#画一个像素
    w=img.get_width()
    h=img.get_height()
    #print(w,h)
    for ih in range(h):
        for iw in range(w):
            pygame.Surface.set_at(screen, (px+iw, py+ih), (img.get_at((ix+iw,iy+ih))))
                        #(px+iw, py+ih)是当前绘制x,y像素位置  img.get_at((ix+iw,iy+ih)是获取图片中对应位置的颜色
            #print(px+iw, py+ih)
    pygame.draw.polygon(screen, color, ((ax,ay), (bx, by), (cx, cy)))#左,中,右
                                        #(70, 580), (160, 300), (200, 580)
    zk=(ay-by)/(ax-bx)#左边斜率
    yk=(by-cy)/(bx-cx)
    #y=kx+b -b=kx-y 但是没法用-b当变量,下面就-abs手动转负数
    jiejuz=(bx*zk)-by#截距
    jz=0
    if jiejuz<0:
        jz=abs(jiejuz)
    else:
        jz=-abs(jiejuz)
    #print(jiejuz,jz)
    '''yz=zk*(70+0.5)+jz
    #y1 = zk * 90 + jieju
    #print(int(46600/90),int(y1), int(yz))
    pygame.Surface.set_at(screen, (90, int(46600/90)), (255,0,0))
    pygame.Surface.set_at(screen, (int(70+0.5), int(yz)), (255,0, 0))
'''
    # (70, 580), (160, 300), (200, 580)

    yk = (by - cy) / (bx - cx)
    jiejuy=(bx*yk)-by#截距

    jy = 0
    if jiejuy < 0:
        jy = abs(jiejuy)
    else:
        jy = -abs(jiejuy)

    yy = yk * 200 + jy

    pygame.Surface.set_at(screen, (200, int(yy)), (0, 255, 0))

    yz = zk * (70 + 0.5) + jz
    #y=kx+b   -kx=b-y
    #xz=((5/3)-(8/3))/(1/3)
    xz = (jz - 300) /zk
    zuoxianx=abs(xz)
    xy=(jy-300)/yk
    youxianx=abs(xy)
    # y1 = zk * 90 + jieju
    # print(int(46600/90),int(y1), int(yz))
    pygame.Surface.set_at(screen, (int(youxianx), 300), (255, 0, 0))
    pygame.Surface.set_at(screen, (int(zuoxianx), 300), (255, 0, 0))
    starx=int(zuoxianx)
    endx=int(youxianx)
    print(yk,"截距左", jz, jy, "右扫描线y", yy, "左边扫描线y", yz,"左扫描线x",zuoxianx,"左扫描线x",youxianx)
    dong=0
    stary=300
    endy=580

    for gao in range(280):

        xz1 = (jz - (gao+300)) / zk
        sx = abs(xz1)
        xy1 = (jy - (gao+300)) / yk
        ex = abs(xy1)#加2是为了填补空白
        xcishu=ex-sx
        print("gao==",gao,"第一次循环",int(sx),int(ex))
        for i in range(int(xcishu)):
            print("i==",i,"第二次循环",int(sx),int(ex))

            # pygame.Surface.set_at(screen, (i, int(580)), (0, 255, 0))
            pygame.Surface.set_at(screen, (int(sx) + i, 300+gao), (255, 0, 0))
    pygame.display.update()


你可能感兴趣的:(pygame,python,开发语言)