• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By Jens Eckervogt
      Hello guys, 
       
      Please tell me! 
      How do I know? Why does wavefront not show for me?
      I already checked I have non errors yet.
      using OpenTK; using System; using System.Collections.Generic; using System.IO; namespace Tutorial_08.net.sourceskyboxer { public class WaveFrontLoader { private static List<Vector3> vertices; private static List<Vector2> textures; private static List<Vector3> normals; private static List<int> indices; private static float[] verticesArray; private static float[] normalsArray; private static float[] texturesArray; private static int[] indicesArray; private static string[] lines; public static RawModel LoadObjModel(string filename, Loader loader) { if (!File.Exists("Contents/" + filename + ".obj")) { throw new FileNotFoundException("Error: wavefront file doesn't exist path: " + filename + ".png"); } vertices = new List<Vector3>(); textures = new List<Vector2>(); normals = new List<Vector3>(); indices = new List<int>(); lines = File.ReadAllLines("Contents/" + filename + ".obj"); try { foreach (string line in lines) { if (line == "" || line.StartsWith("#")) continue; string[] token = line.Split(' '); switch(token[0]) { case ("o"): string o = token[1]; break; case "v": Vector3 vertex = new Vector3(float.Parse(token[1]), float.Parse(token[2]), float.Parse(token[3])); vertices.Add(vertex); break; case "vn": Vector3 normal = new Vector3(float.Parse(token[1]), float.Parse(token[2]), float.Parse(token[3])); normals.Add(normal); break; case "vt": Vector2 texture = new Vector2(float.Parse(token[1]), float.Parse(token[2])); textures.Add(texture); break; case "f": texturesArray = new float[vertices.Count * 2]; normalsArray = new float[vertices.Count * 3]; verticesArray = new float[vertices.Count * 3]; indicesArray = new int[indices.Count]; int vertexPointer = 0; foreach (Vector3 vex in vertices) { verticesArray[vertexPointer++] = vex.X; verticesArray[vertexPointer++] = vex.Y; verticesArray[vertexPointer++] = vex.Z; } for (int i = 0; i < indices.Count; i++) { indicesArray[i] = indices[i]; } break; } } } catch (FileNotFoundException f) { throw new FileNotFoundException($"OBJ file not found: {f.FileName}", f); } catch (ArgumentException ae) { throw new ArgumentException("OBJ file is damaged", ae); } return loader.loadToVAO(verticesArray, texturesArray, indicesArray); } } } And It have tried other method but it can't show for me.  I am mad now. Because any OpenTK developers won't help me.
      Please help me how do I fix.

      And my download (mega.nz) should it is original but I tried no success...
      - Add blend source and png file here I have tried tried,.....  
       
      PS: Why is our community not active? I wait very longer. Stop to lie me!
      Thanks !
    • By codelyoko373
      I wasn't sure if this would be the right place for a topic like this so sorry if it isn't.
      I'm currently working on a project for Uni using FreeGLUT to make a simple solar system simulation. I've got to the point where I've implemented all the planets and have used a Scene Graph to link them all together. The issue I'm having with now though is basically the planets and moons orbit correctly at their own orbit speeds.
      I'm not really experienced with using matrices for stuff like this so It's likely why I can't figure out how exactly to get it working. This is where I'm applying the transformation matrices, as well as pushing and popping them. This is within the Render function that every planet including the sun and moons will have and run.
      if (tag != "Sun") { glRotatef(orbitAngle, orbitRotation.X, orbitRotation.Y, orbitRotation.Z); } glPushMatrix(); glTranslatef(position.X, position.Y, position.Z); glRotatef(rotationAngle, rotation.X, rotation.Y, rotation.Z); glScalef(scale.X, scale.Y, scale.Z); glDrawElements(GL_TRIANGLES, mesh->indiceCount, GL_UNSIGNED_SHORT, mesh->indices); if (tag != "Sun") { glPopMatrix(); } The "If(tag != "Sun")" parts are my attempts are getting the planets to orbit correctly though it likely isn't the way I'm meant to be doing it. So I was wondering if someone would be able to help me? As I really don't have an idea on what I would do to get it working. Using the if statement is truthfully the closest I've got to it working but there are still weird effects like the planets orbiting faster then they should depending on the number of planets actually be updated/rendered.
    • By Jens Eckervogt
      Hello everyone, 
      I have problem with texture
      using System; using OpenTK; using OpenTK.Input; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL4; using System.Drawing; using System.Reflection; namespace Tutorial_05 { class Game : GameWindow { private static int WIDTH = 1200; private static int HEIGHT = 720; private static KeyboardState keyState; private int vaoID; private int vboID; private int iboID; private Vector3[] vertices = { new Vector3(-0.5f, 0.5f, 0.0f), // V0 new Vector3(-0.5f, -0.5f, 0.0f), // V1 new Vector3(0.5f, -0.5f, 0.0f), // V2 new Vector3(0.5f, 0.5f, 0.0f) // V3 }; private Vector2[] texcoords = { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0) }; private int[] indices = { 0, 1, 3, 3, 1, 2 }; private string vertsrc = @"#version 450 core in vec3 position; in vec2 textureCoords; out vec2 pass_textureCoords; void main(void) { gl_Position = vec4(position, 1.0); pass_textureCoords = textureCoords; }"; private string fragsrc = @"#version 450 core in vec2 pass_textureCoords; out vec4 out_color; uniform sampler2D textureSampler; void main(void) { out_color = texture(textureSampler, pass_textureCoords); }"; private int programID; private int vertexShaderID; private int fragmentShaderID; private int textureID; private Bitmap texsrc; public Game() : base(WIDTH, HEIGHT, GraphicsMode.Default, "Tutorial 05 - Texturing", GameWindowFlags.Default, DisplayDevice.Default, 4, 5, GraphicsContextFlags.Default) { } protected override void OnLoad(EventArgs e) { base.OnLoad(e); CursorVisible = true; GL.GenVertexArrays(1, out vaoID); GL.BindVertexArray(vaoID); GL.GenBuffers(1, out vboID); GL.BindBuffer(BufferTarget.ArrayBuffer, vboID); GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * Vector3.SizeInBytes), vertices, BufferUsageHint.StaticDraw); GL.GenBuffers(1, out iboID); GL.BindBuffer(BufferTarget.ElementArrayBuffer, iboID); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(int)), indices, BufferUsageHint.StaticDraw); vertexShaderID = GL.CreateShader(ShaderType.VertexShader); GL.ShaderSource(vertexShaderID, vertsrc); GL.CompileShader(vertexShaderID); fragmentShaderID = GL.CreateShader(ShaderType.FragmentShader); GL.ShaderSource(fragmentShaderID, fragsrc); GL.CompileShader(fragmentShaderID); programID = GL.CreateProgram(); GL.AttachShader(programID, vertexShaderID); GL.AttachShader(programID, fragmentShaderID); GL.LinkProgram(programID); // Loading texture from embedded resource texsrc = new Bitmap(Assembly.GetEntryAssembly().GetManifestResourceStream("Tutorial_05.example.png")); textureID = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, textureID); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texsrc.Width, texsrc.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); System.Drawing.Imaging.BitmapData bitmap_data = texsrc.LockBits(new Rectangle(0, 0, texsrc.Width, texsrc.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texsrc.Width, texsrc.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bitmap_data.Scan0); texsrc.UnlockBits(bitmap_data); GL.Enable(EnableCap.Texture2D); GL.BufferData(BufferTarget.TextureBuffer, (IntPtr)(texcoords.Length * Vector2.SizeInBytes), texcoords, BufferUsageHint.StaticDraw); GL.BindAttribLocation(programID, 0, "position"); GL.BindAttribLocation(programID, 1, "textureCoords"); } protected override void OnResize(EventArgs e) { base.OnResize(e); GL.Viewport(0, 0, ClientRectangle.Width, ClientRectangle.Height); } protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); keyState = Keyboard.GetState(); if (keyState.IsKeyDown(Key.Escape)) { Exit(); } } protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); // Prepare for background GL.Clear(ClearBufferMask.ColorBufferBit); GL.ClearColor(Color4.Red); // Draw traingles GL.EnableVertexAttribArray(0); GL.EnableVertexAttribArray(1); GL.BindVertexArray(vaoID); GL.UseProgram(programID); GL.BindBuffer(BufferTarget.ArrayBuffer, vboID); GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, IntPtr.Zero); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture3D, textureID); GL.BindBuffer(BufferTarget.ElementArrayBuffer, iboID); GL.DrawElements(BeginMode.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0); GL.DisableVertexAttribArray(0); GL.DisableVertexAttribArray(1); SwapBuffers(); } protected override void OnClosed(EventArgs e) { base.OnClosed(e); GL.DeleteVertexArray(vaoID); GL.DeleteBuffer(vboID); } } } I can not remember where do I add GL.Uniform2();
    • By Jens Eckervogt
      Hello everyone
      For @80bserver8 nice job - I have found Google search. How did you port from Javascript WebGL to C# OpenTK.?
      I have been searched Google but it shows f***ing Unity 3D. I really want know how do I understand I want start with OpenTK But I want know where is porting of Javascript and C#?
       
      Thanks!
    • By mike44
      Hi
      I draw in a OpenGL framebuffer. All is fine but it eats FPS (frames per second), hence I wonder if I could execute the framebuffer drawing only every 5-10th loop or so?
      Many thanks
       
  • Advertisement
  • Advertisement
Sign in to follow this  

OpenGL Need clarity on how to implement a spritebatch

This topic is 763 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm programming in C++ with OpenGL, but decided to post here since this is more of a technical, generic question; I'm not asking how to implement one in OpenGL but rather the idea behind it.
Essentially, I'm batching quads using instancing and a texture 2D array which contains the textures of the quads.
Now, my problem lies on how to effectively batch them, I'll explain myself better: previously, to batch quads, I was simply adding their instance data into a VBO, load it all into GPU and render the quads with a single rendering call, after which I would empty the VBO and start a-new (this time with updated quads' data).
However, I found that to be slow, so I'm currently doing this: a new quad needs to be rendered, so I place its instance data into the VBO, which's going to stay there for as long as the quad needs to be rendered and, whenever it changes position, size or whatever, I'll update its current data into the VBO, overwriting its old data.
Is this a good way? Or is there a better, more efficient way? I'd like to hear your thoughts on this.
Also, how does XNA achieve its spritebatching? I read about it around and it seems to enclose its draw calls into some begin() and end() functions which respectively set up and flush the renderer. Does that mean that it acts like my previous batching method, albeit in a better, more performant way?
Thanks to anyone who can shed some light upon this.

Share this post


Link to post
Share on other sites
Advertisement
In any case, you need to be using double- or triple- buffering (whatever it takes to ensure that you are not waiting on resources that are in-use by the GPU).

Instancing doesn’t make sense for extremely small sets of data.
You are better off either just filling the buffer in directly via the CPU or using the technique described here.
 
And, in any case, you don’t need to update the buffer at all unless the data has changed.  It tends to be a good idea to have separate buffers for background objects and dynamic moving objects.
 

I read about it around and it seems to enclose its draw calls into some begin() and end() functions which respectively set up and flush the renderer. Does that mean that it acts like my previous batching method, albeit in a better, more performant way?

Beginning and ending a sprite batch at the very least sets and optionally restores render states for typical 2D drawing, but you can ignore this as you should already been in such a state and there is overhead for switching.
Other than that it begins a batch, likely by getting an unused internal vertex buffer, filling it progressively for each draw call you make, and finally finishes off and renders the buffer all at once when you finish the batch.
This is implementation-dependent, so there may not be a single best answer, but it is likely along those lines.


L. Spiro

Share this post


Link to post
Share on other sites

Excuse me, I forgot to mention that I AM triple-buffering.

Also, probably it wasn't clear, but I'm updating the VBO ONLY when the data changes.


Instancing doesn’t make sense for extremely small sets of data.
You are better off either just filling the buffer in directly via the CPU or using the technique described here.


Mind explaining me why? I'm only ever going to render the same type of object (a quad) whose copies are going to have different textures, positions and whatnot, so I thought instancing would be ideal in this case, without even mentioning the ease at which all the quads can be rendered (a single draw call).

Thanks for the file, I'll make sure to read it later.

Share this post


Link to post
Share on other sites

Sigh. The crappy forum software here combined with my crappy laptop keyboard just lost a _lot_ of good information (wtf a site in 2016 is still losing all your input if you accidentally navigate off the page?).

 

Short version:

 

1) stream to a single VBO instead of double or triple buffering. For each batch, write to a non-overlapping region. Reduces the number of buffers you need to bind and reduces the complicated resource barrier tracking that driver have to do. If you have the address space to spare (hint: you do, even on 32-bit) then use persistently-mapped buffers. If your API is new enough you can use fences to stall when you need to wrap the VBO or just remap with discard when that happens if your API is old and crufty

 

2a) write individual vertices to your VBO and avoid instancing. Instancing has an overhead per-instance, so you should only use it when that overhead is smaller than the overhead of writing individual vertices into your streaming VBO. For quads, it's very unlikely that your driver's instancing overhead will be small enough to be worthwhile.

 

2b) use vertex fetch to avoid both the instancing overhead and the vertex overhead. Fill in your streaming VBO just like you would for instancing but then draw using a non-instanced draw call with no attribute VBO bound. Draw 6*instance_count vertices. This is fully supported as far back as DX9. Your shader now takes the vertex id and divides that by 6 giving you the index into the transform buffer, and can use the vertex id modulu 6 to calculate the quad vertex data. The small bit of extra work in your vertex shader will be negligible.

Share this post


Link to post
Share on other sites

Sorry that you wasted time by typing something that got lost!
I, again, forgot to mention (that's what you get when you post something half-asleep, I guess) that I'm using a persistently-mapped buffer (I had read this) as well.
Anyway, thank you both for your suggestions, I'll try to work on them and profile.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement