issues with laggy c# code in xna game studio - c#

My code seems to compile okay, but when I try to run it, it hangs very badly.
I've been following along with Riemers XNA tutorial here.
I'm pretty familiar with C#, but an expert by no means. I've had no problems getting any of this to work up to this point, and there are no errors or exceptions being thrown... it just hangs up. I've read on his related forum, where users discussed having other problems, usually relating to typos or code errors, but there's nothing like this in there... everyone seems to be able to run it fine.
Is there something I've done wrong perhaps? The nested for-loop at the bottom seems a bit heavy-handed to me. screenWidth and screenHeight are 500 and 500.
BTW: this is run from the LoadContent override method, so it should only run once as far as I know.
private void GenerateTerrainContour()
{
terrainContour = new int[screenWidth];
for (int x = 0; x < screenWidth; x++)
terrainContour[x] = screenHeight / 2;
}
private void CreateForeground()
{
Color[] foregroundColors = new Color[screenWidth * screenHeight];
for (int x = 0; x < screenWidth; x++)
{
for (int y = 0; y < screenHeight; y++)
{
if (y > terrainContour[x])
foregroundColors[x + y * screenWidth] = Color.Green;
else
foregroundColors[x + y * screenWidth] = Color.Transparent;
fgTexture = new Texture2D(device, screenWidth, screenHeight, false, SurfaceFormat.Color);
fgTexture.SetData(foregroundColors);
}
}
}

Probably something to do with the fact that you're creating 250,000 screen sized textures (holy moly)!
Resource allocation is always heavy - especially when you're dealing with media such as sounds and images.
It seems like you only really need one texture here, try moving fgTexture = new Texture2D(device, screenWidth, screenHeight, false, SurfaceFormat.Color); outside of the loop. Then try moving fgTexture.SetData(foregroundColors); outside of the loop too.
private void CreateForeground()
{
Color[] foregroundColors = new Color[screenWidth * screenHeight];
fgTexture = new Texture2D(device, screenWidth, screenHeight, false, SurfaceFormat.Color);
for (int x = 0; x < screenWidth; x++)
{
for (int y = 0; y < screenHeight; y++)
{
if (y > terrainContour[x])
foregroundColors[x + y * screenWidth] = Color.Green;
else
foregroundColors[x + y * screenWidth] = Color.Transparent;
}
}
fgTexture.SetData(foregroundColors);
}

for (int x = 0; x < screenWidth; x++)
{
for (int y = 0; y < screenHeight; y++)
{
if (y > terrainContour[x])
foregroundColors[x + y * screenWidth] = Color.Green;
else
foregroundColors[x + y * screenWidth] = Color.Transparent;
}
}
foregroundTexture = new Texture2D(device, screenWidth, screenHeight, false, SurfaceFormat.Color);
foregroundTexture.SetData(foregroundColors);
Your issue is on the last two lines. In your loop, you're creating 500 x 500 Texture2D objects, which is slowing you down. Move them outside the for loop.

Related

How to fix terrain Z axis going up on the end and on the X axis its going down?

so I'm rewriting my old code for a hydraulic erosion terrain generator, I knew about this problem on my old code but never asked why, but now I'm rewriting it and want to get everything working smoothly
this is the issue on my Z-axis at the edges the terrain has a step up and on the X-axis it goes down but it's hard to see in the photo plz tell me why
I'm using the built-in terrain generator FYI if you need more code just tell me
public void GenerateHeightMap () {
mapSizeWithBorder = mapSize + erosionBrushRadius * 2;
map = FindObjectOfType<HeightMapGenerator> ().GenerateHeightMap (mapSizeWithBorder);
terrain.terrainData = GenerateTerrain(terrain.terrainData);
}
TerrainData GenerateTerrain(TerrainData terrainData) {
Erode();
float[,] noiseMap = new float[mapSizeWithBorder,mapSizeWithBorder];
int x = 0;
int y = 0;
for (int i = 0; i < map.Length; ++i)
{
noiseMap[x, y] = map[i];
y++;
if (y == mapSizeWithBorder)
{
y = 0;
x++;
}
}
terrainData.size = new Vector3(mapSizeWithBorder * scale, elevationScale, mapSizeWithBorder * scale);
terrainData.SetHeights(0, 0, (noiseMap));
return terrainData;
}

