From: <bio...@us...> - 2007-06-02 00:31:21
|
Revision: 1411 http://cs-sdl.svn.sourceforge.net/cs-sdl/?rev=1411&view=rev Author: bioslayer_ Date: 2007-06-01 17:31:11 -0700 (Fri, 01 Jun 2007) Log Message: ----------- Added: Some more options and overloads to SurfaceGl. Modified Paths: -------------- trunk/SdlDotNet/examples/OpenGl/SurfaceGl.cs Modified: trunk/SdlDotNet/examples/OpenGl/SurfaceGl.cs =================================================================== --- trunk/SdlDotNet/examples/OpenGl/SurfaceGl.cs 2007-06-01 08:00:35 UTC (rev 1410) +++ trunk/SdlDotNet/examples/OpenGl/SurfaceGl.cs 2007-06-02 00:31:11 UTC (rev 1411) @@ -31,6 +31,144 @@ namespace SdlDotNet.OpenGl { /// <summary> + /// The texture minifying function is used whenever + /// the pixel being textured maps to an area greater + /// than one texture element. There are six defined + /// minifying functions. Two of them use the nearest + /// one or nearest four texture elements to compute + /// the texture value. The other four use mipmaps. + /// + /// A mipmap is an ordered set of arrays representing + /// the same image at progressively lower resolutions. + /// If the texture has dimensions 2nx2m, there are + /// max(n,m)+1 mipmaps. The first mipmap is the + /// original texture, with dimensions 2nx2m. Each + /// subsequent mipmap has dimensions 2k-1x2l-1, where + /// 2kx2l are the dimensions of the previous mipmap, + /// until either k=0 or l=0. At that point, + /// subsequent mipmaps have dimension 1x2l-1 or 2k-1x1 + /// until the final mipmap, which has dimension 1x1. + /// To define the mipmaps, call glTexImage1D, + /// glTexImage2D, glCopyTexImage1D, or + /// glCopyTexImage2D with the level argument + /// indicating the order of the mipmaps. Level 0 is + /// the original texture; level max(n,m) is the final + /// 1x1 mipmap. + /// </summary> + public enum MinifyingOption : int + { + /// <summary> + /// Returns the value of the texture element + /// that is nearest (in Manhattan distance) + /// to the center of the pixel being + /// textured. + /// </summary> + GL_NEAREST = Gl.GL_NEAREST, + /// <summary> + /// Returns the weighted average of the four + /// texture elements that are closest to the + /// center of the pixel being textured. + /// These can include border texture + /// elements, depending on the values of + /// GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T, + /// and on the exact mapping. + /// </summary> + GL_LINEAR = Gl.GL_LINEAR, + /// <summary> + /// Chooses the mipmap that most closely + /// matches the size of the pixel being + /// textured and uses the GL_NEAREST + /// criterion (the texture element nearest + /// to the center of the pixel) to produce a + /// texture value. + /// </summary> + GL_NEAREST_MIPMAP_NEAREST = Gl.GL_NEAREST_MIPMAP_NEAREST, + /// <summary> + /// Chooses the mipmap that most closely + /// matches the size of the pixel being + /// textured and uses the GL_LINEAR + /// criterion (a weighted average of the + /// four texture elements that are closest + /// to the center of the pixel) to produce a + /// texture value. + /// </summary> + GL_LINEAR_MIPMAP_NEAREST = Gl.GL_LINEAR_MIPMAP_NEAREST, + /// <summary> + /// Chooses the two mipmaps that most + /// closely match the size of the pixel + /// being textured and uses the GL_NEAREST + /// criterion (the texture element nearest + /// to the center of the pixel) to produce a + /// texture value from each mipmap. The + /// final texture value is a weighted + /// average of those two values. + /// </summary> + GL_NEAREST_MIPMAP_LINEAR = Gl.GL_NEAREST_MIPMAP_LINEAR, + /// <summary> + /// Chooses the two mipmaps that most + /// closely match the size of the pixel + /// being textured and uses the GL_LINEAR + /// criterion (a weighted average of the + /// four texture elements that are closest + /// to the center of the pixel) to produce a + /// texture value from each mipmap. The + /// final texture value is a weighted + /// average of those two values. + /// </summary> + GL_LINEAR_MIPMAP_LINEAR = Gl.GL_LINEAR_MIPMAP_LINEAR + } + /// <summary> + /// The texture magnification function is used when + /// the pixel being textured maps to an area less than + /// or equal to one texture element. It sets the + /// texture magnification function to either + /// GL_NEAREST or GL_LINEAR. GL_NEAREST is + /// generally faster than GL_LINEAR, but it can + /// produce textured images with sharper edges because + /// the transition between texture elements is not as + /// smooth. The initial value of GL_TEXTURE_MAG_FILTER + /// is GL_LINEAR. + /// </summary> + public enum MagnificationOption : int + { + /// <summary> + /// Returns the value of the texture element + /// that is nearest (in Manhattan distance) + /// to the center of the pixel being + /// textured. + /// </summary> + GL_NEAREST = Gl.GL_NEAREST, + /// <summary> + /// Returns the weighted average of the four + /// texture elements that are closest to the + /// center of the pixel being textured. + /// These can include border texture + /// elements, depending on the values of + /// GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T, + /// and on the exact mapping. + /// </summary> + GL_LINEAR = Gl.GL_LINEAR + } + /// <summary> + /// The wrap parameter for a texture coordinate + /// </summary> + public enum WrapOption : int + { + /// <summary> + /// Causes texture coordinates to be clamped to the range [0,1] and + /// is useful for preventing wrapping artifacts when + /// mapping a single image onto an object. + /// </summary> + GL_CLAMP = Gl.GL_CLAMP, + /// <summary> + /// Causes texture coordinates to loop around so to remain in the + /// range [0,1] where 1.5 would be .5. this is useful for repeating + /// a texture for a tiled floor. + /// </summary> + GL_REPEAT = Gl.GL_REPEAT + } + + /// <summary> /// Loads a Surface into a OpenGl Texture. /// </summary> [SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", Justification = "Correct Spelling")] @@ -90,6 +228,11 @@ } } + private static bool IsMipMap(MinifyingOption option) + { + return option != MinifyingOption.GL_LINEAR && option != MinifyingOption.GL_NEAREST; + } + #endregion #region Fields @@ -101,6 +244,12 @@ float widthRatio; float heightRatio; + bool needRefresh; + bool needSetOptions; + MinifyingOption minFilter; + MagnificationOption magFilter; + WrapOption wrapS; + WrapOption wrapT; #endregion #region Constructors @@ -116,17 +265,21 @@ /// Creates a new Instance of SurfaceGl. /// </summary> /// <param name="surface">The surface to be copied into a OpenGl Texture.</param> - /// <param name="flipSurface">States if the surface should be flipped when copied into a OpenGl Texture.</param> - public SurfaceGl(Surface surface, bool flipSurface) + /// <param name="isFlipped">States if the surface should be flipped when copied into a OpenGl Texture.</param> + public SurfaceGl(Surface surface, bool isFlipped) { if (surface == null) { throw new ArgumentNullException("surface"); } this.surface = surface; - this.isFlipped = flipSurface; + this.isFlipped = isFlipped; this.textureId = -1; this.textureWidth = -1; this.textureHeight = -1; this.widthRatio = -1; this.heightRatio = -1; + this.minFilter = MinifyingOption.GL_LINEAR; + this.magFilter = MagnificationOption.GL_LINEAR; + this.wrapS = WrapOption.GL_REPEAT; + this.wrapT = WrapOption.GL_REPEAT; } #endregion @@ -144,7 +297,7 @@ if (surface != value) { surface = value; - Refresh(); + needRefresh = true; } } } @@ -199,31 +352,173 @@ { if (isFlipped ^ value) { - Refresh(surface, value); + isFlipped = value; + needRefresh = true; } } } + /// <summary> + /// Gets and Sets + /// The texture minifying function is used whenever + /// the pixel being textured maps to an area greater + /// than one texture element. There are six defined + /// minifying functions. Two of them use the nearest + /// one or nearest four texture elements to compute + /// the texture value. The other four use mipmaps. + /// + /// A mipmap is an ordered set of arrays representing + /// the same image at progressively lower resolutions. + /// If the texture has dimensions 2nx2m, there are + /// max(n,m)+1 mipmaps. The first mipmap is the + /// original texture, with dimensions 2nx2m. Each + /// subsequent mipmap has dimensions 2k-1x2l-1, where + /// 2kx2l are the dimensions of the previous mipmap, + /// until either k=0 or l=0. At that point, + /// subsequent mipmaps have dimension 1x2l-1 or 2k-1x1 + /// until the final mipmap, which has dimension 1x1. + /// To define the mipmaps, call glTexImage1D, + /// glTexImage2D, glCopyTexImage1D, or + /// glCopyTexImage2D with the level argument + /// indicating the order of the mipmaps. Level 0 is + /// the original texture; level max(n,m) is the final + /// 1x1 mipmap. + /// </summary> + public MinifyingOption MinFilter + { + get { return minFilter; } + set + { + if (minFilter != value) + { + if (IsMipMap(minFilter) ^ IsMipMap(value)) + { + needRefresh = true; + } + else + { + needSetOptions = true; + } + minFilter = value; + } + } + } + + /// <summary> + /// Gets and Sets + /// The texture magnification function is used when + /// the pixel being textured maps to an area less than + /// or equal to one texture element. It sets the + /// texture magnification function to either + /// GL_NEAREST or GL_LINEAR. GL_NEAREST is + /// generally faster than GL_LINEAR, but it can + /// produce textured images with sharper edges because + /// the transition between texture elements is not as + /// smooth. The initial value of GL_TEXTURE_MAG_FILTER + /// is GL_LINEAR. + /// </summary> + public MagnificationOption MagFilter + { + get { return magFilter; } + set + { + if (magFilter != value) + { + magFilter = value; + needSetOptions = true; + } + } + } + + /// <summary> + /// Gets and Sets + /// The wrap parameter for texture coordinate s + /// to either GL_CLAMP or GL_REPEAT. GL_CLAMP causes + /// s coordinates to be clamped to the range [0,1] and + /// is useful for preventing wrapping artifacts when + /// mapping a single image onto an object. GL_REPEAT + /// causes the integer part of the s coordinate to be + /// ignored; the GL uses only the fractional part, + /// thereby creating a repeating pattern. Border + /// texture elements are accessed only if wrapping is + /// set to GL_CLAMP. Initially, GL_TEXTURE_WRAP_S is + /// set to GL_REPEAT. + /// </summary> + public WrapOption WrapS + { + get { return wrapS; } + set + { + if (wrapS != value) + { + wrapS = value; + needSetOptions = true; + } + } + } + + /// <summary> + /// Gets and Sets + /// The wrap parameter for texture coordinate t + /// to either GL_CLAMP or GL_REPEAT. GL_CLAMP causes + /// t coordinates to be clamped to the range [0,1] and + /// is useful for preventing wrapping artifacts when + /// mapping a single image onto an object. GL_REPEAT + /// causes the integer part of the s coordinate to be + /// ignored; the GL uses only the fractional part, + /// thereby creating a repeating pattern. Border + /// texture elements are accessed only if wrapping is + /// set to GL_CLAMP. Initially, GL_TEXTURE_WRAP_T is + /// set to GL_REPEAT. + /// </summary> + public WrapOption WrapT + { + get { return wrapT; } + set + { + if (wrapT != value) + { + wrapT = value; + needSetOptions = true; + } + } + } + #endregion #region Methods + private void Check() { - if (textureId <= 0) + if (needRefresh || textureId <= 0) { Refresh(); } + else if (needSetOptions) + { + BindOptions(); + } } - private Surface TransformSurface(bool flipSurface) + private void BindOptions() { + Gl.glBindTexture(Gl.GL_TEXTURE_2D, textureId); + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, (int)minFilter); + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, (int)magFilter); + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, (int)wrapS); + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, (int)wrapT); + needSetOptions = false; + } + + private Surface TransformSurface(bool isFlipped) + { byte alpha = surface.Alpha; Surface textureSurface2 = null; surface.Alpha = 0; try { Surface textureSurface = surface; - if (flipSurface) + if (isFlipped) { textureSurface = textureSurface.CreateFlippedVerticalSurface(); textureSurface2 = textureSurface; @@ -234,7 +529,7 @@ finally { surface.Alpha = alpha; - if (flipSurface) + if (isFlipped) { textureSurface2.Dispose(); } @@ -263,20 +558,34 @@ /// </summary> public void Refresh() { - Refresh(surface, isFlipped); + Refresh(this.surface, this.isFlipped, this.minFilter, this.magFilter, this.wrapS, this.wrapT); } /// <summary> /// Reloads the OpenGl Texture from the Surface. /// </summary> /// <param name="surface">The surface to load from.</param> - /// <param name="flipSurface">States if the surface should be flipped when moved into the OpenGl Texture.</param> - public void Refresh(Surface surface, bool flipSurface) + /// <param name="isFlipped">States if the surface should be flipped when moved into the OpenGl Texture.</param> + public void Refresh(Surface surface, bool isFlipped) { + Refresh(surface, isFlipped, this.minFilter, this.magFilter, this.wrapS, this.wrapT); + } + + /// <summary> + /// Reloads the OpenGl Texture from the Surface. + /// </summary> + /// <param name="surface">The surface to load from.</param> + /// <param name="isFlipped">States if the surface should be flipped when moved into the OpenGl Texture.</param> + /// <param name="minFilter">"The openGl filter used for minifying"</param> + /// <param name="magFilter">"The openGl filter used for magnification"</param> + /// <param name="wrapS">The wrap parameter for texture coordinate S</param> + /// <param name="wrapT">The wrap parameter for texture coordinate T</param> + public void Refresh(Surface surface, bool isFlipped, MinifyingOption minFilter, MagnificationOption magFilter, WrapOption wrapS, WrapOption wrapT) + { if (surface == null) { throw new ArgumentNullException("surface"); } this.surface = surface; this.Delete(); - using (Surface textureSurface = TransformSurface(flipSurface)) + using (Surface textureSurface = TransformSurface(isFlipped)) { int[] textures = new int[1]; Gl.glGenTextures(1, textures); @@ -284,14 +593,34 @@ this.textureWidth = textureSurface.Width; this.textureHeight = textureSurface.Height; - this.isFlipped = flipSurface; + this.isFlipped = isFlipped; + this.minFilter = minFilter; + this.magFilter = magFilter; + this.wrapS = wrapS; + this.wrapT = wrapT; this.widthRatio = (float)surface.Width / textureWidth; this.heightRatio = (float)surface.Height / textureHeight; Gl.glBindTexture(Gl.GL_TEXTURE_2D, textureId); - Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, textureSurface.BytesPerPixel, textureWidth, textureHeight, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, textureSurface.Pixels); - Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR); - Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, (int)minFilter); + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, (int)magFilter); + + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, (int)wrapS); + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, (int)wrapT); + + + + if (minFilter == MinifyingOption.GL_LINEAR || minFilter == MinifyingOption.GL_NEAREST) + { + Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, textureSurface.BytesPerPixel, textureWidth, textureHeight, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, textureSurface.Pixels); + } + else + { + Glu.gluBuild2DMipmaps(Gl.GL_TEXTURE_2D, textureSurface.BytesPerPixel, textureWidth, textureHeight, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, textureSurface.Pixels); + } + + needRefresh = false; + needSetOptions = false; } } @@ -300,7 +629,7 @@ /// </summary> public void Draw() { - this.Draw(0,0); + this.Draw(0, 0, surface.Width, surface.Height); } /// <summary> @@ -309,15 +638,26 @@ /// <param name="location">The offset for the Texture.</param> public void Draw(Point location) { - Draw(location.X, location.Y); + Draw(location.X, location.Y,surface.Width,surface.Height); } + + /// <summary> + /// Draws the Texture. + /// </summary> + /// <param name="rectangle">the rectagle where the texture will be drawn.</param> + public void Draw(Rectangle rectangle) + { + Draw(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); + } /// <summary> /// Draws the Texture. /// </summary> /// <param name="locationX">The x offset for the Texture.</param> /// <param name="locationY">The y offset for the Texture.</param> - public void Draw(float locationX, float locationY) + /// <param name="width">The width fo the area where the Texture will be drawn.</param> + /// <param name="height">The height fo the area where the Texture will be drawn.</param> + public void Draw(float locationX, float locationY, float width, float height) { Check(); Gl.glBindTexture(Gl.GL_TEXTURE_2D, this.textureId); @@ -325,11 +665,11 @@ Gl.glTexCoord2f(0, heightRatio); Gl.glVertex2f(locationX, locationY); Gl.glTexCoord2f(widthRatio, heightRatio); - Gl.glVertex2f(locationX + surface.Width, locationY); + Gl.glVertex2f(locationX + width, locationY); Gl.glTexCoord2f(widthRatio, 0); - Gl.glVertex2f(locationX + surface.Width, locationY + surface.Height); + Gl.glVertex2f(locationX + width, locationY + height); Gl.glTexCoord2f(0, 0); - Gl.glVertex2f(locationX, locationY + surface.Height); + Gl.glVertex2f(locationX, locationY + height); Gl.glEnd(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |