public static void R_RenderBrushPoly(msurface_t fa) { c_brush_polys++; if ((fa.flags & q_shared.SURF_DRAWSKY) != 0) { // warp texture, no lightmaps EmitBothSkyLayers(fa); return; } texture_t t = R_TextureAnimation(fa.texinfo.texture); GL_Bind(t.gl_texturenum); if ((fa.flags & q_shared.SURF_DRAWTURB) != 0) { // warp texture, no lightmaps EmitWaterPolys(fa); return; } if ((fa.flags & q_shared.SURF_UNDERWATER) != 0) { DrawGLWaterPoly(fa.polys); } else { DrawGLPoly(fa.polys); } // add the poly to the proper lightmap chain fa.polys.chain = lightmap_polys[fa.lightmaptexturenum]; lightmap_polys[fa.lightmaptexturenum] = fa.polys; // check for lightmap modification bool modified = false; for (int maps = 0; maps < q_shared.MAXLIGHTMAPS && fa.styles[maps] != 255; maps++) { if (d_lightstylevalue[fa.styles[maps]] != fa.cached_light[maps]) { modified = true; break; } } if (modified || fa.dlightframe == r_framecount || // dynamic this frame fa.cached_dlight) // dynamic previously { if (r_dynamic.value != 0) { lightmap_modified[fa.lightmaptexturenum] = true; UpdateRect(fa, ref lightmap_rectchange[fa.lightmaptexturenum]); int offset = fa.lightmaptexturenum * lightmap_bytes * BLOCK_WIDTH * BLOCK_HEIGHT; offset += fa.light_t * BLOCK_WIDTH * lightmap_bytes + fa.light_s * lightmap_bytes; R_BuildLightMap(fa, new ByteArraySegment(lightmaps, offset), BLOCK_WIDTH * lightmap_bytes); } } }
public static texture_t R_TextureAnimation(texture_t t) { if (currententity.frame != 0) { if (t.alternate_anims != null) { t = t.alternate_anims; } } if (t.anim_total == 0) { return(t); } int reletive = (int)(cl.time * 10) % t.anim_total; int count = 0; while (t.anim_min > reletive || t.anim_max <= reletive) { t = t.anim_next; if (t == null) { Sys_Error("R_TextureAnimation: broken cycle"); } if (++count > 100) { Sys_Error("R_TextureAnimation: infinite cycle"); } } return(t); }
public static void DrawTextureChains() { if (gl_texsort.value == 0) { GL_DisableMultitexture(); if (skychain != null) { R_DrawSkyChain(skychain); skychain = null; } return; } model_t world = cl.worldmodel; for (int i = 0; i < world.numtextures; i++) { texture_t t = world.textures[i]; if (t == null) { continue; } msurface_t s = t.texturechain; if (s == null) { continue; } if (i == skytexturenum) { R_DrawSkyChain(s); } else if (i == mirrortexturenum && r_mirroralpha.value != 1.0f) { R_MirrorChain(s); continue; } else { if ((s.flags & q_shared.SURF_DRAWTURB) != 0 && r_wateralpha.value != 1.0f) { continue; // draw translucent water later } for (; s != null; s = s.texturechain) { R_RenderBrushPoly(s); } } t.texturechain = null; } }
public static void R_InitTextures() { // create a simple checkerboard texture for the default r_notexture_mip = new texture_t(); r_notexture_mip.pixels = new byte[16 * 16 + 8 * 8 + 4 * 4 + 2 * 2]; r_notexture_mip.width = r_notexture_mip.height = 16; int offset = 0; r_notexture_mip.offsets[0] = offset; offset += 16 * 16; r_notexture_mip.offsets[1] = offset; offset += 8 * 8; r_notexture_mip.offsets[2] = offset; offset += 4 * 4; r_notexture_mip.offsets[3] = offset; byte[] dest = r_notexture_mip.pixels; for (int m = 0; m < 4; m++) { offset = r_notexture_mip.offsets[m]; for (int y = 0; y < (16 >> m); y++) { for (int x = 0; x < (16 >> m); x++) { if ((y < (8 >> m)) ^ (x < (8 >> m))) { dest[offset] = 0; } else { dest[offset] = 0xff; } offset++; } } } }
public static void R_DrawWaterSurfaces() { if (r_wateralpha.value == 1.0f && gl_texsort.value != 0) { return; } // // go back to the world matrix // GL.LoadMatrix(ref r_world_matrix); if (r_wateralpha.value < 1.0) { GL.Enable(EnableCap.Blend); GL.Color4(1, 1, 1, r_wateralpha.value); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate); } if (gl_texsort.value == 0) { if (waterchain == null) { return; } for (msurface_t s = waterchain; s != null; s = s.texturechain) { GL_Bind(s.texinfo.texture.gl_texturenum); EmitWaterPolys(s); } waterchain = null; } else { for (int i = 0; i < cl.worldmodel.numtextures; i++) { texture_t t = cl.worldmodel.textures[i]; if (t == null) { continue; } msurface_t s = t.texturechain; if (s == null) { continue; } if ((s.flags & q_shared.SURF_DRAWTURB) == 0) { continue; } // set modulate mode explicitly GL_Bind(t.gl_texturenum); for (; s != null; s = s.texturechain) { EmitWaterPolys(s); } t.texturechain = null; } } if (r_wateralpha.value < 1.0) { GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); GL.Color4(1f, 1, 1, 1); GL.Disable(EnableCap.Blend); } }
public static void R_DrawSequentialPoly(msurface_t s) { // // normal lightmaped poly // if ((s.flags & (q_shared.SURF_DRAWSKY | q_shared.SURF_DRAWTURB | q_shared.SURF_UNDERWATER)) == 0) { R_RenderDynamicLightmaps(s); glpoly_t p = s.polys; texture_t t = R_TextureAnimation(s.texinfo.texture); if (gl_mtexable) { // Binds world to texture env 0 GL_SelectTexture(MTexTarget.TEXTURE0_SGIS); GL_Bind(t.gl_texturenum); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); // Binds lightmap to texenv 1 GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1) GL_Bind(lightmap_textures + s.lightmaptexturenum); int i = s.lightmaptexturenum; if (lightmap_modified[i]) { CommitLightmap(i); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Blend); GL.Begin(BeginMode.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 { GL_Bind(t.gl_texturenum); GL.Begin(BeginMode.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(); GL_Bind(lightmap_textures + s.lightmaptexturenum); GL.Enable(EnableCap.Blend); GL.Begin(BeginMode.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 & q_shared.SURF_DRAWTURB) != 0) { GL_DisableMultitexture(); GL_Bind(s.texinfo.texture.gl_texturenum); EmitWaterPolys(s); return; } // // subdivided sky warp // if ((s.flags & q_shared.SURF_DRAWSKY) != 0) { GL_DisableMultitexture(); GL_Bind(solidskytexture); speedscale = (float)realtime * 8; speedscale -= (int)speedscale & ~127; EmitSkyPolys(s); GL.Enable(EnableCap.Blend); GL_Bind(alphaskytexture); speedscale = (float)realtime * 16; speedscale -= (int)speedscale & ~127; EmitSkyPolys(s); GL.Disable(EnableCap.Blend); return; } // // underwater warped with lightmap // R_RenderDynamicLightmaps(s); if (gl_mtexable) { texture_t t = R_TextureAnimation(s.texinfo.texture); GL_SelectTexture(MTexTarget.TEXTURE0_SGIS); GL_Bind(t.gl_texturenum); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); GL_EnableMultitexture(); GL_Bind(lightmap_textures + s.lightmaptexturenum); int i = s.lightmaptexturenum; if (lightmap_modified[i]) { CommitLightmap(i); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Blend); GL.Begin(BeginMode.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 + realtime) * Math.Sin(v[2] * 0.05 + realtime)); nv[1] = (float)(v[1] + 8 * Math.Sin(v[0] * 0.05 + realtime) * Math.Sin(v[2] * 0.05 + realtime)); nv[2] = v[2]; GL.Vertex3(nv); } GL.End(); } else { glpoly_t p = s.polys; texture_t t = R_TextureAnimation(s.texinfo.texture); GL_Bind(t.gl_texturenum); DrawGLWaterPoly(p); GL_Bind(lightmap_textures + s.lightmaptexturenum); GL.Enable(EnableCap.Blend); DrawGLWaterPolyLightmap(p); GL.Disable(EnableCap.Blend); } }
/* ================= Mod_LoadTextures ================= */ static void Mod_LoadTextures(bspfile.lump_t l) { int i, j, pixels, num, max, altmax; bspfile.miptex_t mt; texture_t tx, tx2; texture_t[] anims = new texture_t[10]; texture_t[] altanims = new texture_t[10]; bspfile.dmiptexlump_t m; for(int kk = 0; kk < 10; kk++) { anims[kk] = new texture_t(); altanims[kk] = new texture_t(); } if (l.filelen == 0) { loadmodel.textures = null; return; } bspfile.ByteBuffer buf = new bspfile.ByteBuffer(mod_base, l.fileofs); m = (bspfile.dmiptexlump_t)buf; loadmodel.numtextures = m.nummiptex; loadmodel.textures = new texture_t[m.nummiptex]; for (i=0 ; i<m.nummiptex ; i++) { loadmodel.textures[i] = new texture_t(); if (m.dataofs[i] == -1) continue; buf.ofs = l.fileofs + m.dataofs[i]; mt = (bspfile.miptex_t)buf; if ( (mt.width & 15) != 0 || (mt.height & 15) != 0 ) sys_linux.Sys_Error ("Texture " + mt.name + " is not 16 aligned"); pixels = (int)(mt.width*mt.height/64*85); tx = new texture_t(); tx.pixels = new byte[pixels]; loadmodel.textures[i] = tx; tx.name = mt.name; tx.width = mt.width; tx.height = mt.height; for (j=0 ; j<bspfile.MIPLEVELS ; j++) tx.offsets[j] = mt.offsets[j]/* + sizeof_texture_t*/ - bspfile.sizeof_miptex_t; // the pixels immediately follow the structures Buffer.BlockCopy(buf.buffer, buf.ofs + bspfile.sizeof_miptex_t, tx.pixels, 0, pixels); if (mt.name.StartsWith("sky")) render.R_InitSky(tx); } // // sequence the animations // for (i=0 ; i<m.nummiptex ; i++) { tx = loadmodel.textures[i]; if (tx == null || tx.name[0] != '+') continue; if (tx.anim_next != null) continue; // allready sequenced // find the number of frames in the animation //memset (anims, 0, sizeof(anims)); //memset (altanims, 0, sizeof(altanims)); max = tx.name[1]; altmax = 0; if (max >= 'a' && max <= 'z') max -= 'a' - 'A'; if (max >= '0' && max <= '9') { max -= '0'; altmax = 0; anims[max] = tx; max++; } else if (max >= 'A' && max <= 'J') { altmax = max - 'A'; max = 0; altanims[altmax] = tx; altmax++; } else sys_linux.Sys_Error ("Bad animating texture " + tx.name); for (j=i+1 ; j<m.nummiptex ; j++) { tx2 = loadmodel.textures[j]; if (tx2 == null || tx2.name[0] != '+') continue; if (tx2.name.Substring(2).CompareTo(tx.name.Substring(2)) != 0) continue; num = tx2.name[1]; if (num >= 'a' && num <= 'z') num -= 'a' - 'A'; if (num >= '0' && num <= '9') { num -= '0'; anims[num] = tx2; if (num+1 > max) max = num + 1; } else if (num >= 'A' && num <= 'J') { num = num - 'A'; altanims[num] = tx2; if (num+1 > altmax) altmax = num+1; } else sys_linux.Sys_Error ("Bad animating texture " + tx.name); } // link them all together for (j=0 ; j<max ; j++) { tx2 = anims[j]; if (tx2 == null) sys_linux.Sys_Error ("Missing frame " + j + " of " + tx.name); tx2.anim_total = max * ANIM_CYCLE; tx2.anim_min = j * ANIM_CYCLE; tx2.anim_max = (j+1) * ANIM_CYCLE; tx2.anim_next = anims[ (j+1)%max ]; if (altmax != 0) tx2.alternate_anims = altanims[0]; } for (j=0 ; j<altmax ; j++) { tx2 = altanims[j]; if (tx2 == null) sys_linux.Sys_Error ("Missing frame " + j + " of " + tx.name); tx2.anim_total = altmax * ANIM_CYCLE; tx2.anim_min = j * ANIM_CYCLE; tx2.anim_max = (j+1) * ANIM_CYCLE; tx2.anim_next = altanims[ (j+1)%altmax ]; if (max != 0) tx2.alternate_anims = anims[0]; } } }
public static void R_InitSky(texture_t mt) { byte[] src = mt.pixels; int offset = mt.offsets[0]; // make an average value for the back to avoid // a fringe on the top level const int size = 128 * 128; uint[] trans = new uint[size]; uint[] v8to24 = d_8to24table; int r = 0; int g = 0; int b = 0; Union4b rgba = Union4b.Empty; for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { int p = src[offset + i * 256 + j + 128]; rgba.ui0 = v8to24[p]; trans[(i * 128) + j] = rgba.ui0; r += rgba.b0; g += rgba.b1; b += rgba.b2; } } rgba.b0 = (byte)(r / size); rgba.b1 = (byte)(g / size); rgba.b2 = (byte)(b / size); rgba.b3 = 0; uint transpix = rgba.ui0; if (solidskytexture == 0) { solidskytexture = GenerateTextureNumber(); } GL_Bind(solidskytexture); GL.TexImage2D(TextureTarget.Texture2D, 0, gl_solid_format, 128, 128, 0, PixelFormat.Rgba, PixelType.UnsignedByte, trans); SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear); for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { int p = src[offset + i * 256 + j]; if (p == 0) { trans[(i * 128) + j] = transpix; } else { trans[(i * 128) + j] = v8to24[p]; } } } if (alphaskytexture == 0) { alphaskytexture = GenerateTextureNumber(); } GL_Bind(alphaskytexture); GL.TexImage2D(TextureTarget.Texture2D, 0, gl_alpha_format, 128, 128, 0, PixelFormat.Rgba, PixelType.UnsignedByte, trans); SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear); }