private static byte[] _LightMaps = new byte[4 * MAX_LIGHTMAPS * BLOCK_WIDTH * BLOCK_HEIGHT]; // lightmaps /// <summary> /// GL_BuildLightmaps /// Builds the lightmap texture with all the surfaces from all brush models /// </summary> private static void BuildLightMaps() { Array.Clear(_Allocated, 0, _Allocated.Length); //memset (allocated, 0, sizeof(allocated)); _FrameCount = 1; // no dlightcache if (_LightMapTextures == 0) { _LightMapTextures = Drawer.GenerateTextureNumberRange(MAX_LIGHTMAPS); } Drawer.LightMapFormat = PixelFormat.Luminance;// GL_LUMINANCE; // default differently on the Permedia if (Scr.IsPermedia) { Drawer.LightMapFormat = PixelFormat.Rgba; } if (common.HasParam("-lm_1")) { Drawer.LightMapFormat = PixelFormat.Luminance; } if (common.HasParam("-lm_a")) { Drawer.LightMapFormat = PixelFormat.Alpha; } //if (Common.HasParam("-lm_i")) // Drawer.LightMapFormat = PixelFormat.Intensity; //if (Common.HasParam("-lm_2")) // Drawer.LightMapFormat = PixelFormat.Rgba4; if (common.HasParam("-lm_4")) { Drawer.LightMapFormat = PixelFormat.Rgba; } switch (Drawer.LightMapFormat) { case PixelFormat.Rgba: _LightMapBytes = 4; break; //case PixelFormat.Rgba4: //_LightMapBytes = 2; //break; case PixelFormat.Luminance: //case PixelFormat.Intensity: case PixelFormat.Alpha: _LightMapBytes = 1; break; } for (int j = 1; j < QDef.MAX_MODELS; j++) { model_t m = client.cl.model_precache[j]; if (m == null) { break; } if (m.name != null && m.name.StartsWith("*")) { continue; } _CurrentVertBase = m.vertexes; _CurrentModel = m; for (int i = 0; i < m.numsurfaces; i++) { CreateSurfaceLightmap(m.surfaces[i]); if ((m.surfaces[i].flags & Surf.SURF_DRAWTURB) != 0) { continue; } if ((m.surfaces[i].flags & Surf.SURF_DRAWSKY) != 0) { continue; } BuildSurfaceDisplayList(m.surfaces[i]); } } if (_glTexSort.Value == 0) { Drawer.SelectTexture(MTexTarget.TEXTURE1_SGIS); } // // upload all lightmaps that were filled // GCHandle handle = GCHandle.Alloc(_LightMaps, GCHandleType.Pinned); try { IntPtr ptr = handle.AddrOfPinnedObject(); long lmAddr = ptr.ToInt64(); for (int i = 0; i < MAX_LIGHTMAPS; i++) { if (_Allocated[i, 0] == 0) { break; // no more used } _LightMapModified[i] = false; _LightMapRectChange[i].l = BLOCK_WIDTH; _LightMapRectChange[i].t = BLOCK_HEIGHT; _LightMapRectChange[i].w = 0; _LightMapRectChange[i].h = 0; Drawer.Bind(_LightMapTextures + i); Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear); long addr = lmAddr + i * BLOCK_WIDTH * BLOCK_HEIGHT * _LightMapBytes; GL.TexImage2D(TextureTarget.Texture2D, 0, (PixelInternalFormat)_LightMapBytes, BLOCK_WIDTH, BLOCK_HEIGHT, 0, Drawer.LightMapFormat, PixelType.UnsignedByte, new IntPtr(addr)); } } finally { handle.Free(); } if (_glTexSort.Value == 0) { Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS); } }
/// <summary> /// R_DrawSequentialPoly /// Systems that have fast state and texture changes can /// just do everything as it passes with no need to sort /// </summary> private static void DrawSequentialPoly(msurface_t s) { // // normal lightmaped poly // if ((s.flags & (Surf.SURF_DRAWSKY | Surf.SURF_DRAWTURB | Surf.SURF_UNDERWATER)) == 0) { RenderDynamicLightmaps(s); glpoly_t p = s.polys; texture_t t = TextureAnimation(s.texinfo.texture); if (vid.glMTexable) { // Binds world to texture env 0 Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS); Drawer.Bind(t.gl_texturenum); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); // Binds lightmap to texenv 1 EnableMultitexture(); // Same as SelectTexture (TEXTURE1) Drawer.Bind(_LightMapTextures + s.lightmaptexturenum); int i = s.lightmaptexturenum; if (_LightMapModified[i]) { CommitLightmap(i); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Blend); GL.Begin(PrimitiveType.Polygon); for (i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.MultiTexCoord2(TextureUnit.Texture0, v[3], v[4]); GL.MultiTexCoord2(TextureUnit.Texture1, v[5], v[6]); GL.Vertex3(v); } GL.End(); return; } else { Drawer.Bind(t.gl_texturenum); GL.Begin(PrimitiveType.Polygon); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.TexCoord2(v[3], v[4]); GL.Vertex3(v); } GL.End(); Drawer.Bind(_LightMapTextures + s.lightmaptexturenum); GL.Enable(EnableCap.Blend); GL.Begin(PrimitiveType.Polygon); for (int i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.TexCoord2(v[5], v[6]); GL.Vertex3(v); } GL.End(); GL.Disable(EnableCap.Blend); } return; } // // subdivided water surface warp // if ((s.flags & Surf.SURF_DRAWTURB) != 0) { DisableMultitexture(); Drawer.Bind(s.texinfo.texture.gl_texturenum); EmitWaterPolys(s); return; } // // subdivided sky warp // if ((s.flags & Surf.SURF_DRAWSKY) != 0) { DisableMultitexture(); Drawer.Bind(_SolidSkyTexture); _SpeedScale = (float)host.RealTime * 8; _SpeedScale -= (int)_SpeedScale & ~127; EmitSkyPolys(s); GL.Enable(EnableCap.Blend); Drawer.Bind(_AlphaSkyTexture); _SpeedScale = (float)host.RealTime * 16; _SpeedScale -= (int)_SpeedScale & ~127; EmitSkyPolys(s); GL.Disable(EnableCap.Blend); return; } // // underwater warped with lightmap // RenderDynamicLightmaps(s); if (vid.glMTexable) { texture_t t = TextureAnimation(s.texinfo.texture); Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS); Drawer.Bind(t.gl_texturenum); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); EnableMultitexture(); Drawer.Bind(_LightMapTextures + s.lightmaptexturenum); int i = s.lightmaptexturenum; if (_LightMapModified[i]) { CommitLightmap(i); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Blend); GL.Begin(PrimitiveType.TriangleFan); glpoly_t p = s.polys; float[] nv = new float[3]; for (i = 0; i < p.numverts; i++) { float[] v = p.verts[i]; GL.MultiTexCoord2(TextureUnit.Texture0, v[3], v[4]); GL.MultiTexCoord2(TextureUnit.Texture1, v[5], v[6]); nv[0] = (float)(v[0] + 8 * Math.Sin(v[1] * 0.05 + host.RealTime) * Math.Sin(v[2] * 0.05 + host.RealTime)); nv[1] = (float)(v[1] + 8 * Math.Sin(v[0] * 0.05 + host.RealTime) * Math.Sin(v[2] * 0.05 + host.RealTime)); nv[2] = v[2]; GL.Vertex3(nv); } GL.End(); } else { glpoly_t p = s.polys; texture_t t = TextureAnimation(s.texinfo.texture); Drawer.Bind(t.gl_texturenum); DrawGLWaterPoly(p); Drawer.Bind(_LightMapTextures + s.lightmaptexturenum); GL.Enable(EnableCap.Blend); DrawGLWaterPolyLightmap(p); GL.Disable(EnableCap.Blend); } }