rb_debug( &ch->ragdoll[k_chpart_foot_r], 0xff00a5ff );
}
-static void character_ragdoll_iter( struct character *ch, scene *sc )
+static void character_ragdoll_iter( struct character *ch )
{
for( int i=0; i<PART_COUNT; i++ )
- {
- rb_build_manifold( &ch->ragdoll[i], sc );
- }
+ rb_build_manifold( &ch->ragdoll[i] );
v3f rv;
free( mgate );
}
-static void gate_fb_resize( void (*resize)(GLuint*,GLuint*,GLuint*) )
+static void gate_fb_resize(void)
{
- resize( &grender.fb, &grender.rgb, &grender.rb );
+ resize_renderbuffer_std( &grender.fb, &grender.rgb, &grender.rb );
}
static void render_gate( teleport_gate *gate, m4x3f camera )
surface[3] = v3_dot( surface, gate->other->co );
m4x4f projection;
- m4x4_projection( projection,
- gpipeline.fov,
- (float)vg_window_x / (float)vg_window_y,
- 0.1f, 900.0f );
+ pipeline_projection( projection, 0.1f, 900.0f );
#if 0 /* For debugging frustum */
{
m4x4_mul( projection, view, projection );
- render_world( projection );
+ render_world( projection, cam_new );
render_water_texture( cam_new );
glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
render_water_surface( projection );
#include "road.h"
#include "scene.h"
#include "ik.h"
-#include "character.h"
#include "terrain.h"
+#include "character.h"
#include "ragdoll.h"
#include "rigidbody.h"
#include "render.h"
#include "gate.h"
#include "water.h"
+#include "world.h"
#include "shaders/blit.h"
#include "shaders/standard.h"
}
player;
-static struct gworld
-{
- scene geo;
- submodel sm_road, sm_terrain;
- glmesh skybox;
-
- v3f tutorial;
-}
-world;
static struct grender
{
}
render;
+#if 0
rigidbody mr_box = {
.bbx = {{ -1.0f, -0.25f, -0.25f }, { 1.0f, 0.25f, 0.25f }}
};
.co = { -8.0f, -3.0f, -17.0f },
.q = { 0.0f, 0.0f, 0.0f, 1.0f }
};
+#endif
static void player_transform_update(void)
{
return 1;
}
-static void create_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb )
-{
- glGenFramebuffers( 1, fb );
- glBindFramebuffer( GL_FRAMEBUFFER, *fb );
-
- 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);
-
- 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);
-
- /* 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 );
-
- glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, *rb );
-}
-
-static void resize_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb )
-{
- 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 );
-
- glBindRenderbuffer( GL_RENDERBUFFER, *rb );
- glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
- vg_window_x, vg_window_y );
-}
void vg_start(void)
{
vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
+#if 0
rb_init( &mr_box );
rb_init( &mrs_box );
mrs_box.co[2] += 2.0f;
+#endif
vg_convar_push( (struct vg_convar){
.name = "frame",
character_load( &player.mdl, "ch_default" );
character_init_ragdoll( &player.mdl );
- /* Setup scene */
- scene_init( &world.geo );
- model *mworld = vg_asset_read( "models/mp_dev.mdl" );
-
- scene_add_model( &world.geo, mworld, submodel_get( mworld, "mp_dev" ),
- (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
- scene_copy_slice( &world.geo, &world.sm_road );
-
- scene_add_model( &world.geo, mworld, submodel_get( mworld, "terrain" ),
- (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
- scene_copy_slice( &world.geo, &world.sm_terrain );
-
- v3_copy( model_marker_get( mworld, "mp_dev_tutorial" )->co, world.tutorial );
-
-
- /* GATE DEV */
- {
- model_marker *ga = model_marker_get(mworld,"gate_a"),
- *gb = model_marker_get(mworld,"gate_a_recv");
-
- v3_copy( ga->co, gate_a.co );
- v3_copy( gb->co, gate_b.co );
- v4_copy( ga->q, gate_a.q );
- v4_copy( gb->q, gate_b.q );
- v2_copy( ga->s, gate_a.dims );
- v2_copy( gb->s, gate_b.dims );
-
- gate_a.other = &gate_b;
- gate_b.other = &gate_a;
-
- gate_transform_update( &gate_a );
- gate_transform_update( &gate_b );
- }
-
- /* WATER DEV */
- {
- glmesh surf;
- submodel *sm = submodel_get(mworld,"mp_dev_water");
- model_unpack_submodel( mworld, &surf, sm );
-
- water_init( create_renderbuffer_std );
- water_set_surface( &surf, sm->pivot[1] );
- }
- {
- model *msky = vg_asset_read("models/rs_skydome.mdl");
- model_unpack( msky, &world.skybox );
- free(msky);
- }
-
- free( mworld );
- scene_upload( &world.geo );
- bvh_create( &world.geo );
+ world_init_default();
reset_player( 1, (const char *[]){ "tutorial" } );
player_transform_update();
render.rgb_background, 0);
gate_init( create_renderbuffer_std );
+ terrain_init();
{
float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
m4x3_mulv( cam_rot, lookdir, lookdir );
m4x3_mulv( cam_rot, sidedir, sidedir );
- float movespeed = 5.0f;
+ float movespeed = 15.0f;
static v2f mouse_last,
view_vel = { 0.0f, 0.0f };
v3_muladds( vel, gravity, timestep, vel );
}
-static int ray_hit_is_ramp( ray_hit *hit )
-{
- return hit->tri[0] < world.sm_road.vertex_count;
-}
-
static void player_start_air(void)
{
player.in_air = 1;
contact.dist = v3_length( vdir );
v3_divs( vdir, contact.dist, vdir);
- if( bvh_raycast( &world.geo, pco1, vdir, &contact ))
+ if( ray_world( pco1, vdir, &contact ))
{
float land_delta = v3_dot( pv, contact.normal );
u32 scolour = (u8)(vg_minf(-land_delta * 2.0f, 255.0f));
{
v3f ground;
v3_copy( pos, ground );
+ ground[1] += 4.0f;
ray_hit hit;
- if( bvh_scene_sample( &world.geo, ground, &hit ) )
+ hit.dist = INFINITY;
+
+ if( ray_world( ground, (v3f){0.0f,-1.0f,0.0f}, &hit ))
{
v3f angle;
v3_copy( player.v, angle );
if( resistance < 0.25f )
{
- v3_copy( ground, pos );
+ v3_copy( hit.pos, pos );
return 1;
}
}
v3f ground_pos;
v3_copy( player.co, ground_pos );
+ ground_pos[1] += 4.0f;
ray_hit hit;
- if( bvh_scene_sample( &world.geo, ground_pos, &hit ) )
+ hit.dist = INFINITY;
+ if( ray_world( ground_pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
{
- if( ground_pos[1] > player.co[1] )
+ if( hit.pos[1] > player.co[1] )
{
player.in_air = 0;
v3_divs( vdir, contact.dist, vdir);
float orig_dist = contact.dist;
- if( bvh_raycast( &world.geo, pco1, vdir, &contact ))
+ if( ray_world( pco1, vdir, &contact ))
{
v3f localup;
m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, localup );
player.iY = 0.0f; /* temp */
+#if 0
/* GATE COLLISION */
if( gate_intersect( &gate_a, player.co, prevco ) )
{
m3x3_q( transport, transport_rotation );
q_mul( transport_rotation, player.rot, player.rot );
}
+#endif
/* Camera and character */
player_transform_update();
character_debug_ragdoll( &player.mdl );
if( player.is_dead )
- character_ragdoll_iter( &player.mdl, &world.geo );
+ character_ragdoll_iter( &player.mdl );
+#if 0
rb_build_manifold( &mr_box, &world.geo );
rb_build_manifold( &mrs_box, &world.geo );
rb_constraint_manifold( &mr_box );
rb_update_transform( &mr_box );
rb_update_transform( &mrs_box );
+#endif
clock = 0;
}
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
GL_RGB, GL_UNSIGNED_BYTE, NULL );
- gate_fb_resize( resize_renderbuffer_std );
- water_fb_resize( resize_renderbuffer_std );
-}
-
-static void render_world( m4x4f projection )
-{
- m4x3f identity_matrix;
- m4x3_identity( identity_matrix );
-
- shader_unlit_use();
- shader_unlit_uPv( projection );
- shader_unlit_uTexMain( 0 );
- vg_tex2d_bind( &tex_sky, 0 );
-
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
-
- mesh_bind( &world.skybox );
- mesh_draw( &world.skybox );
-
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_TRUE);
-
-
- shader_standard_use();
- shader_standard_uPv( projection );
- shader_standard_uMdl( identity_matrix );
-
- vg_tex2d_bind( &tex_grid, 0 );
- shader_standard_uTexMain( 0 );
- shader_standard_uColour( (v4f){0.4f,0.4f,0.4f,1.0f} );
-
- scene_bind( &world.geo );
- scene_draw( &world.geo );
+ gate_fb_resize();
+ water_fb_resize();
}
void vg_render(void)
gpipeline.fov = freecam? 60.0f: 120.0f;
m4x4_projection( vg_pv, gpipeline.fov,
(float)vg_window_x / (float)vg_window_y,
- 0.1f, 1000.0f );
+ 0.025f, 1000.0f );
m4x4_mul( vg_pv, world_4x4, vg_pv );
m4x3f cam_transform;
m4x3_invert_affine( world_matrix, cam_transform );
- render_world( vg_pv );
+ render_world( vg_pv, cam_transform );
render_water_texture( cam_transform );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
render_water_surface( vg_pv );
+#if 0
vg_tex2d_bind( &tex_water, 1 );
render_gate( &gate_a, cam_transform );
+#endif
/* Copy the RGB of what we have into the background buffer */
static void render_water_texture( m4x3f camera );
static void render_water_surface( m4x4f pv );
-static void render_world( m4x4f pv );
+static void render_world( m4x4f projection, m4x3f camera );
/*
* http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
mat[3][2] = c[3];
}
+static void pipeline_projection( m4x4f mat, float nearz, float farz )
+{
+ m4x4_projection( mat,
+ gpipeline.fov,
+ (float)vg_window_x / (float)vg_window_y,
+ nearz, farz );
+}
+
+static void create_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb )
+{
+ glGenFramebuffers( 1, fb );
+ glBindFramebuffer( GL_FRAMEBUFFER, *fb );
+
+ 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);
+
+ 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);
+
+ /* 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 );
+
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, *rb );
+}
+
+static void resize_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb )
+{
+ 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 );
+
+ glBindRenderbuffer( GL_RENDERBUFFER, *rb );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
+ vg_window_x, vg_window_y );
+}
+
#endif /* RENDER_H */
* qu3e - Randy Gaul
*/
+#include "vg/vg.h"
+static void rb_tangent_basis( v3f n, v3f tx, v3f ty );
+
#ifndef RIGIDBODY_H
#define RIGIDBODY_H
#define RB_DEPR
-#include "vg/vg.h"
-#include "scene.h"
+#include "world.h"
#define k_rb_delta (1.0f/60.0f)
v3_cross( n, tx, ty );
}
-static void rb_build_manifold( rigidbody *rb, scene *sc )
+static void rb_build_manifold( rigidbody *rb )
{
v3f *box = rb->bbx;
v3f pts[8];
struct contact *ct = &rb->manifold[rb->manifold_count];
v3f surface;
-
v3_copy( point, surface );
+ surface[1] += 4.0f;
ray_hit hit;
- bvh_scene_sample( sc, surface, &hit );
+ hit.dist = INFINITY;
+ if( !ray_world( surface, (v3f){0.0f,-1.0f,0.0f}, &hit ))
+ continue;
+
v3_copy( hit.normal, ct->n );
+ v3_copy( hit.pos, surface );
float p = vg_minf( surface[1] - point[1], 1.0f );
pscene->indice_count += submodel->indice_count;
}
+static void scene_add_foliage( scene *pscene, model *mdl, submodel *submodel,
+ m4x3f transform )
+{
+ pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count,
+ &pscene->vertex_cap, submodel->vertex_count, sizeof(model_vert) );
+ pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count,
+ &pscene->indice_cap, submodel->indice_count, sizeof(u32) );
+
+ /* Transform and place vertices */
+ model_vert *src_verts = submodel_vert_data( mdl, submodel );
+ u32 *src_indices = submodel_indice_data( mdl, submodel );
+
+ boxf bbxnew;
+ box_copy( submodel->bbx, bbxnew );
+ m4x3_transform_aabb( transform, bbxnew );
+ box_concat( pscene->bbx, bbxnew );
+
+ float rand_hue = vg_randf();
+ for( u32 i=0; i<submodel->vertex_count; i++ )
+ {
+ model_vert *pvert = &pscene->verts[ pscene->vertex_count+i ],
+ *src = &src_verts[ i ];
+
+ m4x3_mulv( transform, src->co, pvert->co );
+ m3x3_mulv( transform, src->norm, pvert->norm );
+
+ v4_copy( src->colour, pvert->colour );
+ v2_copy( src->uv, pvert->uv );
+
+ float rel_y = src->co[1] / submodel->bbx[1][1];
+ pvert->colour[0] = rel_y;
+ pvert->colour[2] = rand_hue;
+ }
+
+ for( u32 i=0; i<submodel->indice_count; i++ )
+ {
+ u32 *pidx = &pscene->indices[ pscene->indice_count+i ];
+ *pidx = src_indices[i] + pscene->vertex_count;
+ }
+
+ pscene->vertex_count += submodel->vertex_count;
+ pscene->indice_count += submodel->indice_count;
+}
+
static void scene_copy_slice( scene *pscene, submodel *sm )
{
sm->indice_start = pscene->submesh.indice_start;
--- /dev/null
+out vec4 FragColor;
+
+uniform vec4 uColour;
+
+in vec4 aColour;
+in vec2 aUv;
+in vec3 aNorm;
+in vec3 aCo;
+
+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);
+ vec3 diffuse = mix( skycolour, horizon, fblend );
+
+ FragColor = vec4(diffuse,1.0);
+}
--- /dev/null
+#ifndef SHADER_sky_H
+#define SHADER_sky_H
+static void shader_sky_link(void);
+static void shader_sky_register(void);
+static struct vg_shader _shader_sky = {
+ .name = "sky",
+ .link = shader_sky_link,
+ .vs =
+{
+.orig_file = "../shaders/standard.vs",
+.static_src =
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec4 a_colour;\n"
+"layout (location=3) in vec2 a_uv;\n"
+"\n"
+"#line 2 0 \n"
+"\n"
+"uniform mat4 uPv;\n"
+"uniform mat4x3 uMdl;\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+" gl_Position = uPv * vec4( uMdl * vec4(a_co,1.0), 1.0 );\n"
+" aColour = a_colour;\n"
+" aUv = a_uv;\n"
+" aNorm = mat3(uMdl) * a_norm;\n"
+" aCo = a_co;\n"
+"}\n"
+""},
+ .fs =
+{
+.orig_file = "../shaders/sky.fs",
+.static_src =
+"out vec4 FragColor;\n"
+"\n"
+"uniform vec4 uColour;\n"
+"\n"
+"in vec4 aColour;\n"
+"in vec2 aUv;\n"
+"in vec3 aNorm;\n"
+"in vec3 aCo;\n"
+"\n"
+"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"
+" vec3 diffuse = mix( skycolour, horizon, fblend );\n"
+"\n"
+" FragColor = vec4(diffuse,1.0);\n"
+"}\n"
+""},
+};
+
+static GLuint _uniform_sky_uPv;
+static GLuint _uniform_sky_uMdl;
+static GLuint _uniform_sky_uColour;
+static void shader_sky_uPv(m4x4f m){
+ glUniformMatrix4fv( _uniform_sky_uPv, 1, GL_FALSE, (float *)m );
+}
+static void shader_sky_uMdl(m4x3f m){
+ glUniformMatrix4x3fv( _uniform_sky_uMdl, 1, GL_FALSE, (float *)m );
+}
+static void shader_sky_uColour(v4f v){
+ glUniform4fv( _uniform_sky_uColour, 1, v );
+}
+static void shader_sky_register(void){
+ vg_shader_register( &_shader_sky );
+}
+static void shader_sky_use(void){ glUseProgram(_shader_sky.id); }
+static void shader_sky_link(void){
+ _uniform_sky_uPv = glGetUniformLocation( _shader_sky.id, "uPv" );
+ _uniform_sky_uMdl = glGetUniformLocation( _shader_sky.id, "uMdl" );
+ _uniform_sky_uColour = glGetUniformLocation( _shader_sky.id, "uColour" );
+}
+#endif /* SHADER_sky_H */
-#include "common.glsl"
+out vec4 FragColor;
+
+uniform sampler2D uTexGarbage;
+uniform sampler2D uTexGradients;
+
+in vec4 aColour;
+in vec2 aUv;
+in vec3 aNorm;
+in vec3 aCo;
void main()
{
+ vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );
+ vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;
+ vec3 qnorm = 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;
+
+ vec4 rgarbage = texture( uTexGarbage, uvdiffuse );
+ float amtgrass = step(qnorm.y,0.6);
+ vec2 uvgradients = vec2( rgarbage.a, -amtgrass*0.125 ) + aUv;
+ vec3 diffuse = texture( uTexGradients, uvgradients ).rgb;
+
+ vec3 shadow = pow(vec3(0.014,0.034,0.084),vec3(1.0/3.2));
+ float light1 = 1.0-(dot( vec3(0.95,0.0,-0.3), qnorm )*0.5+0.5);
+ FragColor = vec4(diffuse*(1.0-light1)+diffuse*shadow*light1, 1.0);
}
{
.orig_file = "../shaders/terrain.vs",
.static_src =
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec4 a_colour;\n"
+"layout (location=3) in vec2 a_uv;\n"
+"\n"
+"#line 2 0 \n"
+"\n"
+"uniform mat4 uPv;\n"
"uniform mat4x3 uMdl;\n"
"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"\n"
"void main()\n"
"{\n"
-"\n"
+" gl_Position = uPv * vec4( uMdl * vec4(a_co,1.0), 1.0 );\n"
+" aColour = a_colour;\n"
+" aUv = a_uv;\n"
+" aNorm = mat3(uMdl) * a_norm;\n"
+" aCo = a_co;\n"
"}\n"
""},
.fs =
{
.orig_file = "../shaders/terrain.fs",
.static_src =
-"// Nothing\n"
+"out vec4 FragColor;\n"
"\n"
-"#line 2 0 \n"
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexGradients;\n"
+"\n"
+"in vec4 aColour;\n"
+"in vec2 aUv;\n"
+"in vec3 aNorm;\n"
+"in vec3 aCo;\n"
"\n"
"void main()\n"
"{\n"
+" vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );\n"
+" vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n"
+" vec3 qnorm = floor(aNorm*4.0+modnorm) * 0.25;\n"
+"\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"
+" vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n"
+" float amtgrass = step(qnorm.y,0.6);\n"
+" vec2 uvgradients = vec2( rgarbage.a, -amtgrass*0.125 ) + aUv;\n"
+" vec3 diffuse = texture( uTexGradients, uvgradients ).rgb;\n"
+" \n"
+" vec3 shadow = pow(vec3(0.014,0.034,0.084),vec3(1.0/3.2));\n"
+" float light1 = 1.0-(dot( vec3(0.95,0.0,-0.3), qnorm )*0.5+0.5);\n"
"\n"
+" FragColor = vec4(diffuse*(1.0-light1)+diffuse*shadow*light1, 1.0);\n"
"}\n"
""},
};
+static GLuint _uniform_terrain_uPv;
static GLuint _uniform_terrain_uMdl;
+static GLuint _uniform_terrain_uTexGarbage;
+static GLuint _uniform_terrain_uTexGradients;
+static void shader_terrain_uPv(m4x4f m){
+ glUniformMatrix4fv( _uniform_terrain_uPv, 1, GL_FALSE, (float *)m );
+}
static void shader_terrain_uMdl(m4x3f m){
glUniformMatrix4x3fv( _uniform_terrain_uMdl, 1, GL_FALSE, (float *)m );
}
+static void shader_terrain_uTexGarbage(int i){
+ glUniform1i( _uniform_terrain_uTexGarbage, i );
+}
+static void shader_terrain_uTexGradients(int i){
+ glUniform1i( _uniform_terrain_uTexGradients, i );
+}
static void shader_terrain_register(void){
vg_shader_register( &_shader_terrain );
}
static void shader_terrain_use(void){ glUseProgram(_shader_terrain.id); }
static void shader_terrain_link(void){
+ _uniform_terrain_uPv = glGetUniformLocation( _shader_terrain.id, "uPv" );
_uniform_terrain_uMdl = glGetUniformLocation( _shader_terrain.id, "uMdl" );
+ _uniform_terrain_uTexGarbage = glGetUniformLocation( _shader_terrain.id, "uTexGarbage" );
+ _uniform_terrain_uTexGradients = glGetUniformLocation( _shader_terrain.id, "uTexGradients" );
}
#endif /* SHADER_terrain_H */
+#include "vertex_standard.glsl"
+
+uniform mat4 uPv;
uniform mat4x3 uMdl;
+out vec4 aColour;
+out vec2 aUv;
+out vec3 aNorm;
+out vec3 aCo;
+
void main()
{
-
+ gl_Position = uPv * vec4( uMdl * vec4(a_co,1.0), 1.0 );
+ aColour = a_colour;
+ aUv = a_uv;
+ aNorm = mat3(uMdl) * a_norm;
+ aCo = a_co;
}
vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 2.0;
vec4 reflected = texture( uTexMain, ssuv+distortamt );
- FragColor = vec4(reflected.rgb*0.9,reflected.a);
+ FragColor = vec4(reflected.rgb*1.0,reflected.a);
}
" vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 2.0;\n"
"\n"
" vec4 reflected = texture( uTexMain, ssuv+distortamt );\n"
-" FragColor = vec4(reflected.rgb*0.1,reflected.a);\n"
+" FragColor = vec4(reflected.rgb*1.0,reflected.a);\n"
"}\n"
""},
};
#include "render.h"
#include "shaders/terrain.h"
+#include "shaders/sky.h"
+
+vg_tex2d tex_terrain_colours = { .path = "textures/gradients.qoi",
+ .flags = VG_TEXTURE_CLAMP | VG_TEXTURE_NEAREST
+};
+vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi",
+ .flags = VG_TEXTURE_NEAREST };
+
+static struct
+{
+ glmesh skydome;
+}
+trender;
static void terrain_register(void)
{
shader_terrain_register();
+ shader_sky_register();
+}
+
+static void terrain_init(void)
+{
+ vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_colours,
+ &tex_terrain_noise }, 2 );
+
+
+ model *msky = vg_asset_read("models/rs_skydome.mdl");
+ model_unpack( msky, &trender.skydome );
+ free(msky);
}
-void test(void)
+static void render_terrain(m4x4f projection)
{
+ shader_terrain_use();
+ shader_terrain_uTexGarbage(0);
+ shader_terrain_uTexGradients(1);
+
+ vg_tex2d_bind( &tex_terrain_noise, 0 );
+ vg_tex2d_bind( &tex_terrain_colours, 1 );
+
+ m4x3f identity_matrix;
+ m4x3_identity( identity_matrix );
+ shader_terrain_uPv( projection );
+ shader_terrain_uMdl( identity_matrix );
+}
+
+static void render_sky(m4x3f camera)
+{
+ m4x4f projection, full;
+ pipeline_projection( projection, 0.4f, 1000.0f );
+
+ m4x3f inverse;
+ m3x3_transpose( camera, inverse );
+ v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
+ m4x3_expand( inverse, full );
+ m4x4_mul( projection, full, full );
+
+ m4x3f identity_matrix;
+ m4x3_identity( identity_matrix );
+ shader_sky_use();
+ shader_sky_uMdl(identity_matrix);
+ shader_sky_uPv(full);
+
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+
+ mesh_bind( &trender.skydome );
+ mesh_draw( &trender.skydome );
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
}
#endif
shader character character.vs character.fs
shader gate gate.vs gate.fs
shader water water.vs water.fs
+shader sky standard.vs sky.fs
shader_water_register();
}
-static void water_init( void (*newfb)(GLuint*,GLuint*,GLuint*))
+static void water_init(void)
{
- newfb( &wrender.fb, &wrender.rgb, &wrender.rb );
+ create_renderbuffer_std( &wrender.fb, &wrender.rgb, &wrender.rb );
}
static void water_set_surface( glmesh *surf, float height )
wrender.height = height;
}
-static void water_fb_resize( void (*resize)(GLuint*,GLuint*,GLuint*) )
+static void water_fb_resize(void)
{
- resize( &wrender.fb, &wrender.rgb, &wrender.fb );
+ resize_renderbuffer_std( &wrender.fb, &wrender.rgb, &wrender.rb );
}
static void render_water_texture( m4x3f camera )
m4x4_mul( projection, view, projection );
glCullFace( GL_FRONT );
- render_world( projection );
+ render_world( projection, new_cam );
glCullFace( GL_BACK );
}
--- /dev/null
+#ifndef WORLD_H
+#define WORLD_H
+
+#define VG_3D
+#include "vg/vg.h"
+
+#include "scene.h"
+#include "terrain.h"
+#include "render.h"
+#include "water.h"
+
+#include "shaders/standard.h"
+
+static struct gworld
+{
+ scene geo, foliage;
+ submodel sm_road, sm_terrain;
+ glmesh skybox;
+
+ v3f tutorial;
+}
+world;
+
+static void render_world( m4x4f projection, m4x3f camera )
+{
+ render_sky( camera );
+
+ m4x3f identity_matrix;
+ m4x3_identity( identity_matrix );
+
+ render_terrain( projection );
+ scene_bind( &world.geo );
+ scene_draw( &world.geo );
+
+ glDisable(GL_CULL_FACE);
+ scene_bind( &world.foliage );
+ scene_draw( &world.foliage );
+ glEnable(GL_CULL_FACE);
+}
+
+static int ray_world( v3f pos, v3f dir, ray_hit *hit )
+{
+ return bvh_raycast( &world.geo, pos, dir, hit );
+}
+
+static int ray_hit_is_ramp( ray_hit *hit )
+{
+ return hit->tri[0] < world.sm_road.vertex_count;
+}
+
+static void world_init_default(void)
+{
+ /* Setup scene */
+ scene_init( &world.geo );
+ model *mworld = vg_asset_read( "models/mp_dev.mdl" );
+
+ scene_add_model( &world.geo, mworld, submodel_get( mworld, "mp_dev" ),
+ (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
+ scene_copy_slice( &world.geo, &world.sm_road );
+
+ scene_add_model( &world.geo, mworld, submodel_get( mworld, "terrain" ),
+ (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
+ scene_copy_slice( &world.geo, &world.sm_terrain );
+
+ v3_copy( model_marker_get( mworld, "mp_dev_tutorial" )->co, world.tutorial );
+
+
+ /* GATE DEV */
+#if 0
+ {
+ model_marker *ga = model_marker_get(mworld,"gate_a"),
+ *gb = model_marker_get(mworld,"gate_a_recv");
+
+ v3_copy( ga->co, gate_a.co );
+ v3_copy( gb->co, gate_b.co );
+ v4_copy( ga->q, gate_a.q );
+ v4_copy( gb->q, gate_b.q );
+ v2_copy( ga->s, gate_a.dims );
+ v2_copy( gb->s, gate_b.dims );
+
+ gate_a.other = &gate_b;
+ gate_b.other = &gate_a;
+
+ gate_transform_update( &gate_a );
+ gate_transform_update( &gate_b );
+ }
+#endif
+
+ /* WATER DEV */
+ {
+ glmesh surf;
+ submodel *sm = submodel_get(mworld,"mp_dev_water");
+ model_unpack_submodel( mworld, &surf, sm );
+
+ water_init();
+ water_set_surface( &surf, sm->pivot[1] );
+ }
+
+ free( mworld );
+ scene_upload( &world.geo );
+ bvh_create( &world.geo );
+
+
+
+ scene_init( &world.foliage );
+ model *mfoliage = vg_asset_read("models/rs_foliage.mdl");
+
+ v3f volume;
+ v3_sub( world.geo.bbx[1], world.geo.bbx[0], volume );
+ volume[1] = 1.0f;
+
+ m4x3f transform;
+
+ for( int i=0;i<100000;i++ )
+ {
+ v3f pos;
+ v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos );
+ v3_add( pos, world.geo.bbx[0], pos );
+
+ ray_hit hit;
+ hit.dist = INFINITY;
+
+ if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
+ {
+ if( hit.normal[1] > 0.8f && !ray_hit_is_ramp(&hit) )
+ {
+ v4f qsurface, qrandom;
+ v3f axis;
+
+ v3_cross( (v3f){0.0f,1.0f,0.0f}, hit.normal, axis );
+
+ float angle = v3_dot(hit.normal,(v3f){0.0f,1.0f,0.0f});
+ q_axis_angle( qsurface, axis, angle );
+ q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf()*VG_TAUf );
+ q_mul( qsurface, qrandom, qsurface );
+ q_m3x3( qsurface, transform );
+
+ v3_copy( hit.pos, transform[3] );
+
+ scene_add_foliage( &world.foliage, mfoliage,
+ model_get_submodel( mfoliage, 0 ), transform );
+ }
+ }
+ }
+
+ free( mfoliage );
+ scene_upload( &world.foliage );
+}
+
+#endif /* WORLD_H */