diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 0d2ae3dc7..0365768be 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -1335,7 +1335,7 @@ static void PM_ListDownloaded(struct dl_download *dl) if (!downloadablelist[i].received) break; } - if (domanifestinstall == MANIFEST_SECURITY_INSTALLER) + if (domanifestinstall == MANIFEST_SECURITY_INSTALLER && manifestpackage) { package_t *meta; meta = PM_MarkedPackage(manifestpackage); diff --git a/engine/client/render.h b/engine/client/render.h index 4bc322f9b..7aa57267b 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -510,7 +510,7 @@ struct relight_ctx_s; struct llightinfo_s; void LightFace (struct relight_ctx_s *ctx, struct llightinfo_s *threadctx, int surfnum); //version that is aware of bsp trees void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *threadctx, qbyte surf_styles[4], qbyte *surf_rgbsamples, qbyte *surf_deluxesamples, vec4_t surf_plane, vec4_t surf_texplanes[2], vec2_t exactmins, vec2_t exactmaxs, int texmins[2], int texsize[2], float lmscale); //special version that doesn't know what a face is or anything. -struct relight_ctx_s *LightStartup(struct relight_ctx_s *ctx, struct model_s *model, qboolean shadows); +struct relight_ctx_s *LightStartup(struct relight_ctx_s *ctx, struct model_s *model, qboolean shadows, qboolean skiplit); void LightReloadEntities(struct relight_ctx_s *ctx, const char *entstring, qboolean ignorestyles); void LightShutdown(struct relight_ctx_s *ctx, struct model_s *mod); extern const size_t lightthreadctxsize; diff --git a/engine/common/common.c b/engine/common/common.c index cca6b6883..0185d6558 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -115,7 +115,7 @@ cvar_t com_highlightcolor = CVARD("com_highlightcolor", STRINGIFY(COLOR_RED), "A cvar_t com_nogamedirnativecode = CVARFD("com_nogamedirnativecode", "1", CVAR_NOTFROMSERVER, FULLENGINENAME" blocks all downloads of files with a .dll or .so extension, however other engines (eg: ezquake and fodquake) do not - this omission can be used to trigger delayed eremote exploits in any engine (including "DISTRIBUTION") which is later run from the same gamedir.\nQuake2, Quake3(when debugging), and KTX typically run native gamecode from within gamedirs, so if you wish to run any of these games you will need to ensure this cvar is changed to 0, as well as ensure that you don't run unsafe clients.\n"); cvar_t sys_platform = CVAR("sys_platform", PLATFORM); cvar_t pm_downloads_url = CVARFD("pm_downloads_url", NULL, CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "The URL of a package updates list."); //read from the default.fmf -cvar_t pm_autoupdate = CVARFD("pm_autoupdate", "1", CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "0: off.\n1: enabled (stable only).\n2: enabled (unstable).\nNote that autoupdate will still prompt the user to actually apply the changes."); //read from the package list only. +cvar_t pm_autoupdate = CVARFD("pm_autoupdate", "1", CVAR_NOTFROMSERVER|CVAR_ARCHIVE, "0: off.\n1: enabled (stable only).\n2: enabled (unstable).\nNote that autoupdate will still prompt the user to actually apply the changes."); //read from the package list only. qboolean com_modified; // set true if using non-id files diff --git a/engine/common/fs_xz.c b/engine/common/fs_xz.c index 924c94d84..84551074f 100644 --- a/engine/common/fs_xz.c +++ b/engine/common/fs_xz.c @@ -3092,7 +3092,7 @@ vfsfile_t *FS_XZ_DecompressWriteFilter(vfsfile_t *outfile) n->outfile = outfile; - n->s = xz_dec_init(XZ_DYNALLOC, 1 << 26); + n->s = xz_dec_init(XZ_DYNALLOC, 1 << 27); if (!n->s) { Z_Free(n); diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index b5c8879cb..8e68600c1 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -2266,7 +2266,7 @@ void QCBUILTIN PF_fread (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals void QCBUILTIN PF_fseek (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; - G_INT(OFS_PARM1) = 0; + G_INT(OFS_RETURN) = -1; if (fnum < 0 || fnum >= MAX_QC_FILES) { PF_Warningf(prinst, "PF_fread: File out of range\n"); @@ -2283,16 +2283,16 @@ void QCBUILTIN PF_fseek (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals return; //this just isn't ours. } - G_INT(OFS_PARM1) = pf_fopen_files[fnum].ofs; - if (prinst->callargc>1 && G_INT(OFS_PARM0) >= 0) + G_INT(OFS_RETURN) = pf_fopen_files[fnum].ofs; + if (prinst->callargc>1 && G_INT(OFS_PARM1) >= 0) { - pf_fopen_files[fnum].ofs = G_INT(OFS_PARM0); + pf_fopen_files[fnum].ofs = G_INT(OFS_PARM1); } } void QCBUILTIN PF_fsize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; - G_INT(OFS_PARM1) = 0; + G_INT(OFS_RETURN) = -1; if (fnum < 0 || fnum >= MAX_QC_FILES) { PF_Warningf(prinst, "PF_fsize: File out of range\n"); @@ -2309,10 +2309,10 @@ void QCBUILTIN PF_fsize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals return; //this just isn't ours. } - G_INT(OFS_PARM1) = pf_fopen_files[fnum].len; - if (prinst->callargc>1 && G_INT(OFS_PARM0) >= 0) + G_INT(OFS_RETURN) = pf_fopen_files[fnum].len; + if (prinst->callargc>1 && G_INT(OFS_PARM1) >= 0) { - size_t newlen = G_INT(OFS_PARM0); + size_t newlen = G_INT(OFS_PARM1); PF_fresizebuffer_internal(&pf_fopen_files[fnum], newlen); pf_fopen_files[fnum].len = min(pf_fopen_files[fnum].bufferlen, newlen); } diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index a15260d47..8b82fad4f 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -91,6 +91,7 @@ struct { const shader_t *crepskyshader; const shader_t *crepopaqueshader; const shader_t *depthonlyshader; + const shader_t *wireframeshader; union programhandle_u allblackshader; int allblack_mvp; @@ -3573,6 +3574,15 @@ void GLBE_SelectMode(backendmode_t mode) default: break; case BEM_WIREFRAME: + if (!shaderstate.wireframeshader && gl_config.arb_shader_objects) + shaderstate.wireframeshader = R_RegisterShader("wireframe", SUF_NONE, + "{\n" + "program wireframe\n" + "{\n" + "nodepthtest\n" + "}\n" + "}\n" + ); break; case BEM_DEPTHONLY: #ifndef GLSLONLY @@ -4128,31 +4138,35 @@ static void DrawMeshes(void) break; case BEM_WIREFRAME: - //FIXME: do this with a shader instead? its not urgent as we can draw the shader normally anyway, just faster. - //FIXME: we need to use a shader for vertex blending. not really an issue with mdl, but more significant with iqms (base pose!). + if (shaderstate.wireframeshader && shaderstate.wireframeshader->prog) + { + shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours[0].gl.vbo; + shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours[0].gl.addr; + shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT; + shaderstate.pendingtexcoordparts[0] = 2; + shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; + shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; + BE_RenderMeshProgram(shaderstate.wireframeshader, shaderstate.wireframeshader->passes, shaderstate.wireframeshader->prog); + } #ifndef GLSLONLY - if (!gl_config_nofixedfunc) + else if (gl_config_nofixedfunc) { BE_SetPassBlendMode(0, PBM_REPLACE); GL_DeSelectProgram(); + + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; + Vector4Set(shaderstate.pendingcolourflat, 1, 1, 1, 1); + while(shaderstate.lastpasstmus>0) + { + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); + } + BE_SendPassBlendDepthMask((shaderstate.curshader->passes[0].shaderbits & ~SBITS_BLEND_BITS) | SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | ((r_wireframe.ival == 1)?SBITS_MISC_NODEPTHTEST:0)); + + BE_EnableShaderAttributes((1u<0) - { - GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); - } - BE_SendPassBlendDepthMask((shaderstate.curshader->passes[0].shaderbits & ~SBITS_BLEND_BITS) | SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | ((r_wireframe.ival == 1)?SBITS_MISC_NODEPTHTEST:0)); - - BE_EnableShaderAttributes((1u<flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright)) diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index fd8c1baf5..5292a9bc4 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -7002,7 +7002,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities) #ifdef RUNTIMELIGHTING hm->entsdirty = true; - hm->relightcontext = LightStartup(NULL, mod, false); + hm->relightcontext = LightStartup(NULL, mod, false, false); hm->lightthreadmem = BZ_Malloc(lightthreadctxsize); hm->inheritedlightthreadmem = false; #endif @@ -7098,7 +7098,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities) submod->loadstate = MLS_LOADED; #ifdef RUNTIMELIGHTING - subhm->relightcontext = LightStartup(hm->relightcontext, submod, false); + subhm->relightcontext = LightStartup(hm->relightcontext, submod, false, false); subhm->lightthreadmem = hm->lightthreadmem; subhm->inheritedlightthreadmem = true; #endif diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 03543ed28..01979654b 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -1882,10 +1882,16 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean #endif #ifdef RUNTIMELIGHTING - if (r_loadlits.value == 2 && !lightmodel && (!litdata || (!luxdata && r_deluxemapping))) + if (!lightmodel && r_loadlits.value == 2 && (!litdata || (!luxdata && r_deluxemapping))) { - if (!litdata) - writelitfile = true; + writelitfile = !litdata; + numlightdata = l->filelen; + lightmodel = loadmodel; + relitsurface = 0; + } + else if (!lightmodel && r_loadlits.value && r_deluxemapping && !luxdata && !(r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value<=0)) + { //if deluxemapping is on, generate missing lux files a little more often, but don't bother if we have rtlights on anyway. + writelitfile = false; numlightdata = l->filelen; lightmodel = loadmodel; relitsurface = 0; @@ -5143,7 +5149,7 @@ TRACE(("LoadBrushModel %i\n", __LINE__)); TRACE(("LoadBrushModel %i\n", __LINE__)); if (lightmodel == mod) { - lightcontext = LightStartup(NULL, lightmodel, true); + lightcontext = LightStartup(NULL, lightmodel, true, !writelitfile); LightReloadEntities(lightcontext, Mod_GetEntitiesString(lightmodel), false); } #endif diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 233e911ea..cda332d4f 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -1238,6 +1238,9 @@ static const char *glsl_hdrs[] = "attribute vec4 v_colour4;" #endif "\n#endif\n" + "#ifndef USE_ARB_SHADOW\n" //fall back on regular samplers if we must + "#define sampler2DShadow sampler2D\n" + "#endif\n" #ifndef NOLEGACY "uniform sampler2DShadow s_shadowmap;" "uniform samplerCube s_projectionmap;" @@ -1640,108 +1643,118 @@ static const char *glsl_hdrs[] = "}\n" , "sys/pcf.h", - "#ifndef r_glsl_pcf\n" - "#define r_glsl_pcf 9\n" - "#endif\n" - "#if r_glsl_pcf < 1\n" - "#undef r_glsl_pcf\n" - "#define r_glsl_pcf 9\n" - "#endif\n" - "#ifndef DEFS_DEFINED\n" - "uniform vec4 l_shadowmapproj;\n" //light projection matrix info - "uniform vec2 l_shadowmapscale;\n" //xy are the texture scale, z is 1, w is the scale. - "#endif\n" - "vec3 ShadowmapCoord(void)\n" - "{\n" - "#ifdef SPOT\n" - //bias it. don't bother figuring out which side or anything, its not needed - //l_projmatrix contains the light's projection matrix so no other magic needed - "return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n" - //"#elif defined(CUBESHADOW)\n" - // vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w; - // #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r + //!!cvardf r_glsl_pcf + "#ifndef PCF\n" + "#define ShadowmapFilter(smap) 1.0\n" //s_shadowmap generally. returns a scaler to say how much light should be used for this pixel. "#else\n" - //figure out which axis to use - //texture is arranged thusly: - //forward left up - //back right down - "vec3 dir = abs(vtexprojcoord.xyz);\n" - //assume z is the major axis (ie: forward from the light) - "vec3 t = vtexprojcoord.xyz;\n" - "float ma = dir.z;\n" - "vec3 axis = vec3(0.5/3.0, 0.5/2.0, 0.5);\n" - "if (dir.x > ma)\n" - "{\n" - "ma = dir.x;\n" - "t = vtexprojcoord.zyx;\n" - "axis.x = 0.5;\n" - "}\n" - "if (dir.y > ma)\n" - "{\n" - "ma = dir.y;\n" - "t = vtexprojcoord.xzy;\n" - "axis.x = 2.5/3.0;\n" - "}\n" - //if the axis is negative, flip it. - "if (t.z > 0.0)\n" - "{\n" - "axis.y = 1.5/2.0;\n" - "t.z = -t.z;\n" - "}\n" - - //we also need to pass the result through the light's projection matrix too - //the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4. - //note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image - //the resulting z is prescaled to result in a value between -0.5 and 0.5. - //also make sure we're in the right quadrant type thing - "return axis + ((l_shadowmapproj.xyz*t.xyz + vec3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n" - "#endif\n" - "}\n" - - "float ShadowmapFilter(sampler2DShadow smap)\n" - "{\n" - "vec3 shadowcoord = ShadowmapCoord();\n" - - "#if 0\n"//def GL_ARB_texture_gather - "vec2 ipart, fpart;\n" - "#define dosamp(x,y) textureGatherOffset(smap, ipart.xy, vec2(x,y)))\n" - "vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n" - "vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n" - "vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n" - "vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));\n" - //we now have 4*4 results, woo - //we can just average them for 1/16th precision, but that's still limited graduations - //the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3 - "vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + " //middle two rows are full strength - "mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y);\n" //top+bottom rows - "return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0));\n" //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds. - "#else\n" - "#define dosamp(x,y) shadow2D(smap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n" - "float s = 0.0;\n" - "#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n" - "s += dosamp(0.0, 0.0);\n" - "return s;\n" - "#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n" - "s += dosamp(-1.0, 0.0);\n" - "s += dosamp(0.0, -1.0);\n" - "s += dosamp(0.0, 0.0);\n" - "s += dosamp(0.0, 1.0);\n" - "s += dosamp(1.0, 0.0);\n" - "return s/5.0;\n" - "#else\n" - "s += dosamp(-1.0, -1.0);\n" - "s += dosamp(-1.0, 0.0);\n" - "s += dosamp(-1.0, 1.0);\n" - "s += dosamp(0.0, -1.0);\n" - "s += dosamp(0.0, 0.0);\n" - "s += dosamp(0.0, 1.0);\n" - "s += dosamp(1.0, -1.0);\n" - "s += dosamp(1.0, 0.0);\n" - "s += dosamp(1.0, 1.0);\n" - "return s/9.0;\n" - "#endif\n" + "#ifndef r_glsl_pcf\n" + "#define r_glsl_pcf 9\n" "#endif\n" - "}\n" + "#if r_glsl_pcf < 1\n" + "#undef r_glsl_pcf\n" + "#define r_glsl_pcf 9\n" + "#endif\n" + "#ifndef DEFS_DEFINED\n" + "uniform vec4 l_shadowmapproj;\n" //light projection matrix info + "uniform vec2 l_shadowmapscale;\n" //xy are the texture scale, z is 1, w is the scale. + "#endif\n" + "vec3 ShadowmapCoord(void)\n" + "{\n" + "#ifdef SPOT\n" + //bias it. don't bother figuring out which side or anything, its not needed + //l_projmatrix contains the light's projection matrix so no other magic needed + "return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n" + //"#elif defined(CUBESHADOW)\n" + // vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w; + // #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r + "#else\n" + //figure out which axis to use + //texture is arranged thusly: + //forward left up + //back right down + "vec3 dir = abs(vtexprojcoord.xyz);\n" + //assume z is the major axis (ie: forward from the light) + "vec3 t = vtexprojcoord.xyz;\n" + "float ma = dir.z;\n" + "vec3 axis = vec3(0.5/3.0, 0.5/2.0, 0.5);\n" + "if (dir.x > ma)\n" + "{\n" + "ma = dir.x;\n" + "t = vtexprojcoord.zyx;\n" + "axis.x = 0.5;\n" + "}\n" + "if (dir.y > ma)\n" + "{\n" + "ma = dir.y;\n" + "t = vtexprojcoord.xzy;\n" + "axis.x = 2.5/3.0;\n" + "}\n" + //if the axis is negative, flip it. + "if (t.z > 0.0)\n" + "{\n" + "axis.y = 1.5/2.0;\n" + "t.z = -t.z;\n" + "}\n" + + //we also need to pass the result through the light's projection matrix too + //the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4. + //note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image + //the resulting z is prescaled to result in a value between -0.5 and 0.5. + //also make sure we're in the right quadrant type thing + "return axis + ((l_shadowmapproj.xyz*t.xyz + vec3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n" + "#endif\n" + "}\n" + + "float ShadowmapFilter(sampler2DShadow smap)\n" + "{\n" + "vec3 shadowcoord = ShadowmapCoord();\n" + + "#if 0\n"//def GL_ARB_texture_gather + "vec2 ipart, fpart;\n" + "#define dosamp(x,y) textureGatherOffset(smap, ipart.xy, vec2(x,y)))\n" + "vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n" + "vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n" + "vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n" + "vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));\n" + //we now have 4*4 results, woo + //we can just average them for 1/16th precision, but that's still limited graduations + //the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3 + "vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + " //middle two rows are full strength + "mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y);\n" //top+bottom rows + "return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0));\n" //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds. + "#else\n" + "#ifdef USE_ARB_SHADOW\n" + //with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows + "#define dosamp(x,y) shadow2D(smap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx))\n" + "#else\n" + "#define dosamp(x,y) float(texture2D(smap, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)\n" + "#endif\n" + "float s = 0.0;\n" + "#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n" + "s += dosamp(0.0, 0.0);\n" + "return s;\n" + "#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n" + "s += dosamp(-1.0, 0.0);\n" + "s += dosamp(0.0, -1.0);\n" + "s += dosamp(0.0, 0.0);\n" + "s += dosamp(0.0, 1.0);\n" + "s += dosamp(1.0, 0.0);\n" + "return s/5.0;\n" + "#else\n" + "s += dosamp(-1.0, -1.0);\n" + "s += dosamp(-1.0, 0.0);\n" + "s += dosamp(-1.0, 1.0);\n" + "s += dosamp(0.0, -1.0);\n" + "s += dosamp(0.0, 0.0);\n" + "s += dosamp(0.0, 1.0);\n" + "s += dosamp(1.0, -1.0);\n" + "s += dosamp(1.0, 0.0);\n" + "s += dosamp(1.0, 1.0);\n" + "return s/9.0;\n" + "#endif\n" + "#endif\n" + "}\n" + "#endif\n" , NULL }; diff --git a/engine/gl/ltface.c b/engine/gl/ltface.c index 6d3b66899..5b3adc172 100644 --- a/engine/gl/ltface.c +++ b/engine/gl/ltface.c @@ -21,6 +21,7 @@ struct relight_ctx_s unsigned int nummodels; model_t *models[2048]; + qboolean skiplit; //lux only qboolean shadows; mentity_t *entities; unsigned int num_entities; @@ -134,12 +135,13 @@ void LightShutdown(struct relight_ctx_s *ctx, model_t *mod) Z_Free(ctx->entities); Z_Free(ctx); } -struct relight_ctx_s *LightStartup(struct relight_ctx_s *ctx, model_t *model, qboolean shadows) +struct relight_ctx_s *LightStartup(struct relight_ctx_s *ctx, model_t *model, qboolean shadows, qboolean skiplit) { if (!ctx) { ctx = Z_Malloc(sizeof(*ctx)); ctx->shadows = shadows; + ctx->skiplit = skiplit; } ctx->models[ctx->nummodels++] = model; return ctx; @@ -848,7 +850,10 @@ void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, qbyte surf_s dulout = GetNormFileSpace (f->lightofs, lightmapsize); } #else - rgbout = surf_rgbsamples; + if (!ctx->skiplit) + rgbout = surf_rgbsamples; + else + rgbout = NULL; if (l->ctx->models[0]->deluxdata) { dulout = surf_deluxesamples; @@ -909,7 +914,8 @@ void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, qbyte surf_s if (total > 0xff) total = 0xff; - *rgbout++ = total; + if (rgbout) + *rgbout++ = total; mean += total; } #ifdef UTILITY @@ -925,9 +931,9 @@ void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, qbyte surf_s VectorSet(temp, 0, 0, 1); else VectorNormalize(temp); - *dulout++ = (temp[0]+1)*128; - *dulout++ = (temp[1]+1)*128; - *dulout++ = (temp[2]+1)*128; + *dulout++ = (temp[0]+1)*127; + *dulout++ = (temp[1]+1)*127; + *dulout++ = (temp[2]+1)*127; } } } diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 4a312d681..43f43fda8 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -7127,6 +7127,128 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "return inp.col * t_lightmap.Sample(s_lightmap, inp.lmtc);\n" "}\n" "#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "wireframe", +"!!ver 100 150\n" +"!!permu TESS\n" +"!!permu FRAMEBLEND\n" +"!!permu SKELETAL\n" +"!!permu FOG\n" +"!!cvardf r_tessellation_level=5\n" + +"#include \"sys/defs.h\"\n" + +//standard shader used for wireframe stuff. +//must support skeletal and 2-way vertex blending or Bad Things Will Happen. + + + + + + + + +"#ifdef VERTEX_SHADER\n" +"#include \"sys/skeletal.h\"\n" + +"#ifdef TESS\n" +"varying vec3 vertex;\n" +"varying vec3 normal;\n" +"#endif\n" + +"void main ()\n" +"{\n" +"vec3 n, s, t, w;\n" +"gl_Position = skeletaltransform_wnst(w,n,s,t);\n" + +"#ifdef TESS\n" +"normal = n;\n" +"vertex = w;\n" +"#endif\n" +"}\n" +"#endif\n" + + + + + + + + + + +"#if defined(TESS_CONTROL_SHADER)\n" +"layout(vertices = 3) out;\n" + +"in vec3 vertex[];\n" +"out vec3 t_vertex[];\n" +"in vec3 normal[];\n" +"out vec3 t_normal[];\n" +"void main()\n" +"{\n" +//the control shader needs to pass stuff through +"#define id gl_InvocationID\n" +"t_vertex[id] = vertex[id];\n" +"t_normal[id] = normal[id];\n" + +"gl_TessLevelOuter[0] = float(r_tessellation_level);\n" +"gl_TessLevelOuter[1] = float(r_tessellation_level);\n" +"gl_TessLevelOuter[2] = float(r_tessellation_level);\n" +"gl_TessLevelInner[0] = float(r_tessellation_level);\n" +"}\n" +"#endif\n" + + + + + + + + + +"#if defined(TESS_EVALUATION_SHADER)\n" +"layout(triangles) in;\n" + +"in vec3 t_vertex[];\n" +"in vec3 t_normal[];\n" + +"#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])\n" +"void main()\n" +"{\n" +"#define factor 1.0\n" +"vec3 w = LERP(t_vertex);\n" + +"vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];\n" +"vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];\n" +"vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];\n" +"w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);\n" + + +"gl_Position = m_modelviewprojection * vec4(w,1.0);\n" +"}\n" +"#endif\n" + + + + + + + + + + +"#ifdef FRAGMENT_SHADER\n" + +"#include \"sys/fog.h\"\n" + +"void main ()\n" +"{\n" +"gl_FragColor = fog4(vec4(1.0) * e_colourident);\n" +"}\n" +"#endif\n" + }, #endif #ifdef GLQUAKE @@ -9654,11 +9776,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#include \"sys/defs.h\"\n" -"#ifndef USE_ARB_SHADOW\n" -//fall back on regular samplers if we must -"#define sampler2DShadow sampler2D\n" -"#endif\n" - //this is the main shader responsible for realtime dlights. //texture units: @@ -9669,14 +9786,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND //SPOT(projected circle //CUBESHADOW -"#ifndef r_glsl_pcf\n" -"#error r_glsl_pcf wasnt defined\n" -"#endif\n" -"#if r_glsl_pcf < 1\n" -"#undef r_glsl_pcf\n" -"#define r_glsl_pcf 9\n" -"#endif\n" - "#if 0 && defined(GL_ARB_texture_gather) && defined(PCF) \n" "#extension GL_ARB_texture_gather : enable\n" "#endif\n" @@ -9850,115 +9959,25 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FRAGMENT_SHADER\n" "#include \"sys/fog.h\"\n" - -"#ifdef PCF\n" -"vec3 ShadowmapCoord(void)\n" -"{\n" -"#ifdef SPOT\n" -//bias it. don't bother figuring out which side or anything, its not needed -//l_projmatrix contains the light's projection matrix so no other magic needed -"return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n" -//#elif defined(CUBESHADOW) -// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w; -// #define dosamp(x,y) shadowCube(s_shadowmap, shadowcoord + vec2(x,y)*texscale.xy).r -"#else\n" -//figure out which axis to use -//texture is arranged thusly: -//forward left up -//back right down -"vec3 dir = abs(vtexprojcoord.xyz);\n" -//assume z is the major axis (ie: forward from the light) -"vec3 t = vtexprojcoord.xyz;\n" -"float ma = dir.z;\n" -"vec3 axis = vec3(0.5/3.0, 0.5/2.0, 0.5);\n" -"if (dir.x > ma)\n" -"{\n" -"ma = dir.x;\n" -"t = vtexprojcoord.zyx;\n" -"axis.x = 0.5;\n" -"}\n" -"if (dir.y > ma)\n" -"{\n" -"ma = dir.y;\n" -"t = vtexprojcoord.xzy;\n" -"axis.x = 2.5/3.0;\n" -"}\n" -//if the axis is negative, flip it. -"if (t.z > 0.0)\n" -"{\n" -"axis.y = 1.5/2.0;\n" -"t.z = -t.z;\n" -"}\n" - -//we also need to pass the result through the light's projection matrix too -//the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4. -//note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image -//the resulting z is prescaled to result in a value between -0.5 and 0.5. -//also make sure we're in the right quadrant type thing -"return axis + ((l_shadowmapproj.xyz*t.xyz + vec3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n" -"#endif\n" -"}\n" - -"float ShadowmapFilter(void)\n" -"{\n" -"vec3 shadowcoord = ShadowmapCoord();\n" - -"#if 0//def GL_ARB_texture_gather\n" -"vec2 ipart, fpart;\n" -"#define dosamp(x,y) textureGatherOffset(s_shadowmap, ipart.xy, vec2(x,y)))\n" -"vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n" -"vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n" -"vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n" -"vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));\n" -//we now have 4*4 results, woo -//we can just average them for 1/16th precision, but that's still limited graduations -//the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3 -"vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + //middle two rows are full strength\n" -"mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y); //top+bottom rows\n" -"return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.\n" - -"#else\n" -"#ifdef USE_ARB_SHADOW\n" -//with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows -"#define dosamp(x,y) shadow2D(s_shadowmap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx))\n" -"#else\n" -//this will probably be a bit blocky. -"#define dosamp(x,y) float(texture2D(s_shadowmap, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)\n" -"#endif\n" -"float s = 0.0;\n" -"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n" -"s += dosamp(0.0, 0.0);\n" -"return s;\n" -"#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n" -"s += dosamp(-1.0, 0.0);\n" -"s += dosamp(0.0, -1.0);\n" -"s += dosamp(0.0, 0.0);\n" -"s += dosamp(0.0, 1.0);\n" -"s += dosamp(1.0, 0.0);\n" -"return s/5.0;\n" -"#else\n" -"s += dosamp(-1.0, -1.0);\n" -"s += dosamp(-1.0, 0.0);\n" -"s += dosamp(-1.0, 1.0);\n" -"s += dosamp(0.0, -1.0);\n" -"s += dosamp(0.0, 0.0);\n" -"s += dosamp(0.0, 1.0);\n" -"s += dosamp(1.0, -1.0);\n" -"s += dosamp(1.0, 0.0);\n" -"s += dosamp(1.0, 1.0);\n" -"return s/9.0;\n" -"#endif\n" -"#endif\n" -"}\n" -"#endif\n" - - +"#include \"sys/pcf.h\"\n" "#ifdef OFFSETMAPPING\n" "#include \"sys/offsetmapping.h\"\n" "#endif\n" "void main ()\n" "{\n" +"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n" +"#ifdef PCF\n" +/*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/ +"colorscale *= ShadowmapFilter(s_shadowmap);\n" +"#endif\n" +"#if defined(SPOT)\n" +/*filter the colour by the spotlight. discard anything behind the light so we don't get a mirror image*/ +"if (vtexprojcoord.w < 0.0) discard;\n" +"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);\n" +"colorscale*=1.0-(dot(spot,spot));\n" +"#endif\n" + //read raw texture samples (offsetmapping munges the tex coords first) "#ifdef OFFSETMAPPING\n" "vec2 tcoffsetmap = offsetmap(s_normalmap, tcbase, eyevector);\n" @@ -9986,7 +10005,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "vec4 specs = texture2D(s_specular, tcbase);\n" "#endif\n" -"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n" "vec3 diff;\n" "#ifdef NOBUMP\n" //surface can only support ambient lighting, even for lights that try to avoid it. @@ -10020,19 +10038,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "diff *= textureCube(s_projectionmap, vtexprojcoord.xyz).rgb;\n" "#endif\n" -"#if defined(SPOT)\n" -/*filter the colour by the spotlight. discard anything behind the light so we don't get a mirror image*/ -"if (vtexprojcoord.w < 0.0) discard;\n" -"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);colorscale*=1.0-(dot(spot,spot));\n" -"#endif\n" - -"#ifdef PCF\n" -/*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/ -//diff.rgb = (vtexprojcoord.xyz/vtexprojcoord.w) * 0.5 + 0.5; -"colorscale *= ShadowmapFilter();\n" -// diff = ShadowmapCoord(); -"#endif\n" - "#if defined(PROJECTION)\n" /*2d projection, not used*/ // diff *= texture2d(s_projectionmap, shadowcoord); diff --git a/engine/shaders/generatebuiltinsl.c b/engine/shaders/generatebuiltinsl.c index ce9d191fc..92701828b 100644 --- a/engine/shaders/generatebuiltinsl.c +++ b/engine/shaders/generatebuiltinsl.c @@ -24,6 +24,7 @@ char shaders[][64] = "defaultwarp", "defaultgammacb", "drawflat_wall", + "wireframe", "lpp_depthnorm", "lpp_light", "lpp_wall", diff --git a/engine/shaders/glsl/rtlight.glsl b/engine/shaders/glsl/rtlight.glsl index 39a058aa5..40678015f 100644 --- a/engine/shaders/glsl/rtlight.glsl +++ b/engine/shaders/glsl/rtlight.glsl @@ -13,11 +13,6 @@ #include "sys/defs.h" -#ifndef USE_ARB_SHADOW -//fall back on regular samplers if we must -#define sampler2DShadow sampler2D -#endif - //this is the main shader responsible for realtime dlights. //texture units: @@ -28,14 +23,6 @@ //SPOT(projected circle //CUBESHADOW -#ifndef r_glsl_pcf -#error r_glsl_pcf wasnt defined -#endif -#if r_glsl_pcf < 1 - #undef r_glsl_pcf - #define r_glsl_pcf 9 -#endif - #if 0 && defined(GL_ARB_texture_gather) && defined(PCF) #extension GL_ARB_texture_gather : enable #endif @@ -209,115 +196,25 @@ void main() #ifdef FRAGMENT_SHADER #include "sys/fog.h" - -#ifdef PCF -vec3 ShadowmapCoord(void) -{ -#ifdef SPOT - //bias it. don't bother figuring out which side or anything, its not needed - //l_projmatrix contains the light's projection matrix so no other magic needed - return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5); -//#elif defined(CUBESHADOW) -// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w; -// #define dosamp(x,y) shadowCube(s_shadowmap, shadowcoord + vec2(x,y)*texscale.xy).r -#else - //figure out which axis to use - //texture is arranged thusly: - //forward left up - //back right down - vec3 dir = abs(vtexprojcoord.xyz); - //assume z is the major axis (ie: forward from the light) - vec3 t = vtexprojcoord.xyz; - float ma = dir.z; - vec3 axis = vec3(0.5/3.0, 0.5/2.0, 0.5); - if (dir.x > ma) - { - ma = dir.x; - t = vtexprojcoord.zyx; - axis.x = 0.5; - } - if (dir.y > ma) - { - ma = dir.y; - t = vtexprojcoord.xzy; - axis.x = 2.5/3.0; - } - //if the axis is negative, flip it. - if (t.z > 0.0) - { - axis.y = 1.5/2.0; - t.z = -t.z; - } - - //we also need to pass the result through the light's projection matrix too - //the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4. - //note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image - //the resulting z is prescaled to result in a value between -0.5 and 0.5. - //also make sure we're in the right quadrant type thing - return axis + ((l_shadowmapproj.xyz*t.xyz + vec3(0.0, 0.0, l_shadowmapproj.w)) / -t.z); -#endif -} - -float ShadowmapFilter(void) -{ - vec3 shadowcoord = ShadowmapCoord(); - - #if 0//def GL_ARB_texture_gather - vec2 ipart, fpart; - #define dosamp(x,y) textureGatherOffset(s_shadowmap, ipart.xy, vec2(x,y))) - vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0)); - vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0)); - vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0)); - vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0)); - //we now have 4*4 results, woo - //we can just average them for 1/16th precision, but that's still limited graduations - //the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3 - vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + //middle two rows are full strength - mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y); //top+bottom rows - return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds. - - #else -#ifdef USE_ARB_SHADOW - //with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows - #define dosamp(x,y) shadow2D(s_shadowmap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)) -#else - //this will probably be a bit blocky. - #define dosamp(x,y) float(texture2D(s_shadowmap, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z) -#endif - float s = 0.0; - #if r_glsl_pcf >= 1 && r_glsl_pcf < 5 - s += dosamp(0.0, 0.0); - return s; - #elif r_glsl_pcf >= 5 && r_glsl_pcf < 9 - s += dosamp(-1.0, 0.0); - s += dosamp(0.0, -1.0); - s += dosamp(0.0, 0.0); - s += dosamp(0.0, 1.0); - s += dosamp(1.0, 0.0); - return s/5.0; - #else - s += dosamp(-1.0, -1.0); - s += dosamp(-1.0, 0.0); - s += dosamp(-1.0, 1.0); - s += dosamp(0.0, -1.0); - s += dosamp(0.0, 0.0); - s += dosamp(0.0, 1.0); - s += dosamp(1.0, -1.0); - s += dosamp(1.0, 0.0); - s += dosamp(1.0, 1.0); - return s/9.0; - #endif - #endif -} -#endif - - +#include "sys/pcf.h" #ifdef OFFSETMAPPING #include "sys/offsetmapping.h" #endif void main () { + float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0); +#ifdef PCF + /*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/ + colorscale *= ShadowmapFilter(s_shadowmap); +#endif +#if defined(SPOT) + /*filter the colour by the spotlight. discard anything behind the light so we don't get a mirror image*/ + if (vtexprojcoord.w < 0.0) discard; + vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w); + colorscale*=1.0-(dot(spot,spot)); +#endif + //read raw texture samples (offsetmapping munges the tex coords first) #ifdef OFFSETMAPPING vec2 tcoffsetmap = offsetmap(s_normalmap, tcbase, eyevector); @@ -345,7 +242,6 @@ void main () vec4 specs = texture2D(s_specular, tcbase); #endif - float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0); vec3 diff; #ifdef NOBUMP //surface can only support ambient lighting, even for lights that try to avoid it. @@ -379,19 +275,6 @@ void main () diff *= textureCube(s_projectionmap, vtexprojcoord.xyz).rgb; #endif -#if defined(SPOT) - /*filter the colour by the spotlight. discard anything behind the light so we don't get a mirror image*/ - if (vtexprojcoord.w < 0.0) discard; - vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);colorscale*=1.0-(dot(spot,spot)); -#endif - -#ifdef PCF - /*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/ -//diff.rgb = (vtexprojcoord.xyz/vtexprojcoord.w) * 0.5 + 0.5; - colorscale *= ShadowmapFilter(); -// diff = ShadowmapCoord(); -#endif - #if defined(PROJECTION) /*2d projection, not used*/ // diff *= texture2d(s_projectionmap, shadowcoord); diff --git a/engine/shaders/glsl/wireframe.glsl b/engine/shaders/glsl/wireframe.glsl new file mode 100644 index 000000000..31b41fc66 --- /dev/null +++ b/engine/shaders/glsl/wireframe.glsl @@ -0,0 +1,118 @@ +!!ver 100 150 +!!permu TESS +!!permu FRAMEBLEND +!!permu SKELETAL +!!permu FOG +!!cvardf r_tessellation_level=5 + +#include "sys/defs.h" + +//standard shader used for wireframe stuff. +//must support skeletal and 2-way vertex blending or Bad Things Will Happen. + + + + + + + + +#ifdef VERTEX_SHADER +#include "sys/skeletal.h" + +#ifdef TESS +varying vec3 vertex; +varying vec3 normal; +#endif + +void main () +{ + vec3 n, s, t, w; + gl_Position = skeletaltransform_wnst(w,n,s,t); + +#ifdef TESS + normal = n; + vertex = w; +#endif +} +#endif + + + + + + + + + + +#if defined(TESS_CONTROL_SHADER) +layout(vertices = 3) out; + +in vec3 vertex[]; +out vec3 t_vertex[]; +in vec3 normal[]; +out vec3 t_normal[]; +void main() +{ + //the control shader needs to pass stuff through +#define id gl_InvocationID + t_vertex[id] = vertex[id]; + t_normal[id] = normal[id]; + + gl_TessLevelOuter[0] = float(r_tessellation_level); + gl_TessLevelOuter[1] = float(r_tessellation_level); + gl_TessLevelOuter[2] = float(r_tessellation_level); + gl_TessLevelInner[0] = float(r_tessellation_level); +} +#endif + + + + + + + + + +#if defined(TESS_EVALUATION_SHADER) +layout(triangles) in; + +in vec3 t_vertex[]; +in vec3 t_normal[]; + +#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2]) +void main() +{ +#define factor 1.0 + vec3 w = LERP(t_vertex); + + vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0]; + vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1]; + vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2]; + w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2); + + + gl_Position = m_modelviewprojection * vec4(w,1.0); +} +#endif + + + + + + + + + + +#ifdef FRAGMENT_SHADER + +#include "sys/fog.h" + +void main () +{ + gl_FragColor = fog4(vec4(1.0) * e_colourident); +} +#endif +