Using gizmos to illustrate the sorting process

The codes below generate 10000cubes(using gizmos). I'm stuck on how to further expand the code and using gizmos to illustrate the sorting process(movement of the cubes when mouse button is click), appreciate if can give me some hint on how to do it.
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
int x;
int y;
int z;
int[,] array1 = new int[100, 100];
int temp;
void Start()
{
for (x = 0; x < 100; x++)
{
for (y = 0; y < 100; y++)
{
array1[x, y] = Random.Range(0, 2);
Debug.Log(string.Format("{0},{1},{2}", x, y, array1[x, y]));
}
}
}
void OnDrawGizmos()
{
for (x = 0; x < 100; x++)
{
for (y = 0; y < 100; y++)
{
Vector2 pos1 = new Vector2(0 + x, 0 + y);
Gizmos.DrawCube(pos1, transform.position);
Gizmos.color = (array1[x, y] == 1) ? Color.black : Color.white;
}
}
}
void OnMouseDown()
{
for (z = 0; z < 100; z++)
{
for (x = 0; x < 100; x++)
{
for (y = 0; y < 100-z; y++)
{
if (array1[x, y] > array1[x, y + 1])
temp = array1[x, y];
array1[x + 1, y] = array1[x, y];
array1[x, y] = temp;
}
}
}
}
}
1.Possible Solution
I provide an answer in this part, and suggest better alternatives below.
The problem with your code is that the sorting happens synchronously, within one frame. What you can do is move the sorting code to Update, and sort a little between each frame. This will let the Gizmos call draw the correct state.
2.Use Progress Bar instead
You may use EditorUtility.DisplayProgressBar to display a progress bar in the Editor. Since you're using Gizmos which don't show up in the Build, this solution assumes you're working in the Editor.
3.Use Compute Buffers
CatLikeCoding has this fantastic article on using Compute Shaders to draw a Graph in high resolution. You can follow it and draw your sorting progress in a very high resolution. Furthermore, this will work in both editor and runtime.

C# XNA 4.0 frame rate problems, possible .SetData missuse

