in a nutshell, im writing vertexes for a cube into a vbo that i have setup correctly with a glbuffersubdata() call every frame, i then use gldrawarrays() and opengl does its thing and sends pixel data to a doublebuffer screen setup which i cycle through using a pygame.dislplay.flip() call. however in some cases, my game will delete some cubes, so after a certain time, it will send less cube data through the glbuffersubdata() call then the previous frame, resulting in the deleted cubes pixel data not being fully overwritten, creating a wierd artifact, where the game is not updating this cube, so its just a static overlay that follows the users camera perspective. i want to get rid of this artifact, but i cant.
first thing that came into mind, was if the the deleted cubes vertex data is not being overwritten, then why dont i just clear the pixel buffer, the alegeed colourbuffer and then send the new vertex data after that, so that only the new and intended verticies are renderes, however, this leads to even more artifacts, such as screen flickering black.
another thing that i thought about was to use the nnumber of triangles to render preset on the gldrawarrays() method, where for those who dont know, the final arguement, takes in the number of triangles i want to render out of all the hundreds of triangels i have sent opengl, so if i have 100 trianglees in my vbo but i set this arguement to 10 it will only render 10, similllarly if i render 0 i should get a black screen, after which i can clear the pixel data and then send new verticies, adnd render the new ones, however none of these were without additional artifacts, and just messing around some of the things i tried added in artifacts without even fixing the original ghosting artifact.
heres the code snippet where the problem i think lies:
if len(models) > 0:
models2 = (ctypes.c_float*len(models))(*models2)
print(len(models))
glBufferSubData(GL_ARRAY_BUFFER, 0, len(models)*4, models2)
glDrawArrays(GL_TRIANGLES,0,len(models))
pygame.display.flip()
sleep(1/fps/2)
else:
glDrawArrays(GL_TRIANGLES,0,0)
pygame.display.flip()
sleep(1/fps/2)
glDrawArrays(GL_TRIANGLES,0,0)
pygame.display.flip()
and here is my simple incomplete game at the moment:
import pygame
from PIL import Image
import math
import ctypes
import numpy as np
from pygame.locals import *
from OpenGL.GL import shaders
from OpenGL.GL import *
from time import sleep
import random
def createcube():
global defaultdistance
cube1 = [0,0,0]
cube2 = []
cube = []
physics = []
physics1 = []
obj = []
newcube = []
randomx = random.uniform(-1,1)
randomy = random.uniform(-0.75,0.75)
for i in range (3):
for y in range(2):
for x in range(2):
cube1[i] = 0
cube1[i-1] = y
cube1[i-2] = x
cube1[0] += abs(randomx)
cube1[1] += abs(randomy)
cube1[2] += defaultdistance
if randomx < 0:
cube1[0] = cube1[0]*-1
if randomy < 0:
cube1[1] = cube1[1]*-1
for f in cube1:
f -= 0.5
cube1.extend([x,y])
cube2.extend([cube1])
cube1 = [0,0,0]
cube2.insert(-1,cube2[1])
cube2.insert(-2,cube2[2])
cube.extend(cube2)
physics.append(cube2)
cube2 = []
for x in cube:
newcube.extend(x)
for i in range(3):
for t in range(3):
if t != i:
obj.extend([(physics[i][0][t],physics[i][5][t])])
obj.extend([physics[i][0][i]])
physics1.append(obj)
obj = []
return(newcube , physics1)
defaultdistance = 3
def main():
reach = 5
pointer1 = [0,0,reach]
cubespawnrate = 0.5 #cubes spawned per second
fps = 15 #target fps
sensitivity = -300
pygame.init()
display = [1000,500]
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
set_fov(45)
set_render_distance(50)
set_view_bearing(0,0,0)
set_cam(0,0,0)
set_aspect_ratio(display[0],display[1])
models1 = []
physics = []
x , phys = createcube()
models1.append(x)
physics.append(phys)
models = []
for t in models1:
models.extend(t)
models2 = []
models2.extend(models)
for i in range(0,len(models),5):
models2[i:i+3] = final_display_position(models[i:i+3],0,0,0,0,0,0,0,0,0)[0:3]
vertex_shader="""
#version 430
in vec3 position;
in vec2 texturecoordinate;
out vec2 texcoordinate;
void main()
{
gl_Position = vec4(position,1.0);
texcoordinate = texturecoordinate;
}
"""
fragment_shader="""
#version 430
precision mediump float;
in vec2 texcoordinate;
uniform sampler2D texturergbadata;
out vec4 colour;
void main()
{
//g =
colour = texture2D(texturergbadata,texcoordinate);
//colour = vec4(1.0f,1.0f,0.5f,1.0f);
}
"""
shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
OpenGL.GL.shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER))
VBO=glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER,VBO)
glBufferData(GL_ARRAY_BUFFER,18000,None,GL_STATIC_DRAW)
position = glGetAttribLocation(shader,"position")
glVertexAttribPointer(position, 3, GL_FLOAT, False, 20, ctypes.c_void_p(0))
glEnableVertexAttribArray(position)
width = 200
height = 151
image = Image.open('box.png')
rgbadata = list(image.getdata())
length = len(rgbadata)
newlist = []
for i in range(height):
for s in range(width):
newlist.extend(rgbadata[-2:-1])
rgbadata.pop(-1)
rgbadata.extend(newlist)
texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, rgbadata)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
texturecoordinate = glGetAttribLocation(shader,"texturecoordinate")
glEnableVertexAttribArray(texturecoordinate)
glVertexAttribPointer(texturecoordinate, 2, GL_FLOAT, False, 20,ctypes.c_void_p(12))
texture = glGetUniformLocation(shader, "texturergbadata")
glActiveTexture(GL_TEXTURE0)
timer = 0
while True:
while escape == 0:
for event in pygame.event.get():
pass
pygame.mouse.set_visible(True)
mousex , mousey = pygame.mouse.get_pos()
# cube spawning
if timer >= fps/cubespawnrate:
x , phys = createcube()
models1.append(x)
physics.append(phys)
models = []
for t in models1:
models.extend(t)
models2 = []
models2.extend(models)
timer = 0
else:
timer += 1
# collision detection
objectindex = 0
for i in physics:
collision = 0
print(pointer)
for s in range(3):
list1 = [0,1,2]
list1.pop(s)
try:
t = i[s][2]/pointer[s]
except:
print('no colision')
continue
intersection = list([t*x for x in pointer])
print(intersection)
h = 0
#if math.sqrt((math.sqrt(intersection[0]**2 + intersection[1]**2))**2 + intersection[2]**2) <= reach:
for p in list1:
g = intersection[p]
if g >= i[s][h][0] and g <= i[s][h][1]:
h += 1
if h == 2:
print('we have a collision')
collision += 1
if collision >= 1:
print('deleting',objectindex,'th/nd/rd/st cube')
print(len(models1),len(physics))
models1.pop(objectindex) # this is where i delete some cubes
physics.pop(objectindex)
models = []
for t in models1:
models.extend(t)
streak += 1
else:
streak = 0
multiplier = 1
objectindex += 1
models2 = []
for i in range(0,len(models),5):
models2.extend(final_display_position(models[i:i+3],0,0,0,0,0,0,0,0,0)[0:3])
models2.extend(models[i+3:i+5]) # all this function does is take 3d coordinates and turn them into 2d display coordinates
# here i am rendering the cubes
if len(models) > 0:
models2 = (ctypes.c_float*len(models))(*models2)
print(len(models))
glBufferSubData(GL_ARRAY_BUFFER, 0, len(models)*4, models2)
glDrawArrays(GL_TRIANGLES,0,len(models))
pygame.display.flip()
sleep(1/fps/2)
else:
glDrawArrays(GL_TRIANGLES,0,0)
pygame.display.flip()
sleep(1/fps/2)
glDrawArrays(GL_TRIANGLES,0,0)
pygame.display.flip()
pygame.mouse.set_pos(display[0]/2,display[1]/2)
sleep(1/fps/2)
keyspressed = pygame.key.get_pressed()
if keyspressed[K_ESCAPE]:
print('escape pressed')
debounce = 1
print(debounce)
#print(mousex , mousey)
elif keyspressed[K_ESCAPE] == False and debounce > 0:
print('debounce initiated,halt started')
escape = 1
debounce = 0
else:
debounce = 0
while escape == 1:
for event in pygame.event.get():
pass
pygame.mouse.set_visible(True)
keyspressed = pygame.key.get_pressed()
if keyspressed[K_ESCAPE]:
print('escape pressed')
debounce = 1
print(debounce)
#print(mousex , mousey)
elif keyspressed[K_ESCAPE] == False and debounce > 0:
print('debounce initiated,halt stopped')
escape = 0
debounce = 0
else:
debounce = 0
main()
updates:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
if len(models) > 0:
models2 = (ctypes.c_float*len(models))(*models2)
print(len(models),len(models2))
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glBufferSubData(GL_ARRAY_BUFFER, 0, len(models)*4, models2)
glDrawArrays(GL_TRIANGLES,0,len(models))
pygame.display.flip()
sleep(1/fps/2)
here is a video showing the issue:
https://drive.google.com/file/d/1m-16b7FkOxaAHrGsF0uSKqVN1bl5EjQQ/view?usp=sharing