diff --git a/Source/client/entry.c b/Source/client/entry.c index 9adec35f..ad4fe486 100644 --- a/Source/client/entry.c +++ b/Source/client/entry.c @@ -35,6 +35,7 @@ void CSQC_Init(float apilevel, string enginename, float engineversion) registercommand("invprev"); registercommand("+showscores"); registercommand("-showscores"); + registercommand("buildcubemaps"); precache_model("sprites/640_pain.spr"); precache_model("sprites/crosshairs.spr"); @@ -97,6 +98,18 @@ void CSQC_UpdateView(float w, float h, float focus) video_res[0] = w; video_res[1] = h; + + if ( g_iCubeProcess == TRUE ) { + clearscene(); + setproperty( VF_DRAWWORLD, TRUE ); + setproperty( VF_DRAWENGINESBAR, FALSE ); + setproperty( VF_DRAWCROSSHAIR, FALSE ); + setproperty( VF_ENVMAP, "$whiteimage" ); + setproperty( VF_ORIGIN, g_vecCubePos ); + setproperty( VF_AFOV, 90 ); + renderscene(); + return; + } clearscene(); setproperty(VF_DRAWENGINESBAR, 0); @@ -463,80 +476,83 @@ float CSQC_ConsoleCommand(string sCMD) tokenize(sCMD); switch (argv(0)) { - case "vox_test": - Sound_PlayVOX(sCMD); - break; - case "+attack2": - pSeat->iInputAttack2 = TRUE; - break; - case "-attack2": - pSeat->iInputAttack2 = FALSE; - break; - case "+reload": - pSeat->iInputReload = TRUE; - break; - case "-reload": - pSeat->iInputReload = FALSE; - break; - case "+use": - pSeat->iInputUse = TRUE; - break; - case "-use": - pSeat->iInputUse = FALSE; - break; - case "+duck": - pSeat->iInputDuck = TRUE; - break; - case "-duck": - pSeat->iInputDuck = FALSE; - break; - case "invnext": - HUD_DrawWeaponSelect_Back(); - break; - case "invprev": - HUD_DrawWeaponSelect_Forward(); - break; - case "lastinv": - HUD_DrawWeaponSelect_Last(); - break; - case "+showscores": - pSeat->iShowScores = TRUE; - break; - case "-showscores": - pSeat->iShowScores = FALSE; - break; - case "slot1": - localcmd("impulse 1\n"); - break; - case "slot2": - localcmd("impulse 2\n"); - break; - case "slot3": - localcmd("impulse 3\n"); - break; - case "slot4": - localcmd("impulse 4\n"); - break; - case "slot5": - localcmd("impulse 5\n"); - break; - case "slot6": - localcmd("impulse 6\n"); - break; - case "slot7": - localcmd("impulse 7\n"); - break; - case "slot8": - localcmd("impulse 8\n"); - break; - case "slot9": - localcmd("impulse 9\n"); - break; - case "slot10": - localcmd("impulse 10\n"); - break; - default: - return Game_ConsoleCommand(); + case "buildcubemaps": + CMap_Build(); + break; + case "vox_test": + Sound_PlayVOX(sCMD); + break; + case "+attack2": + pSeat->iInputAttack2 = TRUE; + break; + case "-attack2": + pSeat->iInputAttack2 = FALSE; + break; + case "+reload": + pSeat->iInputReload = TRUE; + break; + case "-reload": + pSeat->iInputReload = FALSE; + break; + case "+use": + pSeat->iInputUse = TRUE; + break; + case "-use": + pSeat->iInputUse = FALSE; + break; + case "+duck": + pSeat->iInputDuck = TRUE; + break; + case "-duck": + pSeat->iInputDuck = FALSE; + break; + case "invnext": + HUD_DrawWeaponSelect_Back(); + break; + case "invprev": + HUD_DrawWeaponSelect_Forward(); + break; + case "lastinv": + HUD_DrawWeaponSelect_Last(); + break; + case "+showscores": + pSeat->iShowScores = TRUE; + break; + case "-showscores": + pSeat->iShowScores = FALSE; + break; + case "slot1": + localcmd("impulse 1\n"); + break; + case "slot2": + localcmd("impulse 2\n"); + break; + case "slot3": + localcmd("impulse 3\n"); + break; + case "slot4": + localcmd("impulse 4\n"); + break; + case "slot5": + localcmd("impulse 5\n"); + break; + case "slot6": + localcmd("impulse 6\n"); + break; + case "slot7": + localcmd("impulse 7\n"); + break; + case "slot8": + localcmd("impulse 8\n"); + break; + case "slot9": + localcmd("impulse 9\n"); + break; + case "slot10": + localcmd("impulse 10\n"); + break; + default: + return Game_ConsoleCommand(); } return TRUE; } @@ -639,6 +655,10 @@ float CSQC_Ent_ParseMapEntity(void) eEnt = spawn(env_sound); iClass = TRUE; break; + case "env_cubemap": + eEnt = spawn(env_cubemap); + iClass = TRUE; + break; #ifdef REWOLF case "decore_asteroid": eEnt = spawn(decore_asteroid); diff --git a/Source/gs-entbase/client.src b/Source/gs-entbase/client.src index fa95b484..f698154c 100644 --- a/Source/gs-entbase/client.src +++ b/Source/gs-entbase/client.src @@ -4,6 +4,7 @@ ../gs-entbase/client/fade.cpp ../gs-entbase/client/sprite.cpp ../gs-entbase/client/text.cpp +../gs-entbase/client/env_cubemap.cpp ../gs-entbase/client/env_sound.cpp ../gs-entbase/client/worldspawn.cpp #endlist diff --git a/Source/gs-entbase/client/env_cubemap.cpp b/Source/gs-entbase/client/env_cubemap.cpp new file mode 100644 index 00000000..cc860bd0 --- /dev/null +++ b/Source/gs-entbase/client/env_cubemap.cpp @@ -0,0 +1,136 @@ +/*** +* +* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved. +* +* See the file LICENSE attached with the sources for usage details. +* +****/ + +/* +=============================================================================== + + Cubemap Entity Development Functions + +=============================================================================== +*/ + +int g_iCubeProcess; +entity g_eCubeCycle; +vector g_vecCubePos; + +void CMap_Check(void); +void CMap_Shoot(void); + +class env_cubemap:CBaseEntity { + int m_iSize; + + void() env_cubemap; + virtual void(string, string) SpawnKey; +}; + +void env_cubemap::SpawnKey(string strField, string strKey) +{ + switch (strField) { + case "scale": + m_iSize = stoi(strKey); + if (m_iSize <= 16) { + m_iSize = 16; + } else if (m_iSize <= 32) { + m_iSize = 32; + } else if (m_iSize <= 64) { + m_iSize = 64; + } else if (m_iSize <= 128) { + m_iSize = 128; + } else { + m_iSize = 256; + } + break; + default: + CBaseEntity::SpawnKey(strField, strKey); + } +} + +void env_cubemap::env_cubemap(void) +{ + m_iSize = 32; + Init(); +} + +/* +================= +CMap_Check + + Checks whether or not a specific cubemap file was dumped, goes to the next +================= +*/ +void CMap_Shoot(void) +{ + string strReflectcube; + if ( self.owner ) { + env_cubemap tmp = (env_cubemap) self.owner; + print( "^3Cubemap processing...\n" ); + g_vecCubePos = tmp.origin; + strReflectcube = sprintf( + "env/%s_%d_%d_%d.dds", + mapname, + g_vecCubePos[0], + g_vecCubePos[1], + g_vecCubePos[2]); + localcmd(sprintf( + "screenshot_cubemap %s %i\n", + strReflectcube, + tmp.m_iSize)); + self.think = CMap_Check; + self.nextthink = time; + } else { + print( "^2Cubemaps done...\n" ); + localcmd( "mod_findcubemaps\nvid_reload\n" ); + g_iCubeProcess = FALSE; + remove( self ); + } +} + +/* +================= +CMap_Check + + Checks whether or not a specific cubemap file was dumped, goes to the next +================= +*/ +void CMap_Check(void) +{ + if (whichpack(sprintf( + "textures/env/%s_%d_%d_%d.dds", + mapname, + g_vecCubePos[0], + g_vecCubePos[1], + g_vecCubePos[2]))) { + self.owner = find( self.owner, classname, "env_cubemap" ); + self.think = CMap_Shoot; + } + self.nextthink = time; +} + +/* +================= +CMap_Build + + Called upon 'dev_buildcubemaps' +================= +*/ +void CMap_Build(void) +{ + if (g_iCubeProcess == TRUE) { + return; + } + + print("^4Building cubemaps...\n"); + g_eCubeCycle = spawn(); + g_eCubeCycle.owner = find(world, classname, "env_cubemap"); + + if (g_eCubeCycle.owner) { + g_eCubeCycle.think = CMap_Shoot; + g_eCubeCycle.nextthink = time; + g_iCubeProcess = TRUE; + } +} diff --git a/cstrike/data.pk3dir/csprogs.dat b/cstrike/data.pk3dir/csprogs.dat index 53d947f1..8da56edd 100644 Binary files a/cstrike/data.pk3dir/csprogs.dat and b/cstrike/data.pk3dir/csprogs.dat differ diff --git a/rewolf/data.pk3dir/csprogs.dat b/rewolf/data.pk3dir/csprogs.dat index 8cf5b667..156eb0e8 100644 Binary files a/rewolf/data.pk3dir/csprogs.dat and b/rewolf/data.pk3dir/csprogs.dat differ diff --git a/scihunt/data.pk3dir/csprogs.dat b/scihunt/data.pk3dir/csprogs.dat index ff89c3cc..f445aba2 100644 Binary files a/scihunt/data.pk3dir/csprogs.dat and b/scihunt/data.pk3dir/csprogs.dat differ diff --git a/valve/data.pk3dir/csprogs.dat b/valve/data.pk3dir/csprogs.dat index 5f9b1c38..0a370044 100644 Binary files a/valve/data.pk3dir/csprogs.dat and b/valve/data.pk3dir/csprogs.dat differ diff --git a/valve/data.pk3dir/glsl/defaultskin.glsl b/valve/data.pk3dir/glsl/defaultskin.glsl index 24067b77..e86aafa3 100644 --- a/valve/data.pk3dir/glsl/defaultskin.glsl +++ b/valve/data.pk3dir/glsl/defaultskin.glsl @@ -2,7 +2,7 @@ !!permu FRAMEBLEND !!permu SKELETAL !!permu FOG -!!samps diffuse +!!samps diffuse reflectcube !!cvardf gl_affinemodels=0 !!cvardf gl_fake16bit=0 !!cvardf gl_monochrome=0 @@ -16,6 +16,11 @@ #define affine #endif +#ifdef REFLECTCUBE +varying vec3 eyevector; +varying mat3 invsurface; +#endif + affine varying vec2 tex_c; varying vec3 light; @@ -60,16 +65,16 @@ varying vec3 light; tex_c.x = 0.5 + reflected.y * 0.5; tex_c.y = 0.5 - reflected.z * 0.5; #endif - - if (light.r > 1.0f) { - light.r = 1.0f; - } - if (light.g > 1.0f) { - light.g = 1.0f; - } - if (light.b > 1.0f) { - light.b = 1.0f; - } + +#ifdef REFLECTCUBE + invsurface[0] = v_svector; + invsurface[1] = v_tvector; + invsurface[2] = v_normal; + vec3 eyeminusvertex = e_eyepos - v_position.xyz; + eyevector.x = dot( eyeminusvertex, v_svector.xyz ); + eyevector.y = dot( eyeminusvertex, v_tvector.xyz ); + eyevector.z = dot( eyeminusvertex, v_normal.xyz ); +#endif } #endif @@ -79,6 +84,17 @@ varying vec3 light; { vec4 diffuse_f = texture2D(s_diffuse, tex_c); diffuse_f.rgb *= light; + +#ifdef REFLECTCUBE + vec3 cube_c; + vec4 out_f = vec4( 1.0, 1.0, 1.0, 1.0 ); + + cube_c = reflect( normalize( -eyevector ), vec3( 0, 0, 1 ) ); + cube_c = cube_c.x * invsurface[0] + cube_c.y * invsurface[1] + cube_c.z * invsurface[2]; + cube_c = ( m_model * vec4( cube_c.xyz, 0.0 ) ).xyz; + out_f.rgb = mix( textureCube( s_reflectcube, cube_c ).rgb, diffuse_f.rgb, diffuse_f.a ); + diffuse_f = out_f; +#endif diffuse_f *= e_colourident; #if gl_brighten == 1 diff --git a/valve/data.pk3dir/glsl/defaultwall.glsl b/valve/data.pk3dir/glsl/defaultwall.glsl index 247c80e2..f3e03fe3 100644 --- a/valve/data.pk3dir/glsl/defaultwall.glsl +++ b/valve/data.pk3dir/glsl/defaultwall.glsl @@ -1,5 +1,5 @@ !!ver 110 -!!samps diffuse lightmap +!!samps diffuse lightmap reflectcube !!cvardf gl_fake16bit=0 !!cvardf gl_monochrome=0 !!cvardf gl_brighten=0 @@ -9,12 +9,27 @@ varying vec2 tex_c; varying vec2 lm_c; +#ifdef REFLECTCUBE +varying vec3 eyevector; +varying mat3 invsurface; +#endif + #ifdef VERTEX_SHADER void main () { tex_c = v_texcoord; lm_c = v_lmcoord; gl_Position = ftetransform(); + +#ifdef REFLECTCUBE + invsurface[0] = v_svector; + invsurface[1] = v_tvector; + invsurface[2] = v_normal; + vec3 eyeminusvertex = e_eyepos - v_position.xyz; + eyevector.x = dot( eyeminusvertex, v_svector.xyz ); + eyevector.y = dot( eyeminusvertex, v_tvector.xyz ); + eyevector.z = dot( eyeminusvertex, v_normal.xyz ); +#endif } #endif @@ -29,11 +44,24 @@ varying vec2 lm_c; discard; } +#ifdef REFLECTCUBE + vec3 cube_c; + vec4 out_f = vec4( 1.0, 1.0, 1.0, 1.0 ); + + // Modulate the final pixel with the lightmap value + diffuse_f.rgb *= light.rgb * e_lmscale.rgb; + + cube_c = reflect( normalize(-eyevector), vec3(0, 0, 1)); + cube_c = cube_c.x * invsurface[0] + cube_c.y * invsurface[1] + cube_c.z * invsurface[2]; + cube_c = ( m_model * vec4(cube_c.xyz, 0.0)).xyz; + out_f.rgb = mix( textureCube(s_reflectcube, cube_c ).rgb, diffuse_f.rgb, diffuse_f.a); + diffuse_f = out_f; +#else + diffuse_f.rgb *= light.rgb; if (diffuse_f.a < 0.5) { discard; } - - diffuse_f.rgb *= light.rgb; +#endif diffuse_f *= e_colourident; #if gl_brighten == 1