новая структура проекта
This commit is contained in:
+297
@@ -0,0 +1,297 @@
|
||||
import bpy
|
||||
import gpu
|
||||
|
||||
import mathutils
|
||||
|
||||
from typing import Union
|
||||
from bgl import *
|
||||
|
||||
from ...wbs_kernel.render import CWMODrawingBatch
|
||||
from ...wbs_kernel.render import OpenGLUtils
|
||||
from .shaders import WMOShaderPermutations, EGxBLend
|
||||
from .drawing_material import WMODrawingMaterial
|
||||
from ..drawing_elements import ElementTypes
|
||||
from ..utils import render_debug
|
||||
from ..bgl_ext import glCheckError
|
||||
|
||||
|
||||
class WMODrawingBatch:
|
||||
c_batch: CWMODrawingBatch
|
||||
|
||||
# control
|
||||
mesh_type: int = ElementTypes.WmoMesh
|
||||
shader: gpu.types.GPUShader
|
||||
bl_batch_vert_shader_id: int
|
||||
bl_batch_frag_shader_id: int
|
||||
|
||||
# uniform data
|
||||
draw_material: Union[CWMODrawingBatch, None]
|
||||
|
||||
def __init__(self
|
||||
, c_batch: 'CWMODrawingBatch'
|
||||
, draw_obj: 'WMODrawingObject'
|
||||
, context: bpy.types.Context):
|
||||
|
||||
self.c_batch = c_batch
|
||||
self.context = context
|
||||
self.draw_obj = draw_obj
|
||||
|
||||
self.tag_free = False
|
||||
|
||||
self.mat_id = self.c_batch.get_mat_id()
|
||||
|
||||
try:
|
||||
self.draw_material = self.draw_obj.draw_mgr.draw_materials.get(
|
||||
self.draw_obj.bl_obj.data.materials[self.mat_id].name)
|
||||
|
||||
except IndexError:
|
||||
self.draw_material = None
|
||||
|
||||
self.create_vao()
|
||||
|
||||
self.draw_obj.draw_mgr.draw_elements.add_batch(self)
|
||||
|
||||
render_debug('Instantiated drawing batch for object \"{}\"'.format(draw_obj.bl_obj.name))
|
||||
|
||||
@property
|
||||
def is_transparent(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def priority_plane(self) -> int:
|
||||
return 0
|
||||
|
||||
@property
|
||||
def layer(self) -> int:
|
||||
return 0
|
||||
|
||||
@property
|
||||
def is_skybox(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def bb_center(self) -> mathutils.Vector:
|
||||
return mathutils.Vector(self.c_batch.bb_center)
|
||||
|
||||
@property
|
||||
def sort_radius(self) -> float:
|
||||
return self.c_batch.sort_radius
|
||||
|
||||
@property
|
||||
def sort_distance(self):
|
||||
|
||||
perspective_mat = self.draw_obj.draw_mgr.region_3d.perspective_matrix
|
||||
bb_center = self.draw_obj.bl_obj.matrix_world @ self.bb_center
|
||||
|
||||
value = (perspective_mat.to_translation() - bb_center).length
|
||||
|
||||
if self.draw_material.is_inverted or self.draw_material.is_transformed:
|
||||
result_point = bb_center * (1.0 / value) if value > 0.00000023841858 else bb_center
|
||||
|
||||
sort_dist = perspective_mat.to_translation().length * self.sort_radius
|
||||
|
||||
result_point *= sort_dist
|
||||
|
||||
value = (bb_center - result_point).length \
|
||||
if self.draw_material.is_inverted else (bb_center + result_point).length
|
||||
|
||||
return value
|
||||
|
||||
def create_vao(self):
|
||||
self.shader = self.determine_valid_shader()
|
||||
self.c_batch.set_program(self.shader.program)
|
||||
self.c_batch.create_vao()
|
||||
glCheckError('Create VAO')
|
||||
|
||||
def ensure_context(self):
|
||||
mat_test = self.draw_material.bl_material
|
||||
|
||||
if not mat_test:
|
||||
self.tag_free = True
|
||||
|
||||
return self.tag_free
|
||||
|
||||
def _set_active_textures(self):
|
||||
|
||||
gl_texture_slots = (
|
||||
GL_TEXTURE0,
|
||||
GL_TEXTURE1,
|
||||
GL_TEXTURE2,
|
||||
GL_TEXTURE3
|
||||
)
|
||||
|
||||
for i, gl_slot in enumerate(gl_texture_slots):
|
||||
bind_code = self.draw_material.get_bindcode(i)
|
||||
|
||||
if bind_code:
|
||||
glActiveTexture(gl_slot)
|
||||
glBindTexture(GL_TEXTURE_2D, bind_code)
|
||||
|
||||
def determine_valid_shader(self) -> gpu.types.GPUShader:
|
||||
|
||||
shaders = WMOShaderPermutations()
|
||||
|
||||
if self.draw_material:
|
||||
|
||||
shader_rec = WMOShaderPermutations.get_shader_combo(int(self.draw_material.bl_material.wow_wmo_material.shader))
|
||||
self.bl_batch_vert_shader_id = shader_rec.vertex_shader
|
||||
self.bl_batch_frag_shader_id = shader_rec.pixel_shader
|
||||
|
||||
return shaders.get_shader_by_id(self.bl_batch_vert_shader_id,
|
||||
self.bl_batch_frag_shader_id)
|
||||
else:
|
||||
return shaders.default_shader
|
||||
|
||||
def draw(self):
|
||||
|
||||
render_debug('Drawing batch for object \"{}\"'.format(self.draw_obj.bl_obj.name))
|
||||
|
||||
bl_obj = self.draw_obj.bl_obj
|
||||
|
||||
if not bl_obj.visible_get():
|
||||
return
|
||||
|
||||
if self.tag_free:
|
||||
return
|
||||
|
||||
if self.draw_material:
|
||||
self.draw_wmo_batch()
|
||||
else:
|
||||
self.draw_fallback()
|
||||
|
||||
def draw_fallback(self):
|
||||
|
||||
glCheckError('drawfallback pre')
|
||||
|
||||
self.shader = self.determine_valid_shader()
|
||||
self.shader.bind()
|
||||
self.c_batch.set_program(self.shader.program)
|
||||
|
||||
self.shader.uniform_float('uViewProjectionMatrix', self.draw_obj.draw_mgr.region_3d.perspective_matrix)
|
||||
|
||||
self.shader.uniform_float('uPlacementMatrix', self.draw_obj.bl_obj.matrix_world)
|
||||
self.shader.uniform_float('uSunDirAndFogStart', self.draw_obj.draw_mgr.sun_dir_and_fog_start)
|
||||
self.shader.uniform_float('uSunColorAndFogEnd', self.draw_obj.draw_mgr.sun_color_and_fog_end)
|
||||
self.shader.uniform_float('uAmbientLight', self.draw_obj.draw_mgr.ambient_light)
|
||||
self.shader.uniform_float('uFogColorAndAlphaTest', (*self.draw_obj.draw_mgr.fog_color, 1.0 / 255.0))
|
||||
self.shader.uniform_int('UnFogged_IsAffectedByLight_LightCount', (False, True, 0))
|
||||
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
self.c_batch.draw()
|
||||
|
||||
glDisable(GL_DEPTH_TEST)
|
||||
|
||||
gpu.shader.unbind()
|
||||
|
||||
glCheckError('draw fallback post')
|
||||
|
||||
def draw_wmo_batch(self):
|
||||
|
||||
glCheckError('draw')
|
||||
|
||||
#render_debug('Drawing batch for object \"{}\"'.format(self.draw_obj.bl_obj.name))
|
||||
|
||||
color_name = self.draw_material.bl_material.wow_m2_material.color
|
||||
transparency_name = self.draw_material.bl_material.wow_m2_material.transparency
|
||||
color = self.context.scene.wow_m2_colors[color_name].color if color_name else (1.0, 1.0, 1.0, 1.0)
|
||||
|
||||
if transparency_name:
|
||||
transparency_rec = self.context.scene.wow_m2_transparency.get(transparency_name)
|
||||
transparency = transparency_rec.value if transparency_rec else 1.0
|
||||
else:
|
||||
transparency = 1.0
|
||||
|
||||
combined_color = (*color[:3], color[3] * transparency)
|
||||
|
||||
u_alpha_test = 128.0 / 255.0 * combined_color[3] \
|
||||
if self.draw_material.blend_mode.index == EGxBLend.AlphaKey.index else 1.0 / 255.0 # Maybe move this to shader logic?
|
||||
|
||||
self._set_active_textures()
|
||||
|
||||
self.shader = self.determine_valid_shader()
|
||||
self.shader.bind()
|
||||
glCheckError('Pre-link program')
|
||||
self.c_batch.set_program(self.shader.program)
|
||||
glCheckError('Post-link program')
|
||||
|
||||
# draw
|
||||
if self.draw_material.depth_culling:
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
glDepthMask(GL_TRUE if self.draw_material.depth_write else GL_FALSE)
|
||||
|
||||
if self.draw_material.backface_culling:
|
||||
glEnable(GL_CULL_FACE)
|
||||
|
||||
if self.draw_material.blend_mode.blending_enabled:
|
||||
glEnable(GL_BLEND)
|
||||
|
||||
if self.is_skybox:
|
||||
glDepthRange(0.998, 1.0)
|
||||
|
||||
glBlendFunc(self.draw_material.blend_mode.src_color, self.draw_material.blend_mode.dest_color)
|
||||
# OpenGLUtils.glBlendFuncSeparate(self.draw_material.blend_mode.src_color,
|
||||
# self.draw_material.blend_mode.dest_color,
|
||||
# self.draw_material.blend_mode.src_alpha,
|
||||
# self.draw_material.blend_mode.dest_alpha)
|
||||
|
||||
self.shader.uniform_float('uViewProjectionMatrix', self.draw_obj.draw_mgr.region_3d.perspective_matrix)
|
||||
|
||||
self.shader.uniform_float('uPlacementMatrix', self.draw_obj.bl_obj.matrix_world)
|
||||
self.shader.uniform_float('uSunDirAndFogStart', self.draw_obj.draw_mgr.sun_dir_and_fog_start)
|
||||
self.shader.uniform_float('uSunColorAndFogEnd', self.draw_obj.draw_mgr.sun_color_and_fog_end)
|
||||
self.shader.uniform_float('uAmbientLight', self.draw_obj.draw_mgr.ambient_light)
|
||||
self.shader.uniform_float('uFogColorAndAlphaTest', (*self.draw_obj.draw_mgr.fog_color, u_alpha_test))
|
||||
self.shader.uniform_int('UnFogged_IsAffectedByLight_LightCount', (self.draw_material.is_unfogged,
|
||||
not self.draw_material.is_unlit, 0))
|
||||
|
||||
try:
|
||||
self.shader.uniform_int('uTexture', 0)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.shader.uniform_int('uTexture2', 1)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.shader.uniform_int('uTexture3', 2)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.shader.uniform_int('uTexture4', 3)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
self.shader.uniform_float('color_Transparency', combined_color)
|
||||
|
||||
self.c_batch.draw()
|
||||
|
||||
if self.is_skybox:
|
||||
glDepthRange(0, 0.996)
|
||||
|
||||
if self.draw_material.blend_mode.blending_enabled:
|
||||
glDisable(GL_BLEND)
|
||||
|
||||
if self.draw_material.backface_culling:
|
||||
glDisable(GL_CULL_FACE)
|
||||
|
||||
glDepthMask(GL_FALSE if self.draw_material.depth_write else GL_TRUE)
|
||||
|
||||
if self.draw_material.depth_culling:
|
||||
glDisable(GL_DEPTH_TEST)
|
||||
|
||||
gpu.shader.unbind()
|
||||
|
||||
glCheckError('draw end')
|
||||
|
||||
def free(self):
|
||||
|
||||
if self.tag_free:
|
||||
return
|
||||
|
||||
self.tag_free = True
|
||||
self.draw_obj.draw_mgr.draw_elements.remove_batch(self)
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
import bpy
|
||||
|
||||
from .shaders import EGxBlendRecord, WMOBlendingModeToEGxBlend
|
||||
|
||||
|
||||
class WMODrawingMaterial:
|
||||
__slots__ = (
|
||||
'draw_mgr',
|
||||
'bl_material_name',
|
||||
'blend_mode',
|
||||
'backface_culling',
|
||||
'is_unlit',
|
||||
'is_unfogged',
|
||||
'is_exterior_lit',
|
||||
'night_glow',
|
||||
'is_window',
|
||||
'clamp_s',
|
||||
'clamp_t',
|
||||
)
|
||||
|
||||
blend_mode: EGxBlendRecord
|
||||
backface_culling: bool
|
||||
is_unlit: bool
|
||||
is_unfogged: bool
|
||||
is_exterior_lit: bool
|
||||
night_glow: bool
|
||||
is_window: bool
|
||||
clamp_s: bool
|
||||
clamp_t: bool
|
||||
|
||||
def __init__(self, material: bpy.types.Material):
|
||||
self.bl_material_name = material.name
|
||||
|
||||
self.update_uniform_data()
|
||||
|
||||
@property
|
||||
def bl_material(self):
|
||||
try:
|
||||
return bpy.data.materials[self.bl_material_name]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def get_texture(self, tex_index: int):
|
||||
mat = self.bl_material
|
||||
|
||||
if mat:
|
||||
return getattr(mat.wow_wmo_material, 'diff_texture_{}'.format(tex_index + 1))
|
||||
|
||||
@property
|
||||
def texture_count(self):
|
||||
mat = self.bl_material
|
||||
counter = 0
|
||||
|
||||
if mat:
|
||||
for i in range(2):
|
||||
tex = getattr(mat.wow_wmo_material, 'diff_texture_{}'.format(i + 1))
|
||||
if tex:
|
||||
counter += 1
|
||||
|
||||
return counter
|
||||
|
||||
def update_uniform_data(self):
|
||||
|
||||
bl_material = self.bl_material
|
||||
|
||||
if not bl_material:
|
||||
return
|
||||
|
||||
self.blend_mode = WMOBlendingModeToEGxBlend[int(self.bl_material.wow_wmo_material.blending_mode)]
|
||||
self.backface_culling = '4' not in bl_material.wow_wmo_material.render_flags
|
||||
self.is_unlit = '1' in bl_material.wow_wmo_material.render_flags
|
||||
self.is_unfogged = '2' in bl_material.wow_wmo_material.render_flags
|
||||
self.is_exterior_lit = '8' in bl_material.wow_wmo_material.render_flags
|
||||
self.night_glow = '16' in bl_material.wow_wmo_material.render_flags
|
||||
self.is_window = '32' in bl_material.wow_wmo_material.render_flags
|
||||
self.clamp_s = '64' in bl_material.wow_wmo_material.render_flags
|
||||
self.clamp_t = '128' in bl_material.wow_wmo_material.render_flags
|
||||
|
||||
def get_bindcode(self, tex_index: int) -> int:
|
||||
|
||||
texture = self.get_texture(tex_index)
|
||||
|
||||
if texture:
|
||||
if not texture.bindcode:
|
||||
texture.gl_load()
|
||||
|
||||
return texture.bindcode
|
||||
|
||||
return 0
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
import traceback
|
||||
import bpy
|
||||
import numpy as np
|
||||
|
||||
from mathutils import Matrix
|
||||
from typing import List
|
||||
|
||||
from .drawing_batch import M2DrawingBatch
|
||||
from ..utils import render_debug
|
||||
from ...wbs_kernel.render import CM2DrawingMesh, CM2DrawingBatch
|
||||
from ..bgl_ext import glCheckError
|
||||
|
||||
|
||||
class M2DrawingObject:
|
||||
|
||||
batches: List[CM2DrawingBatch]
|
||||
|
||||
def __init__(self
|
||||
, bl_obj: bpy.types.Object
|
||||
, drawing_mgr: 'M2DrawingManager'
|
||||
, context: bpy.types.Context
|
||||
, is_skybox: bool = False):
|
||||
|
||||
self.context = context
|
||||
self.draw_mgr = drawing_mgr
|
||||
self.bl_obj_name = bl_obj.name
|
||||
self.is_skybox = is_skybox
|
||||
self.is_dirty = True
|
||||
self.is_batching_valid = False
|
||||
|
||||
self.mesh_ptr = bl_obj.data.as_pointer()
|
||||
self.c_mesh = CM2DrawingMesh(self.mesh_ptr)
|
||||
self.batches = []
|
||||
bl_obj.data.calc_loop_triangles()
|
||||
render_debug('Initialized drawing object \"{}\"'.format(self.bl_obj_name))
|
||||
|
||||
self.update_geometry()
|
||||
|
||||
def update_geometry(self, bl_obj: bpy.types.Object = None):
|
||||
if bl_obj:
|
||||
self.c_mesh.update_mesh_pointer(bl_obj.data.as_pointer())
|
||||
bl_obj.data.calc_loop_triangles()
|
||||
|
||||
self.is_batching_valid = self.c_mesh.update_geometry(not(self.context.screen.is_animation_playing or self.bl_obj.mode != 'OBJECT'))
|
||||
|
||||
self.is_dirty = True
|
||||
|
||||
def update_geometry_opengl(self, bl_obj: bpy.types.Object = None):
|
||||
|
||||
self.c_mesh.update_buffers()
|
||||
|
||||
if not self.is_batching_valid:
|
||||
|
||||
for batch in self.batches:
|
||||
batch.free()
|
||||
|
||||
self.batches = \
|
||||
[M2DrawingBatch(c_batch, self, self.context) for c_batch in self.c_mesh.get_drawing_batches()]
|
||||
|
||||
self.is_dirty = False
|
||||
|
||||
@property
|
||||
def bl_obj(self):
|
||||
|
||||
try:
|
||||
return bpy.data.objects[self.bl_obj_name]
|
||||
except KeyError:
|
||||
self.free()
|
||||
|
||||
def free(self):
|
||||
|
||||
for batch in self.batches:
|
||||
batch.free()
|
||||
|
||||
del self.draw_mgr.m2_objects[self.bl_obj_name]
|
||||
|
||||
render_debug('Freed drawing object \"{}\"'.format(self.bl_obj_name))
|
||||
|
||||
'''
|
||||
def update_bone_matrices(self):
|
||||
rig = self.bl_rig
|
||||
for i, pbone in enumerate(rig.pose.bones):
|
||||
self.bone_matrices[i] = [j[i] for i in range(4) for j in pbone.matrix_channel]
|
||||
|
||||
def create_batches_from_armature(self, rig: bpy.types.Object):
|
||||
|
||||
for obj in filter(lambda x: x.type == 'MESH', rig.children):
|
||||
|
||||
# Limit bone influences to 4. TODO: rework to be non-destructive!
|
||||
"""
|
||||
if obj.vertex_groups:
|
||||
active_obj = bpy.context.view_layer.objects.active
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
bpy.ops.object.vertex_group_limit_total()
|
||||
bpy.context.view_layer.objects.active = active_obj
|
||||
|
||||
"""
|
||||
|
||||
self.create_batch_from_object(obj)
|
||||
|
||||
def create_batch_from_object(self, obj: bpy.types.Object):
|
||||
self.batches[obj.name] = M2DrawingBatch(obj, self, self.context)
|
||||
|
||||
'''
|
||||
|
||||
|
||||
|
||||
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
import os
|
||||
import gpu
|
||||
|
||||
from enum import IntEnum
|
||||
from ctypes import c_uint, c_uint8
|
||||
from collections import namedtuple
|
||||
from typing import Dict, Tuple
|
||||
|
||||
from ...utils.misc import singleton, Sequence
|
||||
from ..shaders import ShaderPermutationsManager
|
||||
from bgl import *
|
||||
|
||||
|
||||
class WMOPixelShader(IntEnum):
|
||||
NoShader = -1,
|
||||
MapObjDiffuse = 0,
|
||||
MapObjSpecular = 1,
|
||||
MapObjMetal = 2,
|
||||
MapObjEnv = 3,
|
||||
MapObjOpaque = 4,
|
||||
MapObjEnvMetal = 5,
|
||||
MapObjTwoLayerDiffuse = 6, # MapObjComposite
|
||||
MapObjTwoLayerEnvMetal = 7,
|
||||
MapObjTwoLayerTerrain = 8,
|
||||
MapObjDiffuseEmissive = 9,
|
||||
MapObjMaskedEnvMetal = 10,
|
||||
MapObjEnvMetalEmissive = 11,
|
||||
MapObjTwoLayerDiffuseOpaque = 12,
|
||||
MapObjTwoLayerDiffuseEmissive = 13,
|
||||
MapObjAdditiveMaskedEnvMetal = 14,
|
||||
MapObjTwoLayerDiffuseMod2x = 15,
|
||||
MapObjTwoLayerDiffuseMod2xNA = 16,
|
||||
MapObjTwoLayerDiffuseAlpha = 17,
|
||||
MapObjLod = 18,
|
||||
MapObjParallax = 19
|
||||
|
||||
|
||||
class WMOVertexShader(IntEnum):
|
||||
NoShader = -1,
|
||||
MapObjDiffuse_T1 = 0,
|
||||
MapObjDiffuse_T1_Refl = 1,
|
||||
MapObjDiffuse_T1_Env_T2 = 2,
|
||||
MapObjSpecular_T1 = 3,
|
||||
MapObjDiffuse_Comp = 4,
|
||||
MapObjDiffuse_Comp_Refl = 5,
|
||||
MapObjDiffuse_Comp_Terrain = 6,
|
||||
MapObjDiffuse_CompAlpha = 7,
|
||||
MapObjParallax = 8,
|
||||
|
||||
|
||||
EGxBlendRecord = namedtuple('EGxBlendRecord',
|
||||
['blending_enabled', 'src_color', 'dest_color', 'src_alpha', 'dest_alpha', 'index'])
|
||||
|
||||
|
||||
class EGxBLend(metaclass=Sequence):
|
||||
Opaque = EGxBlendRecord(False, GL_ONE, GL_ZERO, GL_ONE, GL_ZERO, 0)
|
||||
AlphaKey = EGxBlendRecord(False, GL_ONE, GL_ZERO, GL_ONE, GL_ZERO, 1)
|
||||
Alpha = EGxBlendRecord(True, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA, 2)
|
||||
Add = EGxBlendRecord(True, GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE, 3)
|
||||
Mod = EGxBlendRecord(True, GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO, 4)
|
||||
Mod2x = EGxBlendRecord(True, GL_DST_COLOR, GL_SRC_COLOR, GL_DST_ALPHA, GL_SRC_ALPHA, 5)
|
||||
ModAdd = EGxBlendRecord(True, GL_DST_COLOR, GL_ONE, GL_DST_ALPHA, GL_ONE, 6)
|
||||
InvSrcAlphaAdd = EGxBlendRecord(True, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, 7)
|
||||
InvSrcAlphaOpaque = EGxBlendRecord(True, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, 8)
|
||||
SrcAlphaOpaque = EGxBlendRecord(True, GL_SRC_ALPHA, GL_ZERO, GL_SRC_ALPHA, GL_ZERO, 9)
|
||||
NoAlphaAdd = EGxBlendRecord(True, GL_ONE, GL_ONE, GL_ZERO, GL_ONE, 10)
|
||||
ConstantAlpha = EGxBlendRecord(True, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_CONSTANT_ALPHA,
|
||||
GL_ONE_MINUS_CONSTANT_ALPHA, 11)
|
||||
Screen = EGxBlendRecord(True, GL_ONE_MINUS_DST_COLOR, GL_ONE, GL_ONE, GL_ZERO, 12)
|
||||
BlendAdd = EGxBlendRecord(True, GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA, 13)
|
||||
|
||||
|
||||
class WMOBlendingModeToEGxBlend(metaclass=Sequence):
|
||||
|
||||
Blend_Opaque = EGxBLend.Opaque
|
||||
Blend_AlphaKey = EGxBLend.AlphaKey
|
||||
Blend_Alpha = EGxBLend.Alpha
|
||||
Blend_NoAlphaAdd = EGxBLend.NoAlphaAdd
|
||||
Blend_Add = EGxBLend.Add
|
||||
Blend_Mod = EGxBLend.Mod
|
||||
Blend_Mod2x = EGxBLend.Mod2x
|
||||
Blend_BlendAdd = EGxBLend.BlendAdd
|
||||
|
||||
|
||||
WMOShaderTableRecord = namedtuple('WMOShaderTableRecord', ['pixel_shader', 'vertex_shader'])
|
||||
|
||||
|
||||
class WMOShaderTable(metaclass=Sequence):
|
||||
MapObjDiffuse = WMOShaderTableRecord(WMOPixelShader.MapObjDiffuse, WMOVertexShader.MapObjDiffuse_T1)
|
||||
|
||||
MapObjSpecular = WMOShaderTableRecord(WMOPixelShader.MapObjSpecular, WMOVertexShader.MapObjSpecular_T1)
|
||||
|
||||
MapObjMetal = WMOShaderTableRecord(WMOPixelShader.MapObjMetal, WMOVertexShader.MapObjSpecular_T1)
|
||||
|
||||
MapObjEnv = WMOShaderTableRecord(WMOPixelShader.MapObjEnv, WMOVertexShader.MapObjDiffuse_T1_Refl)
|
||||
|
||||
MapObjOpaque = WMOShaderTableRecord(WMOPixelShader.MapObjOpaque, WMOVertexShader.MapObjDiffuse_T1)
|
||||
|
||||
MapObjEnvMetal = WMOShaderTableRecord(WMOPixelShader.MapObjEnvMetal, WMOVertexShader.MapObjDiffuse_T1_Refl)
|
||||
|
||||
MapObjTwoLayerDiffuse = WMOShaderTableRecord(WMOPixelShader.MapObjTwoLayerDiffuse,
|
||||
WMOVertexShader.MapObjDiffuse_Comp)
|
||||
|
||||
MapObjTwoLayerEnvMetal = WMOShaderTableRecord(WMOPixelShader.MapObjTwoLayerEnvMetal,
|
||||
WMOVertexShader.MapObjDiffuse_T1)
|
||||
|
||||
TwoLayerTerrain = WMOShaderTableRecord(WMOPixelShader.MapObjTwoLayerTerrain,
|
||||
WMOVertexShader.MapObjDiffuse_Comp_Terrain)
|
||||
|
||||
MapObjDiffuseEmissive = WMOShaderTableRecord(WMOPixelShader.MapObjDiffuseEmissive,
|
||||
WMOVertexShader.MapObjDiffuse_Comp)
|
||||
|
||||
waterWindow = WMOShaderTableRecord(WMOPixelShader.NoShader,
|
||||
WMOVertexShader.NoShader)
|
||||
|
||||
MapObjMaskedEnvMetal = WMOShaderTableRecord(WMOPixelShader.MapObjMaskedEnvMetal,
|
||||
WMOVertexShader.MapObjDiffuse_T1_Env_T2)
|
||||
|
||||
MapObjEnvMetalEmissive = WMOShaderTableRecord(WMOPixelShader.MapObjEnvMetalEmissive,
|
||||
WMOVertexShader.MapObjDiffuse_T1_Env_T2)
|
||||
|
||||
TwoLayerDiffuseOpaque = WMOShaderTableRecord(WMOPixelShader.MapObjTwoLayerDiffuseOpaque,
|
||||
WMOVertexShader.MapObjDiffuse_Comp)
|
||||
|
||||
submarineWindow = WMOShaderTableRecord(WMOPixelShader.NoShader, WMOVertexShader.NoShader)
|
||||
|
||||
TwoLayerDiffuseEmissive = WMOShaderTableRecord(WMOPixelShader.MapObjTwoLayerDiffuseEmissive,
|
||||
WMOVertexShader.MapObjDiffuse_Comp)
|
||||
|
||||
MapObjDiffuseTerrain = WMOShaderTableRecord(WMOPixelShader.MapObjDiffuse,
|
||||
WMOVertexShader.MapObjDiffuse_T1)
|
||||
|
||||
MapObjAdditiveMaskedEnvMetal = WMOShaderTableRecord(WMOPixelShader.MapObjAdditiveMaskedEnvMetal,
|
||||
WMOVertexShader.MapObjDiffuse_T1_Env_T2)
|
||||
|
||||
MapObjTwoLayerDiffuseMod2x = WMOShaderTableRecord(WMOPixelShader.MapObjTwoLayerDiffuseMod2x,
|
||||
WMOVertexShader.MapObjDiffuse_CompAlpha)
|
||||
|
||||
MapObjTwoLayerDiffuseMod2xNA = WMOShaderTableRecord(WMOPixelShader.MapObjTwoLayerDiffuseMod2xNA,
|
||||
WMOVertexShader.MapObjDiffuse_Comp)
|
||||
|
||||
MapObjTwoLayerDiffuseAlpha = WMOShaderTableRecord(WMOPixelShader.MapObjTwoLayerDiffuseAlpha,
|
||||
WMOVertexShader.MapObjDiffuse_CompAlpha)
|
||||
|
||||
MapObjLod = WMOShaderTableRecord(WMOPixelShader.MapObjLod,
|
||||
WMOVertexShader.MapObjDiffuse_T1)
|
||||
|
||||
MapObjParallax = WMOShaderTableRecord(WMOPixelShader.MapObjParallax,
|
||||
WMOVertexShader.MapObjParallax)
|
||||
|
||||
@singleton
|
||||
class WMOShaderPermutations(ShaderPermutationsManager):
|
||||
|
||||
shader_source_path = 'wmo_shader'
|
||||
|
||||
@staticmethod
|
||||
def get_shader_combo_index(vertex_shader_id: int, pixel_shader_id: int):
|
||||
|
||||
for record in WMOShaderTable:
|
||||
if record.value.vertex_shader == vertex_shader_id and record.value.pixel_shader == pixel_shader_id:
|
||||
return record.index
|
||||
|
||||
def get_shader_combo(self, id: int):
|
||||
# TODO: ugly
|
||||
|
||||
count = 0
|
||||
for i, record in enumerate(WMOShaderTable):
|
||||
|
||||
if i == count:
|
||||
return record
|
||||
|
||||
count += 1
|
||||
|
||||
Reference in New Issue
Block a user