7 #include "shaders/gate.h"
8 #include "shaders/gatelq.h"
9 #include "world_water.h"
11 typedef struct teleport_gate teleport_gate
;
15 struct framebuffer fb
;
18 int high_qual
; /* If in high performance mode, we don't use RT's, and
19 instead use stencil buffers.
20 There is therefore no heat warp effect. */
31 static void gate_transform_update( teleport_gate
*gate
)
35 q_m3x3( gate
->q
[0], gate
->to_world
);
36 v3_copy( gate
->co
[0], gate
->to_world
[3] );
38 m4x3_invert_affine( gate
->to_world
, to_local
);
40 q_m3x3( gate
->q
[1], gate
->recv_to_world
);
41 v3_copy( gate
->co
[1], gate
->recv_to_world
[3] );
42 m4x3_mul( gate
->recv_to_world
, to_local
, gate
->transport
);
45 static int world_gates_init(void)
47 vg_info( "world_gates_init\n" );
48 shader_gate_register();
49 shader_gatelq_register();
51 mdl_header
*mgate
= mdl_load( "models/rs_gate.mdl" );
53 if( vg_acquire_thread_sync(1) )
55 if( !fb_init( &grender
.fb
) )
58 vg_release_thread_sync(1);
62 if( !mdl_unpack_glmesh( mgate
, &grender
.mdl
) )
65 fb_free( &grender
.fb
);
66 vg_release_thread_sync(1);
70 vg_release_thread_sync(1);
81 static void world_gates_free(void*_
)
83 fb_free( &grender
.fb
);
86 static void gate_fb_resize(void)
88 fb_resize( &grender
.fb
);
91 static int render_gate( teleport_gate
*gate
, v3f viewpos
, m4x3f camera
)
94 m3x3_mulv( camera
, (v3f
){0.0f
,0.0f
,-1.0f
}, viewdir
);
95 m3x3_mulv( gate
->to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, gatedir
);
98 v3_sub( viewpos
, gate
->co
[0], v0
);
99 if( v3_dot(v0
, gatedir
) >= 0.0f
)
102 if( v3_dist( viewpos
, gate
->co
[0] ) > 100.0f
)
107 float sx
= gate
->dims
[0],
109 m4x3_mulv( gate
->to_world
, (v3f
){-sx
,-sy
,0.0f
}, a
);
110 m4x3_mulv( gate
->to_world
, (v3f
){ sx
,-sy
,0.0f
}, b
);
111 m4x3_mulv( gate
->to_world
, (v3f
){ sx
, sy
,0.0f
}, c
);
112 m4x3_mulv( gate
->to_world
, (v3f
){-sx
, sy
,0.0f
}, d
);
114 vg_line( a
,b
, 0xffffa000 );
115 vg_line( b
,c
, 0xffffa000 );
116 vg_line( c
,d
, 0xffffa000 );
117 vg_line( d
,a
, 0xffffa000 );
119 vg_line2( gate
->co
[0], gate
->co
[1], 0xff0000ff, 0x00000000 );
122 m4x3_mul( gate
->transport
, camera
, cam_new
);
124 vg_line_pt3( cam_new
[3], 0.3f
, 0xff00ff00 );
127 m4x3_copy( gate
->to_world
, gate_xform
);
128 m4x3_scalev( gate_xform
, (v3f
){ gate
->dims
[0], gate
->dims
[1], 1.0f
} );
131 m4x3_invert_affine( cam_new
, inverse
);
134 m4x3_expand( inverse
, view
);
137 m3x3_mulv( gate
->recv_to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, surface
);
138 surface
[3] = v3_dot( surface
, gate
->co
[1] );
141 pipeline_projection( projection
, 0.1f
, 900.0f
);
143 m4x3_mulp( inverse
, surface
, surface
);
144 surface
[3] = -fabsf(surface
[3]);
145 plane_clip_projection( projection
, surface
);
147 m4x4_mul( projection
, view
, projection
);
149 if( grender
.high_qual
)
151 fb_use( &grender
.fb
);
152 glClearColor( 0.11f
, 0.35f
, 0.37f
, 1.0f
);
153 glClear( GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
158 shader_gatelq_uPv( vg_pv
);
159 shader_gatelq_uMdl( gate_xform
);
160 shader_gatelq_uCam( viewpos
);
161 shader_gatelq_uTime( vg_time
*0.25f
);
162 shader_gatelq_uInvRes( (v2f
){
163 1.0f
/ (float)vg_window_x
,
164 1.0f
/ (float)vg_window_y
});
166 glEnable( GL_STENCIL_TEST
);
167 glStencilOp( GL_KEEP
, GL_KEEP
, GL_REPLACE
);
168 glStencilFunc( GL_ALWAYS
, 1, 0xFF );
169 glStencilMask( 0xFF );
171 mesh_bind( &grender
.mdl
);
172 mesh_draw( &grender
.mdl
);
174 glClear( GL_DEPTH_BUFFER_BIT
);
175 glStencilFunc( GL_EQUAL
, 1, 0xFF );
176 glStencilMask( 0x00 );
179 render_world( projection
, cam_new
);
181 if( grender
.high_qual
)
184 * TODO: Need to find a way to draw a stencil buffer into the water
188 render_water_texture( cam_new
);
189 fb_use( &grender
.fb
);
191 render_water_surface( projection
, cam_new
);
196 shader_gate_uPv( vg_pv
);
197 shader_gate_uMdl( gate_xform
);
199 fb_bindtex( &grender
.fb
, 0 );
201 shader_gate_uCam( viewpos
);
202 shader_gate_uTexMain( 0 );
203 shader_gate_uTexWater( 1 );
204 shader_gate_uTime( vg_time
*0.25f
);
205 shader_gate_uInvRes( (v2f
){
206 1.0f
/ (float)vg_window_x
,
207 1.0f
/ (float)vg_window_y
});
210 glBlendFunc(GL_SRC_ALPHA
,GL_ONE_MINUS_SRC_ALPHA
);
211 glBlendEquation(GL_FUNC_ADD
);
213 mesh_bind( &grender
.mdl
);
214 mesh_draw( &grender
.mdl
);
220 glDisable( GL_STENCIL_TEST
);
222 render_water_texture( cam_new
);
224 glEnable( GL_STENCIL_TEST
);
226 render_water_surface( projection
, cam_new
);
228 glStencilMask( 0xFF );
229 glStencilFunc( GL_ALWAYS
, 1, 0xFF );
230 glDisable( GL_STENCIL_TEST
);
236 static int gate_intersect( teleport_gate
*gate
, v3f pos
, v3f last
)
239 m3x3_mulv( gate
->to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, surface
);
240 surface
[3] = v3_dot( surface
, gate
->co
[0] );
242 v3f v0
, c
, delta
, p0
;
243 v3_sub( pos
, last
, v0
);
244 float l
= v3_length( v0
);
245 v3_divs( v0
, l
, v0
);
247 v3_muls( surface
, surface
[3], c
);
248 v3_sub( c
, last
, delta
);
250 float d
= v3_dot(surface
, v0
);
254 float t
= v3_dot(delta
, surface
) / d
;
255 if( t
>= 0.0f
&& t
<= l
)
258 v3_muladds( last
, v0
, t
, local
);
259 v3_sub( gate
->co
[0], local
, rel
);
262 m3x3_mulv( gate
->to_world
, (v3f
){0.0f
,1.0f
,0.0f
}, vup
);
263 m3x3_mulv( gate
->to_world
, (v3f
){1.0f
,0.0f
,0.0f
}, vside
);
265 v2f xy
= { v3_dot( rel
, vside
), v3_dot( rel
, vup
) };
267 if( fabsf(xy
[0]) <= gate
->dims
[0] && fabsf(xy
[1]) <= gate
->dims
[1] )
277 #endif /* WORLD_GATE_H */