OpenGL 4.1 Indexed drawing problems - c#

I am trying to render a quantity of cubes like in "Minecraft" a chunk with C# + OpenTK + OpenGL 4.1.
To do that, I create a buffer with type "ElementArrayBuffer" for indices and a buffer with type "ArrayBuffer" to store the vertices.
But I think to describe it, is more difficult than examine the code.
If someone has questions please tell me.
So now the problem.
The rendering result is not that, what I want and I don't understand why and whats wrong.
If I render this I get this result:
class Chunk
{
// The size of the chunk
// One unit means one cube
public const int WIDTH = 5;
public const int HEIGHT = 5;
public const int DEPTH = 2;
private int[][][] mData;
// The attribute location the the shader program
private int mVePositionLocation;
private int mVertexArray;
private int mIndexBuffer;
private int mVertexBuffer;
private int mIndexCount;
public Chunk(int pVePositionLocation)
{
mVePositionLocation = pVePositionLocation;
GenerateData();
GenerateMesh();
}
private void GenerateData()
{
mData = new int[DEPTH][][];
for(int z = 0; z < DEPTH; z++)
{
mData[z] = new int[HEIGHT][];
for(int y = 0; y < HEIGHT; y++)
{
mData[z][y] = new int[WIDTH];
for(int x = 0; x < WIDTH; x++)
{
mData[z][y][x] = 1;
}
}
}
}
private void GenerateMesh()
{
Queue<float> vertices = new Queue<float>();
Queue<uint> indices = new Queue<uint>();
uint offset = 0;
for (int z = 0; z < DEPTH; z++)
{
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
// If the value is bigger than 0 there is a cube so it should be generated
if(mData[z][y][x] > 0)
{
GenerateCube(x, y, z, offset, vertices, indices);
// Normally 36 indices offset, but for now I only generate the front face of each cube so only 6 indices
offset += 6;
}
}
}
}
// Create and fill the buffer with the indices
mIndexBuffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, mIndexBuffer);
GL.BufferData<uint>(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Count * sizeof(uint)), indices.ToArray(), BufferUsageHint.StaticDraw);
mVertexArray = GL.GenVertexArray();
GL.BindVertexArray(mVertexArray);
// The buffer with the vertices
mVertexBuffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, mVertexBuffer);
GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count * sizeof(float)), vertices.ToArray(), BufferUsageHint.StaticDraw);
// The shader only needs the position
GL.EnableVertexAttribArray(mVePositionLocation);
GL.VertexAttribPointer(mVePositionLocation, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);
// Store the index count, so I can render later
mIndexCount = indices.Count;
}
private void GenerateCube(int pX, int pY, int pZ, uint pOffset, Queue<float> pVertices, Queue<uint> pIndices)
{
// Front face vertices
pVertices.Enqueue(pX);
pVertices.Enqueue(pY);
pVertices.Enqueue(pZ + Cube.DEPTH);
pVertices.Enqueue(pX + Cube.WIDTH);
pVertices.Enqueue(pY);
pVertices.Enqueue(pZ + Cube.DEPTH);
pVertices.Enqueue(pX);
pVertices.Enqueue(pY + Cube.HEIGHT);
pVertices.Enqueue(pZ + Cube.DEPTH);
pVertices.Enqueue(pX + Cube.WIDTH);
pVertices.Enqueue(pY + Cube.HEIGHT);
pVertices.Enqueue(pZ + Cube.DEPTH);
// Front face indices
pIndices.Enqueue(pOffset + 0);
pIndices.Enqueue(pOffset + 2);
pIndices.Enqueue(pOffset + 3);
pIndices.Enqueue(pOffset + 0);
pIndices.Enqueue(pOffset + 3);
pIndices.Enqueue(pOffset + 1);
}
public void Render()
{
GL.BindBuffer(BufferTarget.ElementArrayBuffer, mIndexBuffer);
GL.BindVertexArray(mVertexArray);
GL.DrawElements(BeginMode.Triangles, mIndexCount, DrawElementsType.UnsignedInt, 0);
}
}
The shader program:
string vertexShaderSource = "#version 410\n" +
"\n" +
"uniform mat4 un_Projection; \n" +
"uniform mat4 un_Transform; \n" +
"\n" +
"layout(location = 0) in vec3 ve_Position;\n" +
"\n" +
"out vec4 fr_Color;" +
"\n" +
"void main()\n" +
"{\n" +
" fr_Color = vec4(1, 0, 0, 1);\n" +
" gl_Position = un_Projection * un_Transform * vec4(ve_Position.xyz, 1);\n" +
"}\n";
string fragmentShaderSource = "#version 410\n" +
"\n" +
"in vec4 fr_Color;\n" +
"\n" +
"out vec4 fi_Color;\n" +
"\n" +
"void main()\n" +
"{\n" +
" fi_Color = fr_Color;\n" +
"}\n";
If someone wants the full project folder:
http://www.file-upload.net/download-10301899/Project.zip.html

