public Texture2D ParseImageProgram(string source, ref DateTime timeStamp, ref TextureDepth depth) { _lexer = new idLexer(LexerOptions.NoFatalErrors | LexerOptions.NoStringConcatination | LexerOptions.NoStringEscapeCharacters | LexerOptions.AllowPathNames); _lexer.LoadMemory(source, source); return(ParseImageProgram(ref timeStamp, ref depth, false)); }
public Texture2D ParseImageProgram(string source, ref DateTime timeStamp, ref TextureDepth depth) { _lexer = new idLexer(LexerOptions.NoFatalErrors | LexerOptions.NoStringConcatination | LexerOptions.NoStringEscapeCharacters | LexerOptions.AllowPathNames); _lexer.LoadMemory(source, source); return ParseImageProgram(ref timeStamp, ref depth, false); }
public FrameBufferColor(int w, int h) { IW = w; IH = h; FBO = GL.GenFramebuffer( ); GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO); BB = new Texture2D(w, h, false); DB = new TextureDepth(w, h); DRB = GL.GenRenderbuffer( ); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, DRB); GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent, w, h); GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, DRB); GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, BB.ID, 0); DrawBuffersEnum db = DrawBuffersEnum.ColorAttachment0; GL.DrawBuffers(1, ref db); if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) { Console.WriteLine("Framebuffer failure."); while (true) { } } Console.WriteLine("Framebuffer success."); GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0); }
public Texture2D ParseImageProgram(idLexer lexer) { _lexer = lexer; DateTime timeStamp = DateTime.Now;; TextureDepth depth = TextureDepth.Default; return(ParseImageProgram(ref timeStamp, ref depth, true)); }
// background loading information. /*private idImage _partialImage; // shrunken, space-saving version * private bool _isPartialImage; // true if this is pointed to by another image*/ #endregion #region Constructor public idImage(string name, ImageLoadCallback generator) { _name = name; _generator = generator; _type = TextureType.Disabled; _filter = TextureFilter.Default; _repeat = TextureRepeat.Repeat; _depth = TextureDepth.Default; _cubeFiles = CubeFiles.TwoD; }
public idImage(string name, TextureType type, TextureFilter filter, TextureRepeat repeat, TextureDepth depth, CubeFiles cubeMap, bool allowDownSize) { _name = name; _type = type; _filter = filter; _repeat = repeat; _depth = depth; _cubeFiles = cubeMap; _allowDownSize = allowDownSize; }
public void Dispose() { fixed(uint *FrameBufferPtr = &FrameBufferId) { GL.glDeleteFramebuffers(1, FrameBufferPtr); if ((RenderTargetLayers & RenderTargetLayers.Color) != 0) { TextureColor.Dispose(); } if ((RenderTargetLayers & RenderTargetLayers.Depth) != 0) { TextureDepth.Dispose(); } if ((RenderTargetLayers & RenderTargetLayers.Stencil) != 0) { RenderBufferStencil.Dispose(); } } }
public FrameBufferColorMRT(int num, int w, int h, TextureFormat format = TextureFormat.Normal) { IW = w; IH = h; FBO = GL.GenFramebuffer(); GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO); for (int i = 0; i < num; i++) { Targets.Add(new Texture2D(w, h, false, format)); } //BB = new Texture2D(w, h, false, format); DB = new TextureDepth(w, h); DRB = GL.GenRenderbuffer(); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, DRB); GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent, w, h); GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, DRB); DrawBuffersEnum[] drawb = new DrawBuffersEnum[num]; for (int i = 0; i < num; i++) { FramebufferAttachment fa = FramebufferAttachment.ColorAttachment0; switch (i) { case 0: fa = FramebufferAttachment.ColorAttachment0; drawb[0] = DrawBuffersEnum.ColorAttachment0; break; case 1: fa = FramebufferAttachment.ColorAttachment1; drawb[1] = DrawBuffersEnum.ColorAttachment1; break; case 2: fa = FramebufferAttachment.ColorAttachment2; drawb[2] = DrawBuffersEnum.ColorAttachment2; break; case 3: fa = FramebufferAttachment.ColorAttachment3; drawb[3] = DrawBuffersEnum.ColorAttachment3; break; case 4: fa = FramebufferAttachment.ColorAttachment4; drawb[4] = DrawBuffersEnum.ColorAttachment4; break; case 5: fa = FramebufferAttachment.ColorAttachment5; drawb[5] = DrawBuffersEnum.ColorAttachment5; break; case 6: fa = FramebufferAttachment.ColorAttachment6; drawb[6] = DrawBuffersEnum.ColorAttachment6; break; case 7: fa = FramebufferAttachment.ColorAttachment7; drawb[7] = DrawBuffersEnum.ColorAttachment7; break; } GL.FramebufferTexture(FramebufferTarget.Framebuffer, fa, Targets[i].ID, 0); } // DrawBuffersEnum db = DrawBuffersEnum.ColorAttachment0; GL.DrawBuffers(drawb.Length, drawb); if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) { Console.WriteLine("Framebuffer failure."); } Console.WriteLine("Framebuffer success."); GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0); }
public Texture2D LoadImageProgram(string name, ref DateTime timeStamp, ref TextureDepth depth) { return ParseImageProgram(name, ref timeStamp, ref depth); }
/// <summary> /// Finds or loads the given image, always returning a valid image pointer. /// Loading of the image may be deferred for dynamic loading. /// </summary> /// <param name="name"></param> /// <param name="filter"></param> /// <param name="allowDownSize"></param> /// <param name="repeat"></param> /// <param name="depth"></param> /// <param name="cubeMap"></param> /// <returns></returns> public idImage ImageFromFile(string name, TextureFilter filter, bool allowDownSize, TextureRepeat repeat, TextureDepth depth, CubeFiles cubeMap) { if((name == null) || (name == string.Empty) || (name.Equals("default", StringComparison.OrdinalIgnoreCase) == true) || (name.Equals("_default", StringComparison.OrdinalIgnoreCase) == true)) { idE.DeclManager.MediaPrint("DEFAULTED"); return this.DefaultImage; } idImage image; // strip any .tga file extensions from anywhere in the _name, including image program parameters name = name.Replace(".tga", ""); // // see if the image is already loaded, unless we // are in a reloadImages call // if(_imageDictionary.TryGetValue(name, out image) == true) { // the built in's, like _white and _flat always match the other options if(name.StartsWith("_") == true) { return image; } if(image.CubeFiles != cubeMap) { idConsole.Error("Image '{0}' has been referenced with conflicting cube map states", name); } if((image.Filter != filter) || (image.Repeat != repeat)) { // we might want to have the system reset these parameters on every bind and // share the image data // FIXME: this might be the wrong behaviour. original d3 would return a new image but our dictionary // requires unique keys. return image; } else { if((image.AllowDownSize == allowDownSize) && (image.Depth == depth)) { // note that it is used this level load image.LevelLoadReferenced = true; return image; } // the same image is being requested, but with a different allowDownSize or depth // so pick the highest of the two and reload the old image with those parameters if(image.AllowDownSize == false) { allowDownSize = false; } if(image.Depth > depth) { depth = image.Depth; } if((image.AllowDownSize == allowDownSize) && (image.Depth == depth)) { // the already created one is already the highest quality image.LevelLoadReferenced = true; return image; } /*image.AllowDownSize = allowDownSize; image.Depth = depth;*/ image.LevelLoadReferenced = true; if((idE.CvarSystem.GetBool("image_preload") == true) && (_insideLevelLoad == false)) { image.ReferencedOutsideLevelLoad = true; image.ActuallyLoadImage(true, false); // check for precompressed, load is from front end idE.DeclManager.MediaPrint("{0}x{1} {1} (reload for mixed referneces)", image.Width, image.Height, image.Name); } return image; } } // HACK: to allow keep fonts from being mip'd, as new ones will be introduced with localization // this keeps us from having to make a material for each font tga if(name.Contains("fontImage_") == true) { allowDownSize = false; } // // create a new image // image = CreateImage(name, TextureType.TwoD, filter, repeat, depth, cubeMap, allowDownSize); image.LevelLoadReferenced = true; // load it if we aren't in a level preload if((idE.CvarSystem.GetBool("image_preload") == true) && (_insideLevelLoad == false)) { image.ReferencedOutsideLevelLoad = true; image.ActuallyLoadImage(true, false); // check for precompressed, load is from front end idE.DeclManager.MediaPrint("{0}x{1} {2}", image.Width, image.Height, image.Name); } else { idE.DeclManager.MediaPrint(image.Name); } return image; }
/// <summary> /// Finds or loads the given image, always returning a valid image pointer. /// Loading of the image may be deferred for dynamic loading. /// </summary> /// <param name="name"></param> /// <param name="filter"></param> /// <param name="allowDownSize"></param> /// <param name="repeat"></param> /// <param name="depth"></param> /// <returns></returns> public idImage ImageFromFile(string name, TextureFilter filter, bool allowDownSize, TextureRepeat repeat, TextureDepth depth) { return ImageFromFile(name, filter, allowDownSize, repeat, depth, CubeFiles.TwoD); }
private idImage CreateImage(string name, TextureType type, TextureFilter filter, TextureRepeat repeat, TextureDepth depth, CubeFiles cubeMap, bool allowDownSize) { idImage image = new idImage(name, type, filter, repeat, depth, cubeMap, allowDownSize); _images.Add(image); _imageDictionary.Add(name, image); return image; }
/// <summary> /// If data is NULL, the timestamps will be filled in, but no image will be generated /// If both data and timeStamp are NULL, it will just advance past it, which can be /// used to parse an image program from a text stream. /// </summary> /// <param name="source"></param> /// <param name="timeStamp"></param> /// <param name="depth"></param> /// <returns></returns> public Texture2D ParseImageProgram(string source, ref DateTime timeStamp, ref TextureDepth depth) { return new idImageProgramParser().ParseImageProgram(source, ref timeStamp, ref depth); }
/// <summary> /// Used by callback functions to specify the actual data /// data goes from the bottom to the top line of the image, as OpenGL expects it /// These perform an implicit Bind() on the current texture unit. /// </summary> /// <remarks> /// The alpha channel bytes should be 255 if you don't want the channel. /// We need a material characteristic to ask for specific texture modes. /// Designed limitations of flexibility: /// No support for texture borders. /// No support for texture border color. /// No support for texture environment colors or GL_BLEND or GL_DECAL /// texture environments, because the automatic optimization to single /// or dual component textures makes those modes potentially undefined. /// No non-power-of-two images. /// No palettized textures. /// There is no way to specify separate wrap/clamp values for S and T. /// There is no way to specify explicit mip map levels. /// </remarks> /// <param name="data"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="filter"></param> /// <param name="allowDownSize"></param> /// <param name="repeat"></param> /// <param name="depth"></param> public void Generate(byte[] data, int width, int height, TextureFilter filter, bool allowDownSize, TextureRepeat repeat, TextureDepth depth) { if (this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } // FIXME: should we implement cinematics this way, instead of with explicit calls? /*Purge(); * * _filter = filter; * _allowDownSize = allowDownSize; * _repeat = repeat; * _depth = depth;*/ idConsole.Warning("TODO: generate"); // if we don't have a rendering context, just return after we // have filled in the parms. We must have the values set, or // an image match from a shader before OpenGL starts would miss // the generated texture if (idE.RenderSystem.IsRunning == false) { return; } // don't let mip mapping smear the texture into the clamped border /*bool preserveBorder = (_repeat == TextureRepeat.ClampToZero); * * // make sure it is a power of 2 * int scaledWidth = idHelper.MakePowerOfTwo(width); * int scaledHeight = idHelper.MakePowerOfTwo(height); * * if((scaledWidth != width) || (scaledHeight != height)) * { * idConsole.Error("Image.Generate: not a power of 2 image."); * } * * // Optionally modify our width/height based on options/hardware * GetDownSize(ref scaledWidth, ref scaledHeight); * * byte[] scaledBuffer = null; * /*idE.RenderSystem.CheckOpenGLErrors(); * uint[] tex = new uint[1]; * //Gl.glGenTextures(1, tex); * _texNumber = (int) tex[0]; * idE.RenderSystem.CheckOpenGLErrors();*/ /*_loaded = true; * * // select proper internal format before we resample * _internalFormat = Gl.GL_RGB8; // SelectInternalFormat(data, 1, width, height, depth, out _isMonochrome); * * // copy or resample data as appropriate for first MIP level. * if((scaledWidth == width) && (scaledHeight == height)) * { * // we must copy even if unchanged, because the border zeroing * // would otherwise modify const data * scaledBuffer = data; * } * else * { * idConsole.Warning("TODO: DONT SUPPORT MIMAP RIGHT NOW"); * * // resample down as needed (FIXME: this doesn't seem like it resamples anymore!) * // scaledBuffer = R_ResampleTexture( pic, width, height, width >>= 1, height >>= 1 ); * /*scaledBuffer = R_MipMap( pic, width, height, preserveBorder ); * width >>= 1; * height >>= 1; * if ( width < 1 ) { * width = 1; * } * if ( height < 1 ) { * height = 1; * } * * while ( width > scaled_width || height > scaled_height ) { * shrunk = R_MipMap( scaledBuffer, width, height, preserveBorder ); * R_StaticFree( scaledBuffer ); * scaledBuffer = shrunk; * * width >>= 1; * height >>= 1; * if ( width < 1 ) { * width = 1; * } * if ( height < 1 ) { * height = 1; * } * } * * // one might have shrunk down below the target size * scaled_width = width; * scaled_height = height;*/ /*}*/ /*_uploadWidth = scaledWidth; * _uploadHeight = scaledHeight; * _type = TextureType.TwoD; * * // zero the border if desired, allowing clamped projection textures * // even after picmip resampling or careless artists. * if(repeat == TextureRepeat.ClampToZero) * { * byte[] rgba = new byte[4] { 0, 0, 0, 255 }; * SetBorderTexels(scaledBuffer, width, height, rgba); * } * else if(repeat == TextureRepeat.ClampToZeroAlpha) * { * byte[] rgba = new byte[4] { 255, 255, 255, 0 }; * SetBorderTexels(scaledBuffer, width, height, rgba); * }*/ /*if((_generator == null) && ((_depth == TextureDepth.Bump) && (idE.CvarSystem.GetBool("image_writeNormalTGA") == true) || (_depth != TextureDepth.Bump) && (idE.CvarSystem.GetBool("image_writeTGA") == true))) * { * idConsole.Warning("TODO: gen = null && bump && write"); * // Optionally write out the texture to a .tga * /*char filename[MAX_IMAGE_NAME]; * ImageProgramStringToCompressedFileName( imgName, filename ); * char *ext = strrchr(filename, '.'); * if ( ext ) { * strcpy( ext, ".tga" ); * // swap the red/alpha for the write * /* * if ( depth == TD_BUMP ) { * for ( int i = 0; i < scaled_width * scaled_height * 4; i += 4 ) { * scaledBuffer[ i ] = scaledBuffer[ i + 3 ]; * scaledBuffer[ i + 3 ] = 0; * } * } */ // TODO: R_WriteTGA( filename, scaledBuffer, scaled_width, scaled_height, false ); // put it back /* * if ( depth == TD_BUMP ) { * for ( int i = 0; i < scaled_width * scaled_height * 4; i += 4 ) { * scaledBuffer[ i + 3 ] = scaledBuffer[ i ]; * scaledBuffer[ i ] = 0; * } * } */ /*}*/ /* }*/ // swap the red and alpha for rxgb support // do this even on tga normal maps so we only have to use // one fragment program. // if the image is precompressed (either in palletized mode or true rxgb mode) // then it is loaded above and the swap never happens here. /*if((depth == TextureDepth.Bump) && (idE.CvarSystem.GetInteger("image_useNormalCompression") != 1)) * { * for(int i = 0; i < scaledWidth * scaledHeight * 4; i += 4) * { * scaledBuffer[i + 3] = scaledBuffer[i]; * scaledBuffer[i] = 0; * } * } * * // upload the main image level * Bind(); * * if(_internalFormat == Gl.GL_COLOR_INDEX8_EXT) * { * idConsole.Warning("TODO: UploadCompressedNormalMap( scaled_width, scaled_height, scaledBuffer, 0 );"); * } * else * { * //Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, _internalFormat, scaledWidth, scaledHeight, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, scaledBuffer); * } * * // create and upload the mip map levels, which we do in all cases, even if we don't think they are needed * /*int miplevel = 0; * // TODO: remove this if not needed * while((scaledWidth > 1) || (scaledHeight > 1)) * { * // preserve the border after mip map unless repeating * scaledBuffer = MipMap(scaledBuffer, scaledWidth, scaledHeight, preserveBorder); * scaledWidth >>= 1; * scaledHeight >>= 1; * * if(scaledWidth < 1) * { * scaledWidth = 1; * } * * if(scaledHeight < 1) * { * scaledHeight = 1; * } * * miplevel++; * * // this is a visualization tool that shades each mip map * // level with a different color so you can see the * // rasterizer's texture level selection algorithm * // Changing the color doesn't help with lumminance/alpha/intensity formats... * // TODO * /*if ( depth == TD_DIFFUSE && globalImages->image_colorMipLevels.GetBool() ) { * R_BlendOverTexture( (byte *)scaledBuffer, scaled_width * scaled_height, mipBlendColors[miplevel] ); * }*/ // upload the mip map /*if(_internalFormat == Gl.GL_COLOR_INDEX8_EXT) * { * idConsole.Warning("TODO: UploadCompressedNormalMap( scaled_width, scaled_height, scaledBuffer, miplevel );"); * } * else * { * //Gl.glTexImage2D(Gl.GL_TEXTURE_2D, miplevel, _internalFormat, scaledWidth, scaledHeight, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, scaledBuffer); * } * }*/ //SetImageFilterAndRepeat(); }
private Texture2D ParseImageProgram(ref DateTime timeStamp, ref TextureDepth depth, bool parseOnly) { idToken token = _lexer.ReadToken(); AppendToken(token); string tokenLower = token.ToString().ToLower(); if (tokenLower == "heightmap") { MatchAndAppendToken(_lexer, "("); Texture2D tex = ParseImageProgram(_lexer, ref timeStamp, ref depth); if (tex == null) { return(null); } MatchAndAppendToken(_lexer, ","); token = _lexer.ReadToken(); AppendToken(token); float scale = token.ToFloat(); // process it if (tex != null) { idConsole.Warning("TODO: R_HeightmapToNormalMap( *pic, *width, *height, scale );"); depth = TextureDepth.Bump; } MatchAndAppendToken(_lexer, ")"); return(tex); } else if (tokenLower == "addnormals") { MatchAndAppendToken(_lexer, "("); /*byte *pic2; * int width2, height2;*/ Texture2D tex, tex2; if ((tex = ParseImageProgram(_lexer, ref timeStamp, ref depth)) == null) { return(null); } MatchAndAppendToken(_lexer, ","); if ((tex2 = ParseImageProgram(_lexer, ref timeStamp, ref depth)) == null) { tex.Dispose(); idConsole.Warning("TODO: content doesn't get unloaded, this texture will remain disposed for ever!"); return(null); } // process it if (tex != null) { // TODO: tex2.Dispose(); idConsole.Warning("TODO: content doesn't get unloaded, this texture will remain disposed for ever!"); depth = TextureDepth.Bump; idConsole.Warning("TODO: R_AddNormalMaps( *pic, *width, *height, pic2, width2, height2 );"); } MatchAndAppendToken(_lexer, ")"); return(tex); } else if (tokenLower == "smoothnormals") { idConsole.WriteLine("image program smoothnormals"); /*MatchAndAppendToken( src, "(" ); * * if ( !R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ) ) { * return false; * } * * if ( pic ) { * R_SmoothNormalMap( *pic, *width, *height ); * if ( depth ) { * depth = TD_BUMP; * } * } * * MatchAndAppendToken( src, ")" ); * return true;*/ return(null); } else if (tokenLower == "add") { idConsole.WriteLine("image program add"); /*byte *pic2; * int width2, height2; * * MatchAndAppendToken( src, "(" ); * * if ( !R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ) ) { * return false; * } * * MatchAndAppendToken( src, "," ); * * if ( !R_ParseImageProgram_r( src, pic ? &pic2 : NULL, &width2, &height2, timestamps, depth ) ) { * if ( pic ) { * R_StaticFree( *pic ); * pic = NULL; * } * return false; * } * * // process it * if ( pic ) { * R_ImageAdd( *pic, *width, *height, pic2, width2, height2 ); * R_StaticFree( pic2 ); * } * * MatchAndAppendToken( src, ")" ); * return true;*/ return(null); } else if (tokenLower == "scale") { idConsole.WriteLine("image program scale"); /*float scale[4]; * int i; * * MatchAndAppendToken( src, "(" ); * * R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ); * * for ( i = 0 ; i < 4 ; i++ ) { * MatchAndAppendToken( src, "," ); * src.ReadToken( &token ); * AppendToken( token ); * scale[i] = token.GetFloatValue(); * } * * // process it * if ( pic ) { * R_ImageScale( *pic, *width, *height, scale ); * } * * MatchAndAppendToken( src, ")" ); * return true;*/ return(null); } else if (tokenLower == "invertalpha") { idConsole.WriteLine("image program invertalpha"); /*MatchAndAppendToken( src, "(" ); * * R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ); * * // process it * if ( pic ) { * R_InvertAlpha( *pic, *width, *height ); * } * * MatchAndAppendToken( src, ")" ); * return true;*/ return(null); } else if (tokenLower == "invertcolor") { idConsole.WriteLine("image program invertcolor"); /*MatchAndAppendToken( src, "(" ); * * R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ); * * // process it * if ( pic ) { * R_InvertColor( *pic, *width, *height ); * } * * MatchAndAppendToken( src, ")" ); * return true;*/ return(null); } else if (tokenLower == "makeintensity") { MatchAndAppendToken(_lexer, "("); Texture2D t = ParseImageProgram(ref timeStamp, ref depth, parseOnly); idConsole.Warning("TODO: makeintensity"); /*if(parseOnly == false) * { * // copy red to green, blue, and alpha * int c = width * height * 4; * * for(int i = 0; i < c; i += 4) * { * data[i + 1] = data[i + 2] = data[i + 3] = data[i]; * } * }*/ MatchAndAppendToken(_lexer, ")"); return(t); } else if (tokenLower == "makealpha") { MatchAndAppendToken(_lexer, "("); Texture2D tex = ParseImageProgram(_lexer, ref timeStamp, ref depth); // average RGB into alpha, then set RGB to white if (tex != null) { idConsole.Warning("TODO: average alpha image"); /*int c; * c = *width * *height * 4; * for ( i = 0 ; i < c ; i+=4 ) { * (*pic)[i+3] = ( (*pic)[i+0] + (*pic)[i+1] + (*pic)[i+2] ) / 3; * (*pic)[i+0] = * (*pic)[i+1] = * (*pic)[i+2] = 255; * }*/ } MatchAndAppendToken(_lexer, ")"); return(tex); } // if we are just parsing instead of loading or checking, don't do the R_LoadImage if (parseOnly == true) { return(null); } // load it as an image return(idE.ImageManager.LoadImage(token.ToString(), ref timeStamp, true)); }
public Texture2D ParseImageProgram(idLexer lexer, ref DateTime timeStamp, ref TextureDepth depth) { _lexer = lexer; return(ParseImageProgram(ref timeStamp, ref depth, false)); }
private Texture2D ParseImageProgram(ref DateTime timeStamp, ref TextureDepth depth, bool parseOnly) { idToken token = _lexer.ReadToken(); AppendToken(token); string tokenLower = token.ToString().ToLower(); if(tokenLower == "heightmap") { MatchAndAppendToken(_lexer, "("); Texture2D tex = ParseImageProgram(_lexer, ref timeStamp, ref depth); if(tex == null) { return null; } MatchAndAppendToken(_lexer, ","); token = _lexer.ReadToken(); AppendToken(token); float scale = token.ToFloat(); // process it if(tex != null) { idConsole.Warning("TODO: R_HeightmapToNormalMap( *pic, *width, *height, scale );"); depth = TextureDepth.Bump; } MatchAndAppendToken(_lexer, ")"); return tex; } else if(tokenLower == "addnormals") { MatchAndAppendToken(_lexer, "("); /*byte *pic2; int width2, height2;*/ Texture2D tex, tex2; if((tex = ParseImageProgram(_lexer, ref timeStamp, ref depth)) == null) { return null; } MatchAndAppendToken(_lexer, ","); if((tex2 = ParseImageProgram(_lexer, ref timeStamp, ref depth)) == null) { tex.Dispose(); idConsole.Warning("TODO: content doesn't get unloaded, this texture will remain disposed for ever!"); return null; } // process it if(tex != null) { // TODO: tex2.Dispose(); idConsole.Warning("TODO: content doesn't get unloaded, this texture will remain disposed for ever!"); depth = TextureDepth.Bump; idConsole.Warning("TODO: R_AddNormalMaps( *pic, *width, *height, pic2, width2, height2 );"); } MatchAndAppendToken(_lexer, ")"); return tex; } else if(tokenLower == "smoothnormals") { idConsole.WriteLine("image program smoothnormals"); /*MatchAndAppendToken( src, "(" ); if ( !R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ) ) { return false; } if ( pic ) { R_SmoothNormalMap( *pic, *width, *height ); if ( depth ) { *depth = TD_BUMP; } } MatchAndAppendToken( src, ")" ); return true;*/ return null; } else if(tokenLower == "add") { idConsole.WriteLine("image program add"); /*byte *pic2; int width2, height2; MatchAndAppendToken( src, "(" ); if ( !R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ) ) { return false; } MatchAndAppendToken( src, "," ); if ( !R_ParseImageProgram_r( src, pic ? &pic2 : NULL, &width2, &height2, timestamps, depth ) ) { if ( pic ) { R_StaticFree( *pic ); *pic = NULL; } return false; } // process it if ( pic ) { R_ImageAdd( *pic, *width, *height, pic2, width2, height2 ); R_StaticFree( pic2 ); } MatchAndAppendToken( src, ")" ); return true;*/ return null; } else if(tokenLower == "scale") { idConsole.WriteLine("image program scale"); /*float scale[4]; int i; MatchAndAppendToken( src, "(" ); R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ); for ( i = 0 ; i < 4 ; i++ ) { MatchAndAppendToken( src, "," ); src.ReadToken( &token ); AppendToken( token ); scale[i] = token.GetFloatValue(); } // process it if ( pic ) { R_ImageScale( *pic, *width, *height, scale ); } MatchAndAppendToken( src, ")" ); return true;*/ return null; } else if(tokenLower == "invertalpha") { idConsole.WriteLine("image program invertalpha"); /*MatchAndAppendToken( src, "(" ); R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ); // process it if ( pic ) { R_InvertAlpha( *pic, *width, *height ); } MatchAndAppendToken( src, ")" ); return true;*/ return null; } else if(tokenLower == "invertcolor") { idConsole.WriteLine("image program invertcolor"); /*MatchAndAppendToken( src, "(" ); R_ParseImageProgram_r( src, pic, width, height, timestamps, depth ); // process it if ( pic ) { R_InvertColor( *pic, *width, *height ); } MatchAndAppendToken( src, ")" ); return true;*/ return null; } else if(tokenLower == "makeintensity") { MatchAndAppendToken(_lexer, "("); Texture2D t = ParseImageProgram(ref timeStamp, ref depth, parseOnly); idConsole.Warning("TODO: makeintensity"); /*if(parseOnly == false) { // copy red to green, blue, and alpha int c = width * height * 4; for(int i = 0; i < c; i += 4) { data[i + 1] = data[i + 2] = data[i + 3] = data[i]; } }*/ MatchAndAppendToken(_lexer, ")"); return t; } else if(tokenLower == "makealpha") { MatchAndAppendToken(_lexer, "("); Texture2D tex = ParseImageProgram(_lexer, ref timeStamp, ref depth); // average RGB into alpha, then set RGB to white if(tex != null) { idConsole.Warning("TODO: average alpha image"); /*int c; c = *width * *height * 4; for ( i = 0 ; i < c ; i+=4 ) { (*pic)[i+3] = ( (*pic)[i+0] + (*pic)[i+1] + (*pic)[i+2] ) / 3; (*pic)[i+0] = (*pic)[i+1] = (*pic)[i+2] = 255; }*/ } MatchAndAppendToken(_lexer, ")"); return tex; } // if we are just parsing instead of loading or checking, don't do the R_LoadImage if(parseOnly == true) { return null; } // load it as an image return idE.ImageManager.LoadImage(token.ToString(), ref timeStamp, true); }
// background loading information. /*private idImage _partialImage; // shrunken, space-saving version private bool _isPartialImage; // true if this is pointed to by another image*/ #endregion #region Constructor public idImage(string name, ImageLoadCallback generator) { _name = name; _generator = generator; _type = TextureType.Disabled; _filter = TextureFilter.Default; _repeat = TextureRepeat.Repeat; _depth = TextureDepth.Default; _cubeFiles = CubeFiles.TwoD; }
public Texture2D ParseImageProgram(idLexer lexer, ref DateTime timeStamp, ref TextureDepth depth) { _lexer = lexer; return ParseImageProgram(ref timeStamp, ref depth, false); }
/// <summary> /// Used by callback functions to specify the actual data /// data goes from the bottom to the top line of the image, as OpenGL expects it /// These perform an implicit Bind() on the current texture unit. /// </summary> /// <remarks> /// The alpha channel bytes should be 255 if you don't want the channel. /// We need a material characteristic to ask for specific texture modes. /// Designed limitations of flexibility: /// No support for texture borders. /// No support for texture border color. /// No support for texture environment colors or GL_BLEND or GL_DECAL /// texture environments, because the automatic optimization to single /// or dual component textures makes those modes potentially undefined. /// No non-power-of-two images. /// No palettized textures. /// There is no way to specify separate wrap/clamp values for S and T. /// There is no way to specify explicit mip map levels. /// </remarks> /// <param name="data"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="filter"></param> /// <param name="allowDownSize"></param> /// <param name="repeat"></param> /// <param name="depth"></param> public void Generate(byte[] data, int width, int height, TextureFilter filter, bool allowDownSize, TextureRepeat repeat, TextureDepth depth) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } // FIXME: should we implement cinematics this way, instead of with explicit calls? /*Purge(); _filter = filter; _allowDownSize = allowDownSize; _repeat = repeat; _depth = depth;*/ idConsole.Warning("TODO: generate"); // if we don't have a rendering context, just return after we // have filled in the parms. We must have the values set, or // an image match from a shader before OpenGL starts would miss // the generated texture if(idE.RenderSystem.IsRunning == false) { return; } // don't let mip mapping smear the texture into the clamped border /*bool preserveBorder = (_repeat == TextureRepeat.ClampToZero); // make sure it is a power of 2 int scaledWidth = idHelper.MakePowerOfTwo(width); int scaledHeight = idHelper.MakePowerOfTwo(height); if((scaledWidth != width) || (scaledHeight != height)) { idConsole.Error("Image.Generate: not a power of 2 image."); } // Optionally modify our width/height based on options/hardware GetDownSize(ref scaledWidth, ref scaledHeight); byte[] scaledBuffer = null; /*idE.RenderSystem.CheckOpenGLErrors(); uint[] tex = new uint[1]; //Gl.glGenTextures(1, tex); _texNumber = (int) tex[0]; idE.RenderSystem.CheckOpenGLErrors();*/ /*_loaded = true; // select proper internal format before we resample _internalFormat = Gl.GL_RGB8; // SelectInternalFormat(data, 1, width, height, depth, out _isMonochrome); // copy or resample data as appropriate for first MIP level. if((scaledWidth == width) && (scaledHeight == height)) { // we must copy even if unchanged, because the border zeroing // would otherwise modify const data scaledBuffer = data; } else { idConsole.Warning("TODO: DONT SUPPORT MIMAP RIGHT NOW"); // resample down as needed (FIXME: this doesn't seem like it resamples anymore!) // scaledBuffer = R_ResampleTexture( pic, width, height, width >>= 1, height >>= 1 ); /*scaledBuffer = R_MipMap( pic, width, height, preserveBorder ); width >>= 1; height >>= 1; if ( width < 1 ) { width = 1; } if ( height < 1 ) { height = 1; } while ( width > scaled_width || height > scaled_height ) { shrunk = R_MipMap( scaledBuffer, width, height, preserveBorder ); R_StaticFree( scaledBuffer ); scaledBuffer = shrunk; width >>= 1; height >>= 1; if ( width < 1 ) { width = 1; } if ( height < 1 ) { height = 1; } } // one might have shrunk down below the target size scaled_width = width; scaled_height = height;*/ /*}*/ /*_uploadWidth = scaledWidth; _uploadHeight = scaledHeight; _type = TextureType.TwoD; // zero the border if desired, allowing clamped projection textures // even after picmip resampling or careless artists. if(repeat == TextureRepeat.ClampToZero) { byte[] rgba = new byte[4] { 0, 0, 0, 255 }; SetBorderTexels(scaledBuffer, width, height, rgba); } else if(repeat == TextureRepeat.ClampToZeroAlpha) { byte[] rgba = new byte[4] { 255, 255, 255, 0 }; SetBorderTexels(scaledBuffer, width, height, rgba); }*/ /*if((_generator == null) && ((_depth == TextureDepth.Bump) && (idE.CvarSystem.GetBool("image_writeNormalTGA") == true) || (_depth != TextureDepth.Bump) && (idE.CvarSystem.GetBool("image_writeTGA") == true))) { idConsole.Warning("TODO: gen = null && bump && write"); // Optionally write out the texture to a .tga /*char filename[MAX_IMAGE_NAME]; ImageProgramStringToCompressedFileName( imgName, filename ); char *ext = strrchr(filename, '.'); if ( ext ) { strcpy( ext, ".tga" ); // swap the red/alpha for the write /* if ( depth == TD_BUMP ) { for ( int i = 0; i < scaled_width * scaled_height * 4; i += 4 ) { scaledBuffer[ i ] = scaledBuffer[ i + 3 ]; scaledBuffer[ i + 3 ] = 0; } } */ // TODO: R_WriteTGA( filename, scaledBuffer, scaled_width, scaled_height, false ); // put it back /* if ( depth == TD_BUMP ) { for ( int i = 0; i < scaled_width * scaled_height * 4; i += 4 ) { scaledBuffer[ i + 3 ] = scaledBuffer[ i ]; scaledBuffer[ i ] = 0; } } */ /*}*/ /* }*/ // swap the red and alpha for rxgb support // do this even on tga normal maps so we only have to use // one fragment program. // if the image is precompressed (either in palletized mode or true rxgb mode) // then it is loaded above and the swap never happens here. /*if((depth == TextureDepth.Bump) && (idE.CvarSystem.GetInteger("image_useNormalCompression") != 1)) { for(int i = 0; i < scaledWidth * scaledHeight * 4; i += 4) { scaledBuffer[i + 3] = scaledBuffer[i]; scaledBuffer[i] = 0; } } // upload the main image level Bind(); if(_internalFormat == Gl.GL_COLOR_INDEX8_EXT) { idConsole.Warning("TODO: UploadCompressedNormalMap( scaled_width, scaled_height, scaledBuffer, 0 );"); } else { //Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, _internalFormat, scaledWidth, scaledHeight, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, scaledBuffer); } // create and upload the mip map levels, which we do in all cases, even if we don't think they are needed /*int miplevel = 0; // TODO: remove this if not needed while((scaledWidth > 1) || (scaledHeight > 1)) { // preserve the border after mip map unless repeating scaledBuffer = MipMap(scaledBuffer, scaledWidth, scaledHeight, preserveBorder); scaledWidth >>= 1; scaledHeight >>= 1; if(scaledWidth < 1) { scaledWidth = 1; } if(scaledHeight < 1) { scaledHeight = 1; } miplevel++; // this is a visualization tool that shades each mip map // level with a different color so you can see the // rasterizer's texture level selection algorithm // Changing the color doesn't help with lumminance/alpha/intensity formats... // TODO /*if ( depth == TD_DIFFUSE && globalImages->image_colorMipLevels.GetBool() ) { R_BlendOverTexture( (byte *)scaledBuffer, scaled_width * scaled_height, mipBlendColors[miplevel] ); }*/ // upload the mip map /*if(_internalFormat == Gl.GL_COLOR_INDEX8_EXT) { idConsole.Warning("TODO: UploadCompressedNormalMap( scaled_width, scaled_height, scaledBuffer, miplevel );"); } else { //Gl.glTexImage2D(Gl.GL_TEXTURE_2D, miplevel, _internalFormat, scaledWidth, scaledHeight, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, scaledBuffer); } }*/ //SetImageFilterAndRepeat(); }