/** * initPermTexture(GLuinttexID) - create and load a 2D texture for a combined index permutation * and gradient lookup table. This texture is used for 2D and 3D noise, both classic and simplex. */ private void initPermTexture(GL gl, int[] texID) { ByteBuffer pixels; int i, j; gl.glGenTextures(1, texID, 0); // Generate a unique texture ID gl.glBindTexture(GL.GL_TEXTURE_2D, texID[0]); // Bind the texture to texture unit 0 pixels = ByteBuffer.allocateDirect(256 * 256 * 4); for (i = 0; i < 256; i++) for (j = 0; j < 256; j++) { int offset = (i * 256 + j) * 4; int value = perm[(j + perm[i]) & 0xFF]; pixels.put(offset, (byte) (grad3[value & 0x0F][0] * 64 + 64)); // Gradient x pixels.put(offset + 1, (byte) (grad3[value & 0x0F][1] * 64 + 64)); // Gradient y pixels.put(offset + 2, (byte) (grad3[value & 0x0F][2] * 64 + 64)); // Gradient z pixels.put(offset + 3, (byte) value); // Permuted index } // GLFW texture loading functions won't work here - we need // GL.GL_NEAREST lookup. gl.glTexImage2D( GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, 256, 256, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixels); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); }
/** * Creates a texture in the given OpenGL context. * * @param gl the context * @param image the RGB or RGBA image serving as texture source * @param repeat whether the texture should should have repeat mode activated * @return the texture name (ID) */ private static int createTexture(GL gl, BufferedImage image, boolean repeat) { if (image == null) { return -1; } final int[] tmp = new int[1]; gl.glGenTextures(1, tmp, 0); int tex = tmp[0]; gl.glBindTexture(GL_TEXTURE_2D, tex); int[] data = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); ByteBuffer dest = ByteBuffer.allocate(data.length * BufferUtil.SIZEOF_INT); // TODO direct? dest.order(ByteOrder.nativeOrder()); dest.asIntBuffer().put(data, 0, data.length); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); int wrapMode = (repeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE; gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode); int oglFormat = (image.getType() == BufferedImage.TYPE_INT_ARGB) ? GL_RGBA : GL_RGB; gl.glTexImage2D( GL_TEXTURE_2D, 0, oglFormat, image.getWidth(), image.getHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, dest); // (new GLU()).gluBuild2DMipmaps(GL.GL_TEXTURE_2D, GL.GL_RGB, image.getWidth(), // image.getHeight(), GL.GL_BGRA, // GL.GL_UNSIGNED_BYTE, dest); return tex; }
void LoadTextures(final GL gl) { // There is only one texture needed here--we'll set up a basic // checkerboard--which is used to modulate the diffuse channel in the // fragment shader. final int[] handle = new int[1]; gl.glGenTextures(1, handle, 0); // Basic OpenGL texture state setup gl.glBindTexture(GL.GL_TEXTURE_2D, handle[0]); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_GENERATE_MIPMAP_SGIS, GL.GL_TRUE); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); // Fill in the texture map. final int RES = 512; final float[] data = new float[RES * RES * 4]; int dp = 0; for (int i = 0; i < RES; ++i) for (int j = 0; j < RES; ++j) { if ((i / 32 + j / 32) % 2 != 0) { data[dp++] = .7f; data[dp++] = .7f; data[dp++] = .7f; } else { data[dp++] = .1f; data[dp++] = .1f; data[dp++] = .1f; } data[dp++] = 1.0f; } gl.glTexImage2D( GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, RES, RES, 0, GL.GL_RGBA, GL.GL_FLOAT, FloatBuffer.wrap(data)); // Tell Cg which texture handle should be associated with the sampler2D // parameter to the fragment shader. CgGL.cgGLSetTextureParameter( CgGL.cgGetNamedParameter(fragmentProgram, "diffuseMap"), handle[0]); }
/** * Updates the content area of the specified target of this texture using the data in the given * image. In general this is intended for construction of cube maps. * * @throws GLException if no OpenGL context was current or if any OpenGL-related errors occurred */ public void updateImage(TextureData data, int target) throws GLException { GL gl = GLU.getCurrentGL(); imgWidth = data.getWidth(); imgHeight = data.getHeight(); aspectRatio = (float) imgWidth / (float) imgHeight; mustFlipVertically = data.getMustFlipVertically(); int texTarget = 0; int texParamTarget = this.target; // See whether we have automatic mipmap generation support boolean haveAutoMipmapGeneration = (gl.isExtensionAvailable("GL_VERSION_1_4") || gl.isExtensionAvailable("GL_SGIS_generate_mipmap")); // Indicate to the TextureData what functionality is available data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr")); data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2")); // Note that automatic mipmap generation doesn't work for // GL_ARB_texture_rectangle if ((!isPowerOfTwo(imgWidth) || !isPowerOfTwo(imgHeight)) && !haveNPOT(gl)) { haveAutoMipmapGeneration = false; } boolean expandingCompressedTexture = false; if (data.getMipmap() && !haveAutoMipmapGeneration) { // GLU always scales the texture's dimensions to be powers of // two. It also doesn't really matter exactly what the texture // width and height are because the texture coords are always // between 0.0 and 1.0. imgWidth = nextPowerOfTwo(imgWidth); imgHeight = nextPowerOfTwo(imgHeight); texWidth = imgWidth; texHeight = imgHeight; texTarget = GL.GL_TEXTURE_2D; } else if ((isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight)) || haveNPOT(gl)) { if (DEBUG) { if (isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight)) { System.err.println("Power-of-two texture"); } else { System.err.println("Using GL_ARB_texture_non_power_of_two"); } } texWidth = imgWidth; texHeight = imgHeight; texTarget = GL.GL_TEXTURE_2D; } else if (haveTexRect(gl) && !data.isDataCompressed()) { // GL_ARB_texture_rectangle does not work for compressed textures if (DEBUG) { System.err.println("Using GL_ARB_texture_rectangle"); } texWidth = imgWidth; texHeight = imgHeight; texTarget = GL.GL_TEXTURE_RECTANGLE_ARB; } else { // If we receive non-power-of-two compressed texture data and // don't have true hardware support for compressed textures, we // can fake this support by producing an empty "compressed" // texture image, using glCompressedTexImage2D with that to // allocate the texture, and glCompressedTexSubImage2D with the // incoming data. if (data.isDataCompressed()) { if (data.getMipmapData() != null) { // We don't currently support expanding of compressed, // mipmapped non-power-of-two textures to the nearest power // of two; the obvious port of the non-mipmapped code didn't // work throw new GLException( "Mipmapped non-power-of-two compressed textures only supported on OpenGL 2.0 hardware (GL_ARB_texture_non_power_of_two)"); } expandingCompressedTexture = true; } if (DEBUG) { System.err.println("Expanding texture to power-of-two dimensions"); } if (data.getBorder() != 0) { throw new RuntimeException( "Scaling up a non-power-of-two texture which has a border won't work"); } texWidth = nextPowerOfTwo(imgWidth); texHeight = nextPowerOfTwo(imgHeight); texTarget = GL.GL_TEXTURE_2D; } texParamTarget = texTarget; setImageSize(imgWidth, imgHeight, texTarget); if (target != 0) { // Allow user to override auto detection and skip bind step (for // cubemap construction) texTarget = target; if (this.target == 0) { throw new GLException("Override of target failed; no target specified yet"); } texParamTarget = this.target; gl.glBindTexture(texParamTarget, texID); } else { gl.glBindTexture(texTarget, texID); } if (data.getMipmap() && !haveAutoMipmapGeneration) { int[] align = new int[1]; gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0); // save alignment gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, data.getAlignment()); if (data.isDataCompressed()) { throw new GLException("May not request mipmap generation for compressed textures"); } try { GLU glu = new GLU(); glu.gluBuild2DMipmaps( texTarget, data.getInternalFormat(), data.getWidth(), data.getHeight(), data.getPixelFormat(), data.getPixelType(), data.getBuffer()); } finally { gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, align[0]); // restore alignment } } else { checkCompressedTextureExtensions(data); Buffer[] mipmapData = data.getMipmapData(); if (mipmapData != null) { int width = texWidth; int height = texHeight; for (int i = 0; i < mipmapData.length; i++) { if (data.isDataCompressed()) { // Need to use glCompressedTexImage2D directly to allocate and fill this image // Avoid spurious memory allocation when possible gl.glCompressedTexImage2D( texTarget, i, data.getInternalFormat(), width, height, data.getBorder(), mipmapData[i].remaining(), mipmapData[i]); } else { // Allocate texture image at this level gl.glTexImage2D( texTarget, i, data.getInternalFormat(), width, height, data.getBorder(), data.getPixelFormat(), data.getPixelType(), null); updateSubImageImpl(data, texTarget, i, 0, 0, 0, 0, data.getWidth(), data.getHeight()); } width = Math.max(width / 2, 1); height = Math.max(height / 2, 1); } } else { if (data.isDataCompressed()) { if (!expandingCompressedTexture) { // Need to use glCompressedTexImage2D directly to allocate and fill this image // Avoid spurious memory allocation when possible gl.glCompressedTexImage2D( texTarget, 0, data.getInternalFormat(), texWidth, texHeight, data.getBorder(), data.getBuffer().capacity(), data.getBuffer()); } else { ByteBuffer buf = DDSImage.allocateBlankBuffer(texWidth, texHeight, data.getInternalFormat()); gl.glCompressedTexImage2D( texTarget, 0, data.getInternalFormat(), texWidth, texHeight, data.getBorder(), buf.capacity(), buf); updateSubImageImpl(data, texTarget, 0, 0, 0, 0, 0, data.getWidth(), data.getHeight()); } } else { if (data.getMipmap() && haveAutoMipmapGeneration) { // For now, only use hardware mipmapping for uncompressed 2D // textures where the user hasn't explicitly specified // mipmap data; don't know about interactions between // GL_GENERATE_MIPMAP and glCompressedTexImage2D gl.glTexParameteri(texParamTarget, GL.GL_GENERATE_MIPMAP, GL.GL_TRUE); usingAutoMipmapGeneration = true; } gl.glTexImage2D( texTarget, 0, data.getInternalFormat(), texWidth, texHeight, data.getBorder(), data.getPixelFormat(), data.getPixelType(), null); updateSubImageImpl(data, texTarget, 0, 0, 0, 0, 0, data.getWidth(), data.getHeight()); } } } int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR); int magFilter = GL.GL_LINEAR; int wrapMode = (gl.isExtensionAvailable("GL_VERSION_1_2") ? GL.GL_CLAMP_TO_EDGE : GL.GL_CLAMP); // REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB if (texTarget != GL.GL_TEXTURE_RECTANGLE_ARB) { gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_MIN_FILTER, minFilter); gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_MAG_FILTER, magFilter); gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_S, wrapMode); gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_T, wrapMode); if (this.target == GL.GL_TEXTURE_CUBE_MAP) { gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_R, wrapMode); } } // Don't overwrite target if we're loading e.g. faces of a cube // map if ((this.target == 0) || (this.target == GL.GL_TEXTURE_2D) || (this.target == GL.GL_TEXTURE_RECTANGLE_ARB)) { this.target = texTarget; } // This estimate will be wrong for cube maps estimatedMemorySize = data.getEstimatedMemorySize(); }
/** * Loads a TGA file into memory * * @param gl * @param texture * @param filename * @throws IOException */ private void loadTGA(GL gl, TextureImage texture, String filename) throws IOException { // Used To Compare TGA Header ByteBuffer TGAcompare = GLBuffers.newDirectByteBuffer(12); // Uncompressed TGA Header byte[] TGAheader = new byte[] {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ByteBuffer header = GLBuffers.newDirectByteBuffer(6); // First 6 Useful // Bytes // From The // Header int bytesPerPixel, // Holds Number Of Bytes Per Pixel Used In The TGA // File imageSize, // Used To Store The Image Size When Setting Aside Ram type = GL.GL_RGBA; // Set The Default GL Mode To RBGA (32 BPP) ReadableByteChannel file = null; try { file = Channels.newChannel(ResourceRetriever.getResourceAsStream(filename)); readBuffer(file, TGAcompare); readBuffer(file, header); for (int i = 0; i < TGAcompare.capacity(); i++) // Does The Header Match What We Want? if (TGAcompare.get(i) != TGAheader[i]) { throw new IOException("Invalid TGA header"); } texture.width = header.get(1) << 8 | header.get(0); // Determine The // TGA // Width(highbyte*256+lowbyte) texture.height = header.get(3) << 8 | header.get(2); // Determine // The TGA // Height(highbyte*256+lowbyte) if (texture.width <= 0) { // Is The Width Less Than Or Equal To Zero throw new IOException("Image has negative width"); } if (texture.height <= 0) { // Is The Height Less Than Or Equal To // Zero throw new IOException("Image has negative height"); } if (header.get(4) != 24 && header.get(4) != 32) { // Is The TGA 24 // or 32 Bit? throw new IOException("Image is not 24 or 32-bit"); } texture.bpp = header.get(4); // Grab The TGA's Bits Per Pixel (24 or // 32) bytesPerPixel = texture.bpp / 8; // Divide By 8 To Get The Bytes Per // Pixel // Calculate the memory required for the TGA Data imageSize = texture.width * texture.height * bytesPerPixel; // Reserve memory to hold the TGA Data texture.imageData = GLBuffers.newDirectByteBuffer(imageSize); readBuffer(file, texture.imageData); // Loop Through The Image Data for (int i = 0; i < imageSize; i += bytesPerPixel) { // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue) // Temporarily Store The Value At Image Data 'i' byte temp = texture.imageData.get(i); // Set the 1st Byte to the value Of the 3rd Byte texture.imageData.put(i, texture.imageData.get(i + 2)); // Set The 3rd Byte To The Value In 'temp' (1st Byte Value) texture.imageData.put(i + 2, temp); } // Build A Texture From The Data gl.glGenTextures(1, texture.texID, 0); // Generate OpenGL texture // IDs gl.glBindTexture(GL.GL_TEXTURE_2D, texture.texID[0]); // Bind Our // Texture gl.glTexParameterf( GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); // Linear Filtered gl.glTexParameterf( GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); // Linear Filtered if (texture.bpp == 24) // Was The TGA 24 Bits type = GL.GL_RGB; // If So Set The 'type' To GL_RGB gl.glTexImage2D( GL.GL_TEXTURE_2D, 0, type, texture.width, texture.height, 0, type, GL.GL_UNSIGNED_BYTE, texture.imageData); } finally { if (file != null) { try { file.close(); } catch (IOException n) { } } } }
/* Given user requested textures size, determine if it fits. If it doesn't then * halve both sides and make the determination again until it does fit ( for * IR only ). * Note that proxy textures are not implemented in RE* even though they * advertise the texture extension. * Note that proxy textures are implemented but not according to spec in IMPACT* */ public static void closestFit( GL gl, int target, int width, int height, int internalFormat, int format, int type, int[] newWidth, int[] newHeight) { // Use proxy textures if OpenGL version >= 1.1 if (Double.parseDouble(gl.glGetString(GL.GL_VERSION).trim().substring(0, 3)) >= 1.1) { int widthPowerOf2 = nearestPower(width); int heightPowerOf2 = nearestPower(height); int[] proxyWidth = new int[1]; boolean noProxyTextures = false; // Some drivers (in particular, ATI's) seem to set a GL error // when proxy textures are used even though this is in violation // of the spec. Guard against this and interactions with the // DebugGL by watching for GLException. try { do { // compute level 1 width & height, clamping each at 1 int widthAtLevelOne = ((width > 1) ? (widthPowerOf2 >> 1) : widthPowerOf2); int heightAtLevelOne = ((height > 1) ? (heightPowerOf2 >> 1) : heightPowerOf2); int proxyTarget; assert (widthAtLevelOne > 0); assert (heightAtLevelOne > 0); // does width x height at level 1 & all their mipmaps fit? if (target == GL2GL3.GL_TEXTURE_2D || target == GL2GL3.GL_PROXY_TEXTURE_2D) { proxyTarget = GL2GL3.GL_PROXY_TEXTURE_2D; gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne, heightAtLevelOne, 0, format, type, null); } else if ((target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_X) || (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_X) || (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Y) || (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) || (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Z) || (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)) { proxyTarget = GL2GL3.GL_PROXY_TEXTURE_CUBE_MAP; gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne, heightAtLevelOne, 0, format, type, null); } else { assert (target == GL2GL3.GL_TEXTURE_1D || target == GL2GL3.GL_PROXY_TEXTURE_1D); proxyTarget = GL2GL3.GL_PROXY_TEXTURE_1D; gl.getGL2GL3() .glTexImage1D( proxyTarget, 1, internalFormat, widthAtLevelOne, 0, format, type, null); } if (gl.isGL2GL3()) { gl.getGL2GL3() .glGetTexLevelParameteriv(proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0); } else { proxyWidth[0] = 0; } // does it fit? if (proxyWidth[0] == 0) { // nope, so try again with theses sizes if (widthPowerOf2 == 1 && heightPowerOf2 == 1) { /* A 1x1 texture couldn't fit for some reason so break out. This * should never happen. But things happen. The disadvantage with * this if-statement is that we will never be aware of when this * happens since it will silently branch out. */ noProxyTextures = true; break; } widthPowerOf2 = widthAtLevelOne; heightPowerOf2 = heightAtLevelOne; } // else it does fit } while (proxyWidth[0] == 0); } catch (GLException e) { noProxyTextures = true; } // loop must terminate // return the width & height at level 0 that fits if (!noProxyTextures) { newWidth[0] = widthPowerOf2; newHeight[0] = heightPowerOf2; return; } } int[] maxsize = new int[1]; gl.glGetIntegerv(GL2GL3.GL_MAX_TEXTURE_SIZE, maxsize, 0); // clamp user's texture sizes to maximum sizes, if necessary newWidth[0] = nearestPower(width); if (newWidth[0] > maxsize[0]) { newWidth[0] = maxsize[0]; } newHeight[0] = nearestPower(height); if (newHeight[0] > maxsize[0]) { newHeight[0] = maxsize[0]; } }
public void prerenderToTexture(GL gl) { int texSize = 256; final int[] tmp = new int[1]; gl.glGenTextures(1, tmp, 0); textureID = tmp[0]; gl.glBindTexture(GL_TEXTURE_2D, textureID); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gl.glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_BGRA, GL_UNSIGNED_BYTE, null); final int[] fbo = new int[1]; gl.glGenFramebuffersEXT(1, IntBuffer.wrap(fbo)); gl.glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo[0]); gl.glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureID, 0); gl.glDrawBuffers(1, IntBuffer.wrap(new int[] {GL_COLOR_ATTACHMENT0_EXT})); final int[] rba = new int[1]; gl.glGenRenderbuffersEXT(1, IntBuffer.wrap(rba)); gl.glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rba[0]); gl.glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, texSize, texSize); gl.glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rba[0]); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glPushAttrib(GL_VIEWPORT_BIT); gl.glViewport(0, 0, texSize, texSize); gl.glMatrixMode(GL.GL_PROJECTION); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glOrtho(0, texSize, 0, texSize, 0, 10); gl.glMatrixMode(GL.GL_MODELVIEW); Set<MapElement> map = State.getInstance().getMapInfo().queryElements(detailLevel, bounds, true); gl.glDisable(GL_TEXTURE_2D); gl.glColor3f(1, 1, 1); for (MapElement element : map) { if (element instanceof Street) { drawLine( gl, ((Street) element).getDrawingSize() / (float) Projection.getZoomFactor(detailLevel), ((Street) element).getNodes()); } } gl.glColor3f(0.3f, 0.3f, 0.3f); for (MapElement element : map) { if ((element instanceof Area) && (((Area) element).getWayInfo().isBuilding())) { gl.glBegin(GL_POLYGON); for (Node node : ((Area) element).getNodes()) { Coordinates pos = getLocalCoordinates(node.getPos()); gl.glVertex3f(pos.getLongitude(), pos.getLatitude(), 0f); } gl.glEnd(); } } gl.glEnable(GL_TEXTURE_2D); gl.glMatrixMode(GL.GL_PROJECTION); gl.glPopMatrix(); gl.glMatrixMode(GL.GL_MODELVIEW); gl.glPopAttrib(); gl.glPopMatrix(); gl.glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); gl.glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); gl.glDeleteFramebuffersEXT(1, fbo, 0); gl.glDeleteRenderbuffersEXT(1, rba, 0); }