• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
agleed

Webgl: Is It Possible To Emulate Baseinstance?

4 posts in this topic

I'd like to put all the instance data with the same vertex format into the same buffers. Mainly to save on vertexAttribPointer calls (because they are very slow). However, I can't render all of those instances in one draw call (because of transparency...) so I'd need a way to start drawing with a certain instance offset, so when I draw 1 instance (because I can't batch more) from the middle of the buffer, it pulls (e.g.) the correct matrix from the accompanying vertex buffer that has them. Desktop GL has the BaseInstance versions of all instanced draw calls, but they don't exist in WebGL. Is it possible to emulate them somehow?

 

Optional details:

 

I'm optimizing a 2D renderer and I'm mainly looking to optimize how quads are drawn (since they are almost 100% of our rendering load... quads for text, quads for sprites, quads for tiles, etc.).

 

I already render everything from the same buffer, so that goal is already reached. But I would like to reduce the work that is necessary to prepare all of those buffers, since it turned out to be a bottleneck (Javascript is slow).

 

I batch it by duplicating everything that would be per-instance data (e.g. transform data, colors, etc.). Of course because I'm not instancing yet so I also have to duplicate the actual quad vertex data for each sprite, even though it's the same (they all use a basic 1x1 quad set of vertices and all stretching and sizing is done using the transformation matrix).

 

Using instancing would not only allow me to use less memory in total, it would also allow me to skip a whole lot of copying around of memory each frame. When the order of quads changes, right now I need to copy 4x (4 byte color, 8 byte UVs, 16 byte transform) for each rendered quad (112 bytes). I need to transfer positions too, of course, but that can be done once because they are all the same and never change. 

 

With instancing, all instances would use the same position stream (just 6 elements) and to simulate instancing for UVs (which are different for each quad), I would add another 1 byte 'vertex ID stream' (i.e. also one buffer with 6 elements) and upload the 8 byte of UVs as instance data in a matrix or something, and use the vertex ID stream to index that UV data. So per quad I would only have to handle 1x(16 byte transform, 8 byte UVs, 4 byte color) each frame (= 28 byte, vs previously 116). What I currently don't do is separate all of this stuff out into different streams, so I only need to update the ones that actually change (i.e. only upload matrices each frame), for several reasons which I don't need to get into... but anyways, if I do that as well the ratio of improvement should be the same.

 

(I think, not sure because I haven't implemented it) I could achieve all of the above using emulated software instancing, but then I would have to go through various hassles because the WebGL API is quite limited (so I would have to use 'data textures', a custom instance id stream etc.) so it would be neater if there was a way to just emulate base instance somehow.

0

Share this post


Link to post
Share on other sites

You might be interested in: https://www.khronos.org/registry/gles/extensions/OES/OES_draw_elements_base_vertex.txt

 

You'll need to send uniforms more often (each time the location changes) but that will give you exactly the same result (maybe slower than if instanced were able to be used).

 

There's no WebGL equivalent available, unfortunately. However I'm not sure this would solve my problem anyways. Because I would have the problem that the shared instance data would always be at base vertex 0 (the position + vertex ID stream I mentioned), while only the per-instance data in other buffers would be at a different baseVertex. That's why desktop GL has baseInstance: So the used buffers which don't have any vertexAttribDivisor set still being 'from the start' and only the vertexAttribDivisor ones are offset by the given baseInstance. Am I incorrect?

0

Share this post


Link to post
Share on other sites

Then, you'll need to completly emulate the thing. The idea is that you loop over all your instances, incrementing an instance_id, send it to the shaders, then call to glDrawElements.

 

You can see this for example: https://www.opengl.org/sdk/docs/man/html/glDrawElementsInstancedBaseInstance.xhtml

 

The thing is that you'll need to upload to the shaders the instance_id for each draw call. So, it might be more efficient to do it in a different way.

 

Also, if you have VAO (https://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/), then I highly suggest you to use them. Sending pointers to GL will be far more efficient, since you'll do them only once (at the VAO creation). It might also be possible to use both VAO and the kind of BaseInstance emulation by using dynamic VBO and only update the required part of the buffer (the attrib array that might vary).

 

Hope that helps.

0

Share this post


Link to post
Share on other sites

After some investigation I realized that vertex shader texture fetch isn't possible in WebGL (probably because it's slow on mobile) so emulating instancing would be pretty painful (since I'd have to use the limited amount of uniform slots for all the instanced data that I have...).

 

I can't wait to get back to desktop graphics and proper APIs again. 

 

BTW just to be clear, I'm already simulating instancing by just flattening/duplicating a lot of data and rendering everything in one draw call. This way I can skip ahead to the 'first instance' just by using the offset parameters in drawArrays and drawElements. It's the CPU side copying around of data in typed arrays that I'm trying to optimize (the actual transfer via bufferSubData is fast, I don't need to worry about that for now). Doing it this way is a ton faster than trying to use VAOs and state sorting or what not to try and make draw calls faster (profiled this a lot).

 

I think I might try keeping all of the vertex data for meshes in fixed array locations (so I don't need to update the CPU side buffers at all unless an object is 'dirty') and instead generate only the index buffer every frame... but I remember someone heavily discouraging this for some reason. 

Edited by agleed
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0