public void Render(GLCamera cam, bool renderBG) { cam.LoadProjection(); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); GL.Color4(Color.White); GL.Enable(EnableCap.Texture2D); float halfW = (float)Width / 2.0f, halfH = (float)Height / 2.0f; GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.MatrixMode(MatrixMode.Texture); GL.LoadIdentity(); if (renderBG) { GL.PushAttrib(AttribMask.TextureBit); GLTexture bgTex = TKContext.FindOrCreate <GLTexture>("TexBG", GLTexturePanel.CreateBG); bgTex.Bind(); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); float s = (float)Width / (float)bgTex.Width, t = (float)Height / (float)bgTex.Height; GL.Begin(BeginMode.Quads); GL.TexCoord2(0.0f, 0.0f); GL.Vertex2(-halfW, -halfH); GL.TexCoord2(s, 0.0f); GL.Vertex2(halfW, -halfH); GL.TexCoord2(s, t); GL.Vertex2(halfW, halfH); GL.TexCoord2(0.0f, t); GL.Vertex2(-halfW, halfH); GL.End(); GL.PopAttrib(); } if (Tex0 == null) { return; } Tex0.Prepare(_targetMatRef, -1); GLTexture texture = GLTex; if (texture == null || texture._texId <= 0) { return; } MDL0TextureNode.ApplyGLTextureParameters(_targetMatRef); //These are used to match up the UV overlay to the texture underneath Vector2 topLeft = new Vector2(); Vector2 bottomRight = new Vector2(); float texWidth = texture.Width; float texHeight = texture.Height; float tAspect = (float)texWidth / texHeight; float wAspect = (float)Width / Height; float[] texCoord = new float[8]; //These are used to compensate for padding added on an axis float xCorrect = 1.0f, yCorrect = 1.0f; if (tAspect > wAspect) { //Texture is wider, use horizontal fit //X touches the edges of the window, Y has top and bottom padding //X texCoord[0] = texCoord[6] = 0.0f; texCoord[2] = texCoord[4] = 1.0f; //Y texCoord[1] = texCoord[3] = (yCorrect = tAspect / wAspect) / 2.0f + 0.5f; texCoord[5] = texCoord[7] = 1.0f - texCoord[1]; bottomRight = new Vector2(halfW, (((float)Height - ((float)Width / texWidth * texHeight)) / (float)Height / 2.0f - 0.5f) * (float)Height); topLeft = new Vector2(-halfW, -bottomRight._y); } else { //Window is wider, use vertical fit //Y touches the edges of the window, X has left and right padding //Y texCoord[1] = texCoord[3] = 1.0f; texCoord[5] = texCoord[7] = 0.0f; //X texCoord[2] = texCoord[4] = (xCorrect = wAspect / tAspect) / 2.0f + 0.5f; texCoord[0] = texCoord[6] = 1.0f - texCoord[2]; bottomRight = new Vector2(1.0f - (((float)Width - ((float)Height / texHeight * texWidth)) / Width / 2.0f - 0.5f) * (float)Width, -halfH); topLeft = new Vector2(-bottomRight._x, halfH); } //Apply the texcoord bind transform first TextureFrameState state = _targetMatRef._bindState; GL.MultMatrix((float *)&state._transform); //Translate the texture coordinates to match where the user dragged the camera //Divide by width and height to convert window units (0 to w, 0 to h) to texcoord units (0 to 1) //Then multiply by the correction value if the window is bigger than the texture on an axis Vector3 point = cam.GetPoint(); GL.Translate(point._x / Width * xCorrect, -point._y / Height * yCorrect, 0); //Now to scale the texture after translating. //The scale origin is the top left of the texture on the window (not of the window itself), //so we need to translate the center of the texture to that origin, //scale it up or down, then translate it back to where it was. OpenTK.Vector3 trans = new OpenTK.Vector3(-topLeft._x / Width * xCorrect, topLeft._y / Height * yCorrect, 0.0f); GL.Translate(trans); GL.Scale((OpenTK.Vector3)cam._scale); GL.Translate(-trans); //Bind the material ref's texture GL.BindTexture(TextureTarget.Texture2D, texture._texId); //Draw a quad across the screen and render the texture with the calculated texcoords GL.Begin(BeginMode.Quads); GL.TexCoord2(texCoord[0], texCoord[1]); GL.Vertex2(-halfW, -halfH); GL.TexCoord2(texCoord[2], texCoord[3]); GL.Vertex2(halfW, -halfH); GL.TexCoord2(texCoord[4], texCoord[5]); GL.Vertex2(halfW, halfH); GL.TexCoord2(texCoord[6], texCoord[7]); GL.Vertex2(-halfW, halfH); GL.End(); GL.Disable(EnableCap.Texture2D); //Now load the camera transform and draw the UV overlay over the texture cam.LoadModelView(); //Color the lines limegreen, a bright color that probably won't be in a texture GL.Color4(Color.LimeGreen); Vector2 mdlScale = new Vector2(bottomRight._x - topLeft._x, bottomRight._y - topLeft._y); GL.Translate(topLeft._x, topLeft._y, 0.0f); GL.Scale(mdlScale._x, mdlScale._y, 1.0f); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); GL.LineWidth(1); //Render texture coordinates as vertex points foreach (RenderInfo info in _renderInfo) { info.PrepareStream(); } }