I have a problem regarding frame rate drop while trying to make real time 3D terrain changes. I use C#, XNA 4.0 and VS 2010. This is my old school project and time has come to finish it.
I already did terrain generation from image file, with all effects and stuff and it is running smoothly no matter what resolution image file is. Problem is with my terrain editor. I want it to be able to manually alter the terrain. I did that part too, but it works only if terrain size is equal or less than 128x128 pixels. If the terrain size is greater I start to get frame rate drops around 150x150 pixels, and it is completely unmanageable if terrain size is greater than 512x512 pixels.
I already tried several approaches:
tried to use threads, but then I get weird error saying something like "Draw method can be called in one thread at a time" or something similar, and that I can't resolve.
next I tried to use DynamicVertexBuffer and DynamicIndexBuffer. That helped a lot and now my code is working with acceptable frame rate for terrain size of up to 256x256 pixels.
Have a look at my code:
public void ChangeTerrain(float[,] heightData)
{
int x, y;
int v = 1;
if (currentMouseState.LeftButton == ButtonState.Pressed && currentMouseState.X < 512)
{
x = (int)currentMouseState.X / 2;
y = (int)currentMouseState.Y / 2;
if (x < 5)
x = 5;
if (x >= 251)
x = 251;
if (y < 5)
y = 5;
if (y >= 251)
y = 251;
for (int i = x - 4; i < x + 4; i++)
{
for (int j = y - 4; j < y + 4; j++)
{
if (i == x - 4 || i == x + 3 || j == y - 4 || j == y + 3)
v = 3;
else
v = 5;
if (heightData[i, j] < 210)
{
heightData[i, j] += v;
}
}
}
}
if (currentMouseState.RightButton == ButtonState.Pressed && currentMouseState.X < 512)
{
x = (int)currentMouseState.X / 2;
y = (int)currentMouseState.Y / 2;
if (x < 5)
x = 5;
if (x >= 251)
x = 251;
if (y < 5)
y = 5;
if (y >= 251)
y = 251;
for (int i = x - 4; i < x + 4; i++)
{
for (int j = y - 4; j < y + 4; j++)
{
if (heightData[i, j] > 0)
{
heightData[i, j] -= 1;
}
}
}
}
if (keyState.IsKeyDown(Keys.R))
{
for (int i = 0; i < 256; i++)
for (int j = 0; j < 256; j++)
heightData[i, j] = 0f;
}
SetUpTerrainVertices();
CalculateNormals();
terrainVertexBuffer.SetData(vertices, 0, vertices.Length);
}
I work with resolution of 1024x512 pixels, so I scale mouse position by 1/2 to get terrain position. I use left and right mouse button to alter terrain, i.e. to alter heightData from which 3D terrain is generated.
Last 3 lines create Vertices from new heightData, calculate Normals so shades could be applied and last line is just throwing Vertices data to Vertex Buffer.
Prior to that, I set up dynamic Vertex and Index buffer in LoadContent method and call initial Vertices and Indices setup. This method (ChangeTerrain) is called from Update method.
I did some debugging and found out that maximum size of vertices in most extreme case would be around 260000 +- few thousands. Is it possible that .SetData is so much time consuming it is causing frame rate drops? Or is it something else? How can I fix that and make my editor functioning normally for any terrain size?
Also, i red that I need to use this code with DynamicVertexBuffer, but I can't make it work in XNA 4.0.
terrainVertexBuffer.ContentLost += new EventHandler(TerrainVertexBufferContentLost);
public void TerrainVertexBufferContentLost()
{
terrainVertexBuffer(vertices, 0, vertices.Length, SetDataOptions.NoOverwrite);
}
Thanks for your help!
EDIT:
This is my SetUpTerrainVertices code:
private void SetUpTerrainVertices()
{
vertices = new VertexPositionNormalColored[terrainWidth * terrainLength];
for (int x = 0; x < terrainWidth; x++)
{
for (int y = 0; y < terrainLength; y++)
{
vertices[x + y * terrainWidth].Position = new Vector3(x, heightData[x, y], -y);
vertices[x + y * terrainWidth].Color = Color.Gray;
}
}
}
And my CalculateNormals
private void CalculateNormals()
{
for (int i = 0; i < vertices.Length; i++)
vertices[i].Normal = new Vector3(0, 0, 0);
for (int i = 0; i < indices.Length / 3; i++)
{
int index1 = indices[i * 3];
int index2 = indices[i * 3 + 1];
int index3 = indices[i * 3 + 2];
Vector3 side1 = vertices[index1].Position - vertices[index3].Position;
Vector3 side2 = vertices[index1].Position - vertices[index2].Position;
Vector3 normal = Vector3.Cross(side1, side2);
vertices[index1].Normal += normal;
vertices[index2].Normal += normal;
vertices[index3].Normal += normal;
}
for (int i = 0; i < vertices.Length; i++)
vertices[i].Normal.Normalize();
}
I set up vertex and index buffers in XNA LoadContent Method using lines:
terrainVertexBuffer = new DynamicVertexBuffer(device, VertexPositionNormalColored.VertexDeclaration, vertices.Length,
BufferUsage.None);
terrainIndexBuffer = new DynamicIndexBuffer(device, typeof(int), indices.Length, BufferUsage.None);
I call ChangeTerrain method from Update and this is how i Draw:
private void DrawTerrain(Matrix currentViewMatrix)
{
device.DepthStencilState = DepthStencilState.Default;
device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
effect.CurrentTechnique = effect.Techniques["Colored"];
Matrix worldMatrix = Matrix.Identity;
effect.Parameters["xWorld"].SetValue(worldMatrix);
effect.Parameters["xView"].SetValue(currentViewMatrix);
effect.Parameters["xProjection"].SetValue(projectionMatrix);
effect.Parameters["xEnableLighting"].SetValue(true);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
device.Indices = terrainIndexBuffer;
device.SetVertexBuffer(terrainVertexBuffer);
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, indices.Length / 3);
}
}
EDIT2:
Ok, I decided to go for your second suggestion and got into some problems. I modified my methods like this:
public void ChangeTerrain(Texture2D heightmap)
{
Color[] mapColors = new Color[256 * 256];
Color[] originalColors = new Color[256 * 256];
for (int i = 0; i < 256 * 256; i++)
originalColors[i] = new Color(0, 0, 0);
heightMap2.GetData(mapColors);
device.Textures[0] = null;
device.Textures[1] = null;
int x, y;
int v = 1;
if (currentMouseState.LeftButton == ButtonState.Pressed && currentMouseState.X < 512)
{
x = (int)currentMouseState.X / 2;
y = (int)currentMouseState.Y / 2;
if (x < 4)
x = 4;
if (x >= 251)
x = 251;
if (y < 4)
y = 4;
if (y >= 251)
y = 251;
for (int i = x-4; i < x+4; i++)
{
for (int j = y-4; j < y+4; j++)
{
if (i == x - 4 || i == x + 3 || j == y - 4 || j == y + 3)
v = 3;
else
v = 5;
if (mapColors[i + j * 256].R < 210)
{
mapColors[i + j * 256].R += (byte)(v);
mapColors[i + j * 256].G += (byte)(v);
mapColors[i + j * 256].B += (byte)(v);
}
heightMap2.SetData(mapColors);
}
}
}
if (currentMouseState.RightButton == ButtonState.Pressed && currentMouseState.X < 512)
{
x = (int)currentMouseState.X / 2;
y = (int)currentMouseState.Y / 2;
if (x < 4)
x = 4;
if (x >= 251)
x = 251;
if (y < 4)
y = 4;
if (y >= 251)
y = 251;
for (int i = x - 4; i < x + 4; i++)
{
for (int j = y - 4; j < y + 4; j++)
{
if (mapColors[i + j * 256].R > 0)
{
mapColors[i + j * 256].R -= 1;
mapColors[i + j * 256].G -= 1;
mapColors[i + j * 256].B -= 1;
}
heightMap2.SetData(mapColors);
}
}
}
if (keyState.IsKeyDown(Keys.R))
heightMap2.SetData(originalColors);
}
Generating flat surface - only once in LoadContent() method:
vertices are assigned only once
private void SetUpTerrainVertices()
{
for (int x = 0; x < terrainWidth; x++)
{
for (int y = 0; y < terrainLength; y++)
{
vertices[x + y * terrainWidth].Position = new Vector3(x, 0, -y);
vertices[x + y * terrainLength].Color = Color.Gray;
}
}
}
Draw method is same as previous, but with one extra line:
effect.Parameters["xTexture0"].SetValue(heightMap2);
also, I made new technique called Editor and it looks like this:
//------- Technique: Editor --------
struct EditorVertexToPixel
{
float4 Position : POSITION;
float4 Color : COLOR0;
float LightingFactor: TEXCOORD0;
float2 TextureColor : TEXCOORD1;
};
struct EditorPixelToFrame
{
float4 Color : COLOR0;
};
EditorVertexToPixel EditorVS( float4 inPos : POSITION, float4 inColor: COLOR, float3 inNormal: NORMAL, float2 inTextureColor: TEXCOORD1)
{
EditorVertexToPixel Output = (EditorVertexToPixel)0;
float4x4 preViewProjection = mul (xView, xProjection);
float4x4 preWorldViewProjection = mul (xWorld, preViewProjection);
float4 Height;
float4 position2 = inPos;
position2.y += Height;
Output.Color = inColor;
Output.Position = mul(position2, preWorldViewProjection);
Output.TextureColor = inTextureColor;
float3 Normal = normalize(mul(normalize(inNormal), xWorld));
Output.LightingFactor = 1;
if (xEnableLighting)
Output.LightingFactor = saturate(dot(Normal, -xLightDirection));
return Output;
}
EditorPixelToFrame EditorPS(EditorVertexToPixel PSIn)
{
EditorPixelToFrame Output = (EditorPixelToFrame)0;
//float4 height2 = tex2D(HeightSAmpler, PSIn.TextureColor);
float4 colorNEW = float4(0.1f, 0.1f, 0.6f, 1);
Output.Color = PSIn.Color * colorNEW;
Output.Color.rgb *= saturate(PSIn.LightingFactor) + xAmbient;
return Output;
}
technique Editor
{
pass Pass0
{
VertexShader = compile vs_3_0 EditorVS();
PixelShader = compile ps_3_0 EditorPS();
}
}
this code doesn't work because float4 Height is not set. What I wanted to do is to sample texture colors into float4 Height (using Sample), but I can not use sampler in VertexShader. I get error message "X4532 cannot map expression to vertex shader instruction set".
Then, I red that you can use SampleLevel in VertexShader to sample color data and thought I found solution, but I get strange error that is only documented in one Russian blog, but I can't speak or read Russian. Error is: "X4814 unexpected Alias on texture declaration"
Is there a way to sample colors in PixelShader and then pass them to VertexShader?
This could work cos I managed to set float4 Height to various values and it altered vertices height. Problem is, I don't know how to read texture color in VertexShader, or how to pass red texture color data from PixelShader to VertexShader.
EDIT3:
I think I found solution. Was searching the net and found out about tex2Dlod function to use as VertexShader texture sampler. But there are different syntax displayed and I can't make them work.
Can anyone point out on good HLSL literature to learn a bit about HLSL coding. This task seems pretty easy, but somehow, I can't make it to work.
Ok, so I can't offer "real" performance advice - because I haven't measured your code. And measuring is probably the most important part of performance optimisation - you need to be able to answer the questions: "am I slower than my performance target?" and "why am I slower than my target?"
That being said - here are the things that stand out to me as a seasoned developer:
This method (ChangeTerrain) is called from Update method
You should probably consider splitting that method up so that, rather than recreating your data every frame, it only does work when the terrain is actually changed.
vertices = new VertexPositionNormalColored[terrainWidth * terrainLength];
Allocating a new vertices buffer each frame is huge memory allocation (6MB at 512x512). This is going to put a big strain on the garbage collector - and I suspect this is the primary cause of your performance issues.
Given that you're about to set all the data in that array anyway, simply delete that line and the old data in the array will be overwritten.
Better yet, you could leave the data that doesn't change as-is, and only modify the vertices that are actually changed. In much the same way you are doing for heightData.
As part of this, it would be a very good idea to modify CalculateNormals so that, rather than having to rely on the index buffer and going through every triangle, it could calculate the indices of surrounding vertices (that form triangles) for any specific vertex - something you can do because vertices is ordered. Again, kind of like what you're doing for heightData.
terrainVertexBuffer.SetData(vertices, 0, vertices.Length);
This is sending the full 6MB buffer to the GPU. There are versions of SetData that only send a subset of the full buffer to the GPU. You should probably try and use these.
Just remember that each SetData call comes with some overhead, so don't get too granular. It's probably best to have just one call per vertex buffer, even if that means some unmodified parts of the buffer must be sent.
This is probably the only place where "chunking" your terrain would have an significant impact, as it would allow you to specify a tighter region for each SetData call - allowing you to send less unmodified data. (I'll leave figuring out why this is the case as an exercise.)
(You're already using DynamicVertexBuffer, which is good, because this means the GPU will automatically handle the pipeline issues of having its buffer changed on-the-fly.)
Finally, if performance is still an issue, you could consider a different approach entirely.
One example might be to offload the calculation of the geometry to the GPU. You'd convert your heightData to a texture, and use a vertex shader (with a flat grid of vertices as input) to sample that texture and output the appropriate positions and normals.
One big advantage of this approach is that heightData can be a lot smaller (0.25MB at 512x512) than your vertex buffer - that's much less data that the CPU needs to process and send to the GPU.

ERROR XNA Framework VertexBuffer IndexBuffer usage

I am creating a game after working through a XNA 4.0 book. It will be 3D, but I am already stuck in creating the terrain...
UPDATE: Everything starting from here is an update...
Terrain Update:
public void Update(Matrix view, Matrix projection)
{
View = view;
Projection = projection;
World = Matrix.CreateTranslation(-Width / 2f, 0, Height / 2f);
}
Terrain Draw:
public void Draw(GraphicsDevice g)
{
effect.CurrentTechnique = effect.Techniques["ColoredNoShading"];
effect.Parameters["xView"].SetValue(View);
effect.Parameters["xProjection"].SetValue(Projection);
effect.Parameters["xWorld"].SetValue(World);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
//g.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices, 0, indices.Length / 3, VertexPositionColorNormal.VertexDeclaration);
g.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, indices.Length / 3);
}
}
The commented line is working, in the both cases I am able to see the terrain...
The following code is to initialize Vertex and Index Buffer:
private void SetUpVertices(GraphicsDevice g)
{
float currentH;
int currentI;
vertices = new VertexPositionColorNormal[Width * Height];
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
currentH = heightData[x,y];
currentI = x + y * Width;
vertices[currentI].Position = new Vector3(x, currentH , -y);
if (currentH < minH + (maxH - minH) / 3)
vertices[currentI].Color = Color.ForestGreen;
else if (currentH < maxH - (maxH - minH) / 3)
vertices[currentI].Color = Color.LawnGreen;
else
vertices[currentI].Color = Color.White;
}
}
SetUpIndices(g);
}
private void SetUpIndices(GraphicsDevice g)
{
indices = new int[(Width - 1) * (Height - 1) * 6];
int counter = 0;
for (int y = 0; y < Height - 1; y++)
{
for (int x = 0; x < Width - 1; x++)
{
int lowerLeft = x + y * Width;
int lowerRight = (x + 1) + y * Width;
int topLeft = x + (y + 1) * Width;
int topRight = (x + 1) + (y + 1) * Width;
indices[counter++] = topLeft;
indices[counter++] = lowerRight;
indices[counter++] = lowerLeft;
indices[counter++] = topLeft;
indices[counter++] = topRight;
indices[counter++] = lowerRight;
}
}
SetUpNormals(g);
}
private void SetUpNormals(GraphicsDevice g)
{
for (int i = 0; i < vertices.Length; i++)
{
vertices[i].Normal = Vector3.Zero;
}
int[] index = new int[3];
Vector3 s1, s2, n;
for (int i = 0; i < vertices.Length / 3; i++)
{
for (int y = 0; y < 3; y++)
index[y] = indices[i * 3 + y];
s1 = vertices[index[0]].Position - vertices[index[2]].Position;
s2 = vertices[index[0]].Position - vertices[index[1]].Position;
n = Vector3.Cross(s1, s2);
for (int y = 0; y < 3; y++)
{
vertices[index[y]].Normal += n;
vertices[index[y]].Normal.Normalize();
}
}
FillBuffers(g);
}
private void FillBuffers(GraphicsDevice g)
{
VertexBuffer = new VertexBuffer(g, VertexPositionColorNormal.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
VertexBuffer.SetData(vertices);
IndexBuffer = new IndexBuffer(g, typeof(int), indices.Length, BufferUsage.WriteOnly);
IndexBuffer.SetData(indices);
g.Indices = IndexBuffer;
g.SetVertexBuffer(VertexBuffer);
}
I don't think, that there is a mistake, because it is working with the other line. Might there be an error with the .fx file I am using. If you think so, I am going to switch to BasicEffects...
(You might notice, that the code is from http://www.riemers.net/eng/Tutorials/XNA/Csharp/series1.php )
Thanks for your help...
Yours,
Florian
(Answer to original revision of the question.)
You're not setting your vertex buffer and index buffer onto the graphics device. These two lines of code (untested) should do what you need:
g.GraphicsDevice.Indices = indexBuffer;
g.GraphicsDevice.SetVertexBuffer(vertexBuffer);
Place them just after you set the parameters on your effect (ef), before the loop.
The vertex buffer provides the vertex declaration that the exception message is asking for.
Edit after question update: In your new version you're setting the vertex and index buffers - but it's in the wrong place. You need to set them onto the graphics device each frame. Your code would only work if nothing changes them after you set them in FillBuffers. But I'm guessing that stuff is being drawn outside your class's Draw method?
If that something else is a SpriteBatch, even it works using vertex buffers and index buffers. So it will reset your settings. (It's worth adding that it also sets render states - in which case you might need to see this article.)

Layout Advice for C#

I'm having a difficult time on this issue. I've searched on this site and couldn't find a solution anywhere yet. I have to make a grid of blocks to be displayed on a picture. I've searched and found things about drawing the grid and the GridView class. But all that seems impossible since I have to manipulate the size of the blocks to whatever size. So if anyone can provide any advice I would be very grateful thanks.
If you need simple grid, you can do it by simply drawing it to image:
using (var bitmap = Bitmap.FromFile(#"C:\darbai_test\Penguins.jpg"))
{
var graphics = Graphics.FromImage(bitmap);
var xStep = 10;
var yStep = 15;
for (int i = 0; i < bitmap.Width / xStep; i++)
{
var x = i * xStep;
graphics.DrawLine(Pens.Black, x, 0, x, bitmap.Height);
}
for (int j = 0; j < bitmap.Height / yStep; j++)
{
var y = j * yStep;
graphics.DrawLine(Pens.Black, 0, y, bitmap.Width, y);
}
bitmap.Save(#"c:\darbai_test\penguins_withgrid.jpg");
}

Categories