1 from os
.path
import isfile
, dirname
2 from panda3d
.core
import AmbientLight
, DirectionalLight
, PointLight
, \
3 Spotlight
, LVector4f
, LVector3f
, Vec3
, Shader
, TextureStage
, \
5 from direct
.filter.FilterManager
import FilterManager
6 from ya2
.lib
.builder
import LibP3d
9 def load_shader(vert
, frag
):
12 joinchar
= '/' if LibP3d
.runtime() and not path
.startswith('/') else ''
13 dpath
= LibP3d
.runtime() and dirname(__file__
)
14 return isfile((dpath
or '') + joinchar
+ path
)
15 if is_file(vert
) and is_file(frag
):
16 shader
= Shader
.load(Shader
.SLGLSL
, vert
, frag
)
17 else: shader
= Shader
.make(Shader
.SLGLSL
, vert
, frag
)
23 def __init__(self
, shaders
, gamma
):
24 self
.filter_mgr
= None
25 self
.gamma
, self
.buffer, self
.lcam
, self
.lights
= gamma
, None, None, []
26 if shaders
: self
.setup_post_fx()
28 def __set_lgt(self
, lgt
, col
):
29 if type(col
) in [int, float]: lgt
.set_color_temperature(col
)
30 else: lgt
.set_color(col
)
31 self
.lights
+= [render
.attach_new_node(lgt
)]
32 render
.set_light(self
.lights
[-1])
34 def set_amb_lgt(self
, col
):
35 self
.__set
_lgt
(AmbientLight('ambient light'), col
)
37 def set_dir_lgt(self
, col
, direction
):
38 self
.__set
_lgt
(DirectionalLight('directional light'), col
)
39 self
.lights
[-1].set_hpr(*direction
)
41 def set_shadow_lgt(self
, direction
):
42 self
.__set
_lgt
(DirectionalLight('directional light'), (1, 1, 1, 1))
43 self
.lights
[-1].node().set_shadow_caster(True, 8192, 8192)
44 self
.lights
[-1].node().get_lens().set_film_size(2048, 2048)
45 self
.lights
[-1].node().get_lens().set_near_far(1, 2048)
46 #self.lights[-1].node().show_frustum()
47 self
.lights
[-1].set_hpr(*direction
)
48 return self
.lights
[-1]
50 def set_pnt_lgt(self
, col
, pos
):
51 self
.__set
_lgt
(PointLight('point light'), col
)
52 self
.lights
[-1].set_pos(*pos
)
54 def set_spotlight(self
, col
, exp
, cutoff
, pos
, look_at
):
55 self
.__set
_lgt
(Spotlight('spotlight'), col
)
56 self
.lights
[-1].set_exponent(exp
)
57 self
.lights
[-1].get_lens().set_fov(cutoff
, cutoff
)
58 self
.lights
[-1].set_pos(*pos
)
59 self
.lights
[-1].look_at(*look_at
)
62 def set_default_args(idx
):
63 pref
= 'lights[%s].' % idx
64 args
= [(pref
+ 'pos', LVector4f(0, 0, 0, 1)),
65 (pref
+ 'amb', LVector3f(0, 0, 0)),
66 (pref
+ 'diff', LVector3f(0, 0, 0)),
67 (pref
+ 'spec', LVector3f(0, 0, 0)),
68 (pref
+ 'dir', LVector3f(0, 0, 0)),
70 (pref
+ 'cutoff', .0)]
71 list(map(lambda _args
: render
.set_shader_input(*_args
), args
))
73 def set_lgt_args(self
, idx
, lgt
):
74 self
.set_default_args(idx
)
75 ShaderSetter
.build(lgt
).set('lights[%s].' % idx
, lgt
)
77 def clear_lights(self
):
78 for lgt
in self
.lights
:
79 base
.render
.clear_light(lgt
)
83 def setup_post_fx(self
):
84 self
.filter_mgr
= FilterManager(base
.win
, base
.cam
)
85 # rendered_scene = Texture()
86 # aa_scene = Texture()
87 # filtered_scene = Texture()
88 # filter_quad = self.filter_mgr.renderQuadInto(colortex=filtered_scene)
89 # aa_quad = self.filter_mgr.renderQuadInto(colortex=aa_scene)
90 # final_quad = self.filter_mgr.renderSceneInto(colortex=rendered_scene)
91 # filter_quad.set_shader(self.__load_shader('filter', 'sobel_filter'))
92 # filter_quad.set_shader_input('in_tex', rendered_scene)
93 # aa_quad.set_shader(self.__load_shader('fxaa', 'fxaa'))
94 # aa_quad.set_shader_input('in_tex', filtered_scene)
95 # final_quad.set_shader(self.__load_shader('filter', 'pass'))
96 # final_quad.set_shader_input('gamma', self.gamma)
97 # final_quad.set_shader_input('in_tex', aa_scene)
100 def __load_shader(vshad
, fshad
):
101 with
open('assets/shaders/%s.vert' % vshad
) as vfile
:
103 with
open('assets/shaders/%s.frag' % fshad
) as ffile
:
105 return load_shader(fvert
, ffrag
)
108 # winprops = WindowProperties.size(2048, 2048)
109 # props = FrameBufferProperties()
110 # props.set_rgb_color(1)
111 # props.set_alpha_bits(1)
112 # props.set_depth_bits(1)
113 # lbuffer = base.graphicsEngine.make_output(
114 # base.pipe, 'offscreen buffer', -2, props, winprops,
115 # GraphicsPipe.BFRefuseWindow, base.win.getGsg(), base.win)
116 # self.buffer = lbuffer
117 # ldepthmap = Texture()
118 # lbuffer.addRenderTexture(ldepthmap, GraphicsOutput.RTMBindOrCopy,
119 # GraphicsOutput.RTPDepthStencil)
120 # ldepthmap.set_minfilter(Texture.FTShadow)
121 # ldepthmap.set_magfilter(Texture.FTShadow)
123 # base.camLens.set_near_far(1.0, 10000)
124 # base.camLens.set_fov(75)
126 # self.lcam = base.makeCamera(lbuffer)
127 # self.lcam.node().set_scene(render)
128 # self.lcam.node().get_lens().set_fov(45)
129 # self.lcam.node().get_lens().set_near_far(1, 100)
131 # render.set_shader_input('light', self.lcam)
132 # render.set_shader_input('depthmap', ldepthmap)
133 # render.set_shader_input('ambient', .15, .15, .15, 1.0)
135 # lci = NodePath(PandaNode('light camera initializer'))
136 # lci.set_shader(self.__load_shader('caster', 'caster'))
137 # self.lcam.node().set_initial_state(lci.get_state())
139 # mci = NodePath(PandaNode('main camera initializer'))
140 # # use PTALVecBaseX instead
141 # # setShaderInput('vec3argname', PTALVecBase3(((0, 0, 0), (1, 1, 1))))
142 render
.set_shader(self
.__main
_shader
())
143 # render.set_shader_input('num_lights', len(self.lights))
144 # self.set_shader_pars(render)
146 # lambda lgt: self.set_lgt_args(*lgt), enumerate(self.lights)))
147 # mci.setShader(self.__main_shader())
148 # base.cam.node().set_initial_state(mci.getState())
150 # self.lcam.set_pos(15, 30, 45)
151 # self.lcam.look_at(0, 15, 0)
152 # self.lcam.node().get_lens().set_near_far(1, 100)
154 def __main_shader(self
):
155 with
open('assets/shaders/main.vert') as fvert
:
157 with
open('assets/shaders/main.frag') as ffrag
:
159 frag
= frag
.replace('<LIGHTS>', str(len(self
.lights
)))
160 return load_shader(vert
, frag
)
162 def toggle_shader(self
):
163 if render
.get_shader():
164 render
.set_shader_off()
165 render
.set_shader_auto()
169 def set_shader_pars(self
, model
):
170 texture_stages
= model
.find_all_texture_stages()
171 model
.set_shader_input('gloss_slot', 0)
172 model
.set_shader_input('detail_slot', 0)
173 model
.set_shader_input('detail_scale', (1, 1))
174 for tstage
in texture_stages
:
175 if tstage
.getSort() == 0: continue
176 self
.__set
_slots
(tstage
, model
, 1 if tstage
.getSort() == 10 else 2)
179 def __set_slots(tstage
, model
, slot
):
180 if tstage
.getMode() == TextureStage
.MGloss
:
181 model
.set_shader_input('gloss_slot', slot
)
183 model
.set_shader_input('detail_slot', slot
)
184 attrib_type
= TexMatrixAttrib
.get_class_type()
185 for geom_np
in model
.find_all_matches('**/+GeomNode'):
186 geom_node
= geom_np
.node()
187 for i
in range(geom_node
.get_num_geoms()):
188 state
= geom_node
.get_geom_state(i
)
189 if state
.has_attrib(attrib_type
):
190 attrib
= state
.get_attrib(attrib_type
)
191 for j
in range(attrib
.get_num_stages()):
192 stage
= attrib
.get_stage(j
)
193 scale
= attrib
.get_transform(stage
).get_scale()
194 model
.set_shader_input('detail_scale', scale
)
196 def destroy(self
): self
.clear_lights()
204 AmbientLight
: ShaderSetterAmbient
,
205 PointLight
: ShaderSetterPointLight
,
206 DirectionalLight
: ShaderSetterDirectionalLight
,
207 Spotlight
: ShaderSetterSpotlight
}
208 return cls2sett
[lgt
.node().__class
__]()
211 def _set_pars(pref
, lgt_pos
, lgt
):
212 render
.set_shader_input(pref
+ 'pos', lgt_pos
)
213 render
.set_shader_input(pref
+ 'diff', lgt
.node().get_color())
214 render
.set_shader_input(pref
+ 'spec', lgt
.node().get_color())
217 class ShaderSetterAmbient(ShaderSetter
):
221 render
.set_shader_input(pref
+ 'amb', lgt
.node().get_color())
224 class ShaderSetterPointLight(ShaderSetter
):
228 lgt_pos
= lgt
.get_mat(base
.cam
).xform(LVector4f(0, 0, 0, 1))
229 ShaderSetter
._set
_pars
(pref
, lgt_pos
, lgt
)
232 class ShaderSetterDirectionalLight(ShaderSetter
):
236 lgt_vec
= -render
.get_relative_vector(lgt
, Vec3(0, 1, 0))
237 lgt_pos
= LVector4f(lgt_vec
[0], lgt_vec
[1], lgt_vec
[2], 0)
238 ShaderSetter
._set
_pars
(pref
, lgt_pos
, lgt
)
241 class ShaderSetterSpotlight(ShaderSetter
):
245 lgt_vec
= base
.cam
.get_relative_vector(lgt
, Vec3(0, 1, 0))
246 lgt_pos
= lgt
.get_mat(base
.cam
).xform(LVector4f(0, 0, 0, 1))
247 ShaderSetter
._set
_pars
(pref
, lgt_pos
, lgt
)
248 render
.set_shader_input(pref
+ 'dir', lgt_vec
)
249 render
.set_shader_input(pref
+ 'exp', lgt
.node().get_exponent())
250 cutoff
= lgt
.node().get_lens().get_fov()[0]
251 render
.set_shader_input(pref
+ 'cutoff', cutoff
)