static struct
{
- GLuint fb, rgb, rb;
+ struct framebuffer fb;
glmesh mdl;
int high_qual; /* If in high performance mode, we don't use RT's, and
- instead use stencil buffers.
- There is therefore no heat warp effect. */
+ instead use stencil buffers.
+ There is therefore no heat warp effect. */
}
grender =
{
- .high_qual = 0
+ .high_qual = 0,
+ .fb = {
+ .format = GL_RGB,
+ .div = 1
+ }
};
struct teleport_gate
static void gate_init(void)
{
- create_renderbuffer_std( &grender.fb, &grender.rgb, &grender.rb );
+ fb_init( &grender.fb );
model *mgate = vg_asset_read( "models/rs_gate.mdl" );
model_unpack( mgate, &grender.mdl );
static void gate_fb_resize(void)
{
- resize_renderbuffer_std( &grender.fb, &grender.rgb, &grender.rb );
+ fb_resize( &grender.fb );
}
static void render_gate( teleport_gate *gate, m4x3f camera )
if( grender.high_qual )
{
- glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
+ fb_use( &grender.fb );
glClearColor( 0.11f, 0.35f, 0.37f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
}
*/
render_water_texture( cam_new );
- glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
- render_water_surface( projection );
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ fb_use( &grender.fb );
+
+ render_water_surface( projection, cam_new );
+ fb_use( NULL );
shader_gate_use();
shader_gate_uPv( vg_pv );
shader_gate_uMdl( gate_xform );
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, grender.rgb );
+ fb_bindtex( &grender.fb, 0 );
+
shader_gate_uCam( viewpos );
shader_gate_uTexMain( 0 );
shader_gate_uTexWater( 1 );
vg_init( argc, argv, "Voyager Game Engine" );
}
-#if 0
-rigidbody mr_box = {
- .bbx = {{ -1.0f, -0.25f, -0.25f }, { 1.0f, 0.25f, 0.25f }}
-};
-
-rigidbody mrs_box = {
- .bbx = {{ -0.5f, -0.25f, -0.25f }, { 0.5f, 0.25f, 0.25f }}
-};
-
-#endif
-
static int playermodel( int argc, char const *argv[] )
{
if( argc < 1 ) return 0;
player_transform_update();
}
+void vg_free(void)
+{
+ vg_tex2d_free( texture_list, vg_list_size(texture_list) );
+}
+
void vg_update(void)
{
player_update();
v3f shake = { vg_randf()-0.5f, vg_randf()-0.5f, vg_randf()-0.5f };
v3_muls( shake, speed*0.01f, shake );
- if( player.is_dead )
- {
-#if 0
- v3f delta;
- v3_sub( player.mdl.ragdoll[k_chpart_head].co, player.follow, delta );
- v3_normalize(delta);
-
- v3f follow_pos;
- v3_muladds( player.mdl.ragdoll[k_chpart_head].co, delta,
- -1.5f, follow_pos );
- v3_lerp( player.follow, follow_pos, 0.1f, player.follow );
- v3_negate( player.follow, final );
-
-
- float yaw = atan2f( delta[0], -delta[2] );
- float pitch = asinf( delta[1] );
- m4x3_rotate_x( world_matrix, -pitch );
- m4x3_rotate_y( world_matrix, yaw );
-#endif
- }
- else
- {
- }
-
m4x4f world_4x4;
m4x3_expand( player.camera_inverse, world_4x4 );
render_water_texture( player.camera );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- render_water_surface( vg_pv );
+ render_water_surface( vg_pv, player.camera );
vg_tex2d_bind( &tex_water, 1 );
draw_player();
- /* Draw back in the background */
+ /* Draw back in the background
+ *
+ * TODO: need to disable alpha write in the terrain shader so this works
+ * again.
+ */
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
/* Other shite */
glDisable( GL_DEPTH_TEST );
vg_lines_drawall( (float *)vg_pv );
-
- /* Debugger camera */
-#if 0
- glViewport( 0,0, 800, 800 );
- glClearColor( 0.1f, 0.0f, 0.2f, 1.0f );
- glClear( GL_DEPTH_BUFFER_BIT );
-
- m4x3_identity( world_matrix );
-
- v3f debugcam;
- v3_negate( player.co, debugcam );
- debugcam[2] -= 2.0f;
- debugcam[1] -= 0.7f;
-
- m4x3_translate( world_matrix, debugcam );
- m4x3_expand( world_matrix, world_4x4 );
-
- m4x4_projection( vg_pv,
- 100.0f,
- (float)128.0f / (float)128.0f,
- 0.1f, 1000.0f );
- m4x4_mul( vg_pv, world_4x4, vg_pv );
-
- if(sv_debugcam)
- {
- glEnable( GL_DEPTH_TEST );
- draw_player();
- }
-#endif
-
- glDisable( GL_DEPTH_TEST );
- vg_lines_drawall( (float *)vg_pv );
-
glViewport( 0,0, vg_window_x, vg_window_y );
}
"Gamepad not ready", 1, k_text_align_left );
}
}
-
-void vg_free(void){}
v3f land_target_log[22];
u32 land_target_colours[22];
int land_log_count;
- m3x3f vr;
+ m3x3f vr,vr_pstep;
m4x3f to_world, to_local;
if( vg_get_button_down( "primary" ) )
v2_copy( vg_mouse, mouse_last );
+
else if( vg_get_button( "primary" ) )
{
v2f delta;
v2_muladds( view_vel, delta, 0.005f, view_vel );
}
+ v2_muladds( view_vel,
+ (v2f){ vg_get_axis("h1"), vg_get_axis("v1") },
+ 0.05f, view_vel );
v2_muls( view_vel, 0.7f, view_vel );
v2_add( view_vel, player.angles, player.angles );
player.angles[1] = vg_clampf( player.angles[1], -VG_PIf*0.5f, VG_PIf*0.5f );
-
}
static void player_freecam(void)
best_velocity_mod = vmod;
v3_copy( contact.pos, player.land_target );
-
+
+ m3x3_copy( vr, player.vr_pstep );
q_axis_angle( vr_q, axis, vmod*0.1f );
q_m3x3( vr_q, player.vr );
}
for( int i=0; i<5; i++ )
{
vel[2] = stable_force( vel[2], vg_signf( vel[2] ) * fwd_resistance );
- vel[0] = stable_force( vel[0], vg_signf( vel[0] ) * -7.0f *substep );
+
+ /* This used to be -7.0 */
+ vel[0] = stable_force( vel[0], vg_signf( vel[0] ) * -10.0f *substep );
}
static double start_push = 0.0;
for( int i=0; i<50; i++ )
{
v3_copy( pco, pco1 );
+ m3x3_mulv( player.vr_pstep, pv, pv );
apply_gravity( pv, pstep );
v3_muladds( pco, pv, pstep, pco );
player.iY -= vg_get_axis( "horizontal" ) * 3.6f * ktimestep;
{
- float iX = vg_get_axis( "vertical" ) * 3.6f * limiter * ktimestep;
+ float iX = vg_get_axis( "vertical" ) *
+ player.reverse * 3.6f * limiter * ktimestep;
static float siX = 0.0f;
siX = vg_lerpf( siX, iX, 0.3f );
}
samples[WALKGRID_SIZE][WALKGRID_SIZE];
-#if 0
- u32 geo[256];
-#endif
-
boxf region;
float move; /* Current amount of movement we have left to apply */
boxf region = {{ s->pos[0] -0.01f, s->pos[1] - 4.0f, s->pos[2] -0.01f},
{ s->pos[0] +0.01f, s->pos[1] + 4.0f, s->pos[2] +0.01f}};
-#if 0
- vg_line( region[0],region[1], 0x20ffffff );
-#endif
-
u32 geo[256];
v3f tri[3];
int len = bh_select( &world.geo.bhtris, region, geo, 256 );
{
walk_height = p0[1];
}
-
-#if 0
- draw_cross( p0, 0xffffffff, 0.05f );
-#endif
}
else
{
if( p0[1] > block_height )
block_height = p0[1];
-#if 0
- draw_cross( p0, 0xff0000ff, 0.05f );
-#endif
}
}
}
s->type = k_sample_type_valid;
else
s->type = k_sample_type_air;
-
-#if 0
- if( s->type == k_sample_type_valid )
- {
- vg_line_pt3( s->pos, 0.01f, 0xff00ff00 );
- }
-#endif
-
-#if 0
- int count = 0;
-
- ray_hit hit;
- hit.dist = 10.0f;
- count = bvh_raycast( &world.geo, sample_pos, vdir, &hit );
-
- if( count )
- {
- v3_copy( hit.pos, s->pos );
-
- if( !player_walkgrid_tri_walkable( hit.tri ) )
- {
- draw_cross( pos, 0xff0000ff, 0.05f );
- return 0;
- }
- else
- {
- draw_cross( pos, 0xff00ff00, 0.05f );
- return count;
- }
- }
- else
- return 0;
-#endif
}
float const k_gridscale = 0.5f;
}
}
-static void player_walkgrid_clip( struct grid_sample *sa,
- struct grid_sample *sb,
- enum eclipdir dir )
-{
- int mintype = VG_MIN( sa->type, sb->type ),
- maxtype = VG_MAX( sa->type, sb->type );
-
- if( maxtype == k_sample_type_valid )
- {
- if( mintype == k_sample_type_air || mintype == k_sample_type_invalid )
- {
- player_walkgrid_clip_edge( sa, sb, sa, dir );
- }
-
-#if 0
- else if( mintype == k_sample_type_invalid )
- {
- player_walkgrid_clip_blocker( sa, sb, dir );
- }
-#endif
- }
-}
-
static const struct conf
{
struct confedge
* the intersections with the grid, and any edges that are present
*/
-#if 0
- if( wg->cell_id[0] < 0 || wg->cell_id[0] >= WALKGRID_SIZE-1 ||
- wg->cell_id[1] < 0 || wg->cell_id[1] >= WALKGRID_SIZE-1 )
- {
- /*
- * This condition should never be reached if the grid size is big
- * enough
- */
- wg->move = -1.0f;
- return;
- }
-#endif
-
u32 icolours[] = { 0xffff00ff, 0xff00ffff, 0xffffff00 };
v3f pa, pb, pc, pd, pl0, pl1;
pd[1] = pa[1];
pd[2] = pa[2];
#if 0
+ /* if you want to draw the current cell */
vg_line( pa, pb, 0xff00ffff );
vg_line( pb, pc, 0xff00ffff );
vg_line( pc, pd, 0xff00ffff );
v3_muladds( delta, side, -ktimestep*k_walkspeed, delta );
if( glfwGetKey( vg_window, GLFW_KEY_D ) )
v3_muladds( delta, side, ktimestep*k_walkspeed, delta );
+
+ v3_muladds( delta, fwd,
+ vg_get_axis("vertical")*-ktimestep*k_walkspeed, delta );
+ v3_muladds( delta, side,
+ vg_get_axis("horizontal")*ktimestep*k_walkspeed, delta );
}
/*
wg.cell_id[0] = region_cell_pos[0];
wg.cell_id[1] = region_cell_pos[1];
-
-#if 0
- /* Get surface samples
- *
- * TODO: Replace this with a spiral starting from the player position
- */
- for( int y=0; y<WALKGRID_SIZE; y++ )
- {
- for( int x=0; x<WALKGRID_SIZE; x++ )
- {
- struct grid_sample *s = &wg.samples[y][x];
- v3_muladds( wg.region[0], (v3f){ x, 0, y }, k_gridscale, s->pos );
- s->pos[1] = cell[1];
- player_walkgrid_samplepole( s );
- }
- }
-
- /*
- * Calculate h+v clipping distances.
- * Distances are stored in A always, so you know that if the sample is
- * invalid, this signifies the start of the manifold as opposed to the
- * extent or bounds of it.
- */
- for( int i=0; i<2; i++ )
- {
- for( int x=0; x<WALKGRID_SIZE; x++ )
- {
- for( int z=0; z<WALKGRID_SIZE-1; z++ )
- {
- struct grid_sample *sa, *sb;
- if( i == 1 )
- {
- sa = &wg.samples[z][x];
- sb = &wg.samples[z+1][x];
- }
- else
- {
- sa = &wg.samples[x][z];
- sb = &wg.samples[x][z+1];
- }
-
- player_walkgrid_clip( sa, sb, i );
-
- if( sa->type == k_sample_type_valid &&
- sb->type == k_sample_type_valid )
- vg_line( sa->pos, sb->pos, 0xffffffff );
-#if 0
- if( sa->valid != sb->valid )
- {
- clipdir[i*2] = (float)(sa->valid - sb->valid) * k_gridscale;
-
- player_walkgrid_clip( sa->valid? sa->pos: sb->pos,
- clipdir, sa->clip[i] );
- }
- else
- {
- if( sa->valid )
- {
- vg_line( sa->pos, sb->pos, 0xffffffff );
- }
- }
-#endif
- }
- }
- }
-#endif
-
for(int y=0; y<WALKGRID_SIZE; y++ )
{
for(int x=0; x<WALKGRID_SIZE; x++ )
break;
}
-#if 0
- player.co[0] += wg.dir[0];
- player.co[2] += wg.dir[1];
-#endif
-
-
-
/* Draw connections */
struct grid_sample *corners[4];
for( int x=0; x<WALKGRID_SIZE-1; x++ )
v3_muladds( head, offset, 0.7f, head );
head[1] = vg_clampf( head[1], 0.3f, kheight );
-#if 0
- if( !freecam )
- {
- v3_copy( head, player.view );
- v3f camoffs = {-0.2f,-0.6f,0.00f};
- v3_add( player.view, camoffs, player.view );
- }
-#endif
-
/*
* Animation blending
* ===========================================
if( vg_get_axis("grabl")>0.0f)
reset_player(0,NULL);
+ if( vg_get_button_down( "switchmode" ) )
+ {
+ player.on_board ^= 0x1;
+ }
+
if( freecam )
{
player_freecam();
{
if( player.is_dead )
{
+ /*
+ * Follow camera
+ */
character_ragdoll_iter( &player.mdl );
character_debug_ragdoll( &player.mdl );
+
+ v3f delta;
+ v3f head_pos;
+ v3_copy( player.mdl.ragdoll[k_chpart_head].co, head_pos );
+
+ v3_sub( head_pos, player.camera_pos, delta );
+ v3_normalize( delta );
+
+ v3f follow_pos;
+ v3_muladds( head_pos, delta, -2.5f, follow_pos );
+ v3_lerp( player.camera_pos, follow_pos, 0.1f, player.camera_pos );
+
+ /*
+ * Make sure the camera stays above the ground
+ */
+ v3f min_height = {0.0f,1.0f,0.0f};
+
+ v3f sample;
+ v3_add( player.camera_pos, min_height, sample );
+ ray_hit hit;
+ hit.dist = min_height[1]*2.0f;
+
+ if( ray_world( sample, (v3f){0.0f,-1.0f,0.0f}, &hit ))
+ v3_add( hit.pos, min_height, player.camera_pos );
+
+ player.camera_pos[1] =
+ vg_maxf( wrender.height + 2.0f, player.camera_pos[1] );
+
+ player.angles[0] = atan2f( delta[0], -delta[2] );
+ player.angles[1] = -asinf( delta[1] );
}
else
{
}
gpipeline;
+struct framebuffer
+{
+ GLuint fb, colour, rb;
+ int div;
+ GLuint format;
+};
+
static void render_water_texture( m4x3f camera );
-static void render_water_surface( m4x4f pv );
+static void render_water_surface( m4x4f pv, m4x3f camera );
static void render_world( m4x4f projection, m4x3f camera );
/*
nearz, farz );
}
-static void create_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb )
+static void fb_use( struct framebuffer *fb )
{
- glGenFramebuffers( 1, fb );
- glBindFramebuffer( GL_FRAMEBUFFER, *fb );
+ if( !fb )
+ {
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glViewport( 0, 0, vg_window_x, vg_window_y );
+ }
+ else
+ {
+ glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
+ glViewport( 0, 0, vg_window_x / fb->div, vg_window_y / fb->div );
+ }
+}
- glGenTextures( 1, rgb );
- glBindTexture( GL_TEXTURE_2D, *rgb );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y,
- 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+static void fb_init( struct framebuffer *fb )
+{
+ i32 ix = vg_window_x / fb->div,
+ iy = vg_window_y / fb->div;
+
+ glGenFramebuffers( 1, &fb->fb );
+ glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
+
+ glGenTextures( 1, &fb->colour );
+ glBindTexture( GL_TEXTURE_2D, fb->colour );
+ glTexImage2D( GL_TEXTURE_2D, 0, fb->format, ix, iy,
+ 0, fb->format, GL_UNSIGNED_BYTE, NULL);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, *rgb, 0);
+ GL_TEXTURE_2D, fb->colour, 0);
- /* TODO: Check for DEPTH32f availiblity and use if possible */
-
- glGenRenderbuffers( 1, rb );
- glBindRenderbuffer( GL_RENDERBUFFER, *rb );
- glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
- vg_window_x, vg_window_y );
+ glGenRenderbuffers( 1, &fb->rb );
+ glBindRenderbuffer( GL_RENDERBUFFER, fb->rb );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, *rb );
+ GL_RENDERBUFFER, fb->rb );
}
-static void resize_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb )
+static void fb_bindtex( struct framebuffer *fb, int texture )
{
- glBindTexture( GL_TEXTURE_2D, *rgb );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, 0,
- GL_RGB, GL_UNSIGNED_BYTE, NULL );
+ glActiveTexture( GL_TEXTURE0 + texture );
+ glBindTexture( GL_TEXTURE_2D, fb->colour );
+}
+
+static void fb_resize( struct framebuffer *fb )
+{
+ i32 ix = vg_window_x / fb->div,
+ iy = vg_window_y / fb->div;
+
+ glBindTexture( GL_TEXTURE_2D, fb->colour );
+ glTexImage2D( GL_TEXTURE_2D, 0, fb->format, ix, iy, 0,
+ fb->format, GL_UNSIGNED_BYTE, NULL );
- glBindRenderbuffer( GL_RENDERBUFFER, *rb );
- glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
- vg_window_x, vg_window_y );
+ glBindRenderbuffer( GL_RENDERBUFFER, fb->rb );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy );
}
static void render_fb_resize(void)
*/
#include "common.h"
+#include "bvh.h"
+
static void rb_tangent_basis( v3f n, v3f tx, v3f ty );
+static bh_system bh_system_rigidbodies;
#ifndef RIGIDBODY_H
#define RIGIDBODY_H
-#include "bvh.h"
-
#define RB_DEPR
-
#define k_rb_delta (1.0f/60.0f)
typedef struct rigidbody rigidbody;
}
-
RB_DEPR
static void rb_constraint_angle( rigidbody *rba, v3f va,
rigidbody *rbb, v3f vb,
v3_add( impulse, ra->I, ra->I );
#if 0
+ /*
+ * this could be used for spring joints
+ * its not good for position constraint
+ */
v3f impulse;
v3_muls( delta, 0.5f*spring, impulse );
#include "bvh.h"
typedef struct scene scene;
-#if 0
-typedef struct bvh_node bvh_node;
-#endif
struct scene
{
model_vert *verts;
u32 *indices;
-#if 0
- struct
- {
- bvh_node *nodes;
- u32 node_count;
- }
- bvh;
-#else
bh_tree bhtris;
-#endif
-
u32 vertex_count,
indice_count,
vertex_cap,
void main()
{
float fintensity = 1.0-(abs(aNorm.y)*0.7);
- float angle = -dot(vec3(0.95,0.0,-0.3),aNorm)*0.5+0.5;
- float fblend = pow(fintensity,6.0) * angle;
- vec3 horizon = vec3(0.9,0.9,0.8);
- vec3 skycolour = vec3(0.4,0.5,0.8);
+ float fblend = pow(fintensity,6.0);
+ vec3 horizon = vec3( 0.61, 0.71, 0.86 )*1.5;
+ vec3 skycolour = vec3( 0.31, 0.56, 0.91 );
vec3 diffuse = mix( skycolour, horizon, fblend );
- float fmove = uTime * 0.001;
+ float fmove = uTime * 0.004;
vec2 cloudplane = (aCo.xz / (aCo.y*sign(aNorm.y))) * 0.03;
vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 );
vec4 clouds2 = texture( uTexGarbage, cloudplane + vec2(0.3,0.1)*fmove );
float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0);
- float cloud_e = pow(cloud_d,1.8)*pow(abs(aNorm.y),0.3)*2.0;
+ float cloud_e = pow(cloud_d,1.5)*pow(abs(aNorm.y),0.3)*2.0;
vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );
float fhorizon = step( aNorm.y * 0.5 + 0.5, 0.5 );
- vec3 skycomp = mix(diffuse, vec3(1.0), cloud_e);
+ vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e);
skycomp = mix(mix(pow(colour_ocean,vec3(6.0))*0.6,skycomp, 0.7),skycomp,fhorizon);
- FragColor = vec4(skycomp, 1.0);
+ FragColor = vec4(skycomp, 0.0);
}
"void main()\n"
"{\n"
" float fintensity = 1.0-(abs(aNorm.y)*0.7);\n"
-" float angle = -dot(vec3(0.95,0.0,-0.3),aNorm)*0.5+0.5;\n"
-" float fblend = pow(fintensity,6.0) * angle;\n"
-" vec3 horizon = vec3(0.9,0.9,0.8);\n"
-" vec3 skycolour = vec3(0.4,0.5,0.8);\n"
+" float fblend = pow(fintensity,6.0);\n"
+" vec3 horizon = vec3( 0.61, 0.71, 0.86 )*1.5;\n"
+" vec3 skycolour = vec3( 0.31, 0.56, 0.91 );\n"
" vec3 diffuse = mix( skycolour, horizon, fblend );\n"
"\n"
-" float fmove = uTime * 0.001;\n"
+" float fmove = uTime * 0.004;\n"
" vec2 cloudplane = (aCo.xz / (aCo.y*sign(aNorm.y))) * 0.03;\n"
" vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 );\n"
" vec4 clouds2 = texture( uTexGarbage, cloudplane + vec2(0.3,0.1)*fmove );\n"
"\n"
" float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0);\n"
-" float cloud_e = pow(cloud_d,1.8)*pow(abs(aNorm.y),0.3)*2.0;\n"
+" float cloud_e = pow(cloud_d,1.5)*pow(abs(aNorm.y),0.3)*2.0;\n"
"\n"
" vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );\n"
" float fhorizon = step( aNorm.y * 0.5 + 0.5, 0.5 );\n"
"\n"
-" vec3 skycomp = mix(diffuse, vec3(1.0), cloud_e);\n"
+" vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e);\n"
" skycomp = mix(mix(pow(colour_ocean,vec3(6.0))*0.6,skycomp, 0.7),skycomp,fhorizon);\n"
"\n"
-" FragColor = vec4(skycomp, 1.0);\n"
+" FragColor = vec4(skycomp, 0.0);\n"
"}\n"
""},
};
uniform sampler2D uTexGarbage;
uniform sampler2D uTexGradients;
uniform vec3 uCamera;
+uniform vec4 uPlane;
in vec4 aColour;
in vec2 aUv;
in vec3 aNorm;
in vec3 aCo;
+float water_depth( vec3 pos, vec3 dir, vec4 plane )
+{
+ float d = dot( plane.xyz, dir );
+ float t = dot((plane.xyz*plane.w - pos),plane.xyz) / d;
+ return t*0.05;
+}
+
void main()
{
vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );
+
+ // Creating normal patches
vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;
- vec3 qnorm = floor(aNorm*4.0+modnorm) * 0.25;
-
+ vec3 qnorm = normalize(floor(aNorm*4.0+modnorm) * 0.25);
vec2 dir = normalize(qnorm.xz);
vec2 uvdiffuse = aCo.xz * 0.02;
uvdiffuse = mat2(dir.y, dir.x, -dir.x, dir.y) * uvdiffuse;
-
+
+ // Patch local noise
vec4 rgarbage = texture( uTexGarbage, uvdiffuse );
+
+ // Colour blending
float amtgrass = step(qnorm.y,0.6);
+ float amtsand = min(max((aCo.y + 90.0) * -0.08,0.0)*qnorm.y,1.0);
vec2 uvgradients = vec2( rgarbage.a, -amtgrass*0.125 ) + aUv;
vec3 diffuse = texture( uTexGradients, uvgradients ).rgb;
-
+ diffuse = mix( diffuse, vec3(1.0,0.9,0.7), amtsand );
+
+ // Lighting
vec3 lightdir = vec3(0.95,0.0,-0.3);
vec3 shadow = pow(vec3(0.014,0.034,0.084),vec3(1.0/3.2));
- float light1 = 1.0-(dot( lightdir, qnorm )*0.5+0.5);
+ float light1 = dot( lightdir, mix(qnorm,aNorm,amtsand) )*0.5+0.5;
+ diffuse = diffuse * (light1*vec3(1.0,0.96,0.9)*1.2 + shadow*(1.0-light1));
- qnorm = floor(aNorm*8.0)*0.125;
- vec3 viewdelta = normalize( uCamera - aCo );
+ // Specular lighting
+ vec3 halfview = normalize( uCamera - aCo );
vec3 specdir = reflect( -lightdir, qnorm );
- float spec = pow(max(dot(viewdelta,specdir),0.0),10.0) * 0.2*rgarbage.r;
-
- diffuse = diffuse*(1.0-light1)+diffuse*shadow*light1;
- FragColor = vec4(diffuse+spec, 1.0);
+ float spec = pow(max(dot(halfview,specdir),0.0),10.0) * 0.2*rgarbage.r;
+ diffuse += spec * vec3(1.0,0.8,0.8);
+
+ FragColor = vec4(diffuse, water_depth(aCo,halfview,uPlane));
}
"uniform sampler2D uTexGarbage;\n"
"uniform sampler2D uTexGradients;\n"
"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
"\n"
"in vec4 aColour;\n"
"in vec2 aUv;\n"
"in vec3 aNorm;\n"
"in vec3 aCo;\n"
"\n"
+"float water_depth( vec3 pos, vec3 dir, vec4 plane )\n"
+"{\n"
+" float d = dot( plane.xyz, dir );\n"
+" float t = dot((plane.xyz*plane.w - pos),plane.xyz) / d;\n"
+" return t*0.05;\n"
+"}\n"
+"\n"
"void main()\n"
"{\n"
" vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );\n"
+" \n"
+" // Creating normal patches\n"
" vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n"
-" vec3 qnorm = floor(aNorm*4.0+modnorm) * 0.25;\n"
-"\n"
+" vec3 qnorm = normalize(floor(aNorm*4.0+modnorm) * 0.25);\n"
" vec2 dir = normalize(qnorm.xz);\n"
" vec2 uvdiffuse = aCo.xz * 0.02;\n"
" uvdiffuse = mat2(dir.y, dir.x, -dir.x, dir.y) * uvdiffuse;\n"
-"\n"
+" \n"
+" // Patch local noise\n"
" vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n"
+"\n"
+" // Colour blending\n"
" float amtgrass = step(qnorm.y,0.6);\n"
+" float amtsand = min(max((aCo.y + 90.0) * -0.08,0.0)*qnorm.y,1.0);\n"
" vec2 uvgradients = vec2( rgarbage.a, -amtgrass*0.125 ) + aUv;\n"
" vec3 diffuse = texture( uTexGradients, uvgradients ).rgb;\n"
-" \n"
+" diffuse = mix( diffuse, vec3(1.0,0.9,0.7), amtsand );\n"
+"\n"
+" // Lighting\n"
" vec3 lightdir = vec3(0.95,0.0,-0.3);\n"
" vec3 shadow = pow(vec3(0.014,0.034,0.084),vec3(1.0/3.2));\n"
-" float light1 = 1.0-(dot( lightdir, qnorm )*0.5+0.5);\n"
+" float light1 = dot( lightdir, mix(qnorm,aNorm,amtsand) )*0.5+0.5;\n"
+" diffuse = diffuse * (light1*vec3(1.0,0.96,0.9)*1.2 + shadow*(1.0-light1));\n"
" \n"
-" qnorm = floor(aNorm*8.0)*0.125;\n"
-" vec3 viewdelta = normalize( uCamera - aCo );\n"
+" // Specular lighting\n"
+" vec3 halfview = normalize( uCamera - aCo );\n"
" vec3 specdir = reflect( -lightdir, qnorm );\n"
-" float spec = pow(max(dot(viewdelta,specdir),0.0),10.0) * 0.2*rgarbage.r;\n"
-" \n"
-" diffuse = diffuse*(1.0-light1)+diffuse*shadow*light1;\n"
-" FragColor = vec4(diffuse+spec, 1.0);\n"
+" float spec = pow(max(dot(halfview,specdir),0.0),10.0) * 0.2*rgarbage.r;\n"
+" diffuse += spec * vec3(1.0,0.8,0.8);\n"
+"\n"
+" FragColor = vec4(diffuse, water_depth(aCo,halfview,uPlane));\n"
"}\n"
""},
};
static GLuint _uniform_terrain_uTexGarbage;
static GLuint _uniform_terrain_uTexGradients;
static GLuint _uniform_terrain_uCamera;
+static GLuint _uniform_terrain_uPlane;
static void shader_terrain_uPv(m4x4f m){
glUniformMatrix4fv( _uniform_terrain_uPv, 1, GL_FALSE, (float *)m );
}
static void shader_terrain_uCamera(v3f v){
glUniform3fv( _uniform_terrain_uCamera, 1, v );
}
+static void shader_terrain_uPlane(v4f v){
+ glUniform4fv( _uniform_terrain_uPlane, 1, v );
+}
static void shader_terrain_register(void){
vg_shader_register( &_shader_terrain );
}
_uniform_terrain_uTexGarbage = glGetUniformLocation( _shader_terrain.id, "uTexGarbage" );
_uniform_terrain_uTexGradients = glGetUniformLocation( _shader_terrain.id, "uTexGradients" );
_uniform_terrain_uCamera = glGetUniformLocation( _shader_terrain.id, "uCamera" );
+ _uniform_terrain_uPlane = glGetUniformLocation( _shader_terrain.id, "uPlane" );
}
#endif /* SHADER_terrain_H */
uniform sampler2D uTexMain;
uniform sampler2D uTexDudv;
uniform sampler2D uTexDepth;
+uniform sampler2D uTexBack;
+
uniform vec2 uInvRes;
uniform float uTime;
+uniform vec3 uCamera;
+uniform float uSurfaceY;
+
in vec4 aUv;
in vec3 aCo;
+in float aDepth;
void main()
{
+ // Reflected and warped texture
vec2 ssuv = gl_FragCoord.xy*uInvRes;
- vec4 dudva = texture( uTexDudv, aUv.xy + vec2(uTime*0.04f,uTime*0.03f) );
- vec4 dudvb = texture( uTexDudv, aUv.xy - vec2(uTime*0.1,uTime*0.054) );
- vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 2.0;
+ vec4 dudva = texture( uTexDudv, aUv.xy - vec2(uTime*0.004f,uTime*0.003f) );
+ vec4 dudvb = texture( uTexDudv, aUv.xy*0.7 - vec2(uTime*0.01,uTime*0.0054) );
+ vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 0.6;
vec4 reflected = texture( uTexMain, ssuv+distortamt );
+
+ // Surface colour composite
float depthvalue = texture( uTexDepth, aUv.zw ).r;
- float opacity = smoothstep( 0.0, 0.1, depthvalue );
- vec3 colour_shore = vec3( 0.96, 0.98, 0.9 );
- vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );
- vec3 surface_tint = mix( colour_shore, colour_ocean, depthvalue );
+ vec3 colour_shore = vec3( 0.21, 0.6, 0.8 );
+ vec3 colour_ocean = vec3( 0.01, 0.1, 0.2 );
+ vec3 surface_tint = mix(colour_shore, colour_ocean, pow(depthvalue,1.8))*1.5;
+
+ // Foam
+ float fband = fract( aCo.z*0.1+uTime*0.1-depthvalue*10.0 );
+ fband = step( fband+dudvb.g*0.8, 0.5 ) * max((1.0-depthvalue*4.0),0.0);
- vec3 comp_surf = mix(pow(surface_tint,vec3(6.0))*0.6,reflected.rgb, 0.7);
+ // Lighting
+ vec3 surfnorm = vec3(distortamt.x,1.0,distortamt.y);
- float band = fract( aCo.z*0.1+uTime*0.1-depthvalue*10.0 );
- band = step( band + dudvb.g*0.8, 0.5 ) * max((1.0-depthvalue*4.0),0.0);
+ vec3 halfview = -normalize( aCo-uCamera );
+ float ffresnel = pow(1.0-dot( surfnorm, halfview ),5.0);
- FragColor = vec4(comp_surf + band*0.2,opacity+band*0.2);
+ vec3 lightdir = vec3(0.95,0.0,-0.3);
+ vec3 specdir = reflect( -lightdir, surfnorm );
+ float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3;
+
+ // Depth
+ vec4 backsample = texture( uTexBack, ssuv+distortamt*0.1 );
+ float depthblend = pow(backsample.a,0.8);
+
+ // Composite
+ vec3 vsurface = mix(surface_tint*backsample.rgb, reflected.rgb, ffresnel );
+ vsurface += spec;
+
+ FragColor = mix( vec4(vsurface,depthblend), vec4(1.0,1.0,1.0,0.8), fband );
}
"\n"
"out vec4 aUv;\n"
"out vec3 aCo;\n"
+"out float aDepth;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = uPv * vec4(world_pos,1.0);\n"
"\n"
" vec2 depth_coords = (world_pos.xz-uDepthBounds.xy)*uDepthBounds.zw;\n"
-" aUv = vec4(world_pos.xz*0.1,depth_coords);\n"
+" aUv = vec4(world_pos.xz*0.01,depth_coords);\n"
" aCo = world_pos;\n"
+"\n"
+" aDepth = gl_Position.z;\n"
"}\n"
""},
.fs =
"uniform sampler2D uTexMain;\n"
"uniform sampler2D uTexDudv;\n"
"uniform sampler2D uTexDepth;\n"
+"uniform sampler2D uTexBack;\n"
+"\n"
"uniform vec2 uInvRes;\n"
"uniform float uTime;\n"
"\n"
+"uniform vec3 uCamera;\n"
+"uniform float uSurfaceY;\n"
+"\n"
"in vec4 aUv;\n"
"in vec3 aCo;\n"
+"in float aDepth;\n"
"\n"
"void main()\n"
"{\n"
+" // Reflected and warped texture\n"
" vec2 ssuv = gl_FragCoord.xy*uInvRes;\n"
-" vec4 dudva = texture( uTexDudv, aUv.xy + vec2(uTime*0.04f,uTime*0.03f) );\n"
-" vec4 dudvb = texture( uTexDudv, aUv.xy - vec2(uTime*0.1,uTime*0.054) );\n"
"\n"
-" vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 2.0;\n"
+" vec4 dudva = texture( uTexDudv, aUv.xy - vec2(uTime*0.004f,uTime*0.003f) );\n"
+" vec4 dudvb = texture( uTexDudv, aUv.xy*0.7 - vec2(uTime*0.01,uTime*0.0054) );\n"
+" vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 0.6;\n"
"\n"
" vec4 reflected = texture( uTexMain, ssuv+distortamt );\n"
+" \n"
+" // Surface colour composite\n"
" float depthvalue = texture( uTexDepth, aUv.zw ).r;\n"
-" float opacity = smoothstep( 0.0, 0.1, depthvalue );\n"
"\n"
-" vec3 colour_shore = vec3( 0.96, 0.98, 0.9 );\n"
-" vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );\n"
-" vec3 surface_tint = mix( colour_shore, colour_ocean, depthvalue );\n"
+" vec3 colour_shore = vec3( 0.21, 0.6, 0.8 );\n"
+" vec3 colour_ocean = vec3( 0.01, 0.1, 0.2 );\n"
+" vec3 surface_tint = mix(colour_shore, colour_ocean, pow(depthvalue,1.8))*1.5;\n"
+" \n"
+" // Foam\n"
+" float fband = fract( aCo.z*0.1+uTime*0.1-depthvalue*10.0 );\n"
+" fband = step( fband+dudvb.g*0.8, 0.5 ) * max((1.0-depthvalue*4.0),0.0);\n"
"\n"
-" vec3 comp_surf = mix(pow(surface_tint,vec3(6.0))*0.6,reflected.rgb, 0.7);\n"
+" // Lighting\n"
+" vec3 surfnorm = vec3(distortamt.x,1.0,distortamt.y);\n"
" \n"
-" float band = fract( aCo.z*0.1+uTime*0.1-depthvalue*10.0 );\n"
-" band = step( band + dudvb.g*0.8, 0.5 ) * max((1.0-depthvalue*4.0),0.0);\n"
+" vec3 halfview = -normalize( aCo-uCamera );\n"
+" float ffresnel = pow(1.0-dot( surfnorm, halfview ),5.0);\n"
"\n"
-" FragColor = vec4(comp_surf + band*0.2,opacity+band*0.2);\n"
+" vec3 lightdir = vec3(0.95,0.0,-0.3);\n"
+" vec3 specdir = reflect( -lightdir, surfnorm );\n"
+" float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3;\n"
+" \n"
+" // Depth \n"
+" vec4 backsample = texture( uTexBack, ssuv+distortamt*0.1 );\n"
+" float depthblend = pow(backsample.a,0.8);\n"
+"\n"
+" // Composite\n"
+" vec3 vsurface = mix(surface_tint*backsample.rgb, reflected.rgb, ffresnel );\n"
+" vsurface += spec;\n"
+" \n"
+" FragColor = mix( vec4(vsurface,depthblend), vec4(1.0,1.0,1.0,0.8), fband );\n"
"}\n"
""},
};
static GLuint _uniform_water_uTexMain;
static GLuint _uniform_water_uTexDudv;
static GLuint _uniform_water_uTexDepth;
+static GLuint _uniform_water_uTexBack;
static GLuint _uniform_water_uInvRes;
static GLuint _uniform_water_uTime;
+static GLuint _uniform_water_uCamera;
+static GLuint _uniform_water_uSurfaceY;
static void shader_water_uPv(m4x4f m){
glUniformMatrix4fv( _uniform_water_uPv, 1, GL_FALSE, (float *)m );
}
static void shader_water_uTexDepth(int i){
glUniform1i( _uniform_water_uTexDepth, i );
}
+static void shader_water_uTexBack(int i){
+ glUniform1i( _uniform_water_uTexBack, i );
+}
static void shader_water_uInvRes(v2f v){
glUniform2fv( _uniform_water_uInvRes, 1, v );
}
static void shader_water_uTime(float f){
glUniform1f( _uniform_water_uTime, f );
}
+static void shader_water_uCamera(v3f v){
+ glUniform3fv( _uniform_water_uCamera, 1, v );
+}
+static void shader_water_uSurfaceY(float f){
+ glUniform1f( _uniform_water_uSurfaceY, f );
+}
static void shader_water_register(void){
vg_shader_register( &_shader_water );
}
_uniform_water_uTexMain = glGetUniformLocation( _shader_water.id, "uTexMain" );
_uniform_water_uTexDudv = glGetUniformLocation( _shader_water.id, "uTexDudv" );
_uniform_water_uTexDepth = glGetUniformLocation( _shader_water.id, "uTexDepth" );
+ _uniform_water_uTexBack = glGetUniformLocation( _shader_water.id, "uTexBack" );
_uniform_water_uInvRes = glGetUniformLocation( _shader_water.id, "uInvRes" );
_uniform_water_uTime = glGetUniformLocation( _shader_water.id, "uTime" );
+ _uniform_water_uCamera = glGetUniformLocation( _shader_water.id, "uCamera" );
+ _uniform_water_uSurfaceY = glGetUniformLocation( _shader_water.id, "uSurfaceY" );
}
#endif /* SHADER_water_H */
out vec4 aUv;
out vec3 aCo;
+out float aDepth;
void main()
{
gl_Position = uPv * vec4(world_pos,1.0);
vec2 depth_coords = (world_pos.xz-uDepthBounds.xy)*uDepthBounds.zw;
- aUv = vec4(world_pos.xz*0.1,depth_coords);
+ aUv = vec4(world_pos.xz*0.01,depth_coords);
aCo = world_pos;
+
+ aDepth = gl_Position.z;
}
+#include "common.h"
+
+static void render_terrain(m4x4f projection, v3f camera);
+static void render_sky(m4x3f camera);
+
#ifndef TERRAIN_H
#define TERRAIN_H
-#define VG_3D
-#include "vg/vg.h"
#include "model.h"
#include "render.h"
+#include "water.h"
#include "shaders/terrain.h"
#include "shaders/sky.h"
shader_terrain_uPv( projection );
shader_terrain_uMdl( identity_matrix );
shader_terrain_uCamera( camera );
+ shader_terrain_uPlane( (v4f){ 0.0f,1.0f,0.0f, wrender.height } );
}
static void render_sky(m4x3f camera)
static struct button_binding vg_controller_binds[] =
{
{ "push", GLFW_GAMEPAD_BUTTON_A },
- { "break", GLFW_GAMEPAD_BUTTON_B }
+ { "break", GLFW_GAMEPAD_BUTTON_B },
+ { "switchmode", GLFW_GAMEPAD_BUTTON_Y }
};
static struct axis_binding vg_axis_binds[] =
+#include "common.h"
+#include "model.h"
+
+static void water_register(void);
+static void water_init(void);
+static void water_fb_resize(void);
+static void water_compute_depth( boxf bounds );
+static void water_set_surface( glmesh *surf, float height );
+static float water_height(void);
+
#ifndef WATER_H
#define WATER_H
-#define VG_3D
-#include "vg/vg.h"
-
-#include "model.h"
+#include "world.h"
#include "render.h"
#include "shaders/water.h"
#include "scene.h"
static struct
{
- GLuint fb, rgb, rb;
+ struct framebuffer fbreflect, fbdepth;
glmesh mdl;
GLuint depthmap;
float height;
int enabled;
}
-wrender;
+wrender =
+{
+ .fbreflect = { .format = GL_RGB, .div = 2 },
+ .fbdepth = { .format = GL_RGBA, .div = 2 }
+};
+
+static float water_height(void)
+{
+ return wrender.height;
+}
static void water_register(void)
{
static void water_init(void)
{
/* TODO: probably dont do this every time */
- create_renderbuffer_std( &wrender.fb, &wrender.rgb, &wrender.rb );
wrender.enabled = 1;
+
+ fb_init( &wrender.fbreflect );
+ fb_init( &wrender.fbdepth );
+}
+
+static void water_fb_resize(void)
+{
+ if( !wrender.enabled )
+ return;
+
+ fb_resize( &wrender.fbreflect );
+ fb_resize( &wrender.fbdepth );
}
-static int ray_world( v3f pos, v3f dir, ray_hit *hit );
static void water_compute_depth( boxf bounds )
{
if( !wrender.enabled )
wrender.height = height;
}
-static void water_fb_resize(void)
-{
- if( !wrender.enabled )
- return;
-
- resize_renderbuffer_std( &wrender.fb, &wrender.rgb, &wrender.rb );
-}
-
static void render_water_texture( m4x3f camera )
{
if( !wrender.enabled )
return;
/* Draw reflection buffa */
- glBindFramebuffer( GL_FRAMEBUFFER, wrender.fb );
- glClearColor( 0.11f, 0.35f, 0.37f, 1.0f );
+ fb_use( &wrender.fbreflect );
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
m4x3f new_cam, inverse;
glCullFace( GL_FRONT );
render_world( projection, new_cam );
glCullFace( GL_BACK );
+
+
+ /* Draw beneath texture */
+ fb_use( &wrender.fbdepth );
+ glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+
+ m4x3_invert_affine( camera, inverse );
+ m4x3_expand( inverse, view );
+
+ v4f clippb = { 0.0f, -1.0f, 0.0f, -(wrender.height) };
+ m4x3_mulp( inverse, clippb, clippb );
+ clippb[3] *= -1.0f;
+
+ float depth_loss = camera[3][1]-wrender.height;
+
+ m4x4_projection( projection,
+ gpipeline.fov,
+ (float)vg_window_x / (float)vg_window_y,
+ 0.1f, 900.0f );
+
+ plane_clip_projection( projection, clippb );
+ m4x4_mul( projection, view, projection );
+ render_world( projection, camera );
+
+ glViewport( 0, 0, vg_window_x, vg_window_y );
}
-static void render_water_surface( m4x4f pv )
+static void render_water_surface( m4x4f pv, m4x3f camera )
{
if( !wrender.enabled )
return;
/* Draw surface */
shader_water_use();
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, wrender.rgb );
+ fb_bindtex( &wrender.fbreflect, 0 );
shader_water_uTexMain( 0 );
vg_tex2d_bind( &tex_water_surf, 1 );
1.0f/ (wrender.depthbounds[1][0]-wrender.depthbounds[0][0]),
1.0f/ (wrender.depthbounds[1][2]-wrender.depthbounds[0][2])} );
+ fb_bindtex( &wrender.fbdepth, 3 );
+ shader_water_uTexBack( 3 );
+
shader_water_uTime( vg_time );
+ shader_water_uCamera( camera[3] );
+ shader_water_uSurfaceY( wrender.height );
+
shader_water_uPv( pv );
m4x3f full;
+#include "common.h"
+
+static int ray_world( v3f pos, v3f dir, ray_hit *hit );
+
#ifndef WORLD_H
#define WORLD_H
-#define VG_3D
-#include "vg/vg.h"
-
#include "scene.h"
#include "terrain.h"
#include "render.h"
v3f tutorial;
-#if 0
- rigidbody box;
-#endif
-
teleport_gate gates[16];
u32 gate_count;
return hit->tri[0] < world.sm_road.vertex_count;
}
-static bh_system bh_system_rigidbodies;
static void world_load(void)
{
/* Setup scene */
if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
{
if( hit.normal[1] > 0.8f && !ray_hit_is_ramp(&hit) &&
- hit.pos[1] > wrender.height )
+ hit.pos[1] > water_height()+10.0f )
{
v4f qsurface, qrandom;
v3f axis;
v3_copy( hit.pos, transform[3] );
- if( vg_randf() < 0.00000006f )
+ if( vg_randf() < 0.0006f )
{
m3x3_identity( transform );
scene_add_foliage( &world.foliage, mfoliage, sm_tree, transform);