6 static const float k_gatesize
= 4.0f
;
8 SHADER_DEFINE( shader_gate
,
9 "layout (location=0) in vec3 a_co;"
11 "uniform mat4x3 uMdl;"
15 "gl_Position = uPv * vec4(uMdl * vec4( a_co, 1.0 ),1.0);"
21 "uniform sampler2D uTexMain;"
22 "uniform vec2 uInvRes;"
26 "vec2 uv = gl_FragCoord.xy*uInvRes;"
27 "FragColor = texture( uTexMain, uv );"
30 UNIFORMS({ "uPv", "uMdl", "uTexMain", "uInvRes" })
33 typedef struct teleport_gate teleport_gate
;
37 GLuint fb
, rgb
, rb
, vao
, vbo
;
46 m4x3f to_world
, to_local
;
50 static void gate_transform_update( teleport_gate
*gate
)
52 q_m3x3( gate
->q
, gate
->to_world
);
53 v3_copy( gate
->co
, gate
->to_world
[3] );
55 m4x3_invert_affine( gate
->to_world
, gate
->to_local
);
58 static void gate_register(void)
60 SHADER_INIT( shader_gate
);
63 static void gate_init(void)
65 glGenFramebuffers( 1, &grender
.fb
);
66 glBindFramebuffer( GL_FRAMEBUFFER
, grender
.fb
);
68 glGenTextures( 1, &grender
.rgb
);
69 glBindTexture( GL_TEXTURE_2D
, grender
.rgb
);
70 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGB
, vg_window_x
, vg_window_y
,
71 0, GL_RGB
, GL_UNSIGNED_BYTE
, NULL
);
73 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
74 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
75 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
76 GL_TEXTURE_2D
, grender
.rgb
, 0);
78 /* TODO: Check for DEPTH32f availiblity and use if possible */
80 glGenRenderbuffers( 1, &grender
.rb
);
81 glBindRenderbuffer( GL_RENDERBUFFER
, grender
.rb
);
82 glRenderbufferStorage( GL_RENDERBUFFER
, GL_DEPTH24_STENCIL8
,
83 vg_window_x
, vg_window_y
);
85 glFramebufferRenderbuffer( GL_FRAMEBUFFER
, GL_DEPTH_STENCIL_ATTACHMENT
,
86 GL_RENDERBUFFER
, grender
.rb
);
89 float ksz
= k_gatesize
;
90 float quad
[] = { -ksz
,-ksz
,0.0f
, ksz
, ksz
,0.0f
, -ksz
, ksz
,0.0f
,
91 -ksz
,-ksz
,0.0f
, ksz
,-ksz
,0.0f
, ksz
, ksz
,0.0f
,
92 -ksz
,-ksz
,0.0f
, -ksz
, ksz
,0.0f
, ksz
, ksz
,0.0f
,
93 -ksz
,-ksz
,0.0f
, ksz
, ksz
,0.0f
, ksz
,-ksz
,0.0f
};
95 glGenVertexArrays( 1, &grender
.vao
);
96 glGenBuffers( 1, &grender
.vbo
);
97 glBindVertexArray( grender
.vao
);
98 glBindBuffer( GL_ARRAY_BUFFER
, grender
.vbo
);
99 glBufferData( GL_ARRAY_BUFFER
, sizeof(quad
), quad
, GL_STATIC_DRAW
);
100 glBindVertexArray( grender
.vao
);
101 glVertexAttribPointer( 0, 3, GL_FLOAT
, GL_FALSE
,
102 sizeof(float)*3, (void*)0 );
103 glEnableVertexAttribArray( 0 );
108 static void render_world(m4x4f pv
);
111 * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
113 static void plane_clip_projection( m4x4f mat
, v4f plane
)
117 (vg_signf(plane
[0]) + mat
[2][0]) / mat
[0][0],
118 (vg_signf(plane
[1]) + mat
[2][1]) / mat
[1][1],
120 (1.0f
+ mat
[2][2]) / mat
[3][2]
123 v4_muls( plane
, 2.0f
/ v4_dot(plane
,c
), c
);
127 mat
[2][2] = c
[2] + 1.0f
;
131 static void render_gate( teleport_gate
*gate
, m4x3f camera
, float fov
)
135 m4x3_mul( gate
->other
->to_world
, gate
->to_local
, transport
);
139 float ksz
= k_gatesize
;
140 m4x3_mulv( gate
->to_world
, (v3f
){-ksz
,-ksz
,0.0f
}, a
);
141 m4x3_mulv( gate
->to_world
, (v3f
){ ksz
,-ksz
,0.0f
}, b
);
142 m4x3_mulv( gate
->to_world
, (v3f
){ ksz
, ksz
,0.0f
}, c
);
143 m4x3_mulv( gate
->to_world
, (v3f
){-ksz
, ksz
,0.0f
}, d
);
145 vg_line( a
,b
, 0xffffa000 );
146 vg_line( b
,c
, 0xffffa000 );
147 vg_line( c
,d
, 0xffffa000 );
148 vg_line( d
,a
, 0xffffa000 );
150 vg_line( gate
->co
, gate
->other
->co
, 0xffffffff );
153 m4x3_mul( transport
, camera
, cam_new
);
155 vg_line_pt3( cam_new
[3], 0.3f
, 0xff00ff00 );
157 glBindFramebuffer( GL_FRAMEBUFFER
, grender
.fb
);
158 glClearColor( 0.0f
, 0.0f
, 1.0f
, 1.0f
);
159 glClear( GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
163 m4x3_invert_affine( cam_new
, inverse
);
166 m4x3_expand( inverse
, view
);
169 m3x3_mulv( gate
->other
->to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, surface
);
170 surface
[3] = v3_dot( surface
, gate
->other
->co
);
173 m4x4_projection( projection
,
175 (float)vg_window_x
/ (float)vg_window_y
,
178 #if 0 /* For debugging frustum */
181 m4x4_mul( projection
, view
, devm
);
182 m4x4_inv( devm
, devm
);
186 {-1,-1,-1, 1}, { 1,-1,-1, 1}, { 1, 1,-1, 1}, {-1, 1,-1, 1},
187 {-1,-1, 1, 1}, { 1,-1, 1, 1}, { 1, 1, 1, 1}, {-1, 1, 1, 1}
190 for( int i
=0; i
<vg_list_size(corners
); i
++ )
192 m4x4_mulv( devm
, corners
[i
], corners
[i
] );
193 v3_muls( corners
[i
], 1.0f
/corners
[i
][3], corners
[i
] );
196 vg_line( corners
[0], corners
[1], 0xffffffff );
197 vg_line( corners
[1], corners
[2], 0xffffffff );
198 vg_line( corners
[2], corners
[3], 0xffffffff );
199 vg_line( corners
[3], corners
[0], 0xffffffff );
200 vg_line( corners
[4], corners
[5], 0xffffffff );
201 vg_line( corners
[5], corners
[6], 0xffffffff );
202 vg_line( corners
[6], corners
[7], 0xffffffff );
203 vg_line( corners
[7], corners
[4], 0xffffffff );
204 vg_line( corners
[0], corners
[4], 0xffffffff );
205 vg_line( corners
[1], corners
[5], 0xffffffff );
206 vg_line( corners
[2], corners
[6], 0xffffffff );
207 vg_line( corners
[3], corners
[7], 0xffffffff );
210 for( int i
=0; i
<4; i
++ )
212 v3f v0
, c
, delta
, p0
;
213 v3_sub( corners
[4+i
],corners
[0+i
], v0
);
216 v3_muls( surface
, surface
[3], c
);
217 v3_sub( c
, corners
[0+i
], delta
);
219 float t
= v3_dot(delta
, surface
) / v3_dot(surface
, v0
);
220 v3_muladds( corners
[0+i
], v0
, t
, clipped
[i
] );
223 vg_line( clipped
[0], clipped
[1], 0xff0000ff );
224 vg_line( clipped
[1], clipped
[2], 0xff0000ff );
225 vg_line( clipped
[2], clipped
[3], 0xff0000ff );
226 vg_line( clipped
[3], clipped
[0], 0xff0000ff );
228 m4x3_mulv( gate
->other
->to_world
, (v3f
){-2.0f
,-2.0f
,0.0f
}, a
);
229 m4x3_mulv( gate
->other
->to_world
, (v3f
){ 2.0f
,-2.0f
,0.0f
}, b
);
230 m4x3_mulv( gate
->other
->to_world
, (v3f
){ 2.0f
, 2.0f
,0.0f
}, c
);
231 m4x3_mulv( gate
->other
->to_world
, (v3f
){-2.0f
, 2.0f
,0.0f
}, d
);
233 vg_line( clipped
[0], a
, 0xff0000ff );
234 vg_line( clipped
[1], b
, 0xff0000ff );
235 vg_line( clipped
[2], c
, 0xff0000ff );
236 vg_line( clipped
[3], d
, 0xff0000ff );
240 m4x3_mulp( inverse
, surface
, surface
);
241 surface
[3] = -fabsf(surface
[3]);
242 plane_clip_projection( projection
, surface
);
244 m4x4_mul( projection
, view
, projection
);
246 render_world( projection
);
247 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
249 SHADER_USE( shader_gate
);
251 glUniformMatrix4fv( SHADER_UNIFORM( shader_gate
, "uPv" ),
252 1, GL_FALSE
, (float *)vg_pv
);
253 glUniformMatrix4x3fv( SHADER_UNIFORM( shader_gate
, "uMdl" ),
254 1, GL_FALSE
, (float *)gate
->to_world
);
256 glActiveTexture( GL_TEXTURE0
);
257 glBindTexture( GL_TEXTURE_2D
, grender
.rgb
);
258 glUniform1i( SHADER_UNIFORM( shader_gate
, "uTexMain"), 0 );
259 glUniform2f( SHADER_UNIFORM( shader_gate
, "uInvRes"),
260 1.0f
/ (float)vg_window_x
,
261 1.0f
/ (float)vg_window_y
);
263 glBindVertexArray( grender
.vao
);
264 glDrawArrays( GL_TRIANGLES
, 0, 12 );
267 static int gate_intersect( teleport_gate
*gate
, v3f pos
, v3f last
)
270 m3x3_mulv( gate
->to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, surface
);
271 surface
[3] = v3_dot( surface
, gate
->co
);
273 v3f v0
, c
, delta
, p0
;
274 v3_sub( pos
, last
, v0
);
275 float l
= v3_length( v0
);
276 v3_divs( v0
, l
, v0
);
278 v3_muls( surface
, surface
[3], c
);
279 v3_sub( c
, last
, delta
);
281 float d
= v3_dot(surface
, v0
);
283 if( fabsf(d
) > 0.00001f
)
285 float t
= v3_dot(delta
, surface
) / d
;
286 if( t
>= 0.0f
&& t
<= l
)
289 v3_muladds( last
, v0
, t
, local
);
290 v3_sub( gate
->co
, local
, rel
);
293 m3x3_mulv( gate
->to_world
, (v3f
){0.0f
,1.0f
,0.0f
}, vup
);
294 m3x3_mulv( gate
->to_world
, (v3f
){1.0f
,0.0f
,0.0f
}, vside
);
296 v2f xy
= { v3_dot( rel
, vside
), v3_dot( rel
, vup
) };
298 if( fabsf(xy
[0]) <= k_gatesize
&& fabsf(xy
[1]) <= k_gatesize
)