Ok, I found the mistake.
I should not be
// Normally 36 indices offset, but for now I only generate the front face of each cube so only 6 indices
offset += 6;
It should be
// 4 vertices a face so add 4 offset a cube
offset += 4;

Related

I can create a mesh (in awake) but I cannot see it

this is the part of the code that generate a mesh, if you want more information ask.
So in the scene I cannot see it, I tried to enter play mode but nothing, if I go in the inspector I can see: 4 verts, 2 tris, the right amount of tris and verts.
public void ConstructMesh()
{
Vector3[] vertices = new Vector3[(resolution + 2) * (resolution + 2)];
int[] triangles = new int[(resolution + 1) * (resolution + 1) * 6];
int triIndex = 0;
for (int y = 0; y < resolution; y++)
{
for (int x = 0; x < resolution; x++)
{
int i = x + y * resolution;
Vector2 percent = new Vector2(x, y) / (resolution - 1);
Vector3 pointOnUnitCode = localUp + (percent.x - .5f) * 2 * axisA + (percent.y - .5f) * 2 * axisB;
vertices[i] = pointOnUnitCode;
triangles[triIndex] = i;
triangles[triIndex + 1] = i + resolution + 1;
triangles[triIndex + 2] = i + resolution;
triangles[triIndex + 3] = i;
triangles[triIndex + 4] = i + 1;
triangles[triIndex + 5] = i + resolution + 1;
triIndex += 6;
}
}
planet.Clear();
planet.vertices = vertices;
planet.triangles = triangles;
planet.RecalculateNormals();
}
You need a MeshRenderer and MeshFilter in the GameObject to be able to render your mesh.
Supposing your method ConstructMesh is a MonoBehaviour and it's attached to the same object you want to display the mesh, you can do the following:
GetComponent<MeshFilter>().mesh = planet;

C# two pass image creation

