[DEV] rework mesh compoement and textures

Signed-off-by: Edouard DUPIN <yui.heero@gmail.com>
This commit is contained in:
Edouard DUPIN 2021-05-24 13:49:51 +02:00
parent 5655d3e12b
commit 32236a2c14
22 changed files with 2223 additions and 156 deletions

View File

@ -84,7 +84,7 @@ class ExportEMF(bpy.types.Operator, ExportHelper):
use_selection = BoolProperty( use_selection = BoolProperty(
name="Selection Only", name="Selection Only",
description="Export selected objects only", description="Export selected objects only",
default=True, default=False,
) )
# generate binary file # generate binary file
use_binary = BoolProperty( use_binary = BoolProperty(

View File

@ -1,9 +1,12 @@
import bpy import bpy
bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/workspace-game/atriasoft/ege/blender/io_scene_emf/../../samples/resources/emf/tree1.blend") #bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/workspace-game/atriasoft/ege/blender/io_scene_emf/../../samples/resources/emf/tree1.blend")
#bpy.ops.export_scene.emf(filepath="/home/heero/dev/workspace-game/atriasoft/ege/samples/resources/emf/tree1.emf")
bpy.ops.export_scene.emf(filepath="/home/heero/dev/workspace-game/atriasoft/ege/blender/io_scene_emf/../../samples/resources/emf/tree1.emf")
#bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/workspace-game/atriasoft/ewol/resources/resources/ewol/theme/shape/Entry.blend") #bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/workspace-game/atriasoft/ewol/resources/resources/ewol/theme/shape/Entry.blend")
#bpy.ops.export_scene.emf(filepath="/home/heero/dev/workspace-game/atriasoft/ewol/resources/resources/ewol/theme/shape/Entry.emf") #bpy.ops.export_scene.emf(filepath="/home/heero/dev/workspace-game/atriasoft/ewol/resources/resources/ewol/theme/shape/Entry.emf")
#bpy.ops.export_scene.emf(filepath="/home/heero/dev/workspace-game/atriasoft/ege/samples/resources/emf/Entry.emf")
bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/workspace-game/model/tower.blend")
bpy.ops.export_scene.emf(filepath="/home/heero/dev/workspace-game/atriasoft/ege/samples/resources/emf/tower.emf")

View File

@ -59,7 +59,7 @@ def out_quaternion( q ):
return "%g %g %g %g" % ( q.x, q.y, q.z, q.w ) return "%g %g %g %g" % ( q.x, q.y, q.z, q.w )
def get_physics_shape(obj, mainObjScale): def get_physics_shape(obj):
shape = "" shape = ""
props = { } props = { }
name = obj.name.lower() name = obj.name.lower()
@ -73,7 +73,7 @@ def get_physics_shape(obj, mainObjScale):
# SPHERE # SPHERE
elif name.startswith('sph'): elif name.startswith('sph'):
shape = "Sphere" shape = "Sphere"
props["radius"] = obj.scale.x * mainObjScale.x props["radius"] = obj.scale.x
# CONE # CONE
elif name.startswith('cone'): elif name.startswith('cone'):
shape = "Cone" shape = "Cone"
@ -116,21 +116,21 @@ def get_physics_shape(obj, mainObjScale):
return (shape, props) return (shape, props)
def write_collision_shape(object, file, mainObjScale, offset): def write_collision_shape(objects, file, offset):
fw = file.write fw = file.write
if len(getChildren(object))==0: if len(objects)==0:
# no phisical shape ... # no phisical shape ...
return return
string_offset = "" string_offset = ""
for iii in range(offset): for iii in range(offset):
string_offset += "\t" string_offset += "\t"
fw(string_offset + 'Physics:\n') fw(string_offset + 'Physics:\n')
for subObj in getChildren(object): for subObj in objects:
print(" element='" + subObj.name + "' type '" + str(subObj.type) + "'") print(" element='" + subObj.name + "' type '" + str(subObj.type) + "'")
if subObj.type != 'MESH' \ if subObj.type != 'MESH' \
and subObj.type != 'EMPTY': and subObj.type != 'EMPTY':
continue continue
(shape, props) = get_physics_shape(subObj, mainObjScale) (shape, props) = get_physics_shape(subObj)
if shape=="": if shape=="":
print("error of shape detection type ..."); print("error of shape detection type ...");
continue continue
@ -179,7 +179,11 @@ def write_mtl(scene, file, filepath, path_mode, copy_set, mtl_dict):
#print(" mat: "); #print(" mat: ");
#for elem in dir(mat): #for elem in dir(mat):
# print(" - " + elem); # print(" - " + elem);
fw('Materials:%s\n' % mtl_mat_name) # Define a new material: matname_imgname if mtl_mat_name.lower().startswith("palette_"):
fw('# Just for information:\nPalettes:%s\n' % mtl_mat_name[8:]) # Define a new material: matname_imgname
else:
fw('Materials:%s\n' % mtl_mat_name) # Define a new material: matname_imgname
mat_wrap = node_shader_utils.PrincipledBSDFWrapper(mat) if mat else None mat_wrap = node_shader_utils.PrincipledBSDFWrapper(mat) if mat else None
if mat_wrap: if mat_wrap:
@ -256,9 +260,9 @@ def write_mtl(scene, file, filepath, path_mode, copy_set, mtl_dict):
if tex_wrap.scale != Vector((1.0, 1.0, 1.0)): if tex_wrap.scale != Vector((1.0, 1.0, 1.0)):
options.append('-s %.6f %.6f %.6f' % tex_wrap.scale[:]) options.append('-s %.6f %.6f %.6f' % tex_wrap.scale[:])
if options: if options:
fw('%s %s %s\n' % (key, " ".join(options), repr(filepath)[1:-1])) fw('\t%s %s %s\n' % (key, " ".join(options), repr(filepath)[1:-1]))
else: else:
fw('%s %s\n' % (key, repr(filepath)[1:-1])) fw('\t%s %s\n' % (key, repr(filepath)[1:-1]))
else: else:
# Write a dummy material here? # Write a dummy material here?
@ -295,7 +299,7 @@ def write_mesh(scene, file, object, mtl_dict):
print(object.name + 'is not a mesh type - ignoring type=' + object.type) print(object.name + 'is not a mesh type - ignoring type=' + object.type)
fw('# can not export:"%s":type="%s"\n' % (object.name, str(object.type))) fw('# can not export:"%s":type="%s"\n' % (object.name, str(object.type)))
return return
#print("name:'%s'" % object.name) print("generate Object name:'%s'" % object.name)
#for plop in object.child: #for plop in object.child:
# print(" child:'%s'" % plop.name) # print(" child:'%s'" % plop.name)
# ignore dupli children # ignore dupli children
@ -330,8 +334,10 @@ def write_mesh(scene, file, object, mtl_dict):
mesh_triangulate(me) mesh_triangulate(me)
# calculated normals: # calculated normals:
me.calc_normals() me.calc_normals()
#print("nb UB layers: " + str(len(me.uv_layers)) + " " + str(dir(me.uv_layers)));
# export UV mapping: # export UV mapping:
faceuv = len(me.uv_layers) > 0 faceuv = len(me.uv_layers) > 0
# TODO: This does not work with V facing ==> need to rework it ... designed for Low poly then we use Palette
if faceuv: if faceuv:
uv_texture = me.uv_layers.active.data[:] uv_texture = me.uv_layers.active.data[:]
uv_layer = me.uv_layers.active.data[:] uv_layer = me.uv_layers.active.data[:]
@ -353,13 +359,27 @@ def write_mesh(scene, file, object, mtl_dict):
material_names = [name_compat(None)] material_names = [name_compat(None)]
# Sort by Material, then images # Sort by Material, then images
# so we dont over context switch in the obj file. # so we dont over context switch in the obj file.
if faceuv: if False:
face_index_pairs.sort(key=lambda a: (a[0].material_index, hash(uv_texture[a[1]].image), a[0].use_smooth)) if len(materials) > 1:
elif len(materials) > 1: if smooth_groups:
face_index_pairs.sort(key=lambda a: (a[0].material_index, a[0].use_smooth)) sort_func = lambda a: (a[0].material_index,
smooth_groups[a[1]] if a[0].use_smooth else False)
else:
sort_func = lambda a: (a[0].material_index,
a[0].use_smooth)
else:
# no materials
if smooth_groups:
sort_func = lambda a: smooth_groups[a[1] if a[0].use_smooth else False]
else:
sort_func = lambda a: a[0].use_smooth
face_index_pairs.sort(key=sort_func)
del sort_func
else: else:
# no materials face_index_pairs.sort(key=lambda a: (a[0].material_index))
face_index_pairs.sort(key=lambda a: a[0].use_smooth)
# Set the default mat to no material and no image. # Set the default mat to no material and no image.
contextMat = 0, 0 # Can never be this, so we will label a new material the first chance we get. contextMat = 0, 0 # Can never be this, so we will label a new material the first chance we get.
contextSmooth = None # Will either be true or false, set bad to force initialization switch. contextSmooth = None # Will either be true or false, set bad to force initialization switch.
@ -440,13 +460,21 @@ def write_mesh(scene, file, object, mtl_dict):
########################################################### ###########################################################
fw('\tFace:%d' % len(face_index_pairs)) fw('\tFace:%d' % len(face_index_pairs))
for f, f_index in face_index_pairs: for f, f_index in face_index_pairs:
f_image = None
f_smooth = f.use_smooth f_smooth = f.use_smooth
f_mat = min(f.material_index, len(materials) - 1) f_mat = min(f.material_index, len(materials) - 1)
if faceuv: tmp_faceuv = faceuv
if tmp_faceuv:
tface = uv_texture[f_index] tface = uv_texture[f_index]
f_image = tface.image #print("mesh_uvloop:" + str(dir(tface.uv)))
if 'image' in dir(uv_texture[f_index]):
f_image = tface.image
else:
# TODO: remove export of UV when no UV needed...
#tmp_faceuv = False
pass
# MAKE KEY # MAKE KEY
if faceuv and f_image: # Object is always true. if tmp_faceuv and f_image: # Object is always true.
key = material_names[f_mat], f_image.name key = material_names[f_mat], f_image.name
else: else:
key = material_names[f_mat], None # No image, use None instead. key = material_names[f_mat], None # No image, use None instead.
@ -481,10 +509,10 @@ def write_mesh(scene, file, object, mtl_dict):
mat_data = mtl_dict[key] = mtl_name, materials[f_mat], f_image mat_data = mtl_dict[key] = mtl_name, materials[f_mat], f_image
mtl_rev_dict[mtl_name] = key mtl_rev_dict[mtl_name] = key
# set the use of a material: # set the use of a material:
fw("\n\t\t%s\n\t\t\t" % mat_data[0]) # can be mat_image or (null) fw("\n\t\t%s\n\t\t\t" % mat_data[0].replace("palette_", "palette:")) # can be mat_image or (null)
contextMat = key contextMat = key
f_v = [(vi, me_verts[v_idx]) for vi, v_idx in enumerate(f.vertices)] f_v = [(vi, me_verts[v_idx]) for vi, v_idx in enumerate(f.vertices)]
if faceuv: if tmp_faceuv:
# export the normals: # export the normals:
if f_smooth: # Smoothed, use vertex normals if f_smooth: # Smoothed, use vertex normals
for vi, v in f_v: for vi, v in f_v:
@ -546,7 +574,7 @@ def write_mesh(scene, file, object, mtl_dict):
" @brief Basic write function. The context and options must be already set. " @brief Basic write function. The context and options must be already set.
""" """
def write_file(filepath, def write_file(filepath,
objects, collection,
scene, scene,
EXPORT_PATH_MODE='AUTO', EXPORT_PATH_MODE='AUTO',
EXPORT_BINARY_MODE=False, EXPORT_BINARY_MODE=False,
@ -592,25 +620,18 @@ def write_file(filepath,
print("nb_total_physic: " + str(nb_total_physic)) print("nb_total_physic: " + str(nb_total_physic))
""" """
print("Find Mesh in collection: '" + str(collection.name) + "'")
# Get all meshes # Get all meshes
for ob_main in objects: for ob_main in collection.objects:
if ob_main.type == 'MESH': if ob_main.type == 'MESH':
write_mesh(scene, file, ob_main, mtl_dict) write_mesh(scene, file, ob_main, mtl_dict)
elif ob_main.type == 'EMPTY':
for sub_obj in getChildren(ob_main): print("Find Physics in collection: '" + str(collection.name) + "'")
print(" child:'" + str(sub_obj.name) + "' type=" + sub_obj.type) for col in collection.children:
if sub_obj.type == 'MESH': print(" - name: " + str(col.name) + "/" + str(col.name_full) )
write_mesh(scene, file, sub_obj, mtl_dict) if col.name.lower().startswith("physic"):
elif sub_obj.type == 'EMPTY' \ write_collision_shape(col.objects, file, 0)
and sub_obj.name.lower().startswith("physic"):
print(" child:'" + str(sub_obj.name) + "' type=" + sub_obj.type)
#####################################################################
## Save collision shapes (for one all):
#####################################################################
write_collision_shape(sub_obj, file, sub_obj.scale, 0)
else:
print(" child:'" + str(sub_obj.name) + "' type=" + sub_obj.type + " not parsed ...")
##################################################################### #####################################################################
## Now we have all our materials, save them in the material section ## Now we have all our materials, save them in the material section
##################################################################### #####################################################################
@ -653,14 +674,27 @@ def _write(context,
scene.frame_set(frame, subframe=0.0) scene.frame_set(frame, subframe=0.0)
# get only the object that are selected or all... # get only the object that are selected or all...
if EXPORT_SEL_ONLY: if EXPORT_SEL_ONLY:
objects = context.selected_objects collection = bpy.context.collection
else: else:
objects = scene.objects print("collection auto detect 'root': ")
collection = scene.collection
if collection.name != "root":
for col in collection.children:
if col.name == "root":
collection = col
break
if collection.name != "root":
raise "Can not detect collition 'root'"
#print("* collection name: " + str(collection.name) + "/" + str(collection.name_full) )
print("============================================================================================");
draw_tree(scene.collection, 0, collection);
print("============================================================================================");
full_path = ''.join(context_name) full_path = ''.join(context_name)
write_file(full_path, write_file(full_path,
objects, collection,
scene, scene,
EXPORT_PATH_MODE, EXPORT_PATH_MODE,
EXPORT_BINARY_MODE, EXPORT_BINARY_MODE,
@ -669,6 +703,24 @@ def _write(context,
##
## Display all the element in the collection tree (for help debug exporting)
##
def draw_tree(collection, offset, export_collection):
string_offset = ""
for iii in range(offset):
string_offset += "\t"
if export_collection == collection:
print(string_offset + "- collection: '" + str(collection.name) + "' !!!! exported node !!!!")
else:
print(string_offset + "- collection: '" + str(collection.name) + "'")
for col in collection.children:
draw_tree(col, offset+1, export_collection);
if 'objects' in dir(collection):
for obj in collection.objects:
print(string_offset + "\t- objects: '" + str(obj.name) + "' type '" + str(obj.type) + "'")
""" """
" @brief Save the current element in the file requested. " @brief Save the current element in the file requested.
" "

View File

@ -460,9 +460,7 @@ def write_file(filepath, objects, depsgraph, scene,
if faceuv: if faceuv:
# in case removing some of these dont get defined. # in case removing some of these dont get defined.
uv = f_index = uv_index = uv_key = uv_val = uv_ls = None uv = f_index = uv_index = uv_key = uv_val = uv_ls = None
uv_face_mapping = [None] * len(face_index_pairs) uv_face_mapping = [None] * len(face_index_pairs)
uv_dict = {} uv_dict = {}
uv_get = uv_dict.get uv_get = uv_dict.get
for f, f_index in face_index_pairs: for f, f_index in face_index_pairs:
@ -471,21 +469,17 @@ def write_file(filepath, objects, depsgraph, scene,
uv = uv_layer[l_index].uv uv = uv_layer[l_index].uv
# include the vertex index in the key so we don't share UV's between vertices, # include the vertex index in the key so we don't share UV's between vertices,
# allowed by the OBJ spec but can cause issues for other importers, see: T47010. # allowed by the OBJ spec but can cause issues for other importers, see: T47010.
# this works too, shared UV's for all verts # this works too, shared UV's for all verts
#~ uv_key = veckey2d(uv) #~ uv_key = veckey2d(uv)
uv_key = loops[l_index].vertex_index, veckey2d(uv) uv_key = loops[l_index].vertex_index, veckey2d(uv)
uv_val = uv_get(uv_key) uv_val = uv_get(uv_key)
if uv_val is None: if uv_val is None:
uv_val = uv_dict[uv_key] = uv_unique_count uv_val = uv_dict[uv_key] = uv_unique_count
fw('vt %.6f %.6f\n' % uv[:]) fw('vt %.6f %.6f\n' % uv[:])
uv_unique_count += 1 uv_unique_count += 1
uv_ls.append(uv_val) uv_ls.append(uv_val)
del uv_dict, uv, f_index, uv_index, uv_ls, uv_get, uv_key, uv_val del uv_dict, uv, f_index, uv_index, uv_ls, uv_get, uv_key, uv_val
# Only need uv_unique_count and uv_face_mapping # Only need uv_unique_count and uv_face_mapping
subprogress2.step() subprogress2.step()
# NORMAL, Smooth/Non smoothed. # NORMAL, Smooth/Non smoothed.

1618
samples/hs_err_pid14064.log Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
EMF(STRING)
# Blender v2.92.0 EMF File: 'Entry.blend'
Mesh:EntryBox_Cube
Vertex:16
20.042355 7.751226 20.042355|20.042355 7.751226 -20.042355|20.042355 -4.633502 20.042355|20.042355 -4.633502 -20.042355|-20.042355 7.751226 20.042355|-20.042355 7.751226 -20.042355|-20.042355 -4.633502 20.042355|-20.042355 -4.633502 -20.042355|10.127714 -7.726907 10.127714|10.127714 -7.726907 -10.127714|-10.127714 -7.726907 10.127714|-10.127714 -7.726907 -10.127714|-10.127714 -9.146553 -10.127714|-10.127714 -9.146553 10.127714|10.127714 -9.146553 10.127714|10.127714 -9.146553 -10.127714|
UV-mapping:
0.000100 0.000100|0.999900 0.999900|0.000100 0.999900|0.999900 0.000100|0.074219 0.995849|0.120606 0.943115|0.121582 0.993408|0.112927 0.992387|0.078245 0.948093|0.073324 0.991157|0.101769 0.970961|0.080974 0.959440|0.102023 0.957458|0.111927 0.985005|0.078476 0.953015|0.082167 0.983774|0.074219 0.944092|0.111696 0.944402|0.080720 0.975385|0.113157 0.949323|0.174907 0.947863|0.131613 0.991157|0.132843 0.945402|0.178368 0.944941|0.137534 0.984544|0.142456 0.948632|0.171985 0.949093|0.136074 0.991157|0.137304 0.950323|0.174677 0.949093|0.135074 0.992387|0.136304 0.949093|0.178598 0.993618|0.178368 0.988235|0.173216 0.991157|0.175907 0.989926|0.013265 0.951784|0.051868 0.992387|0.013034 0.993618|0.054098 0.951784|0.137534 0.988235|0.177138 0.947863|0.135074 0.947862|0.172446 0.988465|
Normal(face):22
0.000000 -1.000000 0.000000|-0.297843 -0.954615 0.000000|0.000000 -0.954615 -0.297843|0.000000 -0.954615 0.297843|0.297843 -0.954615 0.000000|0.000000 0.000000 1.000000|-1.000000 0.000000 0.000000|0.000000 0.000000 -1.000000|1.000000 0.000000 -0.000000|0.000000 1.000000 -0.000000|
Face:22
gui_dynamic_1
14/0/0 12/1/0 15/2/0| 14/0/0 13/3/0 12/1/0|
palette:gui_border_1
7/4/1 10/5/1 6/6/1| 3/7/2 11/8/2 7/9/2| 6/10/3 8/11/3 2/12/3| 2/13/4 9/14/4 3/15/4| 7/4/1 11/16/1 10/5/1| 3/7/2 9/17/2 11/8/2| 6/10/3 10/18/3 8/11/3| 2/13/4 8/19/4 9/14/4|
palette:gui_border_2
4/20/5 2/21/5 0/22/5| 6/23/6 5/24/6 7/25/6| 1/26/7 7/27/7 5/28/7| 0/29/8 3/30/8 1/31/8| 4/20/5 6/32/5 2/21/5| 6/23/6 4/33/6 5/24/6| 1/26/7 3/34/7 7/27/7| 0/29/8 2/35/8 3/30/8|
palette:gui_center
9/36/0 10/37/0 11/38/0| 9/36/0 8/39/0 10/37/0|
palette:gui_back
5/40/9 0/41/9 1/42/9| 5/40/9 4/43/9 0/41/9|
Materials:gui_dynamic_1
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2
map_Kd /home/heero/dev/workspace-game/atriasoft/ewol/resources/resources/ewol/theme/shape/empty_area.png
# Just for information:
Palettes:gui_back
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.000000 0.005632
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2
# Just for information:
Palettes:gui_border_1
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.000000 0.002615 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2
# Just for information:
Palettes:gui_border_2
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.000000 0.800000 0.170495
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2
# Just for information:
Palettes:gui_center
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.438544 0.438544 0.438544
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2

View File

@ -0,0 +1,26 @@
{
"default": {
"Ns":225.000000,
"Ka":"1.000000 1.000000 1.000000",
"Kd":"0.346704 0.558341 0.090842",
"Ks":"0.500000 0.500000 0.500000",
"Ke":"0.000000 0.000000 0.000000",
"vNi":"1.000000,
"d":1.000000,
"illum":2
},
"palette": {
"leaf_1":{
"Kd":"0.346704 0.558341 0.090842"
}
"leaf_2":{
"Kd":"0.278894 0.278894 0.023153"
}
"leaf_3":{
"Kd":"0.800000 0.800000 0.800000"
}
"trunk_1":{
"Kd":"0.057805 0.039546 0.013702"
}
}
}

View File

@ -0,0 +1,57 @@
EMF(STRING)
# Blender v2.92.0 EMF File: 'tower.blend'
Mesh:tower_Cube
Vertex:68
1.000000 1.000000 1.968156|1.000000 1.000000 0.509101|1.000000 -1.000000 1.968156|1.000000 -1.000000 0.509101|-1.000000 1.000000 1.968156|-1.000000 1.000000 0.509101|-1.000000 -1.000000 1.968156|-1.000000 -1.000000 0.509101|0.519091 0.519091 2.988363|0.519091 -0.519091 2.988363|-0.519091 0.519091 2.988363|-0.519091 -0.519091 2.988363|1.267435 0.519091 3.279218|1.267435 -0.519091 3.279218|-0.519091 0.519091 3.279218|-0.519091 -0.519091 3.279218|1.267435 0.519091 4.102064|1.267435 -0.519091 4.102064|-0.519091 0.519091 4.102064|-0.519091 -0.519091 4.102064|-1.007701 0.133857 3.584548|-1.007701 -0.133857 3.584548|-1.007701 0.133857 3.796734|-1.007701 -0.133857 3.796734|-3.394721 0.108124 3.604944|-3.394721 -0.108124 3.604944|-3.394721 0.108124 3.776338|-3.394721 -0.108124 3.776338|-3.394721 0.148343 3.573067|-3.394721 -0.148343 3.573067|-3.394721 0.148343 3.808215|-3.394721 -0.148343 3.808215|-3.865651 0.148343 3.573067|-3.865651 -0.148343 3.573067|-3.865651 0.148343 3.808215|-3.865651 -0.148343 3.808215|0.468620 0.227433 3.055862|0.468620 -0.227433 3.055862|-0.227433 0.227433 3.055862|-0.227433 -0.227433 3.055862|0.671236 0.227433 3.376956|0.671236 -0.227433 3.376956|0.216371 0.227433 3.376956|0.216371 -0.227433 3.376956|1.304951 1.304951 0.327262|1.304951 -1.304951 0.327262|-1.304951 1.304951 0.327262|-1.304951 -1.304951 0.327262|1.304951 1.304951 -0.001257|1.304951 -1.304951 -0.001257|-1.304951 1.304951 -0.001257|-1.304951 -1.304951 -0.001257|1.644974 0.319018 3.437792|1.644974 -0.319018 3.437792|1.644974 0.319018 3.943490|1.644974 -0.319018 3.943490|1.469387 0.154815 3.567937|1.469387 -0.154815 3.567937|1.469387 0.154815 3.813344|1.469387 -0.154815 3.813344|-3.865651 0.081533 3.626019|-3.865651 -0.081533 3.626019|-3.865651 0.081533 3.755262|-3.865651 -0.081533 3.755262|0.301836 0.081533 3.626019|0.301836 -0.081533 3.626019|0.301836 0.081533 3.755262|0.301836 -0.081533 3.755262|
Normal(face):128
-0.000000 0.000000 -1.000000|0.000000 1.000000 -0.000000|0.000000 -0.225474 0.974249|-0.225474 0.000000 0.974249|0.000000 0.000000 1.000000|-0.619140 0.785281 0.000000|0.000000 -1.000000 0.000000|-0.529936 0.000000 0.848038|-0.619140 -0.785281 0.000000|-0.529936 0.000000 -0.848038|1.000000 -0.000000 -0.000000|-1.000000 0.000000 0.000000|0.000000 0.225474 0.974249|0.800875 0.000000 0.598832|0.845703 0.000000 -0.533654|-0.586173 0.000000 0.810186|0.595465 0.000000 0.803381|0.683034 0.730387 0.000000|0.595465 0.000000 -0.803381|0.683034 -0.730387 0.000000|0.468253 0.883595 0.000000|-0.010780 -0.999942 0.000000|-0.008544 0.000000 0.999964|-0.010780 0.999942 0.000000|-0.008544 0.000000 -0.999964|0.387250 0.000000 0.921975|0.468253 -0.883595 0.000000|0.387250 0.000000 -0.921975|-0.008544 0.000000 0.999963|-0.008544 -0.000000 -0.999963|0.000000 0.904541 0.426386|0.000000 -0.904541 0.426386|-0.904541 0.000000 0.426386|0.904541 0.000000 0.426386|-0.000000 -0.512150 0.858896|-0.512150 0.000000 0.858896|0.512150 0.000000 0.858896|-0.000000 0.512150 0.858896|
Face:128
palette:canon_2
15/0 12/0 13/0| 14/1 16/1 12/1| 9/2 39/2 11/2| 36/1 42/1 40/1| 11/3 38/3 10/3| 18/4 17/4 16/4| 14/5 22/5 18/5| 13/6 19/6 15/6| 18/7 23/7 19/7| 19/8 21/8 15/8| 15/9 20/9 14/9| 26/10 31/10 27/10| 28/1 34/1 30/1| 24/10 30/10 26/10| 25/10 28/10 24/10| 27/10 29/10 25/10| 35/11 61/11 33/11| 29/0 32/0 28/0| 31/6 33/6 29/6| 30/4 35/4 31/4| 8/12 38/12 36/12| 8/13 37/13 9/13| 40/4 43/4 41/4| 36/14 41/14 37/14| 37/6 43/6 39/6| 39/15 42/15 38/15| 52/16 57/16 53/16| 56/10 59/10 57/10| 53/17 59/17 55/17| 55/18 58/18 54/18| 54/19 56/19 52/19| 60/6 66/6 62/6| 34/11 63/11 35/11| 32/11 62/11 34/11| 33/11 60/11 32/11| 65/11 66/11 64/11| 61/4 64/4 60/4| 63/1 65/1 61/1| 62/0 67/0 63/0| 15/0 14/0 12/0| 14/1 18/1 16/1| 9/2 37/2 39/2| 36/1 38/1 42/1| 11/3 39/3 38/3| 18/4 19/4 17/4| 14/5 20/5 22/5| 13/6 17/6 19/6| 18/7 22/7 23/7| 19/8 23/8 21/8| 15/9 21/9 20/9| 26/10 30/10 31/10| 28/1 32/1 34/1| 24/10 28/10 30/10| 25/10 29/10 28/10| 27/10 31/10 29/10| 35/11 63/11 61/11| 29/0 33/0 32/0| 31/6 35/6 33/6| 30/4 34/4 35/4| 8/12 10/12 38/12| 8/13 36/13 37/13| 40/4 42/4 43/4| 36/14 40/14 41/14| 37/6 41/6 43/6| 39/15 43/15 42/15| 52/16 56/16 57/16| 56/10 58/10 59/10| 53/17 57/17 59/17| 55/18 59/18 58/18| 54/19 58/19 56/19| 60/6 64/6 66/6| 34/11 62/11 63/11| 32/11 60/11 62/11| 33/11 61/11 60/11| 65/11 67/11 66/11| 61/4 65/4 64/4| 63/1 67/1 65/1| 62/0 66/0 67/0|
palette:canon_1
16/20 52/20 12/20| 23/21 25/21 21/21| 22/22 27/22 23/22| 20/23 26/23 22/23| 21/24 24/24 20/24| 17/25 54/25 16/25| 13/26 55/26 17/26| 12/27 53/27 13/27| 16/20 54/20 52/20| 23/21 27/21 25/21| 22/28 26/28 27/28| 20/23 24/23 26/23| 21/29 25/29 24/29| 17/25 55/25 54/25| 13/26 53/26 55/26| 12/27 52/27 53/27|
palette:user_1
4/30 8/30 0/30| 2/6 7/6 3/6| 6/11 5/11 7/11| 0/10 3/10 1/10| 4/1 1/1 5/1| 6/31 9/31 11/31| 6/32 10/32 4/32| 0/33 9/33 2/33| 4/30 10/30 8/30| 2/6 6/6 7/6| 6/11 4/11 5/11| 0/10 2/10 3/10| 4/1 0/1 1/1| 6/31 2/31 9/31| 6/32 11/32 10/32| 0/33 8/33 9/33|
palette:bulding_base_1
7/34 45/34 3/34| 45/10 48/10 44/10| 5/35 47/35 7/35| 3/36 44/36 1/36| 1/37 46/37 5/37| 48/0 51/0 50/0| 44/1 50/1 46/1| 47/6 49/6 45/6| 46/11 51/11 47/11| 7/34 47/34 45/34| 45/10 49/10 48/10| 5/35 46/35 47/35| 3/36 45/36 44/36| 1/37 44/37 46/37| 48/0 49/0 51/0| 44/1 48/1 50/1| 47/6 51/6 49/6| 46/11 50/11 51/11|
# Just for information:
Palettes:bulding_base_1
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.014670 0.014670 0.014670
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2
# Just for information:
Palettes:canon_1
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.000000 0.008711
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2
# Just for information:
Palettes:canon_2
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.001354 0.800000 0.053320
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2
# Just for information:
Palettes:user_1
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.113655 0.510074 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
vNi 1.450000
d 1.000000
illum 2

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -25,5 +25,5 @@ open module org.atriasoft.ege {
requires transitive org.atriasoft.etk; requires transitive org.atriasoft.etk;
requires transitive org.atriasoft.ewol; requires transitive org.atriasoft.ewol;
requires transitive org.atriasoft.ephysics; requires transitive org.atriasoft.ephysics;
requires org.atriasoft.loader3d; requires transitive org.atriasoft.loader3d;
} }

View File

@ -0,0 +1,45 @@
package org.atriasoft.ege.components;
import org.atriasoft.ege.Component;
import org.atriasoft.etk.Uri;
import org.atriasoft.loader3d.resources.ResourceMesh;
import org.atriasoft.loader3d.resources.ResourceStaticMesh;
public class ComponentMesh extends Component {
private ResourceMesh mesh = null;
public ComponentMesh(Uri objectFileName) {
this.mesh = ResourceMesh.create(objectFileName);
}
public void bindForRendering() {
if (this.mesh == null) {
return;
}
this.mesh.bindForRendering();
}
public ResourceStaticMesh getMesh() {
return this.mesh;
}
@Override
public String getType() {
// TODO Auto-generated method stub
return "mesh";
}
public void render() {
if (this.mesh == null) {
return;
}
this.mesh.render();
}
public void unBindForRendering() {
if (this.mesh == null) {
return;
}
this.mesh.unBindForRendering();
}
}

View File

@ -0,0 +1,77 @@
package org.atriasoft.ege.components;
import org.atriasoft.ege.Component;
import org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.Matrix4f;
import org.atriasoft.gale.backend3d.OpenGL;
import org.atriasoft.gale.resource.ResourceProgram;
public class ComponentRenderMeshPalette extends ComponentRender {
private int GLMatrixProjection;
private int GLMatrixTransformation;
private int GLMatrixView;
ComponentMesh mesh = null;
private ComponentPhysics playerPhysics = null;
ComponentPosition position = null;
ResourceProgram program = null;
ComponentTexturePalette texture = null;
public ComponentRenderMeshPalette(final Uri vertexShader, final Uri fragmentShader) {
this.program = ResourceProgram.create(vertexShader, fragmentShader);
if (this.program != null) {
this.GLMatrixTransformation = this.program.getUniform("in_matrixTransformation");
this.GLMatrixProjection = this.program.getUniform("in_matrixProjection");
this.GLMatrixView = this.program.getUniform("in_matrixView");
}
}
@Override
public void addFriendComponent(final Component component) {
if (component.getType().contentEquals("mesh")) {
this.mesh = (ComponentMesh) component;
}
if (component.getType().contentEquals("palette")) {
this.texture = (ComponentTexturePalette) component;
}
if (component.getType().contentEquals("position")) {
this.position = (ComponentPosition) component;
}
if (component.getType().contentEquals("physics")) {
this.playerPhysics = (ComponentPhysics) component;
}
}
@Override
public void removeFriendComponent(final Component component) {
// nothing to do.
}
@Override
public void render() {
this.program.use();
final Matrix4f projectionMatrix = OpenGL.getMatrix();
final Matrix4f viewMatrix = OpenGL.getCameraMatrix();
Matrix4f transformationMatrix = null;
if (this.position != null) {
//Log.warning("position " + this.position.getTransform());
transformationMatrix = this.position.getTransform().getOpenGLMatrix();
} else if (this.playerPhysics != null) {
//Log.warning("playerPosition " + this.playerPhysics.getTransform());
transformationMatrix = this.playerPhysics.getTransform().getOpenGLMatrix();
}
this.mesh.bindForRendering();
this.texture.bindForRendering();
this.program.uniformMatrix(this.GLMatrixView, viewMatrix);
this.program.uniformMatrix(this.GLMatrixProjection, projectionMatrix);
// Change the position for each element with the same pipeline you need to render ...
this.program.uniformMatrix(this.GLMatrixTransformation, transformationMatrix);
// update of flags is done asynchronously ==> need update before drawing...
OpenGL.updateAllFlags();
// Request the draw all the elements:
this.mesh.render();
this.texture.unBindForRendering();
this.mesh.unBindForRendering();
this.program.unUse();
}
}

View File

@ -8,42 +8,43 @@ import org.atriasoft.loader3d.resources.ResourceStaticMeshObj;
public class ComponentStaticMesh extends Component { public class ComponentStaticMesh extends Component {
private ResourceStaticMesh mesh = null; private ResourceStaticMesh mesh = null;
public ComponentStaticMesh(ResourceStaticMesh mesh) {
this.mesh = mesh;
}
public ComponentStaticMesh(Uri objectFileName) {
// TODO check if it is OBJ ...
this.mesh = ResourceStaticMeshObj.create(objectFileName);
}
public void bindForRendering() {
if (this.mesh == null) {
return;
}
this.mesh.bindForRendering();
}
public ResourceStaticMesh getMesh() {
return this.mesh;
}
@Override @Override
public String getType() { public String getType() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return "static-mesh"; return "static-mesh";
} }
public ComponentStaticMesh(Uri objectFileName) {
// TODO check if it is OBJ ...
mesh = ResourceStaticMeshObj.create(objectFileName);
}
public ComponentStaticMesh(ResourceStaticMesh mesh) {
this.mesh = mesh;
}
public ResourceStaticMesh getMesh() {
return mesh;
}
public void bindForRendering() {
if (mesh == null) {
return;
}
mesh.bindForRendering();
}
public void unBindForRendering() {
if (mesh == null) {
return;
}
mesh.unBindForRendering();
}
public void render() { public void render() {
if (mesh == null) { if (this.mesh == null) {
return; return;
} }
mesh.render(); this.mesh.render();
}
public void unBindForRendering() {
if (this.mesh == null) {
return;
}
this.mesh.unBindForRendering();
} }
} }

View File

@ -5,63 +5,64 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.atriasoft.ege.Component; import org.atriasoft.ege.Component;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.loader3d.resources.ResourceStaticMesh; import org.atriasoft.loader3d.resources.ResourceStaticMesh;
import org.atriasoft.loader3d.resources.ResourceStaticMeshObj; import org.atriasoft.loader3d.resources.ResourceStaticMeshObj;
import org.atriasoft.ege.internal.Log;
public class ComponentStaticMeshs extends Component { public class ComponentStaticMeshs extends Component {
private Map<String, ResourceStaticMesh> meshs = new HashMap<String, ResourceStaticMesh>(); private final Map<String, ResourceStaticMesh> meshs = new HashMap<String, ResourceStaticMesh>();
public ComponentStaticMeshs() {
// nothing to do ...
}
public ComponentStaticMeshs(Uri meshUrl) {
// TODO load Mesh
Log.critical("Can not Load the Mesh for now ... " + meshUrl);
final ResourceStaticMeshObj mesh = ResourceStaticMeshObj.create(meshUrl);
setMesh("default", mesh);
}
public void bindForRendering(String name) {
final ResourceStaticMesh mesh = this.meshs.get(name);
if (mesh == null) {
return;
}
mesh.bindForRendering();
}
public Set<String> getKeys() {
return this.meshs.keySet();
}
public ResourceStaticMesh getMesh(String name) {
return this.meshs.get(name);
}
@Override @Override
public String getType() { public String getType() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return "static-meshs"; return "static-meshs";
} }
public ComponentStaticMeshs(Uri meshUrl) {
// TODO load Mesh
Log.critical("Can not Load the Mesh for now ... " + meshUrl);
ResourceStaticMeshObj mesh = ResourceStaticMeshObj.create(meshUrl);
setMesh("default", mesh);
}
public ComponentStaticMeshs() {
// nothing to do ...
}
public Set<String> getKeys() { public void render(String name) {
return meshs.keySet(); final ResourceStaticMesh mesh = this.meshs.get(name);
if (mesh == null) {
return;
}
mesh.render();
} }
public void setMesh(String name, ResourceStaticMesh mesh) { public void setMesh(String name, ResourceStaticMesh mesh) {
this.meshs.put(name, mesh); this.meshs.put(name, mesh);
} }
public ResourceStaticMesh getMesh(String name) {
return meshs.get(name);
}
public void bindForRendering(String name) {
ResourceStaticMesh mesh = meshs.get(name);
if (mesh == null) {
return;
}
mesh.bindForRendering();
}
public void unBindForRendering(String name) { public void unBindForRendering(String name) {
ResourceStaticMesh mesh = meshs.get(name); final ResourceStaticMesh mesh = this.meshs.get(name);
if (mesh == null) { if (mesh == null) {
return; return;
} }
mesh.unBindForRendering(); mesh.unBindForRendering();
} }
public void render(String name) {
ResourceStaticMesh mesh = meshs.get(name);
if (mesh == null) {
return;
}
mesh.render();
}
} }

View File

@ -1,32 +1,35 @@
package org.atriasoft.ege.components; package org.atriasoft.ege.components;
import org.atriasoft.ege.Component; import org.atriasoft.ege.Component;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.gale.resource.ResourceTexture; import org.atriasoft.gale.resource.ResourceTexture;
import org.atriasoft.ege.internal.Log;
public class ComponentTexture extends Component { public class ComponentTexture extends Component {
private ResourceTexture texture; private ResourceTexture texture;
public ComponentTexture(Uri textureName) {
this.texture = ResourceTexture.createFromPng(textureName);
if (this.texture == null) {
Log.error("can not instanciate Texture ...");
}
}
public void bindForRendering() {
this.texture.bindForRendering(0);
}
@Override @Override
public String getType() { public String getType() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return "texture"; return "texture";
} }
public ComponentTexture(Uri textureName) {
this.texture = ResourceTexture.createFromPng(textureName);
if (this.texture == null) {
Log.error("can not instanciate Texture ...");
return;
}
}
public void bindForRendering() {
this.texture.bindForRendering(0);
}
public void unBindForRendering() { public void unBindForRendering() {
this.texture.unBindForRendering(); this.texture.unBindForRendering();
} }
} }

View File

@ -0,0 +1,43 @@
package org.atriasoft.ege.components;
import org.atriasoft.egami.ImageByte;
import org.atriasoft.ege.Component;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.etk.Uri;
import org.atriasoft.gale.resource.ResourceTexture2;
import org.atriasoft.loader3d.resources.ResourcePaletteFile;
public class ComponentTexturePalette extends Component {
private final ResourcePaletteFile palette;
private final ResourceTexture2 texture;
public ComponentTexturePalette(Uri paletteName) {
this.palette = ResourcePaletteFile.create(paletteName);
this.texture = ResourceTexture2.createNamed("TEXTURE_OF_PALETTE:" + paletteName.toString());
if (this.texture == null) {
Log.error("can not instanciate Texture ...");
}
this.palette.onUpdate(() -> {
Log.warning("update palet environnement");
final ImageByte img = this.palette.getImageByte();
this.texture.set(img);
});
}
public void bindForRendering() {
this.texture.bindForRendering(0);
}
@Override
public String getType() {
// TODO Auto-generated method stub
return "texture";
}
public void unBindForRendering() {
this.texture.unBindForRendering();
}
}

View File

@ -4,37 +4,39 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.atriasoft.ege.Component; import org.atriasoft.ege.Component;
import org.atriasoft.ege.Material; import org.atriasoft.ege.internal.Log;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.gale.resource.ResourceTexture; import org.atriasoft.gale.resource.ResourceTexture;
import org.atriasoft.ege.internal.Log;
public class ComponentTextures extends Component { public class ComponentTextures extends Component {
private Map<String, ResourceTexture> textures = new HashMap<String, ResourceTexture>(); private final Map<String, ResourceTexture> textures = new HashMap<String, ResourceTexture>();
@Override
public String getType() {
// TODO Auto-generated method stub
return "textures";
}
public ComponentTextures() { public ComponentTextures() {
} }
public void setTexture(String name, Uri textureName) {
ResourceTexture texture = ResourceTexture.createFromPng(textureName);
if (texture == null) {
Log.error("can not instanciate Texture ...");
return;
}
textures.put(name, texture);
}
public void bindForRendering(String name) { public void bindForRendering(String name) {
this.textures.get(name).bindForRendering(0); this.textures.get(name).bindForRendering(0);
} }
@Override
public String getType() {
// TODO Auto-generated method stub
return "textures";
}
public void setTexture(String name, Uri textureName) {
final ResourceTexture texture = ResourceTexture.createFromPng(textureName);
if (texture == null) {
Log.error("can not instanciate Texture ...");
return;
}
this.textures.put(name, texture);
}
public void unBindForRendering(String name) { public void unBindForRendering(String name) {
this.textures.get(name).unBindForRendering(); this.textures.get(name).unBindForRendering();
} }
} }

View File

@ -10,10 +10,10 @@ import org.atriasoft.loader3d.resources.ResourceListTexturedMesh;
public class ComponentDynamicMeshsVoxelMap extends ComponentDynamicMeshs { public class ComponentDynamicMeshsVoxelMap extends ComponentDynamicMeshs {
private VoxelChunk chunk; private VoxelChunk chunk;
ResourceListTexturedMesh unbreakable = ResourceListTexturedMesh.create(RenderMode.triangle); ResourceListTexturedMesh unbreakable = ResourceListTexturedMesh.create(RenderMode.TRIANGLE);
ResourceListTexturedMesh stone = ResourceListTexturedMesh.create(RenderMode.triangle); ResourceListTexturedMesh stone = ResourceListTexturedMesh.create(RenderMode.TRIANGLE);
ResourceListTexturedMesh dirt = ResourceListTexturedMesh.create(RenderMode.triangle); ResourceListTexturedMesh dirt = ResourceListTexturedMesh.create(RenderMode.TRIANGLE);
ResourceListTexturedMesh grass = ResourceListTexturedMesh.create(RenderMode.triangle); ResourceListTexturedMesh grass = ResourceListTexturedMesh.create(RenderMode.TRIANGLE);
public ComponentDynamicMeshsVoxelMap(final VoxelChunk chunk) { public ComponentDynamicMeshsVoxelMap(final VoxelChunk chunk) {
super(); super();

View File

@ -128,7 +128,7 @@ public class MeshGenerator {
//out.addPoint(_materialName, new Vector3f(iii,-_lineCount,0), etk::color::white); //out.addPoint(_materialName, new Vector3f(iii,-_lineCount,0), etk::color::white);
//out.addPoint(_materialName, new Vector3f(iii,_lineCount,0), etk::color::white); //out.addPoint(_materialName, new Vector3f(iii,_lineCount,0), etk::color::white);
} }
return ResourceStaticColoredMesh.create(meshData.getListOfVertices(), meshData.getListOfColors(), null, meshData.getListOfIndices(), RenderMode.line); return ResourceStaticColoredMesh.create(meshData.getListOfVertices(), meshData.getListOfColors(), null, meshData.getListOfIndices(), RenderMode.LINE);
} }
private MeshGenerator() {} private MeshGenerator() {}

View File

@ -23,8 +23,8 @@ public abstract class ShaderProgram {
public ShaderProgram (String vertexFile, String fragmentFile) { public ShaderProgram (String vertexFile, String fragmentFile) {
vertexShaderID = OpenGL.shaderLoad(new Uri("DATA", vertexFile), OpenGL.ShaderType.vertex); vertexShaderID = OpenGL.shaderLoad(new Uri("DATA", vertexFile), OpenGL.ShaderType.VERTEX);
fragmentShaderID = OpenGL.shaderLoad(new Uri("DATA", fragmentFile), OpenGL.ShaderType.fragment); fragmentShaderID = OpenGL.shaderLoad(new Uri("DATA", fragmentFile), OpenGL.ShaderType.FRAGMENT);
programID = OpenGL.programCreate(); programID = OpenGL.programCreate();
OpenGL.programAttach(programID, vertexShaderID); OpenGL.programAttach(programID, vertexShaderID);
OpenGL.programAttach(programID, fragmentShaderID); OpenGL.programAttach(programID, fragmentShaderID);