So, I'm building a console application to generate 2D perlin(ish) noise that is split among multiple image files. The algorithm I'm using requires that I do the generation in two passes, one to create the seed for the noise, then to generate the noise. I'm saving the generated noise to the same file that the seed is generated to in order to cut down on disk-space, and to make it clean in the end. I'm running into an issue though, during the second pass, I can't actually access the file, as it's already being used by another procces. Here's the full code to see if there is anything that I'm missing:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace MapGenerator
{
class Program
{
public static Random rng = new Random();
public static void Seed(int px, int py)
{
Bitmap seed = new Bitmap(256, 256, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
for (int x = 0; x < seed.Width; x++)
{
for (int y = 0; y < seed.Height; y++)
{
var val = rng.Next(0, 255);
seed.SetPixel(x, y, Color.FromArgb(255, val, val, val));
}
}
if (File.Exists("chunk," + (px - 1) + "," + (py) + ".jpeg"))
{
Bitmap source = new Bitmap("chunk," + (px - 1) + "," + (py) + ".jpeg");
for (int y = 0; y < 256; y++)
{
seed.SetPixel(0, y, Color.FromArgb(255, source.GetPixel(255, y).R, source.GetPixel(255, y).G, source.GetPixel(255, y).B));
}
}
if (File.Exists("chunk," + (px + 1) + "," + (py) + ".jpeg"))
{
Bitmap source = new Bitmap("chunk," + (px + 1) + "," + (py) + ".jpeg");
for (int y = 0; y < 256; y++)
{
seed.SetPixel(255, y, Color.FromArgb(255, source.GetPixel(0, y).R, source.GetPixel(0, y).G, source.GetPixel(0, y).B));
}
}
if (File.Exists("chunk," + (px) + "," + (py - 1) + ".jpeg"))
{
Bitmap source = new Bitmap("chunk," + (px) + "," + (py - 1) + ".jpeg");
for (int x = 0; x < 256; x++)
{
seed.SetPixel(x, 0, Color.FromArgb(255, source.GetPixel(x, 255).R, source.GetPixel(x, 255).G, source.GetPixel(x, 255).B));
}
}
if (File.Exists("chunk," + (px) + "," + (py + 1) + ".jpeg"))
{
Bitmap source = new Bitmap("chunk," + (px) + "," + (py + 1) + ".jpeg");
for (int x = 0; x < 256; x++)
{
seed.SetPixel(x, 255, Color.FromArgb(255, source.GetPixel(x, 0).R, source.GetPixel(x, 0).G, source.GetPixel(x, 0).B));
}
}
seed.Save("chunk," + px + "," + py + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
seed.Dispose();
}
public static void Perlin(int px, int py)
{
Bitmap seed = new Bitmap("chunk," + px + "," + py + ".jpeg");
Bitmap output = new Bitmap(256, 256, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
for (int y = 0; y < 256; y++)
{
for (int x = 0; x < 256; x++)
{
double noise = 0.0;
double scale = 1.0;
double acc = 0.0;
for (int o = 0; o < 8; o++)
{
int pitch = 256 >> o;
int sampleX1 = (x / pitch) * pitch;
int sampleY1 = (y / pitch) * pitch;
int sampleX2 = (sampleX1 + pitch);
int sampleY2 = (sampleY1 + pitch);
sampleX2 = (sampleX2 == 256) ? 255 : sampleX2;
sampleY2 = (sampleY2 == 256) ? 255 : sampleY2;
double Xblend = (double)(x - sampleX1) / (double)pitch;
double Yblend = (double)(y - sampleY1) / (double)pitch;
// interpolate between the two points
double Tsample = ((1 - Xblend) * ((double)seed.GetPixel(sampleX1, sampleY1).R / 255.0)) + (Xblend * ((double)seed.GetPixel(sampleX2, sampleY1).R / 255.0));
double Bsample = ((1 - Xblend) * ((double)seed.GetPixel(sampleX1, sampleY2).R / 255.0)) + (Xblend * ((double)seed.GetPixel(sampleX2, sampleY2).R / 255.0));
noise += (((1 - Yblend) * Tsample) + (Yblend * Bsample)) * scale;
acc += scale;
scale = scale * 0.6;
}
noise = noise / acc;
noise = noise * 255.0;
output.SetPixel(x, y, Color.FromArgb(255, (int)(noise), (int)(noise), (int)(noise)));
}
}
seed.Dispose();
File.Delete("chunk," + px + "," + py + ".jpeg");
output.Save("chunk," + px + "," + py + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
output.Dispose();
}
static void Main(string[] args)
{
int depth = 1;
for(int x = -depth; x <= depth; x++)
{
for(int y = -depth; y <= depth; y++)
{
Seed(x, y);
}
}
for (int x = -depth; x <= depth; x++)
{
for (int y = -depth; y <= depth; y++)
{
Perlin(x, y);
}
}
}
}
}
As you can see, I've tried a lot of disposing of the variables, but to no avail. Any ideas what I'm doing wrong? The odd thing is, when it was only a single function running, I could freely overwrite the base image file, but now that I split it up into two different functions, it's all downhill, and it won't let me manipulate the files.
You need to dispose your bitmaps, as below
Also i would use Lockbits instead of GetPixel and SetPixel and you will get factors better performance
public static void Seed(int px, int py)
{
using (var seed = new Bitmap(256, 256, PixelFormat.Format24bppRgb))
{
for (var x = 0; x < seed.Width; x++)
for (var y = 0; y < seed.Height; y++)
{
var val = rng.Next(0, 255);
seed.SetPixel(x, y, Color.FromArgb(255, val, val, val));
}
if (File.Exists("chunk," + (px - 1) + "," + py + ".jpeg"))
using (var source = new Bitmap("chunk," + (px - 1) + "," + py + ".jpeg"))
for (var y = 0; y < 256; y++)
seed.SetPixel(0, y, Color.FromArgb(255, source.GetPixel(255, y).R, source.GetPixel(255, y).G, source.GetPixel(255, y).B));
if (File.Exists("chunk," + (px + 1) + "," + py + ".jpeg"))
using (var source = new Bitmap("chunk," + (px + 1) + "," + py + ".jpeg"))
for (var y = 0; y < 256; y++)
seed.SetPixel(255, y, Color.FromArgb(255, source.GetPixel(0, y).R, source.GetPixel(0, y).G, source.GetPixel(0, y).B));
if (File.Exists("chunk," + px + "," + (py - 1) + ".jpeg"))
using (var source = new Bitmap("chunk," + px + "," + (py - 1) + ".jpeg"))
for (var x = 0; x < 256; x++)
seed.SetPixel(x, 0, Color.FromArgb(255, source.GetPixel(x, 255).R, source.GetPixel(x, 255).G, source.GetPixel(x, 255).B));
if (File.Exists("chunk," + px + "," + (py + 1) + ".jpeg"))
using (var source = new Bitmap("chunk," + px + "," + (py + 1) + ".jpeg"))
for (var x = 0; x < 256; x++)
seed.SetPixel(x, 255, Color.FromArgb(255, source.GetPixel(x, 0).R, source.GetPixel(x, 0).G, source.GetPixel(x, 0).B));
seed.Save("chunk," + px + "," + py + ".jpeg", ImageFormat.Jpeg);
}
}
Example how to use LockBits and pointers using the unsafe keyword. Basically you are accessing your picture by scan lines in a pinned array using pointers directly accessing the 32 bit ARBG values in memory
using (var seed = new Bitmap(256, 256, PixelFormat.Format24bppRgb))
{
// lock the array for direct access
var bitmapData = seed.LockBits(new Rectangle(0,0,seed.Width,seed.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
// get the pointer
var scan0Ptr = (int*)bitmapData.Scan0;
// get the stride
var stride = bitmapData.Stride / 4;
for (var x = 0; x < seed.Width; x++)
for (var y = 0; y < seed.Height; y++)
{
var val = rng.Next(0, 255);
*(scan0Ptr + x + y * stride) = Color.FromArgb(255, val, val, val).ToArgb();
}
seed.UnlockBits(bitmapData);
...
if (File.Exists("chunk," + (px - 1) + "," + (py) + ".jpeg"))
{
Bitmap source = new Bitmap("chunk," + (px - 1) + "," + (py) + ".jpeg");
for (int y = 0; y < 256; y++)
{
seed.SetPixel(0, y, Color.FromArgb(255, source.GetPixel(255, y).R, source.GetPixel(255, y).G, source.GetPixel(255, y).B));
}
source.Dispose();
}
if (File.Exists("chunk," + (px + 1) + "," + (py) + ".jpeg"))
{
Bitmap source = new Bitmap("chunk," + (px + 1) + "," + (py) + ".jpeg");
for (int y = 0; y < 256; y++)
{
seed.SetPixel(255, y, Color.FromArgb(255, source.GetPixel(0, y).R, source.GetPixel(0, y).G, source.GetPixel(0, y).B));
}
source.Dispose();
}
if (File.Exists("chunk," + (px) + "," + (py - 1) + ".jpeg"))
{
Bitmap source = new Bitmap("chunk," + (px) + "," + (py - 1) + ".jpeg");
for (int x = 0; x < 256; x++)
{
seed.SetPixel(x, 0, Color.FromArgb(255, source.GetPixel(x, 255).R, source.GetPixel(x, 255).G, source.GetPixel(x, 255).B));
}
source.Dispose();
}
if (File.Exists("chunk," + (px) + "," + (py + 1) + ".jpeg"))
{
Bitmap source = new Bitmap("chunk," + (px) + "," + (py + 1) + ".jpeg");
for (int x = 0; x < 256; x++)
{
seed.SetPixel(x, 255, Color.FromArgb(255, source.GetPixel(x, 0).R, source.GetPixel(x, 0).G, source.GetPixel(x, 0).B));
}
source.Dispose();
}
Yeah, I had forgotten to dispose the source variable. also, seems like someone had answered while I was writing this answer.

IndexOutOfRangeException where there is no chance to get it

I'm writing a game in XNA, created simple method to get subImages from textures, but everytime I use it, it throws an exception. I checked the variables and there is no chance to get out of bounds. Code for this two methods below:
public Color[] GetSubImage(Color[] colorData, int width, Rectangle rec)
{
Color[] color = new Color[rec.Width * rec.Height];
for (int x = 0; x < rec.Width; x++)
{
for (int y = 0; y < rec.Height; y++)
{
color[x + y * rec.Width] = colorData[x + rec.X + (y + rec.Y) * width]; // Exception is thrown there
}
}
return color;
}
public void LoadSubImages(Texture2D sourceSpritesheet, List<Texture2D[]> destinationSprites)
{
int count = 0;
Color[] imageData = new Color[sourceSpritesheet.Width * sourceSpritesheet.Height];
Texture2D subImage;
Rectangle sourceRec;
destinationSprites = new List<Texture2D[]>();
for (int i = 0; i < this.NUMFRAMES.Length; i++)
{
Texture2D[] bi = new Texture2D[this.NUMFRAMES[i]];
for (int j = 0; j < this.NUMFRAMES[i]; j++)
{
sourceRec = new Rectangle(j * this.FRAMEWIDTHS[i], count, this.FRAMEWIDTHS[i], this.FRAMEHEIGHTS[i]);
Color[] imagePiece = this.GetSubImage(imageData, sourceSpritesheet.Width, sourceRec);
subImage = new Texture2D(Game1.Instance.GraphicsDevice, sourceRec.Width, sourceRec.Height);
subImage.SetData<Color>(imagePiece);
bi[j] = subImage;
}
destinationSprites.Add(bi);
count += this.FRAMEHEIGHTS[i];
}
}
sourceSpritesheet is 368*550 big, FRAMEWIDTHS = 46, FRAMEHEIGTHS = 50, NUMFRAMES.Length = 11 (with values between 1-8)
Is there something that I can't see?
colorData has indices starting from 0 to width * height. You're accessing indices starting from rec.X + rec.Y * width to (rec.X + width) + (height + rec.Y) * height. If rec.X or rec.Y is greater than 0 (which will happen, given how you construct your rectangles), this will go out of bounds. .NET Framework arrays are luckily working correctly, universe is safe...
colorData is 202,400 in size
In the worst case scenario :
colorData[x + rec.X + (y + rec.Y) * width];
x = 45
rec.x = 7*46 = 322
y = 50
rec.y = 11*50 = 550
width = 368
due to the order of operations your formula would execute like so:
x + rec.X + ((y + rec.Y) * width)
45 + 322 + ((50 + 550) * 368)
367 + (600 * 368)
221,167
and 221,167 is greater then colorData size of 202,400. So in conclusion it is most definitely possible to go out of bounds with your function. I would recommend you rewrite it as it seems to be a horrid case of spaghetti code.

image problems with webcamtexture

I have a little problem in my Unity work, I'm trying to get the images from a Webcam texture, and I'll keep it in a byte []. the problem comes when I show the image, which is not seen correctly, it looks like some type of grid mesh. I think the problem is in the for I use to pass the pixels. I hope you can help me.
void Update()
{
//texto.text = texto.text + width +" / "+ height + " / " + ini.ToString()+ " mal: "+ testo().ToString()+ " SizeIMG: "+ imgData.Length + " NUEVO: "+ nuevo +"\n";
imgData = null;
imgData = new byte[width * height * 3];
resultado = null;
resultado = new byte[width * height * 3];
color = webcam.GetPixels32();
for (int i = 0; i < color.Length; i += 3)
{
imgData[(i * 3)] = color[i].r;
imgData[(i * 3) + 1] = color[i].g;
imgData[(i * 3) + 2] = color[i].b;
}
color = null;
//video(imgData, resultado);
//ProcessFrame(imgData, resultado, 0, 0, 0,0, nuevo);
nuevo = false;
textura2 = new Texture2D(width, height, TextureFormat.RGB24, false);
textura2.LoadRawTextureData(imgData);
textura2.Apply();
//Left IMAGE
renderer.material.mainTexture = textura2;
textura2 = null;
RightImage.GetComponent<Renderer>().material.mainTexture = webcam;
if (kont == 30)
{
texto.text = "";
kont = 0;
}
kont++;
Resources.UnloadUnusedAssets();
}
I think the issue is how your indexing into your imgData array. You're incrementing i by three in addition to multiplying by 3.
int bytesPerPixel = 3;
const int indexR = 0;
const int indexG = 1;
const int indexB = 2;
for(var i = 0; i < color.Length; i++)
{
imgData[(i * bytesPerPixel) + indexR] = color[i].r;
imgData[(i * bytesPerPixel) + indexG] = color[i].g;
imgData[(i * bytesPerPixel) + indexB] = color[i].b;
}

How to increase Gaussian Blur strength in Windows Form

I found some great code here on SO and have implemented it in my app and although it is "working", the blur effect is not strong enough to actually realise (without focusing very hard on it) that it has actually blurred anything.
The code is (quite long, sorry):
Bitmap screenshot = null;
void BlurForm()
{
/*
The best time (I assume) is to change the blur when the user as left the window,
as opposed to doing it when they want to open the window, since this may be a
little intensive.
*/
screenshot = null;
blurred.Image = null; // This variable is the PictureBox that's on the Form
screenshot = Screenshot.TakeSnapshot(this);
BitmapFilter.GaussianBlur(screenshot, 4);
blurred.Image = screenshot;
blurred.SendToBack();
}
public class ConvMatrix
{
public int TopLeft = 0, TopMid = 0, TopRight = 0;
public int MidLeft = 0, Pixel = 1, MidRight = 0;
public int BottomLeft = 0, BottomMid = 0, BottomRight = 0;
public int Factor = 1;
public int Offset = 0;
public void SetAll(int nVal)
{
TopLeft = TopMid = TopRight = MidLeft = Pixel = MidRight = BottomLeft = BottomMid = BottomRight = nVal;
}
}
public class BitmapFilter
{
private static bool Conv3x3(Bitmap b, ConvMatrix m)
{
// Avoid divide by zero errors
if (0 == m.Factor) return false;
Bitmap bSrc = (Bitmap)b.Clone();
// GDI+ still lies to us - the return format is BGR, NOT RGB.
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
int stride2 = stride * 2;
System.IntPtr Scan0 = bmData.Scan0;
System.IntPtr SrcScan0 = bmSrc.Scan0;
unsafe
{
byte* p = (byte*)(void*)Scan0;
byte* pSrc = (byte*)(void*)SrcScan0;
int nOffset = stride + 6 - b.Width * 3;
int nWidth = b.Width - 2;
int nHeight = b.Height - 2;
int nPixel;
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
nPixel = ((((pSrc[2] * m.TopLeft) + (pSrc[5] * m.TopMid) + (pSrc[8] * m.TopRight) +
(pSrc[2 + stride] * m.MidLeft) + (pSrc[5 + stride] * m.Pixel) + (pSrc[8 + stride] * m.MidRight) +
(pSrc[2 + stride2] * m.BottomLeft) + (pSrc[5 + stride2] * m.BottomMid) + (pSrc[8 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);
if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;
p[5 + stride] = (byte)nPixel;
nPixel = ((((pSrc[1] * m.TopLeft) + (pSrc[4] * m.TopMid) + (pSrc[7] * m.TopRight) +
(pSrc[1 + stride] * m.MidLeft) + (pSrc[4 + stride] * m.Pixel) + (pSrc[7 + stride] * m.MidRight) +
(pSrc[1 + stride2] * m.BottomLeft) + (pSrc[4 + stride2] * m.BottomMid) + (pSrc[7 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);
if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;
p[4 + stride] = (byte)nPixel;
nPixel = ((((pSrc[0] * m.TopLeft) + (pSrc[3] * m.TopMid) + (pSrc[6] * m.TopRight) +
(pSrc[0 + stride] * m.MidLeft) + (pSrc[3 + stride] * m.Pixel) + (pSrc[6 + stride] * m.MidRight) +
(pSrc[0 + stride2] * m.BottomLeft) + (pSrc[3 + stride2] * m.BottomMid) + (pSrc[6 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);
if (nPixel < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;
p[3 + stride] = (byte)nPixel;
p += 3;
pSrc += 3;
}
p += nOffset;
pSrc += nOffset;
}
}
b.UnlockBits(bmData);
bSrc.UnlockBits(bmSrc);
return true;
}
public static bool GaussianBlur(Bitmap b, int nWeight /* default to 4*/)
{
ConvMatrix m = new ConvMatrix();
m.SetAll(1);
m.Pixel = nWeight;
m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = 2;
m.Factor = nWeight + 12;
return BitmapFilter.Conv3x3(b, m);
}
}
class Screenshot
{
public static Bitmap TakeSnapshot(Control ctl)
{
Bitmap bmp = new Bitmap(ctl.Size.Width, ctl.Size.Height);
using (Graphics g = System.Drawing.Graphics.FromImage(bmp))
{
g.CopyFromScreen(
ctl.PointToScreen(ctl.ClientRectangle.Location),
new Point(0, 0), ctl.ClientRectangle.Size
);
}
return bmp;
}
}
I've tried changing every single value in there and it doesn't matter which value(s) I change, I just can't get it to have a stronger blur effect. How can I increase the strength of the Gaussian Blur?
The Form is 80% Opaque, so the blur effect you would see is the windows wallpaper or whatever is behind the form - but blurred. Only problem (as I've said) is that the blur is not strong at all.
After just glancing at the code, it looks to me like the blur filter is hardcoded to only operate in a 3x3 area at a time, severely restricting how blurred it can make an image.
Unless I'm mistaken, the only way to significantly increase the amount of blurring is to find a more sophisticated implementation.

Categories